Integration of Pavel Machek's vfs code split and vfs syntax change.
The VFS code can now be used by other applications (if you compile the libvfs.a target and link against this). Syntax has changes internally from the url-like syntax to a new syntax that does not have ambiguities. A default conversor for the new syntax will be provided in the future, also dealing with the user ~/.mc/ext files is currently in a non-optimal state. Keep an eye on this mailing list. Miguel.
Этот коммит содержится в:
родитель
fa9cc8e6a9
Коммит
7a7f7a3d85
2
VERSION
2
VERSION
@ -1 +1 @@
|
||||
#define VERSION "4.1.34"
|
||||
#define VERSION "4.1.35"
|
||||
|
@ -1089,8 +1089,8 @@ AC_DEFUN(AC_WITH_VFS, [
|
||||
if $use_net_code; then
|
||||
AC_DEFINE(USE_NETCODE)
|
||||
fi
|
||||
LIBVFS="libvfs.a"
|
||||
LVFS="-lvfs"
|
||||
LIBVFS="libvfs-mc.a"
|
||||
LVFS="-lvfs-mc"
|
||||
fastdepvfs=fastdepvfs
|
||||
if test $have_socket = yes; then
|
||||
mcserv="mcserv"
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#define WANT_WIDGETS
|
||||
#include "tty.h" /* for KEY_BACKSPACE */
|
||||
#include "x.h"
|
||||
#include "main.h"
|
||||
#include "key.h"
|
||||
@ -19,7 +20,6 @@
|
||||
#include "dir.h"
|
||||
#include "panel.h"
|
||||
#include "gscreen.h"
|
||||
#include "tty.h" /* for KEY_BACKSPACE */
|
||||
#include "command.h"
|
||||
#include "cmd.h"
|
||||
#include "gdesktop.h"
|
||||
|
@ -4,12 +4,12 @@
|
||||
* Written by Miguel de Icaza
|
||||
*/
|
||||
#include <config.h>
|
||||
#include "myslang.h"
|
||||
#include "util.h"
|
||||
#include <gnome.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include <string.h>
|
||||
#include "gconf.h"
|
||||
#include "myslang.h"
|
||||
#include "dlg.h"
|
||||
#undef HAVE_LIBGPM
|
||||
#include "mouse.h"
|
||||
|
@ -56,7 +56,7 @@
|
||||
# then the file will be temporarily copied into a local directory
|
||||
# and %f will be the full path to this local temporal file.
|
||||
# If you don't want to get a local copy and want to get the
|
||||
# virtual fs path (like ftp://ftp.cvut.cz/pub/hungry/xword), then
|
||||
# virtual fs path (like /#ftp:ftp.cvut.cz/pub/hungry/xword), then
|
||||
# use %d/%p instead of %f.
|
||||
# %d -> name of the current directory (pwd, without trailing slash)
|
||||
# %s -> "selected files", i.e. space separated list of tagged files if any
|
||||
@ -70,8 +70,7 @@
|
||||
#
|
||||
# %cd -> the rest is not command, but a path which will mc cd internally
|
||||
# into (cd wouldn't work, since it is a child process, and %cd handles
|
||||
# even the vfs names (e.g. tar:archive.tar/path or
|
||||
# ftp://tsx-11.mit.edu/
|
||||
# even the vfs names
|
||||
#
|
||||
# %view -> the command you type will be piped into mc's internal file viewer
|
||||
# if you type only the %view and no command, viewer will load %f file
|
||||
@ -104,26 +103,26 @@
|
||||
# .tgz, .tpz, .tar.gz, .tar.z, .tar.Z
|
||||
|
||||
regex/\.t([gp]?z|ar\.g?[zZ])$
|
||||
Open=%cd tar:%d/%p/
|
||||
Open=%cd %p#utar
|
||||
View=%view{ascii} gzip -dc %f 2>/dev/null | tar tvvf -
|
||||
Extract=gzip -dc %f 2>/dev/null | tar xf -
|
||||
Icon=compressed.xpm
|
||||
|
||||
regex/\.tar\.bz$
|
||||
# Open=%cd tar:%d/%p/
|
||||
# Open=%cd %p#utar
|
||||
View=%view{ascii} bzip -dc %f 2>/dev/null | tar tvvf -
|
||||
Extract=bzip -dc %f 2>/dev/null | tar xf -
|
||||
Icon=compressed.xpm
|
||||
|
||||
regex/\.tar\.bz2$
|
||||
Open=%cd tar:%d/%p/
|
||||
Open=%cd %p#utar
|
||||
View=%view{ascii} bzip2 -dc %f 2>/dev/null | tar tvvf -
|
||||
Extract=bzip2 -dc %f 2>/dev/null | tar xf -
|
||||
Icon=compressed.xpm
|
||||
|
||||
# .tar
|
||||
shell/.tar
|
||||
Open=%cd tar:%d/%p/
|
||||
Open=%cd %p#utar
|
||||
View=%view{ascii} tar tvvf %f
|
||||
Extract=tar xf %f
|
||||
Icon=tar.xpm
|
||||
@ -208,32 +207,32 @@ directory/^.*$
|
||||
|
||||
# ls-lR
|
||||
regex/^ls-?lR$
|
||||
Open=%cd lslR:%d/%p/
|
||||
Open=%cd %p#lslR
|
||||
View=%view{ascii}
|
||||
Icon=plain_dir.xpm
|
||||
regex/^ls-?lR\.(g?z|Z)$
|
||||
Open=%cd lslR:%d/%p/
|
||||
Open=%cd %p#lslR
|
||||
View=%view{ascii} gunzip -c %f
|
||||
Icon=plain_dir.xpm
|
||||
|
||||
# ftplist
|
||||
regex/\.ftplist$
|
||||
Open=%cd ftplist:%d/%p/
|
||||
Open=%cd %p#ftplist
|
||||
|
||||
# rpm
|
||||
regex/\.rpm$
|
||||
Open=%cd rpm:%d/%p/
|
||||
Open=%cd %p#rpm
|
||||
Install this RPM=rpm -i %f
|
||||
Upgrade this RPM=rpm -U %f
|
||||
|
||||
# deb
|
||||
regex/\.deb$
|
||||
Open=%cd deb:%d/%p/
|
||||
Open=%cd %p#deb
|
||||
View=%view{ascii} dpkg-deb -c %f
|
||||
|
||||
# zip
|
||||
regex/\.(zip|ZIP)$
|
||||
Open=%cd zip:%d/%p/
|
||||
Open=%cd %p#uzip
|
||||
View=%view{ascii} unzip -v %f
|
||||
Icon=zip.xpm
|
||||
Extract=unzip %f
|
||||
@ -242,14 +241,14 @@ regex/\.(zip|ZIP)$
|
||||
|
||||
# zoo
|
||||
shell/.zoo
|
||||
Open=%cd zoo:%d/%p/
|
||||
Open=%cd %p#uzoo
|
||||
View=%view{ascii} zoo l %f
|
||||
Icon=zoo.xpm
|
||||
Extract=zoo x %f '*'
|
||||
|
||||
# lha
|
||||
regex/\.(lha|LHA|lzh|LZH)$
|
||||
Open=%cd lha:%d/%p/
|
||||
Open=%cd %p#ulha
|
||||
View=%view{ascii} lharc l %f
|
||||
Icon=lharc.xpm
|
||||
Extract=lharc x %f '*'
|
||||
@ -257,7 +256,7 @@ regex/\.(lha|LHA|lzh|LZH)$
|
||||
|
||||
# arj
|
||||
regex/\.a(rj|[0-9][0-9])$
|
||||
Open=unarj l %f | %var{PAGER:more}
|
||||
Open=%cd %p#uarj
|
||||
View=%view{ascii} unarj l %f
|
||||
Icon=zip.xpm
|
||||
Extract=unarj x %f '*'
|
||||
@ -265,7 +264,7 @@ regex/\.a(rj|[0-9][0-9])$
|
||||
|
||||
# ar library
|
||||
regex/\.s?a$
|
||||
Open=%cd arfs:%d/%p/
|
||||
Open=%cd %p#uar
|
||||
View=%view{ascii} nm %f
|
||||
|
||||
# C
|
||||
@ -506,7 +505,7 @@ regex/\.html?$
|
||||
|
||||
# rar
|
||||
regex/\.[rR]([aA][rR]|[0-9][0-9])$
|
||||
Open=%cd rar:%d/%p/
|
||||
Open=%cd %p#urar
|
||||
View=%view{ascii} rar v -c- %f
|
||||
Extract=rar x -c- %f '*'
|
||||
Extract (with flags)=I=%{Enter any RAR flags:}; if test -n "$I";then rar x $I %f; fi
|
||||
|
299
po/mc.pot
299
po/mc.pot
@ -1,13 +1,62 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Date: 1998-05-25 00:45:01-0500\n"
|
||||
"Date: 1998-05-25 07:34:02-0500\n"
|
||||
"From: Miguel de Icaza,computo,622-4680 <miguel@metropolis.nuclecu.unam.mx>\n"
|
||||
"Content-Type: text/plain; charset=\n"
|
||||
"Xgettext-Options: --default-domain=mc --directory=.. --add-comments --keyword=_ --keyword=N_ --files-from=./POTFILES.in\n"
|
||||
"Files: vfs/ftpfs.c vfs/mcfs.c edit/edit.c edit/edit_key_translator.c edit/editcmd.c edit/editmenu.c edit/editoptions.c edit/editwidget.c src/fixhlp.c src/achown.c src/background.c src/boxes.c src/chmod.c src/chown.c src/cmd.c src/command.c src/dialog.c src/dir.c src/ext.c src/file.c src/find.c src/help.c src/hotlist.c src/info.c src/layout.c src/learn.c src/main.c src/menu.c src/option.c src/panelize.c src/screen.c src/subshell.c src/tree.c src/user.c src/util.c src/utilunix.c src/view.c src/win.c src/wtools.c gnome/gcmd.c gnome/gdesktop.c gnome/glayout.c gnome/gprop.c gnome/gscreen.c gnome/gtools.c gnome/gview.c gnome/gwidget.c\n"
|
||||
|
||||
#: src/wtools.c:609 vfs/ftpfs.c:444 vfs/ftpfs.c:478 vfs/mcfs.c:184
|
||||
msgid "Password:"
|
||||
#: vfs/ftpfs.c:602
|
||||
msgid " Could not set source routing (%s)"
|
||||
msgstr ""
|
||||
|
||||
#: vfs/ftpfs.c:2778 vfs/ftpfs.c:2793
|
||||
msgid ""
|
||||
"~/.netrc file has not correct mode.\n"
|
||||
"Remove password or correct mode."
|
||||
msgstr ""
|
||||
|
||||
#: vfs/mcfs.c:156
|
||||
msgid " MCFS "
|
||||
msgstr ""
|
||||
|
||||
#: vfs/mcfs.c:156
|
||||
msgid " The server does not support this version "
|
||||
msgstr ""
|
||||
|
||||
#: edit/editcmd.c:413 edit/editcmd.c:722 edit/editcmd.c:734 edit/editcmd.c:835 edit/editcmd.c:918 gnome/gdesktop.c:1330 src/ext.c:295 src/help.c:320 src/main.c:671 src/subshell.c:700 src/subshell.c:726 src/utilunix.c:380 src/utilunix.c:384 src/utilunix.c:450 vfs/mcfs.c:172
|
||||
msgid " Warning "
|
||||
msgstr ""
|
||||
|
||||
#: vfs/mcfs.c:173
|
||||
msgid ""
|
||||
" The remote server is not running on a system port \n"
|
||||
" you need a password to log in, but the information may \n"
|
||||
" not be safe on the remote side. Continue? \n"
|
||||
msgstr ""
|
||||
|
||||
#: vfs/mcfs.c:176
|
||||
msgid " Yes "
|
||||
msgstr ""
|
||||
|
||||
#: vfs/mcfs.c:176
|
||||
msgid " No "
|
||||
msgstr ""
|
||||
|
||||
#: vfs/mcfs.c:178
|
||||
msgid " The remote server is running on stange port. Giving up.\n"
|
||||
msgstr ""
|
||||
|
||||
#: vfs/mcfs.c:190
|
||||
msgid " MCFS Password required "
|
||||
msgstr ""
|
||||
|
||||
#: vfs/mcfs.c:204
|
||||
msgid " Invalid password "
|
||||
msgstr ""
|
||||
|
||||
#: vfs/mcfs.c:270
|
||||
msgid " Too many open connections "
|
||||
msgstr ""
|
||||
|
||||
#. The file-name is printed after the ':'
|
||||
@ -66,10 +115,6 @@ msgstr ""
|
||||
msgid " Save As "
|
||||
msgstr ""
|
||||
|
||||
#: edit/editcmd.c:413 edit/editcmd.c:722 edit/editcmd.c:734 edit/editcmd.c:835 edit/editcmd.c:918 gnome/gdesktop.c:1347 src/ext.c:295 src/help.c:320 src/main.c:685 src/subshell.c:700 src/subshell.c:726 src/utilunix.c:377 src/utilunix.c:381 src/utilunix.c:447
|
||||
msgid " Warning "
|
||||
msgstr ""
|
||||
|
||||
#: edit/editcmd.c:414
|
||||
msgid " A file already exists with this name. "
|
||||
msgstr ""
|
||||
@ -312,11 +357,11 @@ msgstr ""
|
||||
msgid "Cancel quit"
|
||||
msgstr ""
|
||||
|
||||
#: edit/editcmd.c:1969 gnome/gcmd.c:94 gnome/gdesktop.c:625 gnome/gdesktop.c:1204 src/cmd.c:248 src/file.c:2365 src/file.c:2691 src/file.c:2881 src/hotlist.c:1027 src/main.c:840 src/screen.c:2040 src/subshell.c:701 src/subshell.c:727 src/tree.c:1195 src/view.c:410
|
||||
#: edit/editcmd.c:1969 gnome/gcmd.c:94 gnome/gdesktop.c:625 gnome/gdesktop.c:1187 src/cmd.c:248 src/file.c:2365 src/file.c:2691 src/file.c:2881 src/hotlist.c:1027 src/main.c:826 src/screen.c:2040 src/subshell.c:701 src/subshell.c:727 src/tree.c:1195 src/view.c:410
|
||||
msgid "&Yes"
|
||||
msgstr ""
|
||||
|
||||
#: edit/editcmd.c:1969 gnome/gcmd.c:94 gnome/gdesktop.c:625 gnome/gdesktop.c:1204 src/cmd.c:248 src/file.c:2365 src/file.c:2690 src/file.c:2881 src/hotlist.c:1027 src/main.c:840 src/screen.c:2040 src/subshell.c:701 src/subshell.c:727 src/tree.c:1195 src/view.c:410
|
||||
#: edit/editcmd.c:1969 gnome/gcmd.c:94 gnome/gdesktop.c:625 gnome/gdesktop.c:1187 src/cmd.c:248 src/file.c:2365 src/file.c:2690 src/file.c:2881 src/hotlist.c:1027 src/main.c:826 src/screen.c:2040 src/subshell.c:701 src/subshell.c:727 src/tree.c:1195 src/view.c:410
|
||||
msgid "&No"
|
||||
msgstr ""
|
||||
|
||||
@ -581,11 +626,11 @@ msgstr ""
|
||||
msgid "&Save mode..."
|
||||
msgstr ""
|
||||
|
||||
#: edit/editmenu.c:243 edit/editmenu.c:252 src/main.c:1310
|
||||
#: edit/editmenu.c:243 edit/editmenu.c:252 src/main.c:1296
|
||||
msgid "&Layout..."
|
||||
msgstr ""
|
||||
|
||||
#: edit/editmenu.c:262 edit/editmenu.c:271 edit/editmenu.c:388 src/chmod.c:174 src/chown.c:131 src/main.c:1341
|
||||
#: edit/editmenu.c:262 edit/editmenu.c:271 edit/editmenu.c:388 src/chmod.c:174 src/chown.c:131 src/main.c:1327
|
||||
msgid " File "
|
||||
msgstr ""
|
||||
|
||||
@ -597,11 +642,11 @@ msgstr ""
|
||||
msgid " Sear/Repl "
|
||||
msgstr ""
|
||||
|
||||
#: edit/editmenu.c:265 edit/editmenu.c:274 edit/editmenu.c:438 src/main.c:1342
|
||||
#: edit/editmenu.c:265 edit/editmenu.c:274 edit/editmenu.c:438 src/main.c:1328
|
||||
msgid " Command "
|
||||
msgstr ""
|
||||
|
||||
#: edit/editmenu.c:266 edit/editmenu.c:275 src/main.c:1343
|
||||
#: edit/editmenu.c:266 edit/editmenu.c:275 src/main.c:1329
|
||||
msgid " Options "
|
||||
msgstr ""
|
||||
|
||||
@ -762,7 +807,7 @@ msgstr ""
|
||||
msgid "Error initialising editor.\n"
|
||||
msgstr ""
|
||||
|
||||
#: edit/editwidget.c:992 gnome/glayout.c:350 src/help.c:812 src/main.c:1672 src/screen.c:2256 src/screen.c:2290 src/tree.c:1451 src/view.c:1987
|
||||
#: edit/editwidget.c:992 gnome/glayout.c:350 src/help.c:812 src/main.c:1658 src/screen.c:2256 src/screen.c:2290 src/tree.c:1451 src/view.c:1987
|
||||
msgid "Help"
|
||||
msgstr ""
|
||||
|
||||
@ -786,15 +831,15 @@ msgstr ""
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
#: edit/editwidget.c:999 gnome/gdesktop.c:624 gnome/gdesktop.c:1100 gnome/gscreen.c:545 src/screen.c:2263 src/screen.c:2297
|
||||
#: edit/editwidget.c:999 gnome/gdesktop.c:624 gnome/gscreen.c:545 src/screen.c:2263 src/screen.c:2297
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: edit/editwidget.c:1001 src/main.c:1674
|
||||
#: edit/editwidget.c:1001 src/main.c:1660
|
||||
msgid "PullDn"
|
||||
msgstr ""
|
||||
|
||||
#: edit/editwidget.c:1002 gnome/gview.c:286 src/help.c:824 src/main.c:1675 src/view.c:1989 src/view.c:2009
|
||||
#: edit/editwidget.c:1002 gnome/gview.c:286 src/help.c:824 src/main.c:1661 src/view.c:1989 src/view.c:2009
|
||||
msgid "Quit"
|
||||
msgstr ""
|
||||
|
||||
@ -2102,7 +2147,7 @@ msgstr ""
|
||||
msgid "Content: "
|
||||
msgstr ""
|
||||
|
||||
#: src/find.c:158 src/main.c:1206 src/main.c:1227
|
||||
#: src/find.c:158 src/main.c:1192 src/main.c:1213
|
||||
msgid "&Tree"
|
||||
msgstr ""
|
||||
|
||||
@ -2594,7 +2639,7 @@ msgstr ""
|
||||
msgid "key, or click with the mouse to define it. Move around with Tab."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:686
|
||||
#: src/main.c:672
|
||||
msgid ""
|
||||
" The Commander can't change to the directory that \n"
|
||||
" the subshell claims you are in. Perhaps you have \n"
|
||||
@ -2602,131 +2647,131 @@ msgid ""
|
||||
" extra access permissions with the \"su\" command? "
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:761
|
||||
#: src/main.c:747
|
||||
msgid "Press any key to continue..."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:811
|
||||
#: src/main.c:797
|
||||
msgid " The shell is already running a command "
|
||||
msgstr ""
|
||||
|
||||
#: gnome/gcmd.c:92 gnome/gdesktop.c:1202 src/main.c:838 src/screen.c:2038
|
||||
#: gnome/gcmd.c:92 gnome/gdesktop.c:1185 src/main.c:824 src/screen.c:2038
|
||||
msgid " The Midnight Commander "
|
||||
msgstr ""
|
||||
|
||||
#: gnome/gcmd.c:93 src/main.c:839
|
||||
#: gnome/gcmd.c:93 src/main.c:825
|
||||
msgid " Do you really want to quit the Midnight Commander? "
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1203 src/main.c:1224
|
||||
#: src/main.c:1189 src/main.c:1210
|
||||
msgid "&Listing mode..."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1204 src/main.c:1225
|
||||
#: src/main.c:1190 src/main.c:1211
|
||||
msgid "&Quick view C-x q"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1205 src/main.c:1226
|
||||
#: src/main.c:1191 src/main.c:1212
|
||||
msgid "&Info C-x i"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1208 src/main.c:1229
|
||||
#: src/main.c:1194 src/main.c:1215
|
||||
msgid "&Sort order..."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1210 src/main.c:1231
|
||||
#: src/main.c:1196 src/main.c:1217
|
||||
msgid "&Filter..."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1213 src/main.c:1234
|
||||
#: src/main.c:1199 src/main.c:1220
|
||||
msgid "&Network link..."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1214 src/main.c:1235
|
||||
#: src/main.c:1200 src/main.c:1221
|
||||
msgid "FT&P link..."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1218 src/main.c:1239
|
||||
#: src/main.c:1204 src/main.c:1225
|
||||
msgid "&Drive... M-d"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1220 src/main.c:1241
|
||||
#: src/main.c:1206 src/main.c:1227
|
||||
msgid "&Rescan C-r"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1245
|
||||
#: src/main.c:1231
|
||||
msgid "&User menu F2"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1246
|
||||
#: src/main.c:1232
|
||||
msgid "&View F3"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1247
|
||||
#: src/main.c:1233
|
||||
msgid "&Filtered view M-!"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1248
|
||||
#: src/main.c:1234
|
||||
msgid "&Edit F4"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1249
|
||||
#: src/main.c:1235
|
||||
msgid "&Copy F5"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1250
|
||||
#: src/main.c:1236
|
||||
msgid "c&Hmod C-x c"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1252
|
||||
#: src/main.c:1238
|
||||
msgid "&Link C-x l"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1253
|
||||
#: src/main.c:1239
|
||||
msgid "&SymLink C-x s"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1254
|
||||
#: src/main.c:1240
|
||||
msgid "edit s&Ymlink C-x C-s"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1255
|
||||
#: src/main.c:1241
|
||||
msgid "ch&Own C-x o"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1256
|
||||
#: src/main.c:1242
|
||||
msgid "&Advanced chown "
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1258
|
||||
#: src/main.c:1244
|
||||
msgid "&Rename/Move F6"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1259
|
||||
#: src/main.c:1245
|
||||
msgid "&Mkdir F7"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1260
|
||||
#: src/main.c:1246
|
||||
msgid "&Delete F8"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1261
|
||||
#: src/main.c:1247
|
||||
msgid "&Quick cd M-c"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1263
|
||||
#: src/main.c:1249
|
||||
msgid "select &Group M-+"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1264
|
||||
#: src/main.c:1250
|
||||
msgid "u&Nselect group M-\\"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1265
|
||||
#: src/main.c:1251
|
||||
msgid "reverse selec&Tion M-*"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1267
|
||||
#: src/main.c:1253
|
||||
msgid "e&Xit F10"
|
||||
msgstr ""
|
||||
|
||||
@ -2734,111 +2779,111 @@ msgstr ""
|
||||
#. * as a panel still has some problems, I have not yet finished
|
||||
#. * the WTree widget port, sorry.
|
||||
#.
|
||||
#: src/main.c:1276
|
||||
#: src/main.c:1262
|
||||
msgid "&Directory tree"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1277
|
||||
#: src/main.c:1263
|
||||
msgid "&Find file M-?"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1279
|
||||
#: src/main.c:1265
|
||||
msgid "s&Wap panels C-u"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1280
|
||||
#: src/main.c:1266
|
||||
msgid "switch &Panels on/off C-o"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1282
|
||||
#: src/main.c:1268
|
||||
msgid "&Compare directories C-x d"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1283
|
||||
#: src/main.c:1269
|
||||
msgid "e&Xternal panelize C-x !"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1285
|
||||
#: src/main.c:1271
|
||||
msgid "show directory s&Izes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1288
|
||||
#: src/main.c:1274
|
||||
msgid "command &History"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1289
|
||||
#: src/main.c:1275
|
||||
msgid "di&Rectory hotlist C-\\"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1291
|
||||
#: src/main.c:1277
|
||||
msgid "&Active VFS list C-x a"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1294
|
||||
#: src/main.c:1280
|
||||
msgid "&Background jobs C-x j"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1298
|
||||
#: src/main.c:1284
|
||||
msgid "&Undelete files (ext2fs only)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1301
|
||||
#: src/main.c:1287
|
||||
msgid "&Listing format edit"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1303
|
||||
#: src/main.c:1289
|
||||
msgid "&Extension file edit"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1304
|
||||
#: src/main.c:1290
|
||||
msgid "&Menu file edit"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1309
|
||||
#: src/main.c:1295
|
||||
msgid "&Configuration..."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1311
|
||||
#: src/main.c:1297
|
||||
msgid "c&Onfirmation..."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1312
|
||||
#: src/main.c:1298
|
||||
msgid "&Display bits..."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1314
|
||||
#: src/main.c:1300
|
||||
msgid "learn &Keys..."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1317
|
||||
#: src/main.c:1303
|
||||
msgid "&Virtual FS..."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1320
|
||||
#: src/main.c:1306
|
||||
msgid "&Save setup"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1336 src/main.c:1338
|
||||
#: src/main.c:1322 src/main.c:1324
|
||||
msgid " Left "
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1338
|
||||
#: src/main.c:1324
|
||||
msgid " Above "
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1346 src/main.c:1348
|
||||
#: src/main.c:1332 src/main.c:1334
|
||||
msgid " Right "
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1348
|
||||
#: src/main.c:1334
|
||||
msgid " Below "
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1409
|
||||
#: src/main.c:1395
|
||||
msgid " Information "
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1410
|
||||
#: src/main.c:1396
|
||||
msgid ""
|
||||
" Using the fast reload option may not reflect the exact \n"
|
||||
" directory contents. In this cases you'll need to do a \n"
|
||||
@ -2846,149 +2891,149 @@ msgid ""
|
||||
" the details. "
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1673 src/screen.c:2257 src/screen.c:2291
|
||||
#: src/main.c:1659 src/screen.c:2257 src/screen.c:2291
|
||||
msgid "Menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:1884
|
||||
#: src/main.c:1870
|
||||
msgid "Thank you for using GNU Midnight Commander"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2246
|
||||
#: src/main.c:2232
|
||||
msgid "with mouse support on xterm%s.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2247
|
||||
#: src/main.c:2233
|
||||
msgid " and the Linux console"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2340
|
||||
#: src/main.c:2326
|
||||
msgid "The TERM environment variable is unset!\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2592
|
||||
#: src/main.c:2578
|
||||
msgid "Library directory for the Midnight Commander: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2597
|
||||
#: src/main.c:2583
|
||||
msgid "Option -m is obsolete. Please look at Display Bits... in the Option's menu\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2658
|
||||
#: src/main.c:2644
|
||||
msgid "[DEVEL-ONLY: Debug the background code]"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2661
|
||||
#: src/main.c:2647
|
||||
msgid "Create command file to set default directory upon exit."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2663
|
||||
#: src/main.c:2649
|
||||
msgid "Force color mode."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2664
|
||||
#: src/main.c:2650
|
||||
msgid "Specify colors (use --help-colors to get a list)."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2666
|
||||
#: src/main.c:2652
|
||||
msgid "[DEVEL-ONLY: Debug the subshell."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2668
|
||||
#: src/main.c:2654
|
||||
msgid "Startup the internal editor."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2669
|
||||
#: src/main.c:2655
|
||||
msgid "Shows this help message."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2670
|
||||
#: src/main.c:2656
|
||||
msgid "Help on how to specify colors."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2672
|
||||
#: src/main.c:2658
|
||||
msgid "Log ftpfs commands to the file."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2674
|
||||
#: src/main.c:2660
|
||||
msgid "Prints out the configured paths."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2676
|
||||
#: src/main.c:2662
|
||||
msgid "Force black and white display."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2677
|
||||
#: src/main.c:2663
|
||||
msgid "Disable mouse support."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2679
|
||||
#: src/main.c:2665
|
||||
msgid "Force the concurrent subshell mode"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2680
|
||||
#: src/main.c:2666
|
||||
msgid "Disable the concurrent subshell mode."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2681
|
||||
#: src/main.c:2667
|
||||
msgid "Force subshell execution."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2683
|
||||
#: src/main.c:2669
|
||||
msgid "At exit, print the last working directory."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2684
|
||||
#: src/main.c:2670
|
||||
msgid "Reset softkeys (HP terminals only) to their terminfo/termcap default."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2685
|
||||
#: src/main.c:2671
|
||||
msgid "Disables verbose operation (for slow terminals)."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2687
|
||||
#: src/main.c:2673
|
||||
msgid "Use simple symbols for line drawing."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2692
|
||||
#: src/main.c:2678
|
||||
msgid "Activate support for the TERMCAP variable."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2694
|
||||
#: src/main.c:2680
|
||||
msgid "Report versionand configuration options."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2695
|
||||
#: src/main.c:2681
|
||||
msgid "Start up into the viewer mode."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2696
|
||||
#: src/main.c:2682
|
||||
msgid "Force xterm mouse support and screen save/restore"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2697
|
||||
#: src/main.c:2683
|
||||
msgid "Geometry for the window"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2698
|
||||
#: src/main.c:2684
|
||||
msgid "No windows opened at startup"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:2775
|
||||
#: src/main.c:2761
|
||||
msgid "[this dir] [other dir]"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:3017
|
||||
#: src/main.c:3003
|
||||
msgid ""
|
||||
"Couldn't open tty line. You have to run mc without the -P flag.\n"
|
||||
"On some systems you may want to run # `which mc`\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:3105
|
||||
#: src/main.c:3091
|
||||
msgid " Notice "
|
||||
msgstr ""
|
||||
|
||||
#: src/main.c:3106
|
||||
#: src/main.c:3092
|
||||
msgid ""
|
||||
" The Midnight Commander configuration files \n"
|
||||
" are now stored in the ~/.mc directory, the \n"
|
||||
@ -3221,7 +3266,7 @@ msgstr ""
|
||||
msgid "Unknow tag on display format: "
|
||||
msgstr ""
|
||||
|
||||
#: gnome/gdesktop.c:1203 src/screen.c:2039
|
||||
#: gnome/gdesktop.c:1186 src/screen.c:2039
|
||||
msgid " Do you really want to execute? "
|
||||
msgstr ""
|
||||
|
||||
@ -3360,15 +3405,15 @@ msgstr ""
|
||||
msgid " User menu "
|
||||
msgstr ""
|
||||
|
||||
#: src/util.c:232
|
||||
#: src/util.c:235
|
||||
msgid "name_trunc: too big"
|
||||
msgstr ""
|
||||
|
||||
#: src/utilunix.c:377
|
||||
#: src/utilunix.c:380
|
||||
msgid " Pipe failed "
|
||||
msgstr ""
|
||||
|
||||
#: src/utilunix.c:381
|
||||
#: src/utilunix.c:384
|
||||
msgid " Dup failed "
|
||||
msgstr ""
|
||||
|
||||
@ -3709,6 +3754,10 @@ msgstr ""
|
||||
msgid "NumLock on keypad"
|
||||
msgstr ""
|
||||
|
||||
#: src/wtools.c:609
|
||||
msgid "Password:"
|
||||
msgstr ""
|
||||
|
||||
#: src/wtools.c:609
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
@ -3738,19 +3787,15 @@ msgstr ""
|
||||
msgid "Do you want to delete "
|
||||
msgstr ""
|
||||
|
||||
#: gnome/gdesktop.c:1093 gnome/gscreen.c:514 gnome/gscreen.c:515
|
||||
msgid "Properties"
|
||||
msgstr ""
|
||||
|
||||
#: gnome/gdesktop.c:1213
|
||||
#: gnome/gdesktop.c:1196
|
||||
msgid "Open with..."
|
||||
msgstr ""
|
||||
|
||||
#: gnome/gdesktop.c:1214 gnome/gscreen.c:466
|
||||
#: gnome/gdesktop.c:1197 gnome/gscreen.c:466
|
||||
msgid "Enter extra arguments:"
|
||||
msgstr ""
|
||||
|
||||
#: gnome/gdesktop.c:1347
|
||||
#: gnome/gdesktop.c:1330
|
||||
msgid " Could not open %s directory"
|
||||
msgstr ""
|
||||
|
||||
@ -4094,6 +4139,10 @@ msgstr ""
|
||||
msgid " Open with..."
|
||||
msgstr ""
|
||||
|
||||
#: gnome/gscreen.c:514 gnome/gscreen.c:515
|
||||
msgid "Properties"
|
||||
msgstr ""
|
||||
|
||||
#: gnome/gscreen.c:517 gnome/gscreen.c:518
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
|
@ -66,7 +66,7 @@ cons.saver: cons.saver.o
|
||||
check:
|
||||
@echo no tests are supplied.
|
||||
|
||||
mc: $(OBJS) @LIBVFS@ @LIBSLANG@ @LIBEDIT_A@
|
||||
mc: $(OBJS) libvfs-mc.a @LIBSLANG@ @LIBEDIT_A@
|
||||
$(CC) $(LDFLAGS) -o $@ $(OBJS) -L../vfs -L../slang -L../edit $(OURLIBS) $(LIBS)
|
||||
|
||||
mfmt: mfmt.o
|
||||
@ -75,10 +75,10 @@ mfmt: mfmt.o
|
||||
mcmfmt: mfmt
|
||||
cp mfmt mcmfmt
|
||||
|
||||
libvfs.a:
|
||||
cd ../vfs; $(MAKE) libvfs.a
|
||||
@PCENTRULE@ -$(RMF) libvfs.a
|
||||
@PCENTRULE@ $(LN_S) ../vfs/libvfs.a .
|
||||
libvfs-mc.a:
|
||||
cd ../vfs; $(MAKE) libvfs-mc.a
|
||||
@PCENTRULE@ -$(RMF) libvfs-mc.a
|
||||
@PCENTRULE@ $(LN_S) ../vfs/libvfs-mc.a .
|
||||
|
||||
libmcslang.a:
|
||||
cd ../slang; $(MAKE) libmcslang.a
|
||||
@ -109,7 +109,7 @@ TAGS: $(SRCS)
|
||||
|
||||
clean:
|
||||
$(RMF) mc cons.saver man2hlp fixhlp *.o core a.out mc.html mcmfmt
|
||||
$(RMF) libvfs.a libedit.a libmcslang.a mfmt
|
||||
$(RMF) libvfs-mc.a libedit.a libmcslang.a mfmt
|
||||
|
||||
realclean: clean
|
||||
$(RMF) .depend
|
||||
@ -121,7 +121,7 @@ distclean:
|
||||
-$(RMF) $(srcdir)/mfmt
|
||||
-$(RMF) $(srcdir)/man2hlp $(srcdir)/fixhlp $(srcdir)/*.o $(srcdir)/core
|
||||
-$(RMF) $(srcdir)/a.out $(srcdir)/mc.html
|
||||
-$(RMF) $(srcdir)/libvfs.a $(srcdir)/libmcslang.a $(srcdir)/libedit.a
|
||||
-$(RMF) $(srcdir)/libvfs-mc.a $(srcdir)/libmcslang.a $(srcdir)/libedit.a
|
||||
-if test $(srcdir) = .; then $(MAKE) realclean; fi
|
||||
-$(RMF) $(srcdir)/Makefile
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include "tty.h"
|
||||
#include "dlg.h"
|
||||
#include "widget.h"
|
||||
#include "wtools.h"
|
||||
@ -48,7 +49,6 @@
|
||||
#ifdef USE_NETCODE
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
#include "tty.h"
|
||||
#include "util.h"
|
||||
#include "dialog.h"
|
||||
#include "file.h"
|
||||
|
@ -1259,13 +1259,13 @@ static void nice_cd (char *text, char *xtext, char *help, char *prefix, int to_h
|
||||
void netlink_cmd (void)
|
||||
{
|
||||
nice_cd (_(" Link to a remote machine "), _(machine_str),
|
||||
"[Network File System]", "mc:", 1);
|
||||
"[Network File System]", "/#mc:", 1);
|
||||
}
|
||||
|
||||
void ftplink_cmd (void)
|
||||
{
|
||||
nice_cd (_(" FTP to machine "), _(machine_str),
|
||||
"[FTP File System]", "ftp://", 1);
|
||||
"[FTP File System]", "/#ftp:", 1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SETSOCKOPT
|
||||
@ -1296,7 +1296,7 @@ void undelete_cmd (void)
|
||||
nice_cd (_(" Undelete files on an ext2 file system "),
|
||||
_(" Enter the file system name where you want to run the\n "
|
||||
" undelete file system on: (F1 for details)"),
|
||||
"[Undelete File System]", "undel:", 0);
|
||||
"[Undelete File System]", "/#undel/", 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -306,7 +306,7 @@ static int
|
||||
add_dotdot_to_list (dir_list *list, int index)
|
||||
{
|
||||
char buffer [MC_MAXPATHLEN + MC_MAXPATHLEN];
|
||||
char *p, *s;
|
||||
char *p;
|
||||
int i = 0;
|
||||
|
||||
/* Need to grow the *list? */
|
||||
@ -337,7 +337,7 @@ add_dotdot_to_list (dir_list *list, int index)
|
||||
break;
|
||||
}
|
||||
i = 1;
|
||||
if ((s = vfs_path (p)) && !strcmp (s, PATH_SEP_STR)){
|
||||
if (!strcmp (p, PATH_SEP_STR)){
|
||||
free (p);
|
||||
return 1;
|
||||
}
|
||||
|
14
src/main.c
14
src/main.c
@ -387,20 +387,6 @@ cd_try_to_select (WPanel *panel)
|
||||
&& strchr (panel->lwd + strlen (panel->cwd) + 1, PATH_SEP) == 0)
|
||||
try_to_select (panel, panel->lwd);
|
||||
else
|
||||
#ifdef USE_VFS
|
||||
if ((!strncmp (panel->lwd, "tar:", 4) &&
|
||||
!strncmp (panel->lwd + 4, panel->cwd, strlen (panel->cwd))) ||
|
||||
((i = extfs_prefix_to_type (panel->lwd)) != -1 &&
|
||||
!strncmp (panel->lwd + (j = strlen (extfs_get_prefix (i)) + 1),
|
||||
panel->cwd, strlen (panel->cwd)))) {
|
||||
p = strdup (panel->lwd + j + strlen (panel->cwd));
|
||||
q = strchr (p, PATH_SEP);
|
||||
if (q != NULL && (q != p || (q = strchr (q + 1, PATH_SEP)) != NULL))
|
||||
*q = 0;
|
||||
try_to_select (panel, p);
|
||||
free (p);
|
||||
} else
|
||||
#endif
|
||||
try_to_select (panel, NULL);
|
||||
}
|
||||
|
||||
|
@ -1528,7 +1528,7 @@ static int my_mkdir_rec (char *s, mode_t mode)
|
||||
/* FIXME: should check instead if s is at the root of that filesystem */
|
||||
if (!vfs_file_is_local (s))
|
||||
return -1;
|
||||
if (!strcmp (vfs_path(s), PATH_SEP_STR))
|
||||
if (!strcmp (s, PATH_SEP_STR))
|
||||
return ENOTDIR;
|
||||
p = concat_dir_and_file (s, "..");
|
||||
q = vfs_canon (p);
|
||||
|
59
src/util.c
59
src/util.c
@ -103,6 +103,7 @@ char *strdup (const char *s)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef VFS_STANDALONE
|
||||
int is_printable (int c)
|
||||
{
|
||||
static const unsigned char xterm_printable[] = {
|
||||
@ -165,6 +166,7 @@ char *trim (char *s, char *d, int len)
|
||||
strcpy (d, s);
|
||||
return d;
|
||||
}
|
||||
#endif
|
||||
|
||||
char *
|
||||
name_quote (const char *s, int quote_percent)
|
||||
@ -210,6 +212,7 @@ name_quote (const char *s, int quote_percent)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef VFS_STANDALONE
|
||||
char *
|
||||
fake_name_quote (const char *s, int quote_percent)
|
||||
{
|
||||
@ -358,51 +361,24 @@ strip_password (char *path)
|
||||
|
||||
char *strip_home_and_password(char *dir)
|
||||
{
|
||||
static char newdir [MC_MAXPATHLEN], *p, *q;
|
||||
static char newdir [MC_MAXPATHLEN];
|
||||
|
||||
if (home_dir && !strncmp (dir, home_dir, strlen (home_dir))){
|
||||
newdir [0] = '~';
|
||||
strcpy (&newdir [1], &dir [strlen (home_dir)]);
|
||||
return newdir;
|
||||
}
|
||||
#ifdef USE_NETCODE
|
||||
else if (!strncmp (dir, "ftp://", 6)) {
|
||||
strip_password (strcpy (newdir, dir) + 6);
|
||||
if ((p = strchr (newdir + 6, PATH_SEP)) != NULL) {
|
||||
*p = 0;
|
||||
q = ftpfs_gethome (newdir);
|
||||
*p = PATH_SEP;
|
||||
if (q != 0 && strcmp (q, PATH_SEP_STR) && !strncmp (p, q, strlen (q) - 1)) {
|
||||
strcpy (p, "/~");
|
||||
strcat (newdir, p + strlen (q) - 1);
|
||||
}
|
||||
}
|
||||
return newdir;
|
||||
} else if (!strncmp (dir, "mc:", 3)) {
|
||||
char *pth;
|
||||
strcpy (newdir, dir);
|
||||
if (newdir[3] == '/' && newdir[4] == '/') {
|
||||
pth = newdir + 5;
|
||||
strip_password ( newdir + 5);
|
||||
} else {
|
||||
pth = newdir + 3;
|
||||
strip_password (newdir + 3);
|
||||
}
|
||||
if ((p = strchr (pth, PATH_SEP)) != NULL) {
|
||||
*p = 0;
|
||||
q = mcfs_gethome (newdir);
|
||||
*p = PATH_SEP;
|
||||
if (q != NULL ) {
|
||||
if (strcmp (q, PATH_SEP_STR) && !strncmp (p, q, strlen (q) - 1)) {
|
||||
strcpy (p, "/~");
|
||||
strcat (newdir, p + strlen (q) - 1);
|
||||
}
|
||||
free (q);
|
||||
}
|
||||
}
|
||||
return (newdir);
|
||||
|
||||
/* We do not strip homes in /#ftp tree, I do not like ~'s there (see ftpfs.c why) */
|
||||
#define STRIP( name ) \
|
||||
if (strstr( dir, name )) { \
|
||||
strcpy (newdir, dir); \
|
||||
strip_password ( strstr( newdir, name ) + strlen(name) ); \
|
||||
return newdir; \
|
||||
}
|
||||
#endif
|
||||
STRIP( "/#ftp:" );
|
||||
STRIP( "/#mc:" );
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
@ -732,6 +708,7 @@ static void prepare_environment (void)
|
||||
/* MC_CONTROL_FILE has been added to environment on startup */
|
||||
}
|
||||
#endif
|
||||
#endif /* VFS_STANDALONE */
|
||||
|
||||
char *unix_error_string (int error_num)
|
||||
{
|
||||
@ -779,7 +756,8 @@ char *copy_strings (const char *first,...)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#ifndef VFS_STANDALONE
|
||||
long blocks2kilos (int blocks, int bsize)
|
||||
{
|
||||
if (bsize > 1024){
|
||||
@ -866,6 +844,7 @@ int strcasecmp (const char *s, const char *d)
|
||||
return result;
|
||||
}
|
||||
#endif /* HAVE_STRCASECMP */
|
||||
#endif /* VFS_STANDALONE */
|
||||
|
||||
/* getwd is better than getcwd, the later uses a popen ("pwd"); */
|
||||
char *get_current_wd (char *buffer, int size)
|
||||
@ -1001,6 +980,7 @@ decompress_command_and_arg (int type, char **cmd, char **flags)
|
||||
fprintf (stderr, "Fatal: decompress_command called with an unknown argument\n");
|
||||
}
|
||||
|
||||
#ifndef VFS_STANDALONE
|
||||
/* Hooks */
|
||||
void add_hook (Hook **hook_list, void (*hook_fn)(void *), void *data)
|
||||
{
|
||||
@ -1284,6 +1264,7 @@ int truncate (const char *path, long size)
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* VFS_STANDALONE */
|
||||
|
||||
char *
|
||||
concat_dir_and_file (const char *dir, const char *file)
|
||||
|
@ -98,6 +98,7 @@ max_open_files (void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef VFS_STANDALONE
|
||||
void init_groups (void)
|
||||
{
|
||||
int i;
|
||||
@ -246,6 +247,7 @@ void save_stop_handler (void)
|
||||
{
|
||||
sigaction (SIGTSTP, NULL, &startup_handler);
|
||||
}
|
||||
#endif /* VFS_STANDALONE */
|
||||
|
||||
#ifdef HAVE_GNOME
|
||||
#define PORT_HAS_MY_SYSTEM 1
|
||||
@ -351,6 +353,7 @@ char *tilde_expand (char *directory)
|
||||
return directory;
|
||||
}
|
||||
|
||||
#ifndef VFS_STANDALONE
|
||||
int
|
||||
set_nonblocking (int fd)
|
||||
{
|
||||
@ -446,6 +449,7 @@ void check_error_pipe (void)
|
||||
if (len > 0)
|
||||
message (0, _(" Warning "), error);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct sigaction ignore, save_intr, save_quit, save_stop;
|
||||
|
||||
@ -675,6 +679,7 @@ char *canonicalize_pathname (char *path)
|
||||
return path;
|
||||
}
|
||||
|
||||
#ifndef VFS_STANDALONE
|
||||
#ifdef SCO_FLAVOR
|
||||
int gettimeofday( struct timeval * tv, struct timezone * tz)
|
||||
{
|
||||
@ -931,3 +936,4 @@ int socketpair(int dummy1, int dummy2, int dummy3, int fd[2])
|
||||
#endif /* ifndef HAVE_SOCKETPAIR */
|
||||
#endif /* ifdef USE_NETCODE */
|
||||
#endif /* SCO_FLAVOR */
|
||||
#endif /* VFS_STANDALONE */
|
||||
|
@ -25,6 +25,7 @@
|
||||
/* }}} */
|
||||
/* {{{ Declarations */
|
||||
#include <config.h>
|
||||
#include "tty.h"
|
||||
#include "x.h"
|
||||
#include <stdio.h>
|
||||
#ifdef OS2_NT
|
||||
@ -35,7 +36,6 @@
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include "tty.h"
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_MMAP
|
||||
# include <sys/mman.h>
|
||||
|
@ -31,13 +31,29 @@ VFSOBJS = $(NONETFILES) @NETFILES@
|
||||
EXTFSSTUFF = README extfs.ini a cpio.in deb.in ftplist.in lha.in lslR.in \
|
||||
rar.in rpm zip.in zoo.in arfs patchfs mailfs hp48
|
||||
|
||||
#
|
||||
# Commands to build standalone version (.so)
|
||||
#
|
||||
|
||||
VFSSOOBJS = tcputil.so ftpfs.so mcfs.so utilvfs.so local.so vfs.so tar.so names.so container.so extfs.so util-alone.so util.sor utilunix.sor
|
||||
|
||||
%.sor: ../src/%.c
|
||||
$(CC) -c $(CPPFLAGS) $(DEFS) $(CFLAGS) -DVFS_STANDALONE $< -o $@
|
||||
|
||||
%.so: %.c
|
||||
$(CC) -c $(CPPFLAGS) $(DEFS) $(CFLAGS) -DVFS_STANDALONE $< -o $@
|
||||
|
||||
libvfs.so: $(VFSSOOBJS) libvfs.o
|
||||
gcc $(VFSSOOBJS) libvfs.o -shared -o libvfs.so
|
||||
|
||||
|
||||
#
|
||||
# Distribution variables
|
||||
#
|
||||
|
||||
DISTVFS = Makefile.in ChangeLog $(VFSSRCS) $(VFSHDRS)
|
||||
|
||||
all: @LIBVFS@ @mcserv@
|
||||
all: libvfs-mc.a @mcserv@
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CPPFLAGS) $(DEFS) $(CFLAGS) $<
|
||||
@ -59,7 +75,7 @@ mcservx: mcserv.o tcputil.o mad.o
|
||||
$(CC) $(LDFLAGS) -o mcserv mcserv.o tcputil.o mad.o $(LIBS)
|
||||
touch mcservx
|
||||
|
||||
libvfs.a: $(VFSOBJS)
|
||||
libvfs-mc.a: $(VFSOBJS)
|
||||
$(RMF) $@
|
||||
$(AR) cr $@ $(VFSOBJS)
|
||||
-$(RANLIB) $@
|
||||
@ -75,7 +91,7 @@ TAGS: $(VFSSRCS)
|
||||
etags $(VFSSRCS)
|
||||
|
||||
clean:
|
||||
$(RMF) mcserv *.o core a.out libvfs.a mcservx
|
||||
$(RMF) mcserv *.o core a.out libvfs-mc.a mcservx libvfs.so
|
||||
|
||||
realclean: clean
|
||||
$(RMF) .depend
|
||||
@ -84,7 +100,7 @@ realclean: clean
|
||||
|
||||
distclean:
|
||||
-$(RMF) $(srcdir)/*~ $(srcdir)/mcserv $(srcdir)/*.o $(srcdir)/a.out
|
||||
-$(RMF) $(srcdir)/core $(srcdir)/libvfs.a
|
||||
-$(RMF) $(srcdir)/core $(srcdir)/libvfs-mc.a $(srcdir)/libvfs.so
|
||||
-$(RMF) $(srcdir)/mad.c $(srcdir)/mad.h
|
||||
-if test $(srcdir) = .; then $(MAKE) realclean; fi
|
||||
-$(RMF) $(srcdir)/Makefile
|
||||
|
552
vfs/extfs.c
552
vfs/extfs.c
@ -2,6 +2,7 @@
|
||||
Copyright (C) 1995 The Free Software Foundation
|
||||
|
||||
Written by: 1995 Jakub Jelinek
|
||||
Rewritten by: 1998 Pavel Machek
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -37,6 +38,7 @@
|
||||
#include <time.h>
|
||||
#include "../src/fs.h"
|
||||
#include "../src/util.h"
|
||||
#include "../src/dialog.h"
|
||||
#include "../src/mem.h"
|
||||
#include "../src/mad.h"
|
||||
#include "../src/main.h" /* For shell_execute */
|
||||
@ -53,31 +55,18 @@ static struct stat hstat; /* Stat struct corresponding */
|
||||
static char *current_file_name, *current_link_name;
|
||||
static char *extfs_current_dir;
|
||||
|
||||
enum {
|
||||
EFS_ARG_EMPTY,
|
||||
EFS_NEED_FILE,
|
||||
EFS_NEED_ARG
|
||||
};
|
||||
|
||||
#define MAXEXTFS 32
|
||||
static char *extfs_prefixes [MAXEXTFS];
|
||||
static char extfs_need_archive [MAXEXTFS];
|
||||
static int extfs_no = 0;
|
||||
|
||||
struct extfs_ext {
|
||||
char *ext;
|
||||
struct extfs_ext *next;
|
||||
};
|
||||
|
||||
static struct extfs_ext *extfs_extensions [MAXEXTFS];
|
||||
|
||||
void extfs_fill_names (void (*func)(char *))
|
||||
{
|
||||
struct extfs_archive *a = first_archive;
|
||||
char *name;
|
||||
|
||||
while (a){
|
||||
name = copy_strings (extfs_prefixes [a->fstype], ":",
|
||||
name = copy_strings (extfs_prefixes [a->fstype], "#",
|
||||
(a->name ? a->name : ""), "/",
|
||||
a->current_dir->name, 0);
|
||||
(*func)(name);
|
||||
@ -196,9 +185,10 @@ static FILE *open_extfs_archive (int fstype, char *name, struct extfs_archive **
|
||||
struct extfs_archive *current_archive;
|
||||
struct extfs_entry *root_entry;
|
||||
char *local_name = NULL, *tmp = 0;
|
||||
const int uses_archive = extfs_need_archive [fstype];
|
||||
int uses_archive = extfs_need_archive [fstype];
|
||||
char *tmpfile;
|
||||
|
||||
if (uses_archive == EFS_NEED_FILE){
|
||||
if (uses_archive){
|
||||
if (mc_stat (name, &mystat) == -1)
|
||||
return NULL;
|
||||
if (!vfs_file_is_local (name)) {
|
||||
@ -209,9 +199,12 @@ static FILE *open_extfs_archive (int fstype, char *name, struct extfs_archive **
|
||||
tmp = name_quote (name, 0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Sorry, what is this good for? */
|
||||
if (uses_archive == EFS_NEED_ARG){
|
||||
tmp = name_quote (name, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
cmd = copy_strings (LIBDIR "extfs/", extfs_prefixes [fstype],
|
||||
" list ", local_name ? local_name : tmp, 0);
|
||||
@ -226,7 +219,7 @@ static FILE *open_extfs_archive (int fstype, char *name, struct extfs_archive **
|
||||
}
|
||||
|
||||
current_archive = (struct extfs_archive *)
|
||||
xmalloc (sizeof (struct extfs_archive), "Tar archive");
|
||||
xmalloc (sizeof (struct extfs_archive), "Extfs archive");
|
||||
current_archive->fstype = fstype;
|
||||
current_archive->name = name ? strdup (name): name;
|
||||
current_archive->local_name = local_name;
|
||||
@ -272,7 +265,7 @@ int read_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
|
||||
struct extfs_archive *current_archive;
|
||||
|
||||
if ((extfsd = open_extfs_archive (fstype, name, ¤t_archive)) == NULL) {
|
||||
message_3s (1, " Error ", "Couldn't open %s archive\n%s",
|
||||
message_3s (1, MSG_ERROR, _("Couldn't open %s archive\n%s"),
|
||||
extfs_prefixes [fstype], name);
|
||||
return -1;
|
||||
}
|
||||
@ -304,7 +297,7 @@ int read_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
|
||||
goto read_extfs_continue;
|
||||
pent = extfs_find_entry (current_archive->root_entry, q, 1, 0) ;
|
||||
if (pent == NULL) {
|
||||
message_1s (1, " Error ", "Inconsistent extfs archive");
|
||||
message_1s (1, MSG_ERROR, _("Inconsistent extfs archive"));
|
||||
/* FIXME: Should clean everything one day */
|
||||
free (buffer);
|
||||
pclose (extfsd);
|
||||
@ -324,7 +317,7 @@ int read_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
|
||||
if (!S_ISLNK (hstat.st_mode) && current_link_name != NULL) {
|
||||
pent = extfs_find_entry (current_archive->root_entry, current_link_name, 0, 0);
|
||||
if (pent == NULL) {
|
||||
message_1s (1, " Error ", "Inconsistent extfs archive");
|
||||
message_1s (1, MSG_ERROR, _("Inconsistent extfs archive"));
|
||||
/* FIXME: Should clean everything one day */
|
||||
free (buffer);
|
||||
pclose (extfsd);
|
||||
@ -358,7 +351,8 @@ int read_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
|
||||
inode->linkname = current_link_name;
|
||||
current_link_name = NULL;
|
||||
} else {
|
||||
inode->mode &= ~S_IFLNK;
|
||||
if (S_ISLNK( hstat.st_mode))
|
||||
inode->mode &= ~S_IFLNK; /* You *DON'T* want to do this always */
|
||||
inode->linkname = NULL;
|
||||
}
|
||||
if (S_ISDIR (hstat.st_mode))
|
||||
@ -380,112 +374,46 @@ int read_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *extfs_analysis (char *name, char **archive, int *fstype, int is_dir)
|
||||
{
|
||||
char *p, *local;
|
||||
int j;
|
||||
char *archive_name = NULL;
|
||||
struct extfs_ext *ext;
|
||||
/* | this is len of prefix plus some minimum
|
||||
* v space needed for the extension */
|
||||
*fstype = extfs_prefix_to_type (name);
|
||||
if (*fstype == -1) {
|
||||
extfserrno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (extfs_need_archive [*fstype] == EFS_ARG_EMPTY){
|
||||
*archive = 0;
|
||||
return strdup (name + strlen(extfs_prefixes [*fstype]) + 1);
|
||||
}
|
||||
|
||||
if (extfs_need_archive [*fstype] == EFS_NEED_ARG){
|
||||
char c;
|
||||
p = strchr (name + strlen (extfs_prefixes [*fstype]) + 1, '/');
|
||||
if (p){
|
||||
c = *p;
|
||||
*p = 0;
|
||||
}
|
||||
archive_name = strdup (name + strlen (extfs_prefixes [*fstype]) + 1);
|
||||
if (p)
|
||||
*p = c;
|
||||
*archive = archive_name;
|
||||
return p ? strdup (p+1) : NULL;
|
||||
}
|
||||
for (p = name + strlen (name); p > name; p--)
|
||||
if (*p == '/' || (is_dir && !*p))
|
||||
for (ext = extfs_extensions [*fstype]; ext; ext = ext->next) {
|
||||
j = strlen (ext->ext);
|
||||
if (p - j < name + 1)
|
||||
continue;
|
||||
if (!strncmp (p - j, ext->ext, j)) {
|
||||
char c = *p;
|
||||
|
||||
*p = 0;
|
||||
archive_name =
|
||||
vfs_canon (name + strlen (extfs_prefixes [*fstype]) + 1);
|
||||
*archive = archive_name;
|
||||
*p = c;
|
||||
local = strdup (p);
|
||||
return local;
|
||||
}
|
||||
}
|
||||
extfserrno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns allocated path inside the archive or NULL */
|
||||
static char *extfs_get_path (char *inname, struct extfs_archive **archive, int is_dir,
|
||||
int do_not_open)
|
||||
{
|
||||
char *local, *archive_name;
|
||||
char *local, *archive_name, *op;
|
||||
int result = -1;
|
||||
struct extfs_archive *parc;
|
||||
struct vfs_stamping *parent;
|
||||
vfs *v;
|
||||
int fstype;
|
||||
|
||||
local = extfs_analysis (inname, &archive_name, &fstype, is_dir);
|
||||
if (local == NULL) {
|
||||
extfserrno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
archive_name = inname;
|
||||
vfs_split( inname, &local, &op );
|
||||
fstype = extfs_which( op );
|
||||
if (!local)
|
||||
local = "";
|
||||
if (fstype == -1)
|
||||
return NULL;
|
||||
|
||||
/* In the case of the file systems that do not require a local
|
||||
* archive, we compare the fstype instead of the archive name,
|
||||
* of course, this has the drawback that we can't have more than
|
||||
* one external file system for each prefix.
|
||||
/* All filesystems should have some local archive, at least
|
||||
* it can be '/'.
|
||||
*
|
||||
* Actually, we should implement an alias mechanism that would
|
||||
* translate: "a:" to "dos:a.
|
||||
*
|
||||
*/
|
||||
for (parc = first_archive; parc != NULL; parc = parc->next)
|
||||
if (archive_name){
|
||||
if (parc->name) {
|
||||
if (!strcmp (parc->name, archive_name)) {
|
||||
vfs_stamp (&extfs_vfs_ops, (vfsid) parc);
|
||||
goto return_success;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (parc->fstype == fstype){
|
||||
vfs_stamp (&extfs_vfs_ops, (vfsid) parc);
|
||||
if (parc->name) {
|
||||
if (!strcmp (parc->name, archive_name)) {
|
||||
vfs_stamp (&extfs_vfs_ops, (vfsid) parc);
|
||||
goto return_success;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_not_open)
|
||||
result = -1;
|
||||
else
|
||||
result = read_extfs_archive (fstype, archive_name, &parc);
|
||||
|
||||
result = do_not_open ? -1 : read_extfs_archive (fstype, archive_name, &parc);
|
||||
if (result == -1) {
|
||||
extfserrno = EIO;
|
||||
free(local);
|
||||
if (archive_name)
|
||||
free(archive_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (archive_name){
|
||||
v = vfs_type (archive_name);
|
||||
if (v == &local_vfs_ops) {
|
||||
@ -501,8 +429,6 @@ static char *extfs_get_path (char *inname, struct extfs_archive **archive, int i
|
||||
}
|
||||
return_success:
|
||||
*archive = parc;
|
||||
if (archive_name)
|
||||
free (archive_name);
|
||||
return local;
|
||||
}
|
||||
|
||||
@ -591,96 +517,6 @@ static struct extfs_entry *extfs_resolve_symlinks (struct extfs_entry *entry)
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct extfs_entry*
|
||||
__extfs_find_entry (struct extfs_entry *dir, char *name,
|
||||
struct extfs_loop_protect *list, int make_dirs, int make_file)
|
||||
{
|
||||
struct extfs_entry *pent, *pdir;
|
||||
char *p, *q, *name_end;
|
||||
char c;
|
||||
|
||||
if (*name == '/') { /* Handle absolute paths */
|
||||
name++;
|
||||
dir = dir->inode->archive->root_entry;
|
||||
}
|
||||
|
||||
pent = dir;
|
||||
p = name;
|
||||
name_end = name + strlen (name);
|
||||
q = strchr (p, '/');
|
||||
c = '/';
|
||||
if (!q)
|
||||
q = strchr (p, 0);
|
||||
|
||||
for (; pent != NULL && c && *p; ){
|
||||
c = *q;
|
||||
*q = 0;
|
||||
|
||||
if (strcmp (p, ".")){
|
||||
if (!strcmp (p, ".."))
|
||||
pent = pent->dir;
|
||||
else {
|
||||
if ((pent = __extfs_resolve_symlinks (pent, list))==NULL){
|
||||
*q = c;
|
||||
return NULL;
|
||||
}
|
||||
if (c == '/' && !S_ISDIR (pent->inode->mode)){
|
||||
*q = c;
|
||||
notadir = 1;
|
||||
return NULL;
|
||||
}
|
||||
pdir = pent;
|
||||
for (pent = pent->inode->first_in_subdir; pent; pent = pent->next_in_dir)
|
||||
/* Hack: I keep the original semanthic unless
|
||||
q+1 would break in the strchr */
|
||||
if (!strcmp (pent->name, p)){
|
||||
if (q + 1 > name_end){
|
||||
*q = c;
|
||||
notadir = !S_ISDIR (pent->inode->mode);
|
||||
return pent;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* When we load archive, we create automagically
|
||||
* non-existant directories
|
||||
*/
|
||||
if (pent == NULL && make_dirs) {
|
||||
pent = generate_entry (dir->inode->archive, p, pdir, S_IFDIR | 0777);
|
||||
}
|
||||
if (pent == NULL && make_file) {
|
||||
pent = generate_entry (dir->inode->archive, p, pdir, 0777);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Next iteration */
|
||||
*q = c;
|
||||
p = q + 1;
|
||||
q = strchr (p, '/');
|
||||
if (!q)
|
||||
q = strchr (p, 0);
|
||||
}
|
||||
if (pent == NULL)
|
||||
extfserrno = ENOENT;
|
||||
return pent;
|
||||
}
|
||||
|
||||
static struct extfs_entry *extfs_find_entry (struct extfs_entry *dir, char *name, int make_dirs, int make_file)
|
||||
{
|
||||
struct extfs_entry *res;
|
||||
|
||||
errloop = 0;
|
||||
notadir = 0;
|
||||
res = __extfs_find_entry (dir, name, NULL, make_dirs, make_file);
|
||||
if (res == NULL) {
|
||||
if (errloop)
|
||||
extfserrno = ELOOP;
|
||||
else if (notadir)
|
||||
extfserrno = ENOTDIR;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
struct extfs_pseudofile {
|
||||
struct extfs_archive *archive;
|
||||
unsigned int has_changed:1;
|
||||
@ -710,14 +546,18 @@ void extfs_run (char *file)
|
||||
|
||||
if ((p = extfs_get_path (file, &archive, 0, 0)) == NULL)
|
||||
return;
|
||||
q = name_quote (((*p == '/') ? p + 1 : p), 0);
|
||||
q = name_quote (p, 0);
|
||||
|
||||
archive_name = name_quote (get_archive_name(archive), 0);
|
||||
cmd = copy_strings (LIBDIR "extfs/", extfs_prefixes [archive->fstype],
|
||||
" run ", archive_name, " ", q, 0);
|
||||
free (archive_name);
|
||||
free (q);
|
||||
#ifndef VFS_STANDALONE
|
||||
shell_execute(cmd, 0);
|
||||
#else
|
||||
vfs_die( "shell_execute: implement me!" );
|
||||
#endif
|
||||
free(cmd);
|
||||
free(p);
|
||||
}
|
||||
@ -726,28 +566,24 @@ static void *extfs_open (char *file, int flags, int mode)
|
||||
{
|
||||
struct extfs_pseudofile *extfs_info;
|
||||
struct extfs_archive *archive;
|
||||
char *p, *q;
|
||||
char *q;
|
||||
struct extfs_entry *entry;
|
||||
int local_handle;
|
||||
const int do_create = (flags & O_ACCMODE) != O_RDONLY;
|
||||
|
||||
if ((p = extfs_get_path (file, &archive, 0, 0)) == NULL)
|
||||
if ((q = extfs_get_path (file, &archive, 0, 0)) == NULL)
|
||||
return NULL;
|
||||
q = (*p == '/') ? p + 1 : p;
|
||||
entry = extfs_find_entry (archive->root_entry, q, 0, do_create);
|
||||
free (p);
|
||||
if (entry == NULL) {
|
||||
if (entry == NULL)
|
||||
return NULL;
|
||||
}
|
||||
if ((entry = extfs_resolve_symlinks (entry)) == NULL) {
|
||||
if ((entry = extfs_resolve_symlinks (entry)) == NULL)
|
||||
return NULL;
|
||||
}
|
||||
if (S_ISDIR (entry->inode->mode)) {
|
||||
extfserrno = EISDIR;
|
||||
return NULL;
|
||||
}
|
||||
if (entry->inode->local_filename == NULL) {
|
||||
char *cmd, *archive_name;
|
||||
char *cmd, *archive_name, *p;
|
||||
|
||||
entry->inode->local_filename = strdup (tmpnam (NULL));
|
||||
p = extfs_get_path_from_entry (entry);
|
||||
@ -861,144 +697,21 @@ static int extfs_close (void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int extfs_errno (void)
|
||||
{
|
||||
return extfserrno;
|
||||
}
|
||||
#define RECORDSIZE 512
|
||||
#define X_pseudofile extfs_pseudofile
|
||||
#define Xerrno extfserrno
|
||||
|
||||
static void *extfs_opendir (char *dirname)
|
||||
{
|
||||
struct extfs_archive *archive;
|
||||
char *p, *q;
|
||||
struct extfs_entry *entry;
|
||||
struct extfs_entry **extfs_info;
|
||||
|
||||
if ((p = extfs_get_path (dirname, &archive, 1, 0)) == NULL)
|
||||
return NULL;
|
||||
q = (*p == '/') ? p + 1 : p;
|
||||
entry = extfs_find_entry (archive->root_entry, q, 0, 0);
|
||||
free (p);
|
||||
if (entry == NULL)
|
||||
return NULL;
|
||||
if ((entry = extfs_resolve_symlinks (entry)) == NULL)
|
||||
return NULL;
|
||||
if (!S_ISDIR (entry->inode->mode)) {
|
||||
extfserrno = ENOTDIR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extfs_info = (struct extfs_entry **) xmalloc (sizeof (struct extfs_entry *), "Extfs: extfs_opendir");
|
||||
*extfs_info = entry->inode->first_in_subdir;
|
||||
|
||||
return extfs_info;
|
||||
}
|
||||
|
||||
static void *extfs_readdir (void *data)
|
||||
{
|
||||
static struct {
|
||||
struct dirent dir;
|
||||
#ifdef NEED_EXTRA_DIRENT_BUFFER
|
||||
char extra_buffer [MC_MAXPATHLEN];
|
||||
#endif
|
||||
} dir;
|
||||
|
||||
struct extfs_entry **extfs_info = (struct extfs_entry **) data;
|
||||
|
||||
if (*extfs_info == NULL)
|
||||
return NULL;
|
||||
|
||||
strcpy (&(dir.dir.d_name [0]), (*extfs_info)->name);
|
||||
|
||||
#ifndef DIRENT_LENGTH_COMPUTED
|
||||
dir.d_namlen = strlen (dir.dir.d_name);
|
||||
#endif
|
||||
*extfs_info = (*extfs_info)->next_in_dir;
|
||||
|
||||
return (void *)&dir;
|
||||
}
|
||||
|
||||
static int extfs_closedir (void *data)
|
||||
{
|
||||
free (data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _extfs_stat (char *path, struct stat *buf, int resolve)
|
||||
{
|
||||
struct extfs_archive *archive;
|
||||
char *p, *q;
|
||||
struct extfs_entry *entry;
|
||||
struct extfs_inode *inode;
|
||||
|
||||
if ((p = extfs_get_path (path, &archive, 0, 0)) == NULL)
|
||||
return -1;
|
||||
q = (*p == '/') ? p + 1 : p;
|
||||
entry = extfs_find_entry (archive->root_entry, q, 0, 0);
|
||||
free (p);
|
||||
if (entry == NULL)
|
||||
return -1;
|
||||
if (resolve && (entry = extfs_resolve_symlinks (entry)) == NULL)
|
||||
return -1;
|
||||
inode = entry->inode;
|
||||
buf->st_dev = inode->dev;
|
||||
buf->st_ino = inode->inode;
|
||||
buf->st_mode = inode->mode;
|
||||
buf->st_nlink = inode->nlink;
|
||||
buf->st_uid = inode->uid;
|
||||
buf->st_gid = inode->gid;
|
||||
#ifdef HAVE_ST_RDEV
|
||||
buf->st_rdev = inode->rdev;
|
||||
#endif
|
||||
buf->st_size = inode->size;
|
||||
#ifdef HAVE_ST_BLKSIZE
|
||||
buf->st_blksize = 512;
|
||||
#endif
|
||||
#ifdef HAVE_ST_BLOCKS
|
||||
buf->st_blocks = (inode->size + 512 - 1) / 512;
|
||||
#endif
|
||||
buf->st_atime = inode->atime;
|
||||
buf->st_mtime = inode->mtime;
|
||||
buf->st_ctime = inode->ctime;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int extfs_stat (char *path, struct stat *buf)
|
||||
{
|
||||
return _extfs_stat (path, buf, 1);
|
||||
}
|
||||
|
||||
static int extfs_lstat (char *path, struct stat *buf)
|
||||
{
|
||||
return _extfs_stat (path, buf, 0);
|
||||
}
|
||||
|
||||
static int extfs_fstat (void *data, struct stat *buf)
|
||||
{
|
||||
struct extfs_pseudofile *file = (struct extfs_pseudofile *)data;
|
||||
struct extfs_inode *inode;
|
||||
|
||||
inode = file->entry->inode;
|
||||
buf->st_dev = inode->dev;
|
||||
buf->st_ino = inode->inode;
|
||||
buf->st_mode = inode->mode;
|
||||
buf->st_nlink = inode->nlink;
|
||||
buf->st_uid = inode->uid;
|
||||
buf->st_gid = inode->gid;
|
||||
#ifdef HAVE_ST_RDEV
|
||||
buf->st_rdev = inode->rdev;
|
||||
#endif
|
||||
buf->st_size = inode->size;
|
||||
#ifdef HAVE_ST_BLKSIZE
|
||||
buf->st_blksize = 512;
|
||||
#endif
|
||||
#ifdef HAVE_ST_BLOCKS
|
||||
buf->st_blocks = (inode->size + 512 - 1) / 512;
|
||||
#endif
|
||||
buf->st_atime = inode->atime;
|
||||
buf->st_mtime = inode->mtime;
|
||||
buf->st_ctime = inode->ctime;
|
||||
return 0;
|
||||
}
|
||||
#define X_entry extfs_entry
|
||||
#define X_archive extfs_archive
|
||||
#define X_get_path extfs_get_path
|
||||
#define X_find_entry extfs_find_entry
|
||||
#define X_resolve_symlinks extfs_resolve_symlinks
|
||||
#define X_inode extfs_inode
|
||||
#define __X_find_entry __extfs_find_entry
|
||||
#define __X_resolve_symlinks __extfs_resolve_symlinks
|
||||
#define X_loop_protect extfs_loop_protect
|
||||
|
||||
#include "shared.c"
|
||||
|
||||
static int extfs_chmod (char *path, int mode)
|
||||
{
|
||||
@ -1010,31 +723,6 @@ static int extfs_chown (char *path, int owner, int group)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int extfs_readlink (char *path, char *buf, int size)
|
||||
{
|
||||
struct extfs_archive *archive;
|
||||
char *p, *q;
|
||||
int i;
|
||||
struct extfs_entry *entry;
|
||||
|
||||
if ((p = extfs_get_path (path, &archive, 0, 0)) == NULL)
|
||||
return -1;
|
||||
q = (*p == '/') ? p + 1 : p;
|
||||
entry = extfs_find_entry (archive->root_entry, q, 0, 0);
|
||||
free (p);
|
||||
if (entry == NULL)
|
||||
return -1;
|
||||
if (!S_ISLNK (entry->inode->mode)) {
|
||||
extfserrno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (size > (i = strlen (entry->inode->linkname))) {
|
||||
size = i;
|
||||
}
|
||||
strncpy (buf, entry->inode->linkname, i);
|
||||
return i;
|
||||
}
|
||||
|
||||
static int extfs_unlink (char *path)
|
||||
{
|
||||
return -1;
|
||||
@ -1061,31 +749,22 @@ static int extfs_rename (char *a, char *b)
|
||||
static int extfs_chdir (char *path)
|
||||
{
|
||||
struct extfs_archive *archive;
|
||||
char *p, *q, *res;
|
||||
char *q, *res;
|
||||
struct extfs_entry *entry;
|
||||
|
||||
extfserrno = ENOTDIR;
|
||||
if ((p = extfs_get_path (path, &archive, 1, 0)) == NULL)
|
||||
if ((q = extfs_get_path (path, &archive, 1, 0)) == NULL)
|
||||
return -1;
|
||||
q = (*p == '/') ? p + 1 : p;
|
||||
entry = extfs_find_entry (archive->root_entry, q, 0, 0);
|
||||
if (entry == NULL) {
|
||||
free (p);
|
||||
if (!entry)
|
||||
return -1;
|
||||
}
|
||||
entry = extfs_resolve_symlinks (entry);
|
||||
if (entry == NULL) {
|
||||
free (p);
|
||||
if ((!entry) || (!S_ISDIR (entry->inode->mode)))
|
||||
return -1;
|
||||
}
|
||||
if (!S_ISDIR (entry->inode->mode)) {
|
||||
free (p);
|
||||
return -1;
|
||||
}
|
||||
entry->inode->archive->current_dir = entry;
|
||||
res = copy_strings (extfs_prefixes [entry->inode->archive->fstype], ":",
|
||||
entry->inode->archive->name, p, NULL);
|
||||
free (p);
|
||||
res = copy_strings (
|
||||
entry->inode->archive->name, "#", extfs_prefixes [entry->inode->archive->fstype],
|
||||
"/", q, NULL);
|
||||
extfserrno = 0;
|
||||
if (extfs_current_dir)
|
||||
free (extfs_current_dir);
|
||||
@ -1125,14 +804,11 @@ static vfsid extfs_getid (char *path, struct vfs_stamping **parent)
|
||||
struct extfs_archive *archive;
|
||||
vfs *v;
|
||||
vfsid id;
|
||||
char *p;
|
||||
struct vfs_stamping *par;
|
||||
|
||||
*parent = NULL;
|
||||
if ((p = extfs_get_path (path, &archive, 1, 1)) == NULL) {
|
||||
if (!extfs_get_path (path, &archive, 1, 1))
|
||||
return (vfsid) -1;
|
||||
}
|
||||
free (p);
|
||||
if (archive->name){
|
||||
v = vfs_type (archive->name);
|
||||
id = (*v->getid) (archive->name, &par);
|
||||
@ -1253,19 +929,21 @@ vfs extfs_vfs_ops =
|
||||
extfs_read,
|
||||
extfs_write,
|
||||
|
||||
extfs_opendir,
|
||||
extfs_readdir,
|
||||
extfs_closedir,
|
||||
s_opendir,
|
||||
s_readdir,
|
||||
s_closedir,
|
||||
s_telldir,
|
||||
s_seekdir,
|
||||
|
||||
extfs_stat,
|
||||
extfs_lstat,
|
||||
extfs_fstat,
|
||||
s_stat,
|
||||
s_lstat,
|
||||
s_fstat,
|
||||
|
||||
extfs_chmod, /* unimplemented */
|
||||
extfs_chown, /* unimplemented */
|
||||
NULL,
|
||||
|
||||
extfs_readlink,
|
||||
s_readlink,
|
||||
|
||||
extfs_symlink, /* unimplemented */
|
||||
extfs_link, /* unimplemented */
|
||||
@ -1273,7 +951,7 @@ vfs extfs_vfs_ops =
|
||||
|
||||
extfs_rename, /* unimplemented */
|
||||
extfs_chdir,
|
||||
extfs_errno,
|
||||
s_errno,
|
||||
extfs_lseek,
|
||||
extfs_mknod, /* unimplemented */
|
||||
|
||||
@ -1289,6 +967,7 @@ vfs extfs_vfs_ops =
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
, extfs_mmap,
|
||||
extfs_munmap
|
||||
@ -1298,54 +977,56 @@ vfs extfs_vfs_ops =
|
||||
#include "../src/profile.h"
|
||||
void extfs_init (void)
|
||||
{
|
||||
void *keys = profile_init_iterator ("extfs", LIBDIR "extfs/extfs.ini");
|
||||
char *key, *value;
|
||||
char *p, *q, c;
|
||||
|
||||
FILE *cfg = fopen( LIBDIR "extfs/extfs.ini", "r" );
|
||||
if (!cfg) {
|
||||
fprintf( stderr, "Warning: " LIBDIR "extfs/extfs.ini not found\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
extfs_no = 0;
|
||||
for (extfs_no = 0; keys != NULL && extfs_no < MAXEXTFS; extfs_no++) {
|
||||
keys = profile_iterator_next (keys, &key, &value);
|
||||
while ( extfs_no < MAXEXTFS ) {
|
||||
char key[256];
|
||||
char *c;
|
||||
|
||||
if (!fgets( key, 250, cfg ))
|
||||
break;
|
||||
|
||||
/* Handle those with a trailing ':', those flag that the
|
||||
* file system does not require an archive to work
|
||||
*/
|
||||
|
||||
c = key [strlen (key)-1];
|
||||
if (c == ':'){
|
||||
key [strlen (key)-1] = 0;
|
||||
extfs_need_archive [extfs_no] = EFS_ARG_EMPTY;
|
||||
} else if (c == '*'){
|
||||
key [strlen (key)-1] = 0;
|
||||
extfs_need_archive [extfs_no] = EFS_NEED_ARG;
|
||||
} else
|
||||
extfs_need_archive [extfs_no] = EFS_NEED_FILE;
|
||||
|
||||
extfs_prefixes [extfs_no] = strdup (key);
|
||||
|
||||
value = strdup (value);
|
||||
for (q = value; (p = strtok (q, " \t")) != NULL; ){
|
||||
struct extfs_ext *newn;
|
||||
|
||||
q = NULL;
|
||||
newn = xmalloc (sizeof (struct extfs_ext), "prefixes");
|
||||
newn->next = extfs_extensions [extfs_no];
|
||||
newn->ext = strdup (p);
|
||||
extfs_extensions [extfs_no] = newn;
|
||||
if (*key == '[') {
|
||||
/* We may not use vfs_die() message or message_1s or similar,
|
||||
* UI is not initialized at this time and message would not
|
||||
* appear on screen. */
|
||||
fprintf( stderr, "Warning: You need to update your " LIBDIR "extfs/extfs.ini file.\n" );
|
||||
fclose(cfg);
|
||||
return;
|
||||
}
|
||||
free (value);
|
||||
if (*key == '#')
|
||||
continue;
|
||||
|
||||
if ((c = strchr( key, '\n')))
|
||||
*c = 0;
|
||||
c = &key [strlen (key)-1];
|
||||
extfs_need_archive [extfs_no] = !(*c==':');
|
||||
if (*c==':') *c = 0;
|
||||
if (!(*key))
|
||||
continue;
|
||||
|
||||
extfs_prefixes [extfs_no] = strdup (key);
|
||||
extfs_no++;
|
||||
}
|
||||
free_profile_name (LIBDIR "extfs/extfs.ini");
|
||||
fclose(cfg);
|
||||
}
|
||||
|
||||
int extfs_prefix_to_type (char *path)
|
||||
int extfs_which (char *path)
|
||||
{
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < extfs_no; i++) {
|
||||
j = strlen (extfs_prefixes [i]);
|
||||
if (!strncmp (path, extfs_prefixes [i], j) && path [j] == ':')
|
||||
for (i = 0; i < extfs_no; i++)
|
||||
if (!strcmp (path, extfs_prefixes [i]))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1356,19 +1037,10 @@ char *extfs_get_prefix (int idx)
|
||||
|
||||
void extfs_done (void)
|
||||
{
|
||||
struct extfs_ext *current, *old;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < extfs_no; i++ ){
|
||||
for (i = 0; i < extfs_no; i++ )
|
||||
free (extfs_prefixes [i]);
|
||||
current = extfs_extensions [i];
|
||||
while (current){
|
||||
old = current;
|
||||
current = current->next;
|
||||
free (old->ext);
|
||||
free (old);
|
||||
}
|
||||
}
|
||||
extfs_no = 0;
|
||||
if (extfs_current_dir)
|
||||
free (extfs_current_dir);
|
||||
|
@ -1,8 +1,6 @@
|
||||
Writing scripts for Midnight Commander's external vfs
|
||||
|
||||
IMPORTANT NOTE: extfs is not officialy released and fully bug free
|
||||
in 3.0! You have been warned. If you would really like to try it,
|
||||
you can (by typing make install.extfs in the vfs directory).
|
||||
IMPORTANT NOTE: There may be some bugs left in extfs. Enjoy.
|
||||
|
||||
Starting with version 3.1, the Midnight Commander comes with so called
|
||||
extfs, which is one of the virtual filesystems. This system makes it
|
||||
@ -16,18 +14,23 @@ Creating a shell script/program to handle requests.
|
||||
configured or compiled, like /usr/local/lib/mc or /usr/lib/mc).
|
||||
|
||||
The first one is very easy:
|
||||
You assign a vfs prefix and vfs extensions to your vfs. Both will be used in
|
||||
vfs pseudoURL names, like if you assign prefix zip and extensions .zip,
|
||||
.ZIP, then URLs will look like
|
||||
zip:anypath/my.zip/some_path/in_the/archive
|
||||
Then you add a line to the end of the [extfs] section:
|
||||
prefix=space_separated_extensions
|
||||
e.g.
|
||||
zip=.zip .ZIP
|
||||
You assign a vfs suffix. For example, if you have .zip file, and would
|
||||
like to see what's inside it, path will be
|
||||
|
||||
/anypath/my.zip#uzip/some_path/...
|
||||
|
||||
Then you add a line extfs.ini file containing just that extension. If
|
||||
your vfs does not require file to work on, add ':' to the of name.
|
||||
|
||||
In this example, .zip is suffix, but I call vfs 'uzip'. Why? Well,
|
||||
what this vfs essentially does is UNzip. UN is too long, so I choosed
|
||||
U. Note that sometime in future filesystem like zip may exist: It will
|
||||
take whole tree and create .zip file from it. So /usr:zip will be
|
||||
zipfile containing whole /usr tree.
|
||||
|
||||
The second one may require some your knowledge of shell/c programming:
|
||||
You have to create a program (with executable permissions) prefix in
|
||||
$(libdir)/extfs (in our example $(libdir)/extfs/zip).
|
||||
$(libdir)/extfs (in our example $(libdir)/extfs/uzip).
|
||||
|
||||
* Commands that should be implemented by your shell script
|
||||
----------------------------------------------------------
|
||||
@ -51,10 +54,7 @@ SSSSSSSS is the file size
|
||||
FILENAME is the filename
|
||||
PATH is the path from the archive's root without the leading slash (/)
|
||||
DATETIME has one of the following formats:
|
||||
Mon DD hh:mm
|
||||
Mon DD YYYY
|
||||
Mon DD YYYY hh:mm
|
||||
MM-DD-YY hh:mm
|
||||
Mon DD hh:mm, Mon DD YYYY, Mon DD YYYY hh:mm, MM-DD-YY hh:mm
|
||||
|
||||
where Mon is a three digit english month name, DD day
|
||||
1-31, MM month 01-12, YY two digit year, YYYY four digit
|
||||
@ -74,7 +74,8 @@ then it says that this file should be a hardlinked with the other file.
|
||||
* Command: copyout archivename storedfilename extractto
|
||||
|
||||
This should extract from archive archivename the file called
|
||||
storedfilename (possibly with path if not located in archive's root)
|
||||
storedfilename (possibly with path if not located in archive's root
|
||||
[this is wrong. current extfs strips paths! -- pavel@ucw.cz])
|
||||
to file extractto.
|
||||
|
||||
* Command: copyin archivename storedfilename sourcefile
|
||||
@ -88,55 +89,16 @@ archivename will be something like /tmp/f43513254 or just
|
||||
anything. Some archivers do not like it, so you'll have to find some
|
||||
workaround.
|
||||
|
||||
* Command: run
|
||||
|
||||
Undocumented :-)
|
||||
|
||||
---------------------------------------------------------
|
||||
|
||||
Don't forget to mark this file executable (chmod 755 ThisFile, for example)
|
||||
|
||||
This is a skeleton structure of the executable:
|
||||
|
||||
#!/bin/sh
|
||||
|
||||
# Command functions
|
||||
mcvfs_list ()
|
||||
# $1 is the archive name
|
||||
{
|
||||
# Apply a system command to obtain a list of filenames
|
||||
# For example 'zip -l $1'
|
||||
# Scan each line of the 'list' output, discarding unused information, and
|
||||
# constructing a printable line in a form, described above, that mc can use.
|
||||
# Exit
|
||||
}
|
||||
|
||||
mcvfs_copyout ()
|
||||
# $1 is the archive name
|
||||
# $2 is a name of a file within the archive
|
||||
# $3 is a name of a file within the system (to add from or extract to)
|
||||
{
|
||||
# Apply the system command used to extract one file from the archive
|
||||
# Exit
|
||||
}
|
||||
|
||||
mcvfs_copyin ()
|
||||
# $1 is the archive name
|
||||
# $2 is a name of a file within the archive
|
||||
# $3 is a name of a file within the system (to add from or extract to)
|
||||
{
|
||||
# Apply the system command used to add one file to the archive
|
||||
# Exit
|
||||
}
|
||||
|
||||
# Command line parser
|
||||
# $1 is the command
|
||||
# $2 is the archive name
|
||||
# $3 is a name of a file within the archive
|
||||
# $4 is a name of a file within the system (to add from or extract to)
|
||||
case "$1" in
|
||||
list) mcvfs_list $2; exit $?;;
|
||||
copyout) mcvfs_copyout $2 $3 $4; exit $?;;
|
||||
copyin) mcvfs_copyin $2 $3 $4; exit $?;;
|
||||
esac
|
||||
# Show an error if this was called with some other command
|
||||
exit 1
|
||||
For skeleton structure of executable, look at some of filesystems
|
||||
similar to yours.
|
||||
|
||||
---------------------------------------------------------
|
||||
|
||||
|
@ -1,17 +1,22 @@
|
||||
|
||||
[extfs]
|
||||
zip=.zip .ZIP
|
||||
zoo=.zoo
|
||||
arc=.arc .ARC .pak .PAK
|
||||
lha=.lha .LHA .lzh .LZH
|
||||
cpio=.cpio .cpio.Z .cpio.gz
|
||||
rpm=.rpm
|
||||
rar=.rar
|
||||
deb=.deb
|
||||
a:=a
|
||||
b:=a
|
||||
lslR=lslR ls-lR lslR.gz ls-lR.gz lslR.Z ls-lR.Z
|
||||
ftplist=ftplist
|
||||
patch=
|
||||
arfs=.a
|
||||
hp48:=hp48
|
||||
# Popular pc archivers, for arj usage you need special patch to unarj
|
||||
uzip
|
||||
uzoo
|
||||
ulha
|
||||
urar
|
||||
uarj
|
||||
# Unknown to me, it was named arfs before
|
||||
uar
|
||||
# cpio archiver (unix)
|
||||
ucpio
|
||||
# Packages from popular distributions
|
||||
rpm
|
||||
deb
|
||||
# a: - mtools filesystem. I probably broke this one
|
||||
a:
|
||||
# For browsing lslR listings (found on many ftp sites)
|
||||
lslR
|
||||
# Simple fs for list of popular ftp sites
|
||||
ftplist
|
||||
# Hewlet packard calculator
|
||||
hp48:
|
||||
|
203
vfs/ftpfs.c
203
vfs/ftpfs.c
@ -5,6 +5,7 @@
|
||||
1995 Jakub Jelinek
|
||||
1995, 1996, 1997 Miguel de Icaza
|
||||
1997 Norbert Warmuth
|
||||
1998 Pavel Machek
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -28,7 +29,6 @@
|
||||
etc., (tarfs as well), we should give there a user selectable timeout
|
||||
and assign a key sequence.
|
||||
- use hash table instead of linklist to cache ftpfs directory.
|
||||
- complete rename operation.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@ -89,8 +89,6 @@
|
||||
|
||||
#define UPLOAD_ZERO_LENGTH_FILE
|
||||
|
||||
void print_vfs_message(char *, ...);
|
||||
|
||||
static int ftpfserrno;
|
||||
static int code;
|
||||
|
||||
@ -106,7 +104,7 @@ int use_netrc = 1;
|
||||
extern char *home_dir;
|
||||
|
||||
/* Anonymous setup */
|
||||
char *ftpfs_anonymous_passwd;
|
||||
char *ftpfs_anonymous_passwd = 0;
|
||||
int ftpfs_directory_timeout;
|
||||
|
||||
/* Proxy host */
|
||||
@ -132,8 +130,6 @@ static int force_expiration = 0;
|
||||
|
||||
struct linklist *ftpfs_connections_list;
|
||||
|
||||
extern char *last_current_dir;
|
||||
|
||||
/* command wait_flag: */
|
||||
#define NONE 0x00
|
||||
#define WAIT_REPLY 0x01
|
||||
@ -441,7 +437,7 @@ login_server (struct ftpfs_connection *bucket, char *netrcpass)
|
||||
if (!bucket->password){
|
||||
p = copy_strings (" FTP: Password required for ", quser(bucket),
|
||||
" ", NULL);
|
||||
op = input_dialog (p, _("Password:"), "");
|
||||
op = vfs_get_password (p);
|
||||
free (p);
|
||||
if (op == NULL) {
|
||||
ftpfserrno = EPERM;
|
||||
@ -475,7 +471,7 @@ login_server (struct ftpfs_connection *bucket, char *netrcpass)
|
||||
wipe_password (proxypass);
|
||||
p = copy_strings(" Proxy: Password required for ", proxyname, " ",
|
||||
NULL);
|
||||
proxypass = input_dialog (p, _("Password:"), "");
|
||||
proxypass = vfs_get_password (p);
|
||||
free(p);
|
||||
if (proxypass == NULL) {
|
||||
ftpfserrno = EPERM;
|
||||
@ -603,7 +599,7 @@ setup_source_route (int socket, int dest)
|
||||
ptr++;
|
||||
if (setsockopt (socket, IPPROTO_IP, IP_OPTIONS,
|
||||
buffer, ptr - buffer) < 0)
|
||||
message_2s (1, " Error ", " Could not set source routing (%s)", unix_error_string (errno));
|
||||
message_2s (1, MSG_ERROR, _(" Could not set source routing (%s)"), unix_error_string (errno));
|
||||
}
|
||||
#else
|
||||
#define setup_source_route(x,y)
|
||||
@ -619,7 +615,7 @@ load_no_proxy_list ()
|
||||
{
|
||||
/* FixMe: shouldn't be hardcoded!!! */
|
||||
char s[258]; /* provide for 256 characters and nl */
|
||||
struct no_proxy_entry *np, *current;
|
||||
struct no_proxy_entry *np, *current = 0;
|
||||
FILE *npf;
|
||||
int c;
|
||||
char *p;
|
||||
@ -890,13 +886,7 @@ open_command_connection (char *host, char *user, int port, char *netrcpass)
|
||||
qhome(bucket) = ftpfs_get_current_directory (bucket);
|
||||
if (!qhome(bucket))
|
||||
qhome(bucket) = strdup ("/");
|
||||
if (last_current_dir) {
|
||||
if (last_current_dir [strlen (last_current_dir) - 1] == '/')
|
||||
qupdir(bucket) = strdup (last_current_dir);
|
||||
else
|
||||
qupdir(bucket) = copy_strings (last_current_dir, "/", NULL);
|
||||
} else
|
||||
qupdir(bucket) = strdup ("/");
|
||||
qupdir(bucket) = strdup ("/"); /* FIXME: I changed behavior to ignore last_current_dir */
|
||||
return bucket;
|
||||
}
|
||||
|
||||
@ -1018,7 +1008,7 @@ void ftpfs_fill_names (void (*func)(char *))
|
||||
do {
|
||||
if ((bucket = lptr->data) != 0){
|
||||
|
||||
path_name = copy_strings ("ftp://", quser (bucket),
|
||||
path_name = copy_strings ("/#ftp.", quser (bucket),
|
||||
"@", qhost (bucket),
|
||||
qcdir(bucket), 0);
|
||||
(*func)(path_name);
|
||||
@ -1177,36 +1167,47 @@ ftpfs_get_path (struct ftpfs_connection **bucket, char *path)
|
||||
char *user, *host, *remote_path, *pass;
|
||||
int port;
|
||||
|
||||
/* An absolute path name, try to determine connection socket */
|
||||
if (strncmp (path, "ftp://", 6) == 0){
|
||||
path += 6;
|
||||
#ifndef BROKEN_PATHS
|
||||
if (strncmp (path, "/#ftp:", 6))
|
||||
return NULL; /* Normal: consider cd /bla/#ftp */
|
||||
#else
|
||||
if (!(path = strstr (path, "/#ftp:")))
|
||||
return NULL;
|
||||
#endif
|
||||
path += 6;
|
||||
|
||||
if (!(remote_path = ftpfs_get_host_and_username (path, &host, &user,
|
||||
&port, &pass))) {
|
||||
ftpfserrno = ENOENT;
|
||||
free (host);
|
||||
free (user);
|
||||
if (pass)
|
||||
wipe_password (pass);
|
||||
return NULL;
|
||||
if (!(remote_path = ftpfs_get_host_and_username (path, &host, &user, &port, &pass)))
|
||||
ftpfserrno = ENOENT;
|
||||
else {
|
||||
if ((*bucket = ftpfs_open_link (host, user, port, pass)) == NULL) {
|
||||
free (remote_path);
|
||||
remote_path = NULL;
|
||||
}
|
||||
if ((*bucket = ftpfs_open_link (host, user, port, pass)) == NULL) {
|
||||
free (remote_path);
|
||||
free (host);
|
||||
free (user);
|
||||
if (pass)
|
||||
wipe_password (pass);
|
||||
return NULL;
|
||||
}
|
||||
free (host);
|
||||
free (user);
|
||||
if (pass)
|
||||
wipe_password (pass);
|
||||
return remote_path;
|
||||
}
|
||||
/* never get here !!! */
|
||||
message_1s(1, " Error ", " Oops, you just hit a bug in the code ");
|
||||
return NULL;
|
||||
free (host);
|
||||
free (user);
|
||||
if (pass)
|
||||
wipe_password (pass);
|
||||
|
||||
if (!remote_path)
|
||||
return NULL;
|
||||
|
||||
/* NOTE: Usage of tildes is deprecated, consider:
|
||||
* cd /#ftp:pavel@hobit
|
||||
* cd ~
|
||||
* And now: what do I want to do? Do I want to go to /home/pavel or to
|
||||
* /#ftp:hobit/home/pavel? I think first has better sense...
|
||||
*/
|
||||
{
|
||||
int f = !strcmp( remote_path, "/~" );
|
||||
if (f || !strncmp( remote_path, "/~/", 3 )) {
|
||||
char *s;
|
||||
s = concat_dir_and_file( qhome (*bucket), remote_path +3-f );
|
||||
free (remote_path);
|
||||
remote_path = s;
|
||||
}
|
||||
}
|
||||
return remote_path;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1635,7 +1636,7 @@ int retrieve_file_start(struct ftpentry *fe)
|
||||
|
||||
int retrieve_file_start2(struct ftpentry *fe)
|
||||
{
|
||||
remotelocal_handle = open(fe->local_filename, O_RDWR | O_CREAT | O_TRUNC, 0600);
|
||||
remotelocal_handle = open(fe->local_filename, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0600);
|
||||
if (remotelocal_handle == -1) {
|
||||
ftpfserrno = EIO;
|
||||
free(fe->local_filename);
|
||||
@ -1649,11 +1650,13 @@ int retrieve_file_start2(struct ftpentry *fe)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ftpfs_flushdir ()
|
||||
void ftpfs_flushdir (void)
|
||||
{
|
||||
force_expiration = 1;
|
||||
}
|
||||
|
||||
static int remove_temp_file (char *file_name);
|
||||
|
||||
int ftpfs_ctl (void *data, int ctlop, int arg)
|
||||
{
|
||||
int n = 0;
|
||||
@ -1731,6 +1734,9 @@ int ftpfs_ctl (void *data, int ctlop, int arg)
|
||||
int ftpfs_setctl (char *path, int ctlop, char *arg)
|
||||
{
|
||||
switch (ctlop) {
|
||||
case MCCTL_REMOVELOCALCOPY:
|
||||
return remove_temp_file (path);
|
||||
|
||||
case MCCTL_SETREMOTECOPY: if (localname) free (localname);
|
||||
localname = strdup (vfs_canon (arg));
|
||||
return 1;
|
||||
@ -1748,7 +1754,7 @@ int retrieve_file(struct ftpentry *fe)
|
||||
if (fe->local_filename)
|
||||
return 1;
|
||||
fe->local_stat.st_mtime = 0;
|
||||
fe->local_filename = strdup(tmpnam(NULL));
|
||||
fe->local_filename = tempnam (0, "ftpfs");
|
||||
fe->local_is_temp = 1;
|
||||
if (fe->local_filename == NULL) {
|
||||
ftpfserrno = ENOMEM;
|
||||
@ -1911,7 +1917,7 @@ _get_file_entry(struct ftpfs_connection *bucket, char *file_name,
|
||||
ent->local_filename = 0;
|
||||
}
|
||||
if (flags & O_TRUNC) {
|
||||
ent->local_filename = strdup(tmpnam(NULL));
|
||||
ent->local_filename = tempnam (0, "ftpfs");
|
||||
if (ent->local_filename == NULL) {
|
||||
ftpfserrno = ENOMEM;
|
||||
return NULL;
|
||||
@ -1964,7 +1970,7 @@ _get_file_entry(struct ftpfs_connection *bucket, char *file_name,
|
||||
ent->bucket = bucket;
|
||||
ent->name = strdup(p);
|
||||
ent->remote_filename = strdup(file_name);
|
||||
ent->local_filename = strdup(tmpnam(NULL));
|
||||
ent->local_filename = tempnam(0, "ftpfs");
|
||||
if (!ent->name && !ent->remote_filename && !ent->local_filename) {
|
||||
ftpentry_destructor(ent);
|
||||
ftpfserrno = ENOMEM;
|
||||
@ -2002,6 +2008,43 @@ _get_file_entry(struct ftpfs_connection *bucket, char *file_name,
|
||||
}
|
||||
}
|
||||
|
||||
/* this just free's the local temp file. I don't know if the
|
||||
remote file can be used after this without crashing - paul
|
||||
psheer@obsidian.co.za psheer@icon.co.za */
|
||||
static int remove_temp_file (char *file_name)
|
||||
{
|
||||
char *p, q;
|
||||
struct ftpfs_connection *bucket;
|
||||
struct ftpentry *ent;
|
||||
struct linklist *file_list, *lptr;
|
||||
struct ftpfs_dir *dcache;
|
||||
|
||||
if (!(file_name = ftpfs_get_path (&bucket, file_name)))
|
||||
return -1;
|
||||
p = strrchr (file_name, '/');
|
||||
q = *p;
|
||||
*p = '\0';
|
||||
dcache = retrieve_dir (bucket, *file_name ? file_name : "/");
|
||||
if (dcache == NULL)
|
||||
return -1;
|
||||
file_list = dcache->file_list;
|
||||
*p++ = q;
|
||||
if (!*p)
|
||||
p = ".";
|
||||
for (lptr = file_list->next; lptr != file_list; lptr = lptr->next) {
|
||||
ent = lptr->data;
|
||||
if (strcmp (p, ent->name) == 0) {
|
||||
if (ent->local_filename) {
|
||||
unlink (ent->local_filename);
|
||||
free (ent->local_filename);
|
||||
ent->local_filename = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct ftpentry *
|
||||
get_file_entry(char *path, int op, int flags)
|
||||
{
|
||||
@ -2194,7 +2237,7 @@ static int ftpfs_errno (void)
|
||||
|
||||
/* Explanation:
|
||||
* On some operating systems (Slowaris 2 for example)
|
||||
* the d_name member is just a char long (Nice trick that break everything,
|
||||
* the d_name member is just a char long (nice trick that break everything),
|
||||
* so we need to set up some space for the filename.
|
||||
*/
|
||||
struct ftpfs_dirent {
|
||||
@ -2206,27 +2249,7 @@ struct ftpfs_dirent {
|
||||
struct ftpfs_dir *dcache;
|
||||
};
|
||||
|
||||
char *ftpfs_gethome (char *servername)
|
||||
{
|
||||
struct ftpfs_connection *bucket;
|
||||
char *remote_path;
|
||||
|
||||
if (!(remote_path = ftpfs_get_path (&bucket, servername)))
|
||||
return NULL;
|
||||
free (remote_path);
|
||||
return qhome(bucket);
|
||||
}
|
||||
|
||||
char *ftpfs_getupdir (char *servername)
|
||||
{
|
||||
struct ftpfs_connection *bucket;
|
||||
char *remote_path;
|
||||
|
||||
if (!(remote_path = ftpfs_get_path (&bucket, servername)))
|
||||
return NULL;
|
||||
free (remote_path);
|
||||
return qupdir(bucket);
|
||||
}
|
||||
/* Possible FIXME: what happens if one directory is opened twice ? */
|
||||
|
||||
static void *ftpfs_opendir (char *dirname)
|
||||
{
|
||||
@ -2271,6 +2294,32 @@ static void *ftpfs_readdir (void *data)
|
||||
return (void *) &dirp->dent;
|
||||
}
|
||||
|
||||
static int ftpfs_telldir (void *data)
|
||||
{
|
||||
struct ftpfs_dirent *dirp = data;
|
||||
struct linklist *pos;
|
||||
int i = 0;
|
||||
|
||||
pos = dirp->dcache->file_list->next;
|
||||
while( pos!=dirp->dcache->file_list) {
|
||||
if (pos == dirp->pos)
|
||||
return i;
|
||||
pos = pos->next;
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void ftpfs_seekdir (void *data, int pos)
|
||||
{
|
||||
struct ftpfs_dirent *dirp = data;
|
||||
int i;
|
||||
|
||||
dirp->pos = dirp->dcache->file_list->next;
|
||||
for (i=0; i<pos; i++)
|
||||
ftpfs_readdir(data);
|
||||
}
|
||||
|
||||
static int ftpfs_closedir (void *info)
|
||||
{
|
||||
struct ftpfs_dirent *dirp = info;
|
||||
@ -2580,6 +2629,8 @@ vfs ftpfs_vfs_ops = {
|
||||
ftpfs_opendir,
|
||||
ftpfs_readdir,
|
||||
ftpfs_closedir,
|
||||
ftpfs_telldir,
|
||||
ftpfs_seekdir,
|
||||
|
||||
ftpfs_stat,
|
||||
ftpfs_lstat,
|
||||
@ -2724,8 +2775,8 @@ int lookup_netrc (char *host, char **login, char **pass)
|
||||
stat (netrcname, &mystat) >= 0 &&
|
||||
(mystat.st_mode & 077)) {
|
||||
if (be_angry) {
|
||||
message_1s (1, "Error", "~/.netrc file has not correct mode.\n"
|
||||
"Remove password or correct mode.");
|
||||
message_1s (1, MSG_ERROR, _("~/.netrc file has not correct mode.\n"
|
||||
"Remove password or correct mode."));
|
||||
be_angry = 0;
|
||||
}
|
||||
free (netrc);
|
||||
@ -2739,8 +2790,8 @@ int lookup_netrc (char *host, char **login, char **pass)
|
||||
if (stat (netrcname, &mystat) >= 0 &&
|
||||
(mystat.st_mode & 077)) {
|
||||
if (be_angry) {
|
||||
message_1s (1, "Error", "~/.netrc file has not correct mode.\n"
|
||||
"Remove password or correct mode.");
|
||||
message_1s (1, MSG_ERROR, _("~/.netrc file has not correct mode.\n"
|
||||
"Remove password or correct mode."));
|
||||
be_angry = 0;
|
||||
}
|
||||
free (netrc);
|
||||
|
12
vfs/local.c
12
vfs/local.c
@ -80,6 +80,16 @@ static void *local_opendir (char *dirname)
|
||||
return local_info;
|
||||
}
|
||||
|
||||
static int local_telldir (void *data)
|
||||
{
|
||||
return telldir( *(DIR **) data );
|
||||
}
|
||||
|
||||
static void local_seekdir (void *data, int offset)
|
||||
{
|
||||
seekdir( *(DIR **) data, offset );
|
||||
}
|
||||
|
||||
static void *local_readdir (void *data)
|
||||
{
|
||||
return readdir (*(DIR **) data);
|
||||
@ -249,6 +259,8 @@ vfs local_vfs_ops = {
|
||||
local_opendir,
|
||||
local_readdir,
|
||||
local_closedir,
|
||||
local_telldir,
|
||||
local_seekdir,
|
||||
|
||||
local_stat,
|
||||
local_lstat,
|
||||
|
126
vfs/mcfs.c
126
vfs/mcfs.c
@ -73,6 +73,8 @@ static mcfs_connection *current_dir_connection;
|
||||
|
||||
char *mcfs_current_dir = 0;
|
||||
|
||||
static char *mcfs_gethome (mcfs_connection *mc);
|
||||
|
||||
/* Extract the hostname and username from the path */
|
||||
/* path is in the form: hostname:user/remote-dir */
|
||||
char *mcfs_get_host_and_username (char *path, char **host, char **user,
|
||||
@ -89,7 +91,7 @@ void mcfs_fill_names (void (*func)(char *))
|
||||
for (i = 0; i < MCFS_MAX_CONNECTIONS; i++){
|
||||
if (mcfs_connections [i].host == 0)
|
||||
continue;
|
||||
name = copy_strings ("mc:", mcfs_connections [i].user,
|
||||
name = copy_strings ("/#mc:", mcfs_connections [i].user,
|
||||
"@", mcfs_connections [i].host, 0);
|
||||
(*func) (name);
|
||||
free (name);
|
||||
@ -137,8 +139,6 @@ int mcfs_invalidate_socket (int sock)
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern char *last_current_dir;
|
||||
|
||||
/* This routine checks the server RPC version and logs the user in */
|
||||
static int mcfs_login_server (int my_socket, char *user, int port,
|
||||
int port_autodetected, char *netrcpass,
|
||||
@ -153,26 +153,32 @@ static int mcfs_login_server (int my_socket, char *user, int port,
|
||||
return 0;
|
||||
|
||||
if (result != MC_VERSION_OK){
|
||||
message_1s (1, " MCFS ", " The server does not support this version ");
|
||||
message_1s (1, _(" MCFS "), _(" The server does not support this version "));
|
||||
close (my_socket);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rpc_send (my_socket, RPC_INT, MC_LOGIN, RPC_STRING, last_current_dir,
|
||||
/* FIXME: figure out why last_current_dir used to be passed here */
|
||||
rpc_send (my_socket, RPC_INT, MC_LOGIN, RPC_STRING, "/",
|
||||
RPC_STRING, user, RPC_END);
|
||||
|
||||
if (0 == rpc_get (my_socket, RPC_INT, &result, RPC_END))
|
||||
if (0 == rpc_get (my_socket, RPC_INT, &result, RPC_END))
|
||||
return 0;
|
||||
|
||||
if (result == MC_NEED_PASSWORD){
|
||||
if (port > 1024 && port_autodetected){
|
||||
int v;
|
||||
|
||||
v = query_dialog (" Warning ",
|
||||
" The remote server is not running on a system port \n"
|
||||
" you need a password to log in, but the information may \n"
|
||||
" not be safe on the remote side. Continue? \n", 3, 2,
|
||||
" Yes ", " No ");
|
||||
#ifndef VFS_STANDALONE
|
||||
v = query_dialog (_(" Warning "),
|
||||
_(" The remote server is not running on a system port \n"
|
||||
" you need a password to log in, but the information may \n"
|
||||
" not be safe on the remote side. Continue? \n"), 3, 2,
|
||||
_(" Yes "), _(" No "));
|
||||
#else
|
||||
message_1s( 1, " MCFS ", _(" The remote server is running on stange port. Giving up.\n"));
|
||||
v = 1;
|
||||
#endif
|
||||
|
||||
if (v == 1){
|
||||
close (my_socket);
|
||||
return 0;
|
||||
@ -181,7 +187,7 @@ static int mcfs_login_server (int my_socket, char *user, int port,
|
||||
if (netrcpass != NULL)
|
||||
pass = strdup (netrcpass);
|
||||
else
|
||||
pass = input_dialog (" MCFS Password required ", _("Password:"), "");
|
||||
pass = vfs_get_password (_(" MCFS Password required "));
|
||||
if (!pass){
|
||||
rpc_send (my_socket, RPC_INT, MC_QUIT, RPC_END);
|
||||
close (my_socket);
|
||||
@ -195,7 +201,7 @@ static int mcfs_login_server (int my_socket, char *user, int port,
|
||||
return 0;
|
||||
|
||||
if (result != MC_LOGINOK){
|
||||
message_1s (1, " MCFS ", " Invalid password ");
|
||||
message_1s (1, " MCFS ", _(" Invalid password "));
|
||||
rpc_send (my_socket, RPC_INT, MC_QUIT, RPC_END);
|
||||
close (my_socket);
|
||||
return 0;
|
||||
@ -237,8 +243,8 @@ static mcfs_connection *mcfs_get_free_bucket ()
|
||||
return &mcfs_connections [i];
|
||||
}
|
||||
/* This can't happend, since we have checked for max connections before */
|
||||
fprintf (stderr, "Internal error: mcfs_get_free_bucket");
|
||||
return 0;
|
||||
vfs_die("Internal error: mcfs_get_free_bucket");
|
||||
return 0; /* shut up, stupid gcc */
|
||||
}
|
||||
|
||||
/* This routine keeps track of open connections */
|
||||
@ -261,7 +267,7 @@ static mcfs_connection *mcfs_open_link (char *host, char *user, int *port, char
|
||||
return &mcfs_connections [i];
|
||||
}
|
||||
if (mcfs_open_connections == MCFS_MAX_CONNECTIONS){
|
||||
message_1s (1, " Error ", " Too many open connections ");
|
||||
message_1s (1, MSG_ERROR, _(" Too many open connections "));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -305,43 +311,40 @@ static char *mcfs_get_path (mcfs_connection **mc, char *path)
|
||||
int port;
|
||||
|
||||
/* An absolute path name, try to determine connection socket */
|
||||
if (strncmp (path, "mc:", 3) == 0){
|
||||
path += 3;
|
||||
|
||||
/* 1.11.96 bor: add mc:// URL syntax */
|
||||
if (path[0] == '/' && path[1] == '/')
|
||||
path += 2;
|
||||
|
||||
/* Port = 0 means that open_tcp_link will try to contact the
|
||||
* remote portmapper to get the port number
|
||||
*/
|
||||
port = 0;
|
||||
if (!(remote_path = mcfs_get_host_and_username
|
||||
(path, &host, &user, &port, &pass))){
|
||||
free (host);
|
||||
free (user);
|
||||
if (pass)
|
||||
wipe_password (pass);
|
||||
return 0;
|
||||
}
|
||||
if (strncmp (path, "/#mc:", 5)) {
|
||||
vfs_die( "Mcfs: this should not happen.\n" );
|
||||
/* We used to *mc = current_dir_connection; return strdup (path); */
|
||||
}
|
||||
path += 5;
|
||||
|
||||
/* Port = 0 means that open_tcp_link will try to contact the
|
||||
* remote portmapper to get the port number
|
||||
*/
|
||||
port = 0;
|
||||
if ((remote_path = mcfs_get_host_and_username(path, &host, &user, &port, &pass)))
|
||||
if (!(*mc = mcfs_open_link (host, user, &port, pass))){
|
||||
free (remote_path);
|
||||
free (host);
|
||||
free (user);
|
||||
if (pass)
|
||||
wipe_password (pass);
|
||||
return 0;
|
||||
remote_path = NULL;
|
||||
}
|
||||
free (host);
|
||||
free (user);
|
||||
if (pass)
|
||||
wipe_password (pass);
|
||||
|
||||
if (!remote_path)
|
||||
return NULL;
|
||||
|
||||
/* NOTE: tildes are deprecated. See ftpfs.c */
|
||||
{
|
||||
int f = !strcmp( remote_path, "/~" );
|
||||
if (f || !strncmp( remote_path, "/~/", 3 )) {
|
||||
char *s;
|
||||
s = concat_dir_and_file( mcfs_gethome (*mc), remote_path +3-f );
|
||||
free (remote_path);
|
||||
remote_path = s;
|
||||
}
|
||||
free (host);
|
||||
free (user);
|
||||
if (pass)
|
||||
wipe_password (pass);
|
||||
return remote_path;
|
||||
}
|
||||
*mc = current_dir_connection;
|
||||
|
||||
return strdup (path);
|
||||
return remote_path;
|
||||
}
|
||||
|
||||
/* Simple function for routines returning only an integer from the server */
|
||||
@ -436,15 +439,10 @@ static int mcfs_rpc_path_int_int (int command, char *path, int n1, int n2)
|
||||
return mcfs_handle_simple_error (mc->sock, 0);
|
||||
}
|
||||
|
||||
char *mcfs_gethome (char *servername)
|
||||
static char *mcfs_gethome (mcfs_connection *mc)
|
||||
{
|
||||
char *remote_file;
|
||||
char *buffer;
|
||||
mcfs_connection *mc;
|
||||
|
||||
if (!(remote_file = mcfs_get_path (&mc, servername)))
|
||||
return 0;
|
||||
free (remote_file);
|
||||
if (mc->home)
|
||||
return strdup (mc->home);
|
||||
else {
|
||||
@ -456,22 +454,6 @@ char *mcfs_gethome (char *servername)
|
||||
}
|
||||
}
|
||||
|
||||
char *mcfs_getupdir (char *servername)
|
||||
{
|
||||
char *remote_file;
|
||||
mcfs_connection *mc;
|
||||
char *buffer;
|
||||
|
||||
if (!(remote_file = mcfs_get_path (&mc, servername)))
|
||||
return 0;
|
||||
free (remote_file);
|
||||
rpc_send (mc->sock, RPC_INT, MC_GETUPDIR, RPC_END);
|
||||
if (0 == rpc_get (mc->sock, RPC_STRING, &buffer, RPC_END)) {
|
||||
return strdup ("/");
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* The callbacks */
|
||||
static void *mcfs_open (char *file, int flags, int mode)
|
||||
{
|
||||
@ -1114,6 +1096,8 @@ vfs mcfs_vfs_ops = {
|
||||
mcfs_opendir,
|
||||
mcfs_readdir,
|
||||
mcfs_closedir,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
mcfs_stat,
|
||||
mcfs_lstat,
|
||||
|
@ -1305,3 +1305,9 @@ char *strdup (char *s)
|
||||
return t;
|
||||
}
|
||||
#endif
|
||||
|
||||
void vfs_die( char *m )
|
||||
{
|
||||
fprintf (stderr,m);
|
||||
exit (1);
|
||||
}
|
||||
|
@ -36,6 +36,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#ifndef TUNMLEN
|
||||
#define TUNMLEN 256
|
||||
#endif
|
||||
#ifndef TGNMLEN
|
||||
#define TGNMLEN 256
|
||||
#endif
|
||||
|
||||
static int saveuid = -993;
|
||||
static char saveuname[TUNMLEN];
|
||||
static int my_uid = -993;
|
||||
|
414
vfs/tar.c
414
vfs/tar.c
@ -2,6 +2,7 @@
|
||||
Copyright (C) 1995 The Free Software Foundation
|
||||
|
||||
Written by: 1995 Jakub Jelinek
|
||||
Rewritten by: 1998 Pavel Machek
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -37,6 +38,7 @@
|
||||
#include <time.h>
|
||||
#include "../src/fs.h"
|
||||
#include "../src/util.h"
|
||||
#include "../src/dialog.h" /* For MSG_ERROR */
|
||||
#include "../src/mem.h"
|
||||
#include "../src/mad.h"
|
||||
#include "vfs.h"
|
||||
@ -80,7 +82,7 @@ static struct tarfs_archive *first_archive = NULL;
|
||||
static int tarerrno = 0;
|
||||
static struct stat hstat; /* Stat struct corresponding */
|
||||
static char *current_file_name, *current_link_name;
|
||||
static struct tarfs_entry *tarfs_find_entry (struct tarfs_entry *dir, char *name, int make_dirs);
|
||||
static struct tarfs_entry *tarfs_find_entry (struct tarfs_entry *dir, char *name, int make_dirs, int make_file);
|
||||
|
||||
void tarfs_fill_names (void (*func)(char *))
|
||||
{
|
||||
@ -88,7 +90,7 @@ void tarfs_fill_names (void (*func)(char *))
|
||||
char *name;
|
||||
|
||||
while (a){
|
||||
name = copy_strings ("tar:", a->name, "/",
|
||||
name = copy_strings ( a->name, "#tar/",
|
||||
a->current_dir->name, 0);
|
||||
(*func)(name);
|
||||
free (name);
|
||||
@ -573,7 +575,7 @@ static int read_header (struct tarfs_archive *archive, int tard)
|
||||
size -= written) {
|
||||
data = get_next_record (archive, tard)->charptr;
|
||||
if (data == NULL) {
|
||||
message_1s (1, " Error ", "Unexpected EOF on archive file");
|
||||
message_1s (1, MSG_ERROR, _("Unexpected EOF on archive file"));
|
||||
return 0;
|
||||
}
|
||||
written = RECORDSIZE;
|
||||
@ -625,9 +627,9 @@ static int read_header (struct tarfs_archive *archive, int tard)
|
||||
q = current_file_name;
|
||||
}
|
||||
|
||||
pent = tarfs_find_entry (archive->root_entry, q, 1);
|
||||
pent = tarfs_find_entry (archive->root_entry, q, 1, 0);
|
||||
if (pent == NULL) {
|
||||
message_1s (1, " Error ", "Inconsistent tar archive");
|
||||
message_1s (1, MSG_ERROR, _("Inconsistent tar archive"));
|
||||
}
|
||||
|
||||
entry = (struct tarfs_entry *) xmalloc (sizeof (struct tarfs_entry), "Tar: tarfs_entry");
|
||||
@ -646,9 +648,9 @@ static int read_header (struct tarfs_archive *archive, int tard)
|
||||
free (current_file_name);
|
||||
|
||||
if (header->header.linkflag == LF_LINK) {
|
||||
pent = tarfs_find_entry (archive->root_entry, current_link_name, 0);
|
||||
pent = tarfs_find_entry (archive->root_entry, current_link_name, 0, 0);
|
||||
if (pent == NULL) {
|
||||
message_1s (1, " Error ", "Inconsistent tar archive");
|
||||
message_1s (1, MSG_ERROR, _("Inconsistent tar archive"));
|
||||
} else {
|
||||
entry->inode = pent->inode;
|
||||
pent->inode->nlink++;
|
||||
@ -748,7 +750,7 @@ int read_tar_archive (char *name, struct tarfs_archive **pparc)
|
||||
struct tarfs_archive *archive;
|
||||
|
||||
if ((tard = open_tar_archive (name, &archive)) == -1) { /* Open for reading */
|
||||
message_2s (1, " Error ", "Couldn't open tar archive\n%s", name);
|
||||
message_2s (1, MSG_ERROR, _("Couldn't open tar archive\n%s"), name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -767,7 +769,7 @@ int read_tar_archive (char *name, struct tarfs_archive **pparc)
|
||||
case 0: /* Invalid header */
|
||||
switch (prev_status) {
|
||||
case 3: /* Error on first record */
|
||||
message_2s (1, " Error ", "Hmm,...\n%s\ndoesn't look like a tar archive.", name);
|
||||
message_2s (1, MSG_ERROR, _("Hmm,...\n%s\ndoesn't look like a tar archive."), name);
|
||||
/* FALL THRU */
|
||||
case 2: /* Error after record of zeroes */
|
||||
case 1: /* Error after header rec */
|
||||
@ -791,43 +793,6 @@ int read_tar_archive (char *name, struct tarfs_archive **pparc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *tarfs_analysis (char *name, char **archive, int is_dir)
|
||||
{
|
||||
static struct {
|
||||
int len; /* strlen (ext) */
|
||||
char *ext;
|
||||
} tarext[] = {{4, ".tar"},
|
||||
{4, ".tgz"},
|
||||
{7, ".tar.gz"},
|
||||
{4, ".taz"},
|
||||
{4, ".tpz"},
|
||||
{6, ".tar.z"},
|
||||
{7, ".tar.bz"},
|
||||
{8, ".tar.bz2"},
|
||||
{6, ".tar.Z"} };
|
||||
char *p, *local;
|
||||
unsigned int i;
|
||||
char *archive_name = NULL;
|
||||
|
||||
/* | this is len of "tar:" plus some minimum
|
||||
* v space needed for the extension */
|
||||
for (p = name + strlen (name); p >= name + 8; p--)
|
||||
if (*p == '/' || (is_dir && !*p))
|
||||
for (i = 0; i < sizeof (tarext) / sizeof (tarext [0]); i++)
|
||||
if (!strncmp (p - tarext [i].len, tarext [i].ext, tarext [i].len)) {
|
||||
char c = *p;
|
||||
|
||||
*p = 0;
|
||||
archive_name = vfs_canon (name + 4);
|
||||
*archive = archive_name;
|
||||
*p = c;
|
||||
local = strdup (p);
|
||||
return local;
|
||||
}
|
||||
tarerrno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns allocated path inside the archive or NULL */
|
||||
static char *tarfs_get_path (char *inname, struct tarfs_archive **archive, int is_dir,
|
||||
int do_not_open)
|
||||
@ -839,11 +804,10 @@ static char *tarfs_get_path (char *inname, struct tarfs_archive **archive, int i
|
||||
vfs *v;
|
||||
struct stat stat_buf;
|
||||
|
||||
local = tarfs_analysis (inname, &archive_name, is_dir);
|
||||
if (local == NULL) {
|
||||
tarerrno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
archive_name = inname;
|
||||
vfs_split( inname, &local, NULL );
|
||||
if (!local)
|
||||
local = "";
|
||||
|
||||
mc_stat (archive_name, &stat_buf);
|
||||
|
||||
@ -865,8 +829,6 @@ static char *tarfs_get_path (char *inname, struct tarfs_archive **archive, int i
|
||||
result = read_tar_archive (archive_name, &parc);
|
||||
if (result == -1) {
|
||||
tarerrno = EIO;
|
||||
free(local);
|
||||
free(archive_name);
|
||||
return NULL;
|
||||
}
|
||||
v = vfs_type (archive_name);
|
||||
@ -882,7 +844,6 @@ static char *tarfs_get_path (char *inname, struct tarfs_archive **archive, int i
|
||||
vfs_rm_parents (parent);
|
||||
return_success:
|
||||
*archive = parc;
|
||||
free (archive_name);
|
||||
return local;
|
||||
}
|
||||
|
||||
@ -895,7 +856,7 @@ static int notadir;
|
||||
|
||||
static struct tarfs_entry *
|
||||
__tarfs_find_entry (struct tarfs_entry *dir, char *name,
|
||||
struct tarfs_loop_protect *list, int make_dirs);
|
||||
struct tarfs_loop_protect *list, int make_dirs, int make_file);
|
||||
|
||||
static struct tarfs_entry *
|
||||
__tarfs_resolve_symlinks (struct tarfs_entry *entry,
|
||||
@ -916,7 +877,7 @@ __tarfs_resolve_symlinks (struct tarfs_entry *entry,
|
||||
"Tar: symlink looping protection");
|
||||
looping->entry = entry;
|
||||
looping->next = list;
|
||||
pent = __tarfs_find_entry (entry->dir, entry->inode->linkname, looping, 0);
|
||||
pent = __tarfs_find_entry (entry->dir, entry->inode->linkname, looping, 0, 0);
|
||||
free (looping);
|
||||
if (pent == NULL)
|
||||
tarerrno = ENOENT;
|
||||
@ -939,93 +900,6 @@ static struct tarfs_entry *tarfs_resolve_symlinks (struct tarfs_entry *entry)
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct tarfs_entry*
|
||||
__tarfs_find_entry (struct tarfs_entry *dir, char *name,
|
||||
struct tarfs_loop_protect *list, int make_dirs)
|
||||
{
|
||||
struct tarfs_entry *pent, *pdir;
|
||||
char *p, *q, *name_end;
|
||||
char c;
|
||||
|
||||
if (*name == '/') { /* Handle absolute paths */
|
||||
name++;
|
||||
dir = dir->inode->archive->root_entry;
|
||||
}
|
||||
|
||||
pent = dir;
|
||||
p = name;
|
||||
name_end = name + strlen (name);
|
||||
q = strchr (p, '/');
|
||||
c = '/';
|
||||
if (!q)
|
||||
q = strchr (p, 0);
|
||||
|
||||
for (; pent != NULL && c && *p; ){
|
||||
c = *q;
|
||||
*q = 0;
|
||||
|
||||
if (strcmp (p, ".")){
|
||||
if (!strcmp (p, ".."))
|
||||
pent = pent->dir;
|
||||
else {
|
||||
if ((pent = __tarfs_resolve_symlinks (pent, list))==NULL){
|
||||
*q = c;
|
||||
return NULL;
|
||||
}
|
||||
if (c == '/' && !S_ISDIR (pent->inode->mode)){
|
||||
*q = c;
|
||||
notadir = 1;
|
||||
return NULL;
|
||||
}
|
||||
pdir = pent;
|
||||
for (pent = pent->inode->first_in_subdir; pent; pent = pent->next_in_dir)
|
||||
/* Hack: I keep the original semanthic unless
|
||||
q+1 would break in the strchr */
|
||||
if (!strcmp (pent->name, p)){
|
||||
if (q + 1 > name_end){
|
||||
*q = c;
|
||||
notadir = !S_ISDIR (pent->inode->mode);
|
||||
return pent;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* When we load archive, we create automagically
|
||||
* non-existant directories
|
||||
*/
|
||||
if (pent == NULL && make_dirs) {
|
||||
pent = generate_entry (dir->inode->archive, p, pdir, S_IFDIR | 0777);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Next iteration */
|
||||
*q = c;
|
||||
p = q + 1;
|
||||
q = strchr (p, '/');
|
||||
if (!q)
|
||||
q = strchr (p, 0);
|
||||
}
|
||||
if (pent == NULL)
|
||||
tarerrno = ENOENT;
|
||||
return pent;
|
||||
}
|
||||
|
||||
static struct tarfs_entry *tarfs_find_entry (struct tarfs_entry *dir, char *name, int make_dirs)
|
||||
{
|
||||
struct tarfs_entry *res;
|
||||
|
||||
errloop = 0;
|
||||
notadir = 0;
|
||||
res = __tarfs_find_entry (dir, name, NULL, make_dirs);
|
||||
if (res == NULL) {
|
||||
if (errloop)
|
||||
tarerrno = ELOOP;
|
||||
else if (notadir)
|
||||
tarerrno = ENOTDIR;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
struct tar_pseudofile {
|
||||
struct tarfs_archive *archive;
|
||||
long pos;
|
||||
@ -1034,18 +908,18 @@ struct tar_pseudofile {
|
||||
struct tarfs_entry *entry;
|
||||
};
|
||||
|
||||
static struct tarfs_entry *tarfs_find_entry (struct tarfs_entry *dir, char *name, int make_dirs, int make_file);
|
||||
|
||||
static void *tar_open (char *file, int flags, int mode)
|
||||
{
|
||||
struct tar_pseudofile *tar_info;
|
||||
struct tarfs_archive *archive;
|
||||
char *p, *q;
|
||||
char *q;
|
||||
struct tarfs_entry *entry;
|
||||
|
||||
if ((p = tarfs_get_path (file, &archive, 0, 0)) == NULL)
|
||||
if ((q = tarfs_get_path (file, &archive, 0, 0)) == NULL)
|
||||
return NULL;
|
||||
q = (*p == '/') ? p + 1 : p;
|
||||
entry = tarfs_find_entry (archive->root_entry, q, 0);
|
||||
free (p);
|
||||
entry = tarfs_find_entry (archive->root_entry, q, 0, 0);
|
||||
if (entry == NULL)
|
||||
return NULL;
|
||||
if ((entry = tarfs_resolve_symlinks (entry)) == NULL)
|
||||
@ -1150,178 +1024,31 @@ static int tar_close (void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tar_errno (void)
|
||||
{
|
||||
return tarerrno;
|
||||
}
|
||||
#define X_pseudofile tar_pseudofile
|
||||
#define Xerrno tarerrno
|
||||
|
||||
static void *tar_opendir (char *dirname)
|
||||
{
|
||||
struct tarfs_archive *archive;
|
||||
char *p, *q;
|
||||
struct tarfs_entry *entry;
|
||||
struct tarfs_entry **tar_info;
|
||||
#define X_entry tarfs_entry
|
||||
#define X_archive tarfs_archive
|
||||
#define X_get_path tarfs_get_path
|
||||
#define X_find_entry tarfs_find_entry
|
||||
#define X_resolve_symlinks tarfs_resolve_symlinks
|
||||
#define X_inode tarfs_inode
|
||||
#define __X_find_entry __tarfs_find_entry
|
||||
#define __X_resolve_symlinks __tarfs_resolve_symlinks
|
||||
#define X_loop_protect tarfs_loop_protect
|
||||
|
||||
if ((p = tarfs_get_path (dirname, &archive, 1, 0)) == NULL)
|
||||
return NULL;
|
||||
q = (*p == '/') ? p + 1 : p;
|
||||
entry = tarfs_find_entry (archive->root_entry, q, 0);
|
||||
free (p);
|
||||
if (entry == NULL)
|
||||
return NULL;
|
||||
if ((entry = tarfs_resolve_symlinks (entry)) == NULL)
|
||||
return NULL;
|
||||
if (!S_ISDIR (entry->inode->mode)) {
|
||||
tarerrno = ENOTDIR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tar_info = (struct tarfs_entry **) xmalloc (sizeof (struct tarfs_entry *), "Tar: tar_opendir");
|
||||
*tar_info = entry->inode->first_in_subdir;
|
||||
|
||||
return tar_info;
|
||||
}
|
||||
|
||||
static void *tar_readdir (void *data)
|
||||
{
|
||||
static struct {
|
||||
struct dirent dir;
|
||||
#ifdef NEED_EXTRA_DIRENT_BUFFER
|
||||
char extra_buffer [MC_MAXPATHLEN];
|
||||
#endif
|
||||
} dir;
|
||||
|
||||
struct tarfs_entry **tar_info = (struct tarfs_entry **) data;
|
||||
|
||||
if (*tar_info == NULL)
|
||||
return NULL;
|
||||
|
||||
strcpy (&(dir.dir.d_name [0]), (*tar_info)->name);
|
||||
|
||||
#ifndef DIRENT_LENGTH_COMPUTED
|
||||
dir.d_namlen = strlen (dir.dir.d_name);
|
||||
#endif
|
||||
*tar_info = (*tar_info)->next_in_dir;
|
||||
|
||||
return (void *)&dir;
|
||||
}
|
||||
|
||||
static int tar_closedir (void *data)
|
||||
{
|
||||
free (data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _tar_stat (char *path, struct stat *buf, int resolve)
|
||||
{
|
||||
struct tarfs_archive *archive;
|
||||
char *p, *q;
|
||||
struct tarfs_entry *entry;
|
||||
struct tarfs_inode *inode;
|
||||
|
||||
if ((p = tarfs_get_path (path, &archive, 0, 0)) == NULL)
|
||||
return -1;
|
||||
q = (*p == '/') ? p + 1 : p;
|
||||
entry = tarfs_find_entry (archive->root_entry, q, 0);
|
||||
free (p);
|
||||
if (entry == NULL)
|
||||
return -1;
|
||||
if (resolve && (entry = tarfs_resolve_symlinks (entry)) == NULL)
|
||||
return -1;
|
||||
inode = entry->inode;
|
||||
buf->st_dev = inode->dev;
|
||||
buf->st_ino = inode->inode;
|
||||
buf->st_mode = inode->mode;
|
||||
buf->st_nlink = inode->nlink;
|
||||
buf->st_uid = inode->uid;
|
||||
buf->st_gid = inode->gid;
|
||||
#ifdef HAVE_ST_RDEV
|
||||
buf->st_rdev = inode->rdev;
|
||||
#endif
|
||||
buf->st_size = inode->size;
|
||||
#ifdef HAVE_ST_BLKSIZE
|
||||
buf->st_blksize = RECORDSIZE;
|
||||
#endif
|
||||
#ifdef HAVE_ST_BLOCKS
|
||||
buf->st_blocks = (inode->size + RECORDSIZE - 1) / RECORDSIZE;
|
||||
#endif
|
||||
buf->st_atime = inode->atime;
|
||||
buf->st_mtime = inode->mtime;
|
||||
buf->st_ctime = inode->ctime;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tar_stat (char *path, struct stat *buf)
|
||||
{
|
||||
return _tar_stat (path, buf, 1);
|
||||
}
|
||||
|
||||
static int tar_lstat (char *path, struct stat *buf)
|
||||
{
|
||||
return _tar_stat (path, buf, 0);
|
||||
}
|
||||
|
||||
static int tar_fstat (void *data, struct stat *buf)
|
||||
{
|
||||
struct tar_pseudofile *file = (struct tar_pseudofile *)data;
|
||||
struct tarfs_inode *inode;
|
||||
|
||||
inode = file->entry->inode;
|
||||
buf->st_dev = inode->dev;
|
||||
buf->st_ino = inode->inode;
|
||||
buf->st_mode = inode->mode;
|
||||
buf->st_nlink = inode->nlink;
|
||||
buf->st_uid = inode->uid;
|
||||
buf->st_gid = inode->gid;
|
||||
buf->st_rdev = inode->rdev;
|
||||
buf->st_size = inode->size;
|
||||
#ifdef HAVE_ST_BLKSIZE
|
||||
buf->st_blksize = RECORDSIZE;
|
||||
#endif
|
||||
#ifdef HAVE_ST_BLOCKS
|
||||
buf->st_blocks = (inode->size + RECORDSIZE - 1) / RECORDSIZE;
|
||||
#endif
|
||||
buf->st_atime = inode->atime;
|
||||
buf->st_mtime = inode->mtime;
|
||||
buf->st_ctime = inode->ctime;
|
||||
return 0;
|
||||
}
|
||||
#include "shared.c"
|
||||
|
||||
static int tar_chmod (char *path, int mode)
|
||||
{
|
||||
{ /* Fixme: are you sure? IMO this is guaranteed to fail */
|
||||
return chmod (path, mode);
|
||||
}
|
||||
|
||||
static int tar_chown (char *path, int owner, int group)
|
||||
{
|
||||
{ /* Fixme: are you sure? IMO this is guaranteed to fail */
|
||||
return chown (path, owner, group);
|
||||
}
|
||||
|
||||
static int tar_readlink (char *path, char *buf, int size)
|
||||
{
|
||||
struct tarfs_archive *archive;
|
||||
char *p, *q;
|
||||
int i;
|
||||
struct tarfs_entry *entry;
|
||||
|
||||
if ((p = tarfs_get_path (path, &archive, 0, 0)) == NULL)
|
||||
return -1;
|
||||
q = (*p == '/') ? p + 1 : p;
|
||||
entry = tarfs_find_entry (archive->root_entry, q, 0);
|
||||
free (p);
|
||||
if (entry == NULL)
|
||||
return -1;
|
||||
if (!S_ISLNK (entry->inode->mode)) {
|
||||
tarerrno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (size > (i = strlen (entry->inode->linkname))) {
|
||||
size = i;
|
||||
}
|
||||
strncpy (buf, entry->inode->linkname, i);
|
||||
return i;
|
||||
}
|
||||
|
||||
static int tar_unlink (char *path)
|
||||
{
|
||||
return -1;
|
||||
@ -1345,29 +1072,19 @@ static int tar_rename (char *a, char *b)
|
||||
static int tar_chdir (char *path)
|
||||
{
|
||||
struct tarfs_archive *archive;
|
||||
char *p, *q;
|
||||
char *q;
|
||||
struct tarfs_entry *entry;
|
||||
|
||||
tarerrno = ENOTDIR;
|
||||
if ((p = tarfs_get_path (path, &archive, 1, 0)) == NULL)
|
||||
if ((q = tarfs_get_path (path, &archive, 1, 0)) == NULL)
|
||||
return -1;
|
||||
q = (*p == '/') ? p + 1 : p;
|
||||
entry = tarfs_find_entry (archive->root_entry, q, 0);
|
||||
if (entry == NULL) {
|
||||
free (p);
|
||||
entry = tarfs_find_entry (archive->root_entry, q, 0, 0);
|
||||
if (!entry)
|
||||
return -1;
|
||||
}
|
||||
entry = tarfs_resolve_symlinks (entry);
|
||||
if (entry == NULL) {
|
||||
free (p);
|
||||
if ((!entry) || (!S_ISDIR (entry->inode->mode)))
|
||||
return -1;
|
||||
}
|
||||
if (!S_ISDIR (entry->inode->mode)) {
|
||||
free (p);
|
||||
return -1;
|
||||
}
|
||||
entry->inode->archive->current_dir = entry;
|
||||
free (p);
|
||||
tarerrno = 0;
|
||||
return 0;
|
||||
}
|
||||
@ -1423,7 +1140,6 @@ static vfsid tar_getid (char *path, struct vfs_stamping **parent)
|
||||
if ((p = tarfs_get_path (path, &archive, 0, 1)) == NULL) {
|
||||
return (vfsid) -1;
|
||||
}
|
||||
free (p);
|
||||
v = vfs_type (archive->name);
|
||||
id = (*v->getid) (archive->name, &par);
|
||||
if (id != (vfsid)-1) {
|
||||
@ -1491,12 +1207,12 @@ static char *tar_getlocalcopy (char *path)
|
||||
struct tarfs_archive *archive;
|
||||
char *p, *q;
|
||||
struct tarfs_entry *entry;
|
||||
char buf[MC_MAXPATHLEN];
|
||||
|
||||
if ((p = tarfs_get_path (path, &archive, 1, 0)) == NULL)
|
||||
strcpy( buf, path );
|
||||
if ((q = tarfs_get_path (path, &archive, 1, 0)) == NULL)
|
||||
return NULL;
|
||||
q = (*p == '/') ? p + 1 : p;
|
||||
entry = tarfs_find_entry (archive->root_entry, q, 0);
|
||||
free (p);
|
||||
entry = tarfs_find_entry (archive->root_entry, q, 0, 0);
|
||||
if (entry == NULL)
|
||||
return NULL;
|
||||
if ((entry = tarfs_resolve_symlinks (entry)) == NULL)
|
||||
@ -1504,7 +1220,7 @@ static char *tar_getlocalcopy (char *path)
|
||||
|
||||
if (entry->inode->local_filename != NULL)
|
||||
return entry->inode->local_filename;
|
||||
p = mc_def_getlocalcopy (path);
|
||||
p = mc_def_getlocalcopy (buf);
|
||||
if (p != NULL) {
|
||||
entry->inode->local_filename = p;
|
||||
}
|
||||
@ -1534,30 +1250,32 @@ vfs tarfs_vfs_ops =
|
||||
tar_open,
|
||||
tar_close,
|
||||
tar_read,
|
||||
tar_write,
|
||||
tar_write, /* unimplemented */
|
||||
|
||||
tar_opendir,
|
||||
tar_readdir,
|
||||
tar_closedir,
|
||||
s_opendir,
|
||||
s_readdir,
|
||||
s_closedir,
|
||||
s_telldir,
|
||||
s_seekdir,
|
||||
|
||||
tar_stat,
|
||||
tar_lstat,
|
||||
tar_fstat,
|
||||
s_stat,
|
||||
s_lstat,
|
||||
s_fstat,
|
||||
|
||||
tar_chmod,
|
||||
tar_chown,
|
||||
NULL,
|
||||
|
||||
tar_readlink,
|
||||
tar_symlink,
|
||||
tar_link,
|
||||
tar_unlink,
|
||||
s_readlink,
|
||||
tar_symlink, /* unimplemented */
|
||||
tar_link, /* unimplemented */
|
||||
tar_unlink, /* unimplemented */
|
||||
|
||||
tar_rename,
|
||||
tar_rename, /* unimplemented */
|
||||
tar_chdir,
|
||||
tar_errno,
|
||||
s_errno,
|
||||
tar_lseek,
|
||||
tar_mknod,
|
||||
tar_mknod, /* unipmelemented */
|
||||
|
||||
tar_getid,
|
||||
tar_nothingisopen,
|
||||
@ -1566,13 +1284,13 @@ vfs tarfs_vfs_ops =
|
||||
tar_getlocalcopy,
|
||||
tar_ungetlocalcopy,
|
||||
|
||||
tar_mkdir,
|
||||
tar_rmdir,
|
||||
tar_mkdir, /* unimplemented */
|
||||
tar_rmdir, /* unimplemented */
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
#ifdef HAVE_MMAP
|
||||
, tar_mmap,
|
||||
tar_munmap
|
||||
, tar_mmap, /* unimplemented */
|
||||
tar_munmap /* unimplemented */
|
||||
#endif
|
||||
};
|
||||
|
@ -54,6 +54,7 @@
|
||||
{ tcp_invalidate_socket (sock); return got_sigpipe = 0; }
|
||||
|
||||
extern void tcp_invalidate_socket (int);
|
||||
extern void vfs_die (char *);
|
||||
|
||||
int got_sigpipe;
|
||||
|
||||
@ -134,8 +135,7 @@ int rpc_send (int sock, ...)
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf (stderr, "Unknown rpc message\n");
|
||||
abort ();
|
||||
vfs_die ("Unknown rpc message\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -223,8 +223,7 @@ int rpc_get (int sock, ...)
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf (stderr, "Unknown rpc message\n");
|
||||
abort ();
|
||||
vfs_die ("Unknown rpc message\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -262,8 +261,8 @@ void tcp_init (void)
|
||||
|
||||
int get_remote_port (struct sockaddr_in *sin, int *version)
|
||||
{
|
||||
int port;
|
||||
#ifdef HAVE_PMAP_GETMAPS
|
||||
int port;
|
||||
struct pmaplist *pl;
|
||||
|
||||
*version = 1;
|
||||
@ -278,6 +277,7 @@ int get_remote_port (struct sockaddr_in *sin, int *version)
|
||||
return port;
|
||||
#else
|
||||
#ifdef HAVE_PMAP_GETPORT
|
||||
int port;
|
||||
for (*version = RPC_PROGVER; *version >= 1; (*version)--)
|
||||
if (port = pmap_getport (sin, RPC_PROGNUM, *version, IPPROTO_TCP))
|
||||
return port;
|
||||
|
@ -769,6 +769,8 @@ vfs undelfs_vfs_ops = {
|
||||
undelfs_opendir,
|
||||
undelfs_readdir,
|
||||
undelfs_closedir,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
undelfs_stat,
|
||||
undelfs_lstat,
|
||||
|
981
vfs/vfs.c
981
vfs/vfs.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
29
vfs/vfs.h
29
vfs/vfs.h
@ -1,6 +1,18 @@
|
||||
#ifndef __VFS_H
|
||||
#define __VFS_H
|
||||
|
||||
#ifdef VFS_STANDALONE
|
||||
#include "util-alone.h"
|
||||
#undef USE_EXT2FSLIB
|
||||
#else
|
||||
#define BROKEN_PATHS
|
||||
/*
|
||||
* We should really only allow /:ftp/ tree to export ftp, but midnight's users may
|
||||
* like to be able to cd .. to get back where there were before ftp. How to solve?
|
||||
* Ok, we'll allow /any/path/:ftp/ to access ftp tree. Broken, yes.
|
||||
*/
|
||||
#endif
|
||||
|
||||
#if !defined(SCO_FLAVOR) || !defined(_SYS_SELECT_H)
|
||||
# include <sys/time.h> /* alex: this redefines struct timeval */
|
||||
#endif /* SCO_FLAVOR */
|
||||
@ -35,6 +47,8 @@ struct utimbuf {
|
||||
void *(*opendir)(char *dirname);
|
||||
void *(*readdir)(void *vfs_info);
|
||||
int (*closedir)(void *vfs_info);
|
||||
int (*telldir)(void *dir);
|
||||
void (*seekdir)(void *dir, int offset);
|
||||
|
||||
int (*stat)(char *path, struct stat *buf);
|
||||
int (*lstat)(char *path, struct stat *buf);
|
||||
@ -139,12 +153,6 @@ struct utimbuf {
|
||||
void ftpfs_fill_names (void (*)(char *));
|
||||
void tarfs_fill_names (void (*)(char *));
|
||||
|
||||
char *ftpfs_gethome (char *);
|
||||
char *mcfs_gethome (char *);
|
||||
|
||||
char *ftpfs_getupdir (char *);
|
||||
char *mcfs_getupdir (char *);
|
||||
|
||||
/* Only the routines outside of the VFS module need the emulation macros */
|
||||
|
||||
int mc_open (char *file, int flags, ...);
|
||||
@ -157,6 +165,8 @@ struct utimbuf {
|
||||
DIR *mc_opendir (char *dirname);
|
||||
struct dirent *mc_readdir(DIR *dirp);
|
||||
int mc_closedir (DIR *dir);
|
||||
int mc_telldir (DIR *dir);
|
||||
void mc_seekdir (DIR *dir, int offset);
|
||||
|
||||
int mc_stat (char *path, struct stat *buf);
|
||||
int mc_lstat (char *path, struct stat *buf);
|
||||
@ -192,6 +202,8 @@ struct utimbuf {
|
||||
# undef USE_NETCODE
|
||||
#endif
|
||||
|
||||
# undef USE_NETCODE
|
||||
|
||||
# define vfs_fill_names(x)
|
||||
# define vfs_add_current_stamps()
|
||||
# define vfs_current_is_local() 1
|
||||
@ -207,6 +219,8 @@ struct utimbuf {
|
||||
# define mc_opendir opendir
|
||||
# define mc_readdir readdir
|
||||
# define mc_closedir closedir
|
||||
# define mc_telldir telldir
|
||||
# define mc_seekdir seekdir
|
||||
|
||||
# define mc_get_current_wd(x,size) get_current_wd (x, size)
|
||||
# define mc_fstat fstat
|
||||
@ -276,12 +290,15 @@ struct utimbuf {
|
||||
#ifdef WANT_PARSE_LS_LGA
|
||||
int parse_ls_lga (char *p, struct stat *s, char **filename, char **linkname);
|
||||
#endif
|
||||
extern void vfs_die (char *msg);
|
||||
extern char *vfs_get_password (char *msg);
|
||||
|
||||
#define MCCTL_SETREMOTECOPY 0
|
||||
#define MCCTL_ISREMOTECOPY 1
|
||||
#define MCCTL_REMOTECOPYCHUNK 2
|
||||
#define MCCTL_FINISHREMOTE 3
|
||||
#define MCCTL_FLUSHDIR 4
|
||||
#define MCCTL_REMOVELOCALCOPY 5
|
||||
|
||||
/* Return codes from the ${fs}_ctl routine */
|
||||
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user