Merge branch '2361_vfs_uri'
* 2361_vfs_uri: (60 commits) Fixed vfs_class->fill_names() functions (Fish, Ftpfs, Smbfs) for return URL-like paths Fixed nice_cd() behavior with vfs-prefixed. added converter benween old-style and url-stype VFS prefixes Code cleanup vfs_path_get_by_index(): added check for valid element index Fixed memory leaks in folowing functions: Removed function vfs_s_get_path(); Function vfs_s_get_path_mangle() renamed to vfs_s_get_path() Added function mc_build_filename() for processing URL-paths as well fixed x_basename function for handle URL-like paths added vfs_path_element_valid() function Changes in man-files for describe new URL-like paths change name of user bindings file to mc.ext vfs_path_to_str() now return URL string instead of old representation Added URL-like path parser Reorder VFS parser to work with VFS parameters: Handle path /some/path/#vfsprefix:/path as /some/path#vfsprefix:/path Remove usage of vfs_path_t->raw_url_str from src/* files Following prototypes of functions was changed in VFS-module API: Added function vfs_path_url_split() for parse VFS parameters Removed vfs_get_class() function Following prototypes of functions was changed in VFS-module API: ...
Этот коммит содержится в:
Коммит
f2ebbd2eb4
@ -609,6 +609,7 @@ if test x$enable_tests != xno; then
|
||||
AC_CONFIG_FILES([
|
||||
lib/tests/Makefile
|
||||
lib/tests/mcconfig/Makefile
|
||||
lib/tests/vfs/Makefile
|
||||
])
|
||||
|
||||
fi
|
||||
|
@ -1355,7 +1355,7 @@ comando cd interno\&.
|
||||
.\"NODE " Extension File Edit"
|
||||
.SH " Editar el Archivo de Extensiones"
|
||||
Abre el archivo
|
||||
.I ~/.local/share/mc/bindings
|
||||
.I ~/.local/share/mc/mc.ext
|
||||
en nuestro editor. El administrador puede optar por editar, en su lugar,
|
||||
el archivo de extensiones del sistema
|
||||
.IR @prefix@/share/mc/mc.ext .
|
||||
@ -2703,7 +2703,7 @@ El sistema de archivos tar y los archivos tar comprimidos pueden consultarse usa
|
||||
el comando chdir. Para mostrar en el panel el contenido de un archivo tar, cambiamos
|
||||
de directorio empleando la siguiente sintaxis:
|
||||
.PP
|
||||
.I /archivo.tar#utar/[directorio\-dentro\-tar]
|
||||
.I /archivo.tar/utar://[directorio\-dentro\-tar]
|
||||
.PP
|
||||
El archivo mc.ext también ofrece un atajo para los archivos tar, esto quiere decir
|
||||
que normalmente basta con apuntar a un archivo tar y pulsar Intro para entrar en el
|
||||
@ -2716,8 +2716,8 @@ para obtener más detalles sobre cómo hacer esto.
|
||||
Ejemplos:
|
||||
.PP
|
||||
.nf
|
||||
mc\-3.0.tar.gz#utar/mc\-3.0/vfs
|
||||
/ftp/GCC/gcc\-2.7.0.tar#utar
|
||||
mc\-3.0.tar.gz/utar://mc\-3.0/vfs
|
||||
/ftp/GCC/gcc\-2.7.0.tar/utar://
|
||||
.fi
|
||||
.PP
|
||||
En este último se indica la ruta completa hasta el archivo tar.
|
||||
@ -2732,7 +2732,7 @@ o simplemente emplear la orden
|
||||
como cuando cambiamos habitualmente de directorio, pero indicando
|
||||
como ruta:
|
||||
.PP
|
||||
.I /#ftp:[!][usuario[:clave]@]maquina[:puerto][dir\-remoto]
|
||||
.I ftp://[!][usuario[:clave]@]maquina[:puerto][dir\-remoto]
|
||||
.PP
|
||||
Los elementos
|
||||
.IR usuario ,
|
||||
@ -2759,12 +2759,12 @@ delante del nombre de la máquina.
|
||||
Ejemplos:
|
||||
.PP
|
||||
.nf
|
||||
/#ftp:ftp.nuclecu.unam.mx/linux/local
|
||||
/#ftp:tsx\-11.mit.edu/pub/linux/packages
|
||||
/#ftp:!detras.barrera.edu/pub
|
||||
/#ftp:guest@pcremoto.com:40/pub
|
||||
/#ftp:miguel:xxx@servidor/pub
|
||||
/#ftp:ftp.um.es/pub
|
||||
ftp://ftp.nuclecu.unam.mx/linux/local
|
||||
ftp://tsx\-11.mit.edu/pub/linux/packages
|
||||
ftp://!detras.barrera.edu/pub
|
||||
ftp://guest@pcremoto.com:40/pub
|
||||
ftp://miguel:xxx@servidor/pub
|
||||
ftp://ftp.um.es/pub
|
||||
.fi
|
||||
.PP
|
||||
La opciones de FTPfs se encuentran entre las opciones de configuración del
|
||||
@ -2782,7 +2782,7 @@ o permitir la conexión a una shell de tipo bash.
|
||||
Para conectar con la máquina remota basta cambiar de directorio a un
|
||||
directorio virtual cuyo nombre sea de la forma:
|
||||
.PP
|
||||
.I /#sh:[usuario@]maquina[:opciones]/[directorio\-remoto]
|
||||
.I sh://[usuario@]maquina[:opciones]/[directorio\-remoto]
|
||||
.PP
|
||||
Los elementos
|
||||
.IR usuario ,
|
||||
@ -2805,9 +2805,9 @@ remota.
|
||||
Ejemplos:
|
||||
.PP
|
||||
.nf
|
||||
/#sh:solorsh.es:r/linux/local
|
||||
/#sh:pepe@quiero.comprension.edu:C/privado
|
||||
/#sh:pepe@sincomprimir.ssh.edu/privado
|
||||
sh://solorsh.es:r/linux/local
|
||||
sh://pepe@quiero.comprension.edu:C/privado
|
||||
sh://pepe@sincomprimir.ssh.edu/privado
|
||||
.fi
|
||||
|
||||
.\"NODE " SMB File System"
|
||||
@ -2819,7 +2819,7 @@ se puede emplear la "Conexión por SMB..." (accesible desde la barra de
|
||||
menús) o bien cambiar de directorio a un directorio virtual cuyo nombre
|
||||
sea de la forma:
|
||||
.PP
|
||||
.I /#smb:[usuario@]maquina[/recurso][/directorio\-remoto]
|
||||
.I smb://[usuario@]maquina[/recurso][/directorio\-remoto]
|
||||
.PP
|
||||
Los elementos
|
||||
.IR usuario ,
|
||||
@ -2836,9 +2836,9 @@ se pueden especificar en un cuadro de diálogo.
|
||||
Ejemplos:
|
||||
.PP
|
||||
.nf
|
||||
/#smb:maquina/Compartido
|
||||
/#smb:otramaquina
|
||||
/#smb:invitado@maquina/publico/leyes
|
||||
smb://maquina/Compartido
|
||||
smb://otramaquina
|
||||
smb://invitado@maquina/publico/leyes
|
||||
.fi
|
||||
|
||||
.\"NODE " Undelete File System"
|
||||
@ -2852,14 +2852,14 @@ restaurar todos los archivos borrados en un ext2fs y proporciona
|
||||
la extracción selectiva de archivos en una partición regular.
|
||||
.PP
|
||||
Para usar este sistema de archivos, tendremos que hacer un chdir a un nombre de archivo especial
|
||||
formado por el prefijo "/#undel" y el nombre de archivo donde se encuentra el
|
||||
formado por el prefijo "/undel://" y el nombre de archivo donde se encuentra el
|
||||
sistema de archivos actual.
|
||||
.PP
|
||||
Por ejemplo, para recuperar archivos borrados en la segunda partición del
|
||||
primer disco scsi en Linux, usaríamos el siguiente nombre de ruta:
|
||||
.PP
|
||||
.nf
|
||||
/#undel:sda2
|
||||
undel://sda2
|
||||
.fi
|
||||
.PP
|
||||
Esto le llevaría un tiempo a undelfs para cargar la información
|
||||
@ -2876,7 +2876,7 @@ Los sistemas de archivos Extfs son de dos tipos:
|
||||
1. Sistemas de archivos autónomos, que no están asociados a ningún
|
||||
archivo existente. Representan algún tipo de información relacionada con
|
||||
el sistema en forma de árbol de directorios. Se accede a ellos ejecutando
|
||||
.RI ' "cd #nombrefs" '
|
||||
.RI ' "cd nombrefs://" '
|
||||
donde nombrefs es el nombre corto que identifica el extfs (ver más
|
||||
adelante). Ejemplos de éstos son audio (lista de pistas de sonido en
|
||||
el CD) o apt (lista de paquetes de tipo Debian en el sistema).
|
||||
@ -2884,7 +2884,7 @@ el CD) o apt (lista de paquetes de tipo Debian en el sistema).
|
||||
Por ejemplo, para listar las pistas de música del CD, escribir
|
||||
.PP
|
||||
.nf
|
||||
cd #audio
|
||||
cd audio://
|
||||
.fi
|
||||
.PP
|
||||
2. Sistemas de archivos en un archivo (como rpm, patchfs y más), que
|
||||
@ -2893,7 +2893,7 @@ Puede tratarse de archivos reales empaquetados o comprimidos en un archivo
|
||||
(urar, rpm) o archivos virtuales, como puede ser el caso de mensajes
|
||||
en un archivo de correo electrónico (mailfs) o partes de un archivo de
|
||||
modificaciones o parches (patchfs). Para acceder a ellos se añade
|
||||
.RI ' #nombrefs '
|
||||
.RI ' nombrefs:// '
|
||||
al nombre del archivo a abrir. Este archivo podría él mismo estar en
|
||||
otro sistema de archivos virtual.
|
||||
.PP
|
||||
@ -2901,7 +2901,7 @@ Por ejemplo, para listar los contenidos de un archivo documentos.zip
|
||||
comprimido hay que escribir
|
||||
.PP
|
||||
.nf
|
||||
cd documentos.zip#uzip
|
||||
cd documentos.zip/uzip://
|
||||
.fi
|
||||
.PP
|
||||
En muchos aspectos, se puede tratar un sistema de archivos externo como
|
||||
@ -2915,57 +2915,57 @@ archivos externos:
|
||||
.TP
|
||||
.B a
|
||||
acceder a un disquete DOS/Windows 'A:'
|
||||
.RI ( "cd #a" ).
|
||||
.RI ( "cd a://" ).
|
||||
.TP
|
||||
.B apt
|
||||
monitor del sistema de gestión de paquetes APT de Debian
|
||||
.RI ( "cd #apt" ).
|
||||
.RI ( "cd apt://" ).
|
||||
.TP
|
||||
.B audio
|
||||
acceso y audición de CDs
|
||||
.RI ( "cd #audio"
|
||||
.RI ( "cd audio://"
|
||||
o
|
||||
.IR "cd dispositivo#audio" ).
|
||||
.IR "cd dispositivo/audio://" ).
|
||||
.TP
|
||||
.B bpp
|
||||
paquete de la distribución GNU/Linux Bad Penguin
|
||||
.RI ( "cd archivo.bpp#bpp" ).
|
||||
.RI ( "cd archivo.bpp/bpp://" ).
|
||||
.TP
|
||||
.B deb
|
||||
paquete de la distribución GNU/Linux Debian
|
||||
.RI ( "cd archivo.deb#deb" ).
|
||||
.RI ( "cd archivo.deb/deb://" ).
|
||||
.TP
|
||||
.B dpkg
|
||||
paquetes instalados en Debian GNU/Linux
|
||||
.RI ( "cd #deb" ).
|
||||
.RI ( "cd deb://" ).
|
||||
.TP
|
||||
.B hp48
|
||||
ver o copiar archivos a/desde una calculadora HP48
|
||||
.RI ( "cd #hp48" ).
|
||||
.RI ( "cd hp48://" ).
|
||||
.TP
|
||||
.B lslR
|
||||
navegación en listados lslR empleados en bastantes sitios FTP
|
||||
.RI ( "cd filename#lslR" ).
|
||||
.RI ( "cd filename/lslR://" ).
|
||||
.TP
|
||||
.B mailfs
|
||||
soporte para archivos de correo electrónico tipo mbox
|
||||
.RI ( "cd archivo_mbox#mailfs" ).
|
||||
.RI ( "cd archivo_mbox/mailfs://" ).
|
||||
.TP
|
||||
.B patchfs
|
||||
manipulación de archivos de cambios/parches tipo diff
|
||||
.RI ( "cd archivo#patchfs" ).
|
||||
.RI ( "cd archivo/patchfs://" ).
|
||||
.TP
|
||||
.B rpm
|
||||
paquete RPM
|
||||
.RI ( "cd archivo#rpm" ).
|
||||
.RI ( "cd archivo/rpm://" ).
|
||||
.TP
|
||||
.B rpms
|
||||
base de datos de paquetes RPM instalados
|
||||
.RI ( "cd #rpms" ).
|
||||
.RI ( "cd rpms://" ).
|
||||
.TP
|
||||
.B ulha, urar, uzip, uzoo, uar, uha
|
||||
herramientas de compresión
|
||||
.RI ( "cd archivo#xxxx"
|
||||
.RI ( "cd archivo/xxxx://"
|
||||
siendo xxxx uno de estos:
|
||||
.IR ulha ,
|
||||
.IR urar ,
|
||||
@ -2984,7 +2984,7 @@ paquetes Debian:
|
||||
.PP
|
||||
.nf
|
||||
regex/\.deb$
|
||||
Open=%cd %p#deb
|
||||
Open=%cd %p/deb://
|
||||
.fi
|
||||
.\"NODE "Colors"
|
||||
.SH "Colores"
|
||||
@ -3666,7 +3666,7 @@ Archivo de ayuda.
|
||||
.IP
|
||||
Archivo de extensiones por defecto del sistema.
|
||||
.PP
|
||||
.I ~/.local/share/mc/bindings
|
||||
.I ~/.local/share/mc/mc.ext
|
||||
.IP
|
||||
Archivo de usuario de extensiones y configuración de visor y editor. Si
|
||||
está presente prevalece sobre el contenido de los archivos del sistema.
|
||||
|
@ -1289,7 +1289,7 @@ A cd belső parancs
|
||||
leírásánál.
|
||||
.\"NODE " Extension File Edit"
|
||||
.SH " Társítások"
|
||||
Ez az ~/.local/share/mc/bindings szerkesztéséhez segítségül fogja hívni a
|
||||
Ez az ~/.local/share/mc/mc.ext szerkesztéséhez segítségül fogja hívni a
|
||||
szövegszerkesztődet. A fájl formátuma a következő (a formátum a 3.0\-ás
|
||||
verzióval megváltozott):
|
||||
.PP
|
||||
@ -2581,7 +2581,7 @@ panel FTP kapcsolat... parancsát (elérhető a menüből), vagy
|
||||
közvetlenül átválthatsz a jelenlegi könyvtárból a cd
|
||||
parancs használatával, valahogy így:
|
||||
.PP
|
||||
.I /#ftp:[!][felhasználó[:jelszó]@]machine[:port][távoli\-könyvtár]
|
||||
.I ftp://[!][felhasználó[:jelszó]@]machine[:port][távoli\-könyvtár]
|
||||
.PP
|
||||
A
|
||||
.I felhasználó, port
|
||||
@ -2601,14 +2601,14 @@ ekkor sem lesz minden esetben tökéletesen biztonságos megoldás).
|
||||
Példák:
|
||||
.PP
|
||||
.nf
|
||||
/#ftp:ftp.nuclecu.unam.mx/linux/local
|
||||
/#ftp:tsx\-11.mit.edu/pub/linux/packages
|
||||
/#ftp:!behind.firewall.edu/pub
|
||||
/#ftp:guest@remote\-host.com:40/pub
|
||||
/#ftp:miguel:xxx@server/pub
|
||||
ftp://ftp.nuclecu.unam.mx/linux/local
|
||||
ftp://tsx\-11.mit.edu/pub/linux/packages
|
||||
ftp://!behind.firewall.edu/pub
|
||||
ftp://guest@remote\-host.com:40/pub
|
||||
ftp://miguel:xxx@server/pub
|
||||
.fi
|
||||
.PP
|
||||
Tűzfalon keresztüli kapcsolat létrehozásához, az /#ftp:! kiegészítés
|
||||
Tűzfalon keresztüli kapcsolat létrehozásához, az ftp://! kiegészítés
|
||||
használatára van szükséged (pl., felkiáltójel a dupla perjel után)
|
||||
ahhoz, hogy a Midnight Commander használni tudja a proxy host\-ot az ftp
|
||||
átvitelhez. A
|
||||
@ -2667,8 +2667,8 @@ részt, hogy megismerhesd az ezzel kapcsolatos információkat:
|
||||
Példák:
|
||||
.PP
|
||||
.nf
|
||||
mc\-3.0.tar.gz#utar/mc\-3.0/vfs
|
||||
/ftp/GCC/gcc\-2.7.0.tar#utar
|
||||
mc\-3.0.tar.gz/utar://mc\-3.0/vfs
|
||||
/ftp/GCC/gcc\-2.7.0.tar/utar://
|
||||
.fi
|
||||
.PP
|
||||
Az utóbbi meghatározás a tar arhívum teljes elérési útját tartalmazza.
|
||||
@ -2683,7 +2683,7 @@ A távoli géphez történő kapcsolódáshoz csak könyvtárat kell váltanod a
|
||||
következő formátumnak megfelelő könyvtárba:
|
||||
.PP
|
||||
.nf
|
||||
/#sh:[felhasználó@]machine[:opciók];/[távoli\-könyvtár];</em>
|
||||
sh://[felhasználó@]machine[:opciók];/[távoli\-könyvtár];</em>
|
||||
.fi
|
||||
.PP
|
||||
A
|
||||
@ -2707,9 +2707,9 @@ elemet beírtad, a távoli gépnek ezt a könyvtárát állítod be.
|
||||
Példák:
|
||||
.PP
|
||||
.nf
|
||||
/#sh:onlyrsh.mx:r/linux/local
|
||||
/#sh:joe@want.compression.edu:C/private
|
||||
/#sh:joe@noncompressed.ssh.edu/private
|
||||
sh://onlyrsh.mx:r/linux/local
|
||||
sh://joe@want.compression.edu:C/private
|
||||
sh://joe@noncompressed.ssh.edu/private
|
||||
.fi
|
||||
.\"NODE " Undelete File System"
|
||||
.SH " Törlés visszaállítása"
|
||||
@ -2724,7 +2724,7 @@ fájlnevet az ext2fs\-en, megjeleníti őket és a kiválasztott fájlokat a
|
||||
kiteszi a megadott partícióra.
|
||||
.PP
|
||||
Ezen fájlrendszer használatához abba a speciális fájlrendszerbe kell
|
||||
belépned, amely "/#undel" meghatározással kezdődik, és annak az aktuális
|
||||
belépned, amely "undel://" meghatározással kezdődik, és annak az aktuális
|
||||
fájlrendszernek a nevét tartalmazza, ahol a visszaállítani kívánt file
|
||||
található.
|
||||
.PP
|
||||
@ -2733,11 +2733,156 @@ szeretnénk visszaállítani, akkor a következő elérési utat kell
|
||||
megadnunk:
|
||||
.PP
|
||||
.nf
|
||||
/#undel:sda2
|
||||
undel://sda2
|
||||
.fi
|
||||
.PP
|
||||
Persze várakozni kell, amíg az undelfs a szükséges információkat
|
||||
beolvassa, a fájl böngészés megkezdése előtt.
|
||||
.SH " SMB File System"
|
||||
The smbfs allows you to manipulate files on remote machines with SMB
|
||||
(or CIFS) protocol. These include Windows for Workgroups,
|
||||
Windows 9x/ME/XP, Windows NT, Windows 2000 and Samba.
|
||||
To actually use it, you may try to use the panel command "SMB link..."
|
||||
(accessible from the menubar) or you may directly change your current
|
||||
directory to it using the cd command to a path name that looks like this:
|
||||
.PP
|
||||
.I smb://[user@]machine[/service][/remote\-dir]
|
||||
.PP
|
||||
The
|
||||
.IR user ,
|
||||
.I service
|
||||
and
|
||||
.I remote\-dir
|
||||
elements are optional.
|
||||
The
|
||||
.IR user ,
|
||||
.I domain
|
||||
and
|
||||
.I password
|
||||
can be specified in an input dialog.
|
||||
.PP
|
||||
Examples:
|
||||
.PP
|
||||
.nf
|
||||
smb://machine/Share
|
||||
smb://other_machine
|
||||
smb://guest@machine/Public/Irlex
|
||||
.fi
|
||||
.\"NODE " EXTernal File System"
|
||||
.SH " EXTernal File System"
|
||||
.B extfs
|
||||
allows to integrate numerous features and file types into GNU Midnight
|
||||
Commander in an easy way, by writing scripts.
|
||||
.PP
|
||||
Extfs filesystems can be divided into two categories:
|
||||
.PP
|
||||
1. Stand\-alone filesystems, which are not associated with any existing
|
||||
file. They represent certain system\-wide data as a directory tree.
|
||||
You can invoke them by typing
|
||||
.RI ' "cd fsname://" '
|
||||
where fsname is an extfs short name (see below). Examples of such
|
||||
filesystems include audio (list audio tracks on the CD) or apt (list of
|
||||
all Debian packages in the system).
|
||||
.PP
|
||||
For example, to list CD\-Audio tracks on your CD\-ROM drive, type
|
||||
.PP
|
||||
.nf
|
||||
cd audio://
|
||||
.fi
|
||||
.PP
|
||||
2. 'Archive' filesystems (like rpm, patchfs and more), which represent
|
||||
contents of a file as a directory tree. It can consist of 'real' files
|
||||
compressed in an archive (urar, rpm) or virtual files, like messages
|
||||
in a mailbox (mailfs) or parts of a patch (patchfs). To access such
|
||||
filesystems
|
||||
.RI ' fsname:// '
|
||||
should be appended to the archive name. Note that the archive itself
|
||||
can be on another vfs.
|
||||
.PP
|
||||
For example, to list contents of a zip archive documents.zip type
|
||||
.PP
|
||||
.nf
|
||||
cd documents.zip/uzip://
|
||||
.fi
|
||||
.PP
|
||||
In many aspects, you could treat extfs like any other directory. For
|
||||
instance, you can add it to the hotlist or change to it from directory
|
||||
history. An important limitation is that you cannot invoke shell
|
||||
commands inside extfs, just like any other non\-local VFS.
|
||||
.PP
|
||||
Common extfs scripts included with Midnight Commander are:
|
||||
.TP
|
||||
.B a
|
||||
access 'A:' DOS/Windows diskette
|
||||
.RI ( "cd a://" ).
|
||||
.TP
|
||||
.B apt
|
||||
front end to Debian's APT package management system
|
||||
.RI ( "cd apt://" ).
|
||||
.TP
|
||||
.B audio
|
||||
audio CD ripping and playing
|
||||
.RI ( "cd audio://"
|
||||
or
|
||||
.IR "cd device/audio://" ).
|
||||
.TP
|
||||
.B bpp
|
||||
package of Bad Penguin GNU/Linux distribution
|
||||
.RI ( "cd file.bpp/bpp://" ).
|
||||
.TP
|
||||
.B deb
|
||||
package of Debian GNU/Linux distribution
|
||||
.RI ( "cd file.deb/deb://" ).
|
||||
.TP
|
||||
.B dpkg
|
||||
Debian GNU/Linux installed packages
|
||||
.RI ( "cd deb://" ).
|
||||
.TP
|
||||
.B hp48
|
||||
view and copy files to/from a HP48 calculator
|
||||
.RI ( "cd hp48://" ).
|
||||
.TP
|
||||
.B lslR
|
||||
browsing of lslR listings as found on many FTPs
|
||||
.RI ( "cd filename/lslR://" ).
|
||||
.TP
|
||||
.B mailfs
|
||||
mbox\-style mailbox files support
|
||||
.RI ( "cd mailbox/mailfs://" ).
|
||||
.TP
|
||||
.B patchfs
|
||||
extfs to handle unified and context diffs
|
||||
.RI ( "cd filename/patchfs://" ).
|
||||
.TP
|
||||
.B rpm
|
||||
RPM package
|
||||
.RI ( "cd filename/rpm://" ).
|
||||
.TP
|
||||
.B rpms
|
||||
RPM database management
|
||||
.RI ( "cd rpms://" ).
|
||||
.TP
|
||||
.B ulha, urar, uzip, uzoo, uar, uha
|
||||
archivers
|
||||
.RI ( "cd archive/xxxx://"
|
||||
where xxxx is one of:
|
||||
.IR ulha ,
|
||||
.IR urar ,
|
||||
.IR uzip ,
|
||||
.IR uzoo ,
|
||||
.IR uar ,
|
||||
.IR uha ).
|
||||
.PP
|
||||
You could bind file type/extension to specified extfs as described in the
|
||||
.\"LINK2"
|
||||
Extension File Edit
|
||||
.\"Extension File Edit"
|
||||
section. Here is an example entry for Debian packages:
|
||||
.PP
|
||||
.nf
|
||||
regex/\.deb$
|
||||
Open=%cd %p/deb://
|
||||
.fi
|
||||
.\"NODE "Colors"
|
||||
.SH "Színek"
|
||||
A Midnight Commander megpróbálja megállapítani azt, hogy a terminál
|
||||
@ -3033,7 +3178,7 @@ A program súgó fájlja.
|
||||
.IP
|
||||
Az alapértelmezett rendszerszintű kiterjesztés fájl.
|
||||
.PP
|
||||
.I ~/.local/share/mc/bindings
|
||||
.I ~/.local/share/mc/mc.ext
|
||||
.IP
|
||||
A felhasználó saját kiterjesztései, nézet beállítások és szerkesztési
|
||||
beállítások. Ezek felülbírálják a rendszerszintű fájl bejegyzéseit, ha
|
||||
|
@ -1304,7 +1304,7 @@ comando cd interno\&.
|
||||
.\"NODE " Extension File Edit"
|
||||
.SH " Modifica file estensioni"
|
||||
Questo comando invocherà l'editor sul file
|
||||
.IR ~/.local/share/mc/bindings .
|
||||
.IR ~/.local/share/mc/mc.ext .
|
||||
Il fomato di questo file è il seguente (il formato è cambiato dalla
|
||||
versione 3.0):
|
||||
.PP
|
||||
@ -2621,7 +2621,7 @@ la directory corrente con un comando
|
||||
.I cd
|
||||
verso un percorso simile al seguente:
|
||||
.PP
|
||||
.I /#ftp:[!][utente[:pass]@]macchina[:porta][dir\-remota]
|
||||
.I ftp://[!][utente[:pass]@]macchina[:porta][dir\-remota]
|
||||
.PP
|
||||
Gli elementi
|
||||
.IR utente ,
|
||||
@ -2647,11 +2647,11 @@ Per abilitare l'uso del proxy FTP, anteporre
|
||||
Esempi:
|
||||
.PP
|
||||
.nf
|
||||
/#ftp:ftp.nuclecu.unam.mx/linux/local
|
||||
/#ftp:tsx\-11.mit.edu/pub/linux/packages
|
||||
/#ftp:!dietro.il.firewall.edu/pub
|
||||
/#ftp:guest@host\-remoto.com:40/pub
|
||||
/#ftp:miguel:xxx@server/pub
|
||||
ftp://ftp.nuclecu.unam.mx/linux/local
|
||||
ftp://tsx\-11.mit.edu/pub/linux/packages
|
||||
ftp://!dietro.il.firewall.edu/pub
|
||||
ftp://guest@host\-remoto.com:40/pub
|
||||
ftp://miguel:xxx@server/pub
|
||||
.fi
|
||||
.PP
|
||||
Controllare la finestra di dialogo
|
||||
@ -2665,7 +2665,7 @@ Il file system tar fornisce un accesso in sola lettura ai file tar
|
||||
e tar compressi usando il comando chdir. Per cambiare la directory corrente
|
||||
al file tar usare la seguente sintassi:
|
||||
.PP
|
||||
.I /nomefile.tar#utar/[dir\-dentro\-tar]
|
||||
.I /nomefile.tar/utar://[dir\-dentro\-tar]
|
||||
.PP
|
||||
Il file mc.ext già fornisce un collegamento per il file tar; ciò
|
||||
significa che normalmente basta selezionare un file tar e premere invio
|
||||
@ -2678,8 +2678,8 @@ per i dettagli su come questo viene fatto.
|
||||
Esempi:
|
||||
.PP
|
||||
.nf
|
||||
mc\-3.0.tar.gz#utar/mc\-3.0/vfs
|
||||
/ftp/GCC/gcc\-2.7.0.tar#utar
|
||||
mc\-3.0.tar.gz/utar://mc\-3.0/vfs
|
||||
/ftp/GCC/gcc\-2.7.0.tar/utar://
|
||||
.fi
|
||||
.PP
|
||||
L'ultima riga, specifica il percorso completo dell'archivio tar.
|
||||
@ -2694,7 +2694,7 @@ Per collegarsi ad una macchina remota, basta solo fare cd
|
||||
in una speciale directory il cui nome ha il seguente formato:
|
||||
.PP
|
||||
.nf
|
||||
/#sh:[utente@]macchina[:opzioni]/[dir\-remota]
|
||||
sh://[utente@]macchina[:opzioni]/[dir\-remota]
|
||||
.fi
|
||||
Gli elementi
|
||||
.IR utente ,
|
||||
@ -2717,9 +2717,9 @@ a questo valore.
|
||||
Esempi:
|
||||
.PP
|
||||
.nf
|
||||
/#sh:solorsh.mx:r/linux/locale
|
||||
/#sh:joe@vuole.lacompressione.edu:C/privato
|
||||
/#sh:joe@noncompresso.ssh.edu/privato
|
||||
sh://solorsh.mx:r/linux/locale
|
||||
sh://joe@vuole.lacompressione.edu:C/privato
|
||||
sh://joe@noncompresso.ssh.edu/privato
|
||||
.fi
|
||||
.\"NODE " Undelete File System"
|
||||
.SH " Recupero file cancellati"
|
||||
@ -2732,14 +2732,14 @@ file cancellati su un fs ext2 e fornisce ed estrae i file selezionati
|
||||
in una partizione normale.
|
||||
.PP
|
||||
Per usare questo file system, è necessario entrare nella directory
|
||||
con il nome speciale formato dal prefisso "/#undel" e dal nome del
|
||||
con il nome speciale formato dal prefisso "undel://" e dal nome del
|
||||
file system dove il file risiede.
|
||||
.PP
|
||||
Per esempio, per recuperare file cancellati sulla seconda partizione
|
||||
del primo disco SCSI su Linux, si dovrà usare il seguente percorso:
|
||||
.PP
|
||||
.nf
|
||||
/#undel:sda2
|
||||
undel://sda2
|
||||
.fi
|
||||
.PP
|
||||
Il recupero può metterci un po' di tempo per caricare le informazioni
|
||||
@ -2754,7 +2754,7 @@ Per usarlo, si può provare il comando dal pannello
|
||||
direttamente cambiare directory corrente usando il comando cd verso
|
||||
un percorso simile a questo:
|
||||
.PP
|
||||
.I /#smb:[utente@]macchina[/servizio][/dir\-remota]
|
||||
.I smb://[utente@]macchina[/servizio][/dir\-remota]
|
||||
.PP
|
||||
L'elemento
|
||||
.I utente, servizio
|
||||
@ -2770,9 +2770,124 @@ possono essere specificati nella finestra di dialogo di ingresso.
|
||||
Esempi:
|
||||
.PP
|
||||
.nf
|
||||
/#smb:macchina/Condivisione
|
||||
/#smb:altra_macchina
|
||||
/#smb:guest@macchina/Public/Irlex
|
||||
smb://macchina/Condivisione
|
||||
smb://altra_macchina
|
||||
smb://guest@macchina/Public/Irlex
|
||||
.fi
|
||||
.\"NODE " EXTernal File System"
|
||||
.SH " EXTernal File System"
|
||||
.B extfs
|
||||
allows to integrate numerous features and file types into GNU Midnight
|
||||
Commander in an easy way, by writing scripts.
|
||||
.PP
|
||||
Extfs filesystems can be divided into two categories:
|
||||
.PP
|
||||
1. Stand\-alone filesystems, which are not associated with any existing
|
||||
file. They represent certain system\-wide data as a directory tree.
|
||||
You can invoke them by typing
|
||||
.RI ' "cd fsname://" '
|
||||
where fsname is an extfs short name (see below). Examples of such
|
||||
filesystems include audio (list audio tracks on the CD) or apt (list of
|
||||
all Debian packages in the system).
|
||||
.PP
|
||||
For example, to list CD\-Audio tracks on your CD\-ROM drive, type
|
||||
.PP
|
||||
.nf
|
||||
cd audio://
|
||||
.fi
|
||||
.PP
|
||||
2. 'Archive' filesystems (like rpm, patchfs and more), which represent
|
||||
contents of a file as a directory tree. It can consist of 'real' files
|
||||
compressed in an archive (urar, rpm) or virtual files, like messages
|
||||
in a mailbox (mailfs) or parts of a patch (patchfs). To access such
|
||||
filesystems
|
||||
.RI ' fsname:// '
|
||||
should be appended to the archive name. Note that the archive itself
|
||||
can be on another vfs.
|
||||
.PP
|
||||
For example, to list contents of a zip archive documents.zip type
|
||||
.PP
|
||||
.nf
|
||||
cd documents.zip/uzip://
|
||||
.fi
|
||||
.PP
|
||||
In many aspects, you could treat extfs like any other directory. For
|
||||
instance, you can add it to the hotlist or change to it from directory
|
||||
history. An important limitation is that you cannot invoke shell
|
||||
commands inside extfs, just like any other non\-local VFS.
|
||||
.PP
|
||||
Common extfs scripts included with Midnight Commander are:
|
||||
.TP
|
||||
.B a
|
||||
access 'A:' DOS/Windows diskette
|
||||
.RI ( "cd a://" ).
|
||||
.TP
|
||||
.B apt
|
||||
front end to Debian's APT package management system
|
||||
.RI ( "cd apt://" ).
|
||||
.TP
|
||||
.B audio
|
||||
audio CD ripping and playing
|
||||
.RI ( "cd audio://"
|
||||
or
|
||||
.IR "cd device/audio://" ).
|
||||
.TP
|
||||
.B bpp
|
||||
package of Bad Penguin GNU/Linux distribution
|
||||
.RI ( "cd file.bpp/bpp://" ).
|
||||
.TP
|
||||
.B deb
|
||||
package of Debian GNU/Linux distribution
|
||||
.RI ( "cd file.deb/deb://" ).
|
||||
.TP
|
||||
.B dpkg
|
||||
Debian GNU/Linux installed packages
|
||||
.RI ( "cd deb://" ).
|
||||
.TP
|
||||
.B hp48
|
||||
view and copy files to/from a HP48 calculator
|
||||
.RI ( "cd hp48://" ).
|
||||
.TP
|
||||
.B lslR
|
||||
browsing of lslR listings as found on many FTPs
|
||||
.RI ( "cd filename/lslR://" ).
|
||||
.TP
|
||||
.B mailfs
|
||||
mbox\-style mailbox files support
|
||||
.RI ( "cd mailbox/mailfs://" ).
|
||||
.TP
|
||||
.B patchfs
|
||||
extfs to handle unified and context diffs
|
||||
.RI ( "cd filename/patchfs://" ).
|
||||
.TP
|
||||
.B rpm
|
||||
RPM package
|
||||
.RI ( "cd filename/rpm://" ).
|
||||
.TP
|
||||
.B rpms
|
||||
RPM database management
|
||||
.RI ( "cd rpms://" ).
|
||||
.TP
|
||||
.B ulha, urar, uzip, uzoo, uar, uha
|
||||
archivers
|
||||
.RI ( "cd archive/xxxx://"
|
||||
where xxxx is one of:
|
||||
.IR ulha ,
|
||||
.IR urar ,
|
||||
.IR uzip ,
|
||||
.IR uzoo ,
|
||||
.IR uar ,
|
||||
.IR uha ).
|
||||
.PP
|
||||
You could bind file type/extension to specified extfs as described in the
|
||||
.\"LINK2"
|
||||
Extension File Edit
|
||||
.\"Extension File Edit"
|
||||
section. Here is an example entry for Debian packages:
|
||||
.PP
|
||||
.nf
|
||||
regex/\.deb$
|
||||
Open=%cd %p/deb://
|
||||
.fi
|
||||
.\"NODE "Colors"
|
||||
.SH "Colori"
|
||||
@ -3058,7 +3173,7 @@ Il file di aiuto per il programma.
|
||||
.IP
|
||||
Il file delle estensioni di sistema predefinito.
|
||||
.PP
|
||||
.I ~/.local/share/mc/bindings
|
||||
.I ~/.local/share/mc/mc.ext
|
||||
.IP
|
||||
Le estensioni dell'utente, la configurazione del visualizzatore e
|
||||
dell'editor di file. Se presenti, questi file si sovrappongono ai file di
|
||||
|
@ -1473,7 +1473,7 @@ description.
|
||||
.\"NODE " Extension File Edit"
|
||||
.SH " Extension File Edit"
|
||||
This will invoke your editor on the file
|
||||
.IR ~/.local/share/mc/bindings .
|
||||
.IR ~/.local/share/mc/mc.ext .
|
||||
The format of this file following:
|
||||
.PP
|
||||
All lines starting with # or empty lines are thrown away.
|
||||
@ -3110,7 +3110,7 @@ item in the menu or directly change your current directory using the
|
||||
.I cd
|
||||
command to a path name that looks like this:
|
||||
.PP
|
||||
.I /#ftp:[!][user[:pass]@]machine[:port][remote\-dir]
|
||||
.I ftp://[!][user[:pass]@]machine[:port][remote\-dir]
|
||||
.PP
|
||||
The
|
||||
.IR user ,
|
||||
@ -3135,11 +3135,11 @@ To enable using FTP proxy, prepend
|
||||
Examples:
|
||||
.PP
|
||||
.nf
|
||||
/#ftp:ftp.nuclecu.unam.mx/linux/local
|
||||
/#ftp:tsx\-11.mit.edu/pub/linux/packages
|
||||
/#ftp:!behind.firewall.edu/pub
|
||||
/#ftp:guest@remote\-host.com:40/pub
|
||||
/#ftp:miguel:xxx@server/pub
|
||||
ftp://ftp.nuclecu.unam.mx/linux/local
|
||||
ftp://tsx\-11.mit.edu/pub/linux/packages
|
||||
ftp://!behind.firewall.edu/pub
|
||||
ftp://guest@remote\-host.com:40/pub
|
||||
ftp://miguel:xxx@server/pub
|
||||
.fi
|
||||
.PP
|
||||
Please check the
|
||||
@ -3154,7 +3154,7 @@ files and compressed tar files by using the chdir command. To change
|
||||
your directory to a tar file, you change your current directory to the
|
||||
tar file by using the following syntax:
|
||||
.PP
|
||||
.I /filename.tar#utar/[dir\-inside\-tar]
|
||||
.I /filename.tar/utar://[dir\-inside\-tar]
|
||||
.PP
|
||||
The mc.ext file already provides a shortcut for tar files, this means
|
||||
that usually you just point to a tar file and press return to enter
|
||||
@ -3167,8 +3167,8 @@ section for details on how this is done.
|
||||
Examples:
|
||||
.PP
|
||||
.nf
|
||||
mc\-3.0.tar.gz#utar/mc\-3.0/vfs
|
||||
/ftp/GCC/gcc\-2.7.0.tar#utar
|
||||
mc\-3.0.tar.gz/utar://mc\-3.0/vfs
|
||||
/ftp/GCC/gcc\-2.7.0.tar/utar://
|
||||
.fi
|
||||
.PP
|
||||
The latter specifies the full path of the tar archive.
|
||||
@ -3183,7 +3183,7 @@ To connect to a remote machine, you just need to chdir
|
||||
into a special directory which name is in the following
|
||||
format:
|
||||
.PP
|
||||
.I /#sh:[user@]machine[:options]/[remote\-dir]
|
||||
.I sh://[user@]machine[:options]/[remote\-dir]
|
||||
.PP
|
||||
The
|
||||
.I user,
|
||||
@ -3211,10 +3211,10 @@ set to this one.
|
||||
Examples:
|
||||
.PP
|
||||
.nf
|
||||
/#sh:onlyrsh.mx:r/linux/local
|
||||
/#sh:joe@want.compression.edu:C/private
|
||||
/#sh:joe@noncompressed.ssh.edu/private
|
||||
/#sh:joe@somehost.ssh.edu:2222/private
|
||||
sh://onlyrsh.mx:r/linux/local
|
||||
sh://joe@want.compression.edu:C/private
|
||||
sh://joe@noncompressed.ssh.edu/private
|
||||
sh://joe@somehost.ssh.edu:2222/private
|
||||
.fi
|
||||
.\"NODE " Undelete File System"
|
||||
.SH " Undelete File System"
|
||||
@ -3226,14 +3226,14 @@ retrieve all of the deleted files names on an ext2fs and provides and
|
||||
to extract the selected files into a regular partition.
|
||||
.PP
|
||||
To use this file system, you have to chdir into the special file name
|
||||
formed by the "/#undel" prefix and the file name where the actual
|
||||
formed by the "undel://" prefix and the file name where the actual
|
||||
file system resides.
|
||||
.PP
|
||||
For example, to recover deleted files on the second partition of the
|
||||
first SCSI disk on Linux, you would use the following path name:
|
||||
.PP
|
||||
.nf
|
||||
/#undel:sda2
|
||||
undel://sda2
|
||||
.fi
|
||||
.PP
|
||||
It may take a while for the undelfs to load the required information
|
||||
@ -3247,7 +3247,7 @@ To actually use it, you may try to use the panel command "SMB link..."
|
||||
(accessible from the menubar) or you may directly change your current
|
||||
directory to it using the cd command to a path name that looks like this:
|
||||
.PP
|
||||
.I /#smb:[user@]machine[/service][/remote\-dir]
|
||||
.I smb://[user@]machine[/service][/remote\-dir]
|
||||
.PP
|
||||
The
|
||||
.IR user ,
|
||||
@ -3265,9 +3265,9 @@ can be specified in an input dialog.
|
||||
Examples:
|
||||
.PP
|
||||
.nf
|
||||
/#smb:machine/Share
|
||||
/#smb:other_machine
|
||||
/#smb:guest@machine/Public/Irlex
|
||||
smb://machine/Share
|
||||
smb://other_machine
|
||||
smb://guest@machine/Public/Irlex
|
||||
.fi
|
||||
.\"NODE " EXTernal File System"
|
||||
.SH " EXTernal File System"
|
||||
@ -3280,7 +3280,7 @@ Extfs filesystems can be divided into two categories:
|
||||
1. Stand\-alone filesystems, which are not associated with any existing
|
||||
file. They represent certain system\-wide data as a directory tree.
|
||||
You can invoke them by typing
|
||||
.RI ' "cd #fsname" '
|
||||
.RI ' "cd fsname://" '
|
||||
where fsname is an extfs short name (see below). Examples of such
|
||||
filesystems include audio (list audio tracks on the CD) or apt (list of
|
||||
all Debian packages in the system).
|
||||
@ -3288,7 +3288,7 @@ all Debian packages in the system).
|
||||
For example, to list CD\-Audio tracks on your CD\-ROM drive, type
|
||||
.PP
|
||||
.nf
|
||||
cd #audio
|
||||
cd audio://
|
||||
.fi
|
||||
.PP
|
||||
2. 'Archive' filesystems (like rpm, patchfs and more), which represent
|
||||
@ -3296,14 +3296,14 @@ contents of a file as a directory tree. It can consist of 'real' files
|
||||
compressed in an archive (urar, rpm) or virtual files, like messages
|
||||
in a mailbox (mailfs) or parts of a patch (patchfs). To access such
|
||||
filesystems
|
||||
.RI ' #fsname '
|
||||
.RI ' fsname:// '
|
||||
should be appended to the archive name. Note that the archive itself
|
||||
can be on another vfs.
|
||||
.PP
|
||||
For example, to list contents of a zip archive documents.zip type
|
||||
.PP
|
||||
.nf
|
||||
cd documents.zip#uzip
|
||||
cd documents.zip/uzip://
|
||||
.fi
|
||||
.PP
|
||||
In many aspects, you could treat extfs like any other directory. For
|
||||
@ -3315,57 +3315,57 @@ Common extfs scripts included with Midnight Commander are:
|
||||
.TP
|
||||
.B a
|
||||
access 'A:' DOS/Windows diskette
|
||||
.RI ( "cd #a" ).
|
||||
.RI ( "cd a://" ).
|
||||
.TP
|
||||
.B apt
|
||||
front end to Debian's APT package management system
|
||||
.RI ( "cd #apt" ).
|
||||
.RI ( "cd apt://" ).
|
||||
.TP
|
||||
.B audio
|
||||
audio CD ripping and playing
|
||||
.RI ( "cd #audio"
|
||||
.RI ( "cd audio://"
|
||||
or
|
||||
.IR "cd device#audio" ).
|
||||
.IR "cd device/audio://" ).
|
||||
.TP
|
||||
.B bpp
|
||||
package of Bad Penguin GNU/Linux distribution
|
||||
.RI ( "cd file.bpp#bpp" ).
|
||||
.RI ( "cd file.bpp/bpp://" ).
|
||||
.TP
|
||||
.B deb
|
||||
package of Debian GNU/Linux distribution
|
||||
.RI ( "cd file.deb#deb" ).
|
||||
.RI ( "cd file.deb/deb://" ).
|
||||
.TP
|
||||
.B dpkg
|
||||
Debian GNU/Linux installed packages
|
||||
.RI ( "cd #deb" ).
|
||||
.RI ( "cd deb://" ).
|
||||
.TP
|
||||
.B hp48
|
||||
view and copy files to/from a HP48 calculator
|
||||
.RI ( "cd #hp48" ).
|
||||
.RI ( "cd hp48://" ).
|
||||
.TP
|
||||
.B lslR
|
||||
browsing of lslR listings as found on many FTPs
|
||||
.RI ( "cd filename#lslR" ).
|
||||
.RI ( "cd filename/lslR://" ).
|
||||
.TP
|
||||
.B mailfs
|
||||
mbox\-style mailbox files support
|
||||
.RI ( "cd mailbox#mailfs" ).
|
||||
.RI ( "cd mailbox/mailfs://" ).
|
||||
.TP
|
||||
.B patchfs
|
||||
extfs to handle unified and context diffs
|
||||
.RI ( "cd filename#patchfs" ).
|
||||
.RI ( "cd filename/patchfs://" ).
|
||||
.TP
|
||||
.B rpm
|
||||
RPM package
|
||||
.RI ( "cd filename#rpm" ).
|
||||
.RI ( "cd filename/rpm://" ).
|
||||
.TP
|
||||
.B rpms
|
||||
RPM database management
|
||||
.RI ( "cd #rpms" ).
|
||||
.RI ( "cd rpms://" ).
|
||||
.TP
|
||||
.B ulha, urar, uzip, uzoo, uar, uha
|
||||
archivers
|
||||
.RI ( "cd archive#xxxx"
|
||||
.RI ( "cd archive/xxxx://"
|
||||
where xxxx is one of:
|
||||
.IR ulha ,
|
||||
.IR urar ,
|
||||
@ -3382,7 +3382,7 @@ section. Here is an example entry for Debian packages:
|
||||
.PP
|
||||
.nf
|
||||
regex/\.deb$
|
||||
Open=%cd %p#deb
|
||||
Open=%cd %p/deb://
|
||||
.fi
|
||||
.\"NODE "Colors"
|
||||
.SH "Colors"
|
||||
@ -4104,7 +4104,7 @@ The help file for the program.
|
||||
.IP
|
||||
The default system\-wide extensions file.
|
||||
.PP
|
||||
.I ~/.local/share/mc/bindings
|
||||
.I ~/.local/share/mc/mc.ext
|
||||
.IP
|
||||
User's own extension, view configuration and edit configuration
|
||||
file. They override the contents of the system wide files if present.
|
||||
|
@ -1085,7 +1085,7 @@ przemieszczanie.
|
||||
.PP
|
||||
.\"NODE " Extension File Edit"
|
||||
.SH " Edycja rozszerzeń pliów (Extension File Edit)"
|
||||
Ta komenda wywoła twój edytor na plik ~/.local/share/mc/bindings. Format tego pliku jest
|
||||
Ta komenda wywoła twój edytor na plik ~/.local/share/mc/mc.ext. Format tego pliku jest
|
||||
następujący (zmienił się on począwszy od wersji 3.0):
|
||||
.PP
|
||||
Wszystkie linie zaczynające się od #, lub puste, nie są brane pod uwagę.
|
||||
@ -2228,7 +2228,7 @@ normalnego użytku, możesz próbować używać panelowych komend FTP i dowiąza
|
||||
(dostępnych z linii menu) lub zmienić ścieżkę bezpośrednio za pomocą zwykłej
|
||||
komendy cd wyglądającej tak jak poniżej:
|
||||
.PP
|
||||
.I /#ftp:[!][użytkownik[:hasło]@]komputer[:port][zdalny katalog]
|
||||
.I ftp://[!][użytkownik[:hasło]@]komputer[:port][zdalny katalog]
|
||||
.PP
|
||||
Parametry
|
||||
.IR użytkownik ,
|
||||
@ -2249,11 +2249,11 @@ do tego dostępu).
|
||||
Przykłady:
|
||||
.PP
|
||||
.nf
|
||||
/#ftp:ftp.nuclecu.unam.mx/linux/local
|
||||
/#ftp:tsx\-11.mit.edu/pub/linux/packages
|
||||
/#ftp:!behind.firewall.edu/pub
|
||||
/#ftp:guest@remote\-host.com:40/pub
|
||||
/#ftp:miguel:xxx@server/pub
|
||||
ftp://ftp.nuclecu.unam.mx/linux/local
|
||||
ftp://tsx\-11.mit.edu/pub/linux/packages
|
||||
ftp://!behind.firewall.edu/pub
|
||||
ftp://guest@remote\-host.com:40/pub
|
||||
ftp://miguel:xxx@server/pub
|
||||
.fi
|
||||
.PP
|
||||
Aby połączyć się z serwerem znajdującym się za firewallem, będziesz musiał
|
||||
@ -2301,8 +2301,8 @@ zostało to pomyślane.
|
||||
Przykłady
|
||||
.PP
|
||||
.nf
|
||||
mc\-3.0.tar.gz#utar/mc\-3.0/vfs
|
||||
/ftp/GCC/gcc\-2.7.0.tar#utar
|
||||
mc\-3.0.tar.gz/utar://mc\-3.0/vfs
|
||||
/ftp/GCC/gcc\-2.7.0.tar/utar://
|
||||
.fi
|
||||
.PP
|
||||
Późniejszy podaje pełną ścieżkę archiwum tar.
|
||||
@ -2318,7 +2318,7 @@ Aby połączyć się z obcą maszyną, musisz tylko zmienić katalog do
|
||||
specjalnego katalogu, którego nazwa jest w następującym formacie:
|
||||
.PP
|
||||
.nf
|
||||
/#sh:[użytkownik@]komputer[:opcje];/[zdalny\-katalog];</em>
|
||||
sh://[użytkownik@]komputer[:opcje];/[zdalny\-katalog];</em>
|
||||
.fi
|
||||
Elementy
|
||||
.IR użytkownik ,
|
||||
@ -2340,9 +2340,9 @@ na niego.
|
||||
Przykłady:
|
||||
.PP
|
||||
.nf
|
||||
/#sh:onlyrsh.mx:r/linux/local
|
||||
/#sh:joe@want.compression.edu:C/private
|
||||
/#sh:joe@noncompressed.ssh.edu/private
|
||||
sh://onlyrsh.mx:r/linux/local
|
||||
sh://joe@want.compression.edu:C/private
|
||||
sh://joe@noncompressed.ssh.edu/private
|
||||
.fi
|
||||
.\"NODE " Undelete File System"
|
||||
.SH " Odzyskiwanie plików"
|
||||
@ -2353,19 +2353,165 @@ system plików jest tylko nakładką na bibliotekę ext2fs: odzyskiwanie nazw
|
||||
wszystkich skasowanych plików i próba uczynienia z nich normalnej partycji.
|
||||
.PP
|
||||
Żeby używać tych systemów plików, będziesz musiał przejść od specjalnego
|
||||
pliku, którego nazwa składa się z przedrostka "undel:" i nazwy pliku,
|
||||
pliku, którego nazwa składa się z przedrostka "undel://" i nazwy pliku,
|
||||
w której ów plik rezyduje.
|
||||
.PP
|
||||
Na przykład, aby odzyskać skasowane pliki z drugiej partycji pierwszego
|
||||
dysku scsi Linux, będziesz musiał użyć następującej ścieżki:
|
||||
.PP
|
||||
.nf
|
||||
undel:/dev/sda2
|
||||
undel:///dev/sda2
|
||||
.fi
|
||||
.PP
|
||||
Może to chwilkę potrwać zanim pliki zostaną pokazane i będziesz mógł je
|
||||
normalnie oglądać.
|
||||
.PP
|
||||
.\"NODE " SMB File System"
|
||||
.SH " SMB File System"
|
||||
The smbfs allows you to manipulate files on remote machines with SMB
|
||||
(or CIFS) protocol. These include Windows for Workgroups,
|
||||
Windows 9x/ME/XP, Windows NT, Windows 2000 and Samba.
|
||||
To actually use it, you may try to use the panel command "SMB link..."
|
||||
(accessible from the menubar) or you may directly change your current
|
||||
directory to it using the cd command to a path name that looks like this:
|
||||
.PP
|
||||
.I smb://[user@]machine[/service][/remote\-dir]
|
||||
.PP
|
||||
The
|
||||
.IR user ,
|
||||
.I service
|
||||
and
|
||||
.I remote\-dir
|
||||
elements are optional.
|
||||
The
|
||||
.IR user ,
|
||||
.I domain
|
||||
and
|
||||
.I password
|
||||
can be specified in an input dialog.
|
||||
.PP
|
||||
Examples:
|
||||
.PP
|
||||
.nf
|
||||
smb://machine/Share
|
||||
smb://other_machine
|
||||
smb://guest@machine/Public/Irlex
|
||||
.fi
|
||||
.\"NODE " EXTernal File System"
|
||||
.SH " EXTernal File System"
|
||||
.B extfs
|
||||
allows to integrate numerous features and file types into GNU Midnight
|
||||
Commander in an easy way, by writing scripts.
|
||||
.PP
|
||||
Extfs filesystems can be divided into two categories:
|
||||
.PP
|
||||
1. Stand\-alone filesystems, which are not associated with any existing
|
||||
file. They represent certain system\-wide data as a directory tree.
|
||||
You can invoke them by typing
|
||||
.RI ' "cd fsname://" '
|
||||
where fsname is an extfs short name (see below). Examples of such
|
||||
filesystems include audio (list audio tracks on the CD) or apt (list of
|
||||
all Debian packages in the system).
|
||||
.PP
|
||||
For example, to list CD\-Audio tracks on your CD\-ROM drive, type
|
||||
.PP
|
||||
.nf
|
||||
cd audio://
|
||||
.fi
|
||||
.PP
|
||||
2. 'Archive' filesystems (like rpm, patchfs and more), which represent
|
||||
contents of a file as a directory tree. It can consist of 'real' files
|
||||
compressed in an archive (urar, rpm) or virtual files, like messages
|
||||
in a mailbox (mailfs) or parts of a patch (patchfs). To access such
|
||||
filesystems
|
||||
.RI ' fsname:// '
|
||||
should be appended to the archive name. Note that the archive itself
|
||||
can be on another vfs.
|
||||
.PP
|
||||
For example, to list contents of a zip archive documents.zip type
|
||||
.PP
|
||||
.nf
|
||||
cd documents.zip/uzip://
|
||||
.fi
|
||||
.PP
|
||||
In many aspects, you could treat extfs like any other directory. For
|
||||
instance, you can add it to the hotlist or change to it from directory
|
||||
history. An important limitation is that you cannot invoke shell
|
||||
commands inside extfs, just like any other non\-local VFS.
|
||||
.PP
|
||||
Common extfs scripts included with Midnight Commander are:
|
||||
.TP
|
||||
.B a
|
||||
access 'A:' DOS/Windows diskette
|
||||
.RI ( "cd a://" ).
|
||||
.TP
|
||||
.B apt
|
||||
front end to Debian's APT package management system
|
||||
.RI ( "cd apt://" ).
|
||||
.TP
|
||||
.B audio
|
||||
audio CD ripping and playing
|
||||
.RI ( "cd audio://"
|
||||
or
|
||||
.IR "cd device/audio://" ).
|
||||
.TP
|
||||
.B bpp
|
||||
package of Bad Penguin GNU/Linux distribution
|
||||
.RI ( "cd file.bpp/bpp://" ).
|
||||
.TP
|
||||
.B deb
|
||||
package of Debian GNU/Linux distribution
|
||||
.RI ( "cd file.deb/deb://" ).
|
||||
.TP
|
||||
.B dpkg
|
||||
Debian GNU/Linux installed packages
|
||||
.RI ( "cd deb://" ).
|
||||
.TP
|
||||
.B hp48
|
||||
view and copy files to/from a HP48 calculator
|
||||
.RI ( "cd hp48://" ).
|
||||
.TP
|
||||
.B lslR
|
||||
browsing of lslR listings as found on many FTPs
|
||||
.RI ( "cd filename/lslR://" ).
|
||||
.TP
|
||||
.B mailfs
|
||||
mbox\-style mailbox files support
|
||||
.RI ( "cd mailbox/mailfs://" ).
|
||||
.TP
|
||||
.B patchfs
|
||||
extfs to handle unified and context diffs
|
||||
.RI ( "cd filename/patchfs://" ).
|
||||
.TP
|
||||
.B rpm
|
||||
RPM package
|
||||
.RI ( "cd filename/rpm://" ).
|
||||
.TP
|
||||
.B rpms
|
||||
RPM database management
|
||||
.RI ( "cd rpms://" ).
|
||||
.TP
|
||||
.B ulha, urar, uzip, uzoo, uar, uha
|
||||
archivers
|
||||
.RI ( "cd archive/xxxx://"
|
||||
where xxxx is one of:
|
||||
.IR ulha ,
|
||||
.IR urar ,
|
||||
.IR uzip ,
|
||||
.IR uzoo ,
|
||||
.IR uar ,
|
||||
.IR uha ).
|
||||
.PP
|
||||
You could bind file type/extension to specified extfs as described in the
|
||||
.\"LINK2"
|
||||
Extension File Edit
|
||||
.\"Extension File Edit"
|
||||
section. Here is an example entry for Debian packages:
|
||||
.PP
|
||||
.nf
|
||||
regex/\.deb$
|
||||
Open=%cd %p/deb://
|
||||
.fi
|
||||
.SH Polskie znaki
|
||||
Midnight Commander bardzo dobrze radzi sobie z obsługą znaków
|
||||
nieamerykańskich (160+) w tym polskich. Ważne jest aby mieć ustawione
|
||||
@ -2733,7 +2879,7 @@ Plik pomocy dla programu.
|
||||
.IP
|
||||
Standardowy plik rozszerzeń plików.
|
||||
.PP
|
||||
~/.local/share/mc/bindings
|
||||
~/.local/share/mc/mc.ext
|
||||
.IP
|
||||
Własny plik użytkownika, konfiguruje podgląd i edycje plików. Ma wyższy
|
||||
priorytet niż plik systemowy.
|
||||
|
@ -1578,7 +1578,7 @@ CDPATH (смотрите описание
|
||||
.SH " Файл расширений"
|
||||
Этот пункт меню "Команда" служит для вызова редактора и редактирования
|
||||
файла
|
||||
.BR ~/.local/share/mc/bindings .
|
||||
.BR ~/.local/share/mc/mc.ext .
|
||||
Этот файл имеет следующий формат (формат был изменен в версии 3.0):
|
||||
.PP
|
||||
Все строки, начинающиеся с # или пустые строки игнорируются.
|
||||
@ -3432,7 +3432,7 @@ MC может быть собран с поддержкой файловой с
|
||||
сменить текущий каталог командой cd, задав путь к каталогу следующим
|
||||
образом:
|
||||
.PP
|
||||
.I /#ftp:[!][user[:pass]@]machine[:port][remote\-dir]
|
||||
.I ftp://[!][user[:pass]@]machine[:port][remote\-dir]
|
||||
.PP
|
||||
Элементы
|
||||
.IR user ", " port
|
||||
@ -3451,15 +3451,15 @@ MC может быть собран с поддержкой файловой с
|
||||
нельзя быть полностью уверенным в безопасности).
|
||||
.PP
|
||||
.nf
|
||||
/#ftp:ftp.nuclecu.unam.mx/linux/local
|
||||
/#ftp:tsx\-11.mit.edu/pub/linux/packages
|
||||
/#ftp:!behind.firewall.edu/pub
|
||||
/#ftp:guest@remote\-host.com:40/pub
|
||||
/#ftp:miguel:xxx@server/pub
|
||||
ftp://ftp.nuclecu.unam.mx/linux/local
|
||||
ftp://tsx\-11.mit.edu/pub/linux/packages
|
||||
ftp://!behind.firewall.edu/pub
|
||||
ftp://guest@remote\-host.com:40/pub
|
||||
ftp://miguel:xxx@server/pub
|
||||
.fi
|
||||
.PP
|
||||
Для того, чтобы соединиться с сервером, который расположен за firewall,
|
||||
нужно использовать префикс /#ftp:! (то есть добавить восклицательный
|
||||
нужно использовать префикс ftp://! (то есть добавить восклицательный
|
||||
знак перед именем сервера), чтобы указать Midnight Commander на
|
||||
необходимость использовать прокси для осуществления передач по ftp. Вы
|
||||
можете задать имя прокси в диалоговом окне
|
||||
@ -3515,7 +3515,7 @@ tar\-файлам, используя команду chdir. Для перехо
|
||||
представляющий список файлов tar\-файла, нужно использовать команду,
|
||||
имеющую следующий формат:
|
||||
.PP
|
||||
.I cd ./filename.tar#utar/[dir\-inside\-tar]
|
||||
.I cd ./filename.tar/utar://[dir\-inside\-tar]
|
||||
.PP
|
||||
Файл mc.ext по умолчанию содержит команды для просмотра
|
||||
tar\-файлов, то есть обычно для получения списка файлов tar\-архива
|
||||
@ -3528,8 +3528,8 @@ Enter. Чтобы понять, как это достигается, смотр
|
||||
Примеры:
|
||||
.PP
|
||||
.nf
|
||||
mc\-3.0.tar.gz#utar/mc\-3.0/vfs
|
||||
/ftp/GCC/gcc\-2.7.0.tar#utar
|
||||
mc\-3.0.tar.gz/utar://mc\-3.0/vfs
|
||||
/ftp/GCC/gcc\-2.7.0.tar/utar://
|
||||
.fi
|
||||
.PP
|
||||
В последнем примере указан полный путь к tar\-архиву.
|
||||
@ -3544,7 +3544,7 @@ bash\-совместимая оболочка shell.
|
||||
Для соединения с удаленным компьютером нужно выполнить команду
|
||||
перехода в каталог (chdir), имя которого задается в следующем формате:
|
||||
.PP
|
||||
.I /#sh:[user@]machine[:options]/[remote\-dir]
|
||||
.I sh://[user@]machine[:options]/[remote\-dir]
|
||||
.PP
|
||||
Элементы
|
||||
.IR user ", " options
|
||||
@ -3573,10 +3573,10 @@ bash\-совместимая оболочка shell.
|
||||
Примеры:
|
||||
.PP
|
||||
.nf
|
||||
/#sh:onlyrsh.mx:r/linux/local
|
||||
/#sh:joe@want.compression.edu:C/private
|
||||
/#sh:joe@noncompressed.ssh.edu/private
|
||||
/#sh:joe@somehost.ssh.edu:2222/private
|
||||
sh://onlyrsh.mx:r/linux/local
|
||||
sh://joe@want.compression.edu:C/private
|
||||
sh://joe@noncompressed.ssh.edu/private
|
||||
sh://joe@somehost.ssh.edu:2222/private
|
||||
.fi
|
||||
.\"NODE " Undelete File System"
|
||||
.SH " Файловая система UFS (Undelete File System)"
|
||||
@ -3589,7 +3589,7 @@ ext2fs, позволяющий восстановить имена всех уд
|
||||
.PP
|
||||
Для того, чтобы воспользоваться этой возможностью (этой файловой
|
||||
системой), нужно выполнить команду перехода (chdir) в специальный
|
||||
каталог, имя которого образуется из префикса "/#undel" и имени
|
||||
каталог, имя которого образуется из префикса "undel://" и имени
|
||||
специального файла устройства, на котором находится реальная файловая
|
||||
система.
|
||||
.PP
|
||||
@ -3597,7 +3597,7 @@ ext2fs, позволяющий восстановить имена всех уд
|
||||
SCSI\-диска, нужно использовать следующее имя:
|
||||
.PP
|
||||
.nf
|
||||
/#undel:sda2
|
||||
undel://sda2
|
||||
.fi
|
||||
.PP
|
||||
Загрузка списка удаленных файлов требует некоторого времени, так что
|
||||
@ -3614,7 +3614,7 @@ SCSI\-диска, нужно использовать следующее имя:
|
||||
панелей) или же непосредственно сменить текущий каталог командой cd,
|
||||
задав путь к каталогу следующим образом:
|
||||
.PP
|
||||
.I /#smb:[username@]machine[/service][/remote\-dir]
|
||||
.I smb://[username@]machine[/service][/remote\-dir]
|
||||
.PP
|
||||
Элементы
|
||||
.IR username ", " service
|
||||
@ -3629,9 +3629,123 @@ SCSI\-диска, нужно использовать следующее имя:
|
||||
Примеры:
|
||||
.PP
|
||||
.nf
|
||||
/#smb:machine/Share
|
||||
/#smb:other_machine
|
||||
/#smb:guest@machine/Public/Irlex
|
||||
smb://machine/Share
|
||||
smb://other_machine
|
||||
smb://guest@machine/Public/Irlex
|
||||
.fi
|
||||
.\"NODE " EXTernal File System"
|
||||
.SH " Внешняя файловая система (EXTernal File System)"
|
||||
.B extfs
|
||||
Внешняя файловая система позволяет очень просто интегрировать новые
|
||||
файловые контейнера и типы файлов простым написанием скриптов.
|
||||
.PP
|
||||
Файловая система Extfs подраздляется на две категории:
|
||||
.PP
|
||||
1. Автономные файловые системы, которые не ассоциированы ни с одним из
|
||||
типов файлов.они представляют некоторые системные данные как дерево каталогов
|
||||
Вы можете их вызвать набрав
|
||||
.RI ' "cd fsname://" '
|
||||
Где fsname \- это короткое имя extfs (см. ниже). Примеры этих ВФС включают
|
||||
audio (список всех звуковых дорожек на CD) или apt (список всех установленных
|
||||
в системе пакетов Debian).
|
||||
.PP
|
||||
Например, для получения списка звуковых дорожек на CD наберите:
|
||||
.PP
|
||||
.nf
|
||||
cd audio://
|
||||
.fi
|
||||
.PP
|
||||
2. "Архивные" файловые системы (такие как rpm, patchfs и прочие), представляют
|
||||
содержимое файла как дерево каталогов. Они могут состоять из 'реальных' файлов,
|
||||
находящихся в сжатом виде в архивах (urar, rpm) или из виртуальных файлов;
|
||||
например, сообщения в файле mailbox (mailfs) или части diff\-файла (patchfs).
|
||||
Для доступа к этим ВФС суффикс
|
||||
.RI 'fsname:// '
|
||||
должен быть добавлен к имени архива. Сам архив может находиться в другой ВФС.
|
||||
.PP
|
||||
Например, для получения списка содержимого архива documents.zip наберите:
|
||||
.PP
|
||||
.nf
|
||||
cd documents.zip/uzip://
|
||||
.fi
|
||||
.PP
|
||||
Можно манипулировать extfs\-путями как обычными каталогами и файлами. Например,
|
||||
можно добавить их в справочник каталогов или перейти на него из истории
|
||||
каталогов в панели. Основное ограничение: нельзя запускать shell\-команды
|
||||
внутри extfs, как и на любой другой нелокальной ВФС.
|
||||
.PP
|
||||
Список некоторых extfs\-скриптов, включённых в Midnight Commander:
|
||||
.TP
|
||||
.B a
|
||||
доступ к DOS/Windows диску 'A:'
|
||||
.RI ( "cd a://" ).
|
||||
.TP
|
||||
.B apt
|
||||
front end для системы управления пакетами APT (Debian)
|
||||
.RI ( "cd apt://" ).
|
||||
.TP
|
||||
.B audio
|
||||
Чтение и воспроизведение звуковых дорожек с CD
|
||||
.RI ( "cd audio://"
|
||||
or
|
||||
.IR "cd device/audio://" ).
|
||||
.TP
|
||||
.B bpp
|
||||
пакеты дистрибутива Bad Penguin GNU/Linux
|
||||
.RI ( "cd file.bpp/bpp://" ).
|
||||
.TP
|
||||
.B deb
|
||||
пакеты дистрибутива Debian GNU/Linux
|
||||
.RI ( "cd file.deb/deb://" ).
|
||||
.TP
|
||||
.B dpkg
|
||||
Управление установленными deb\-пакетами
|
||||
.RI ( "cd deb://" ).
|
||||
.TP
|
||||
.B hp48
|
||||
просмотр и копирование файлов с/на калькулятор HP48
|
||||
.RI ( "cd hp48://" ).
|
||||
.TP
|
||||
.B lslR
|
||||
просмотр lslR\-файлов, находящихся на многих FTP\-серверах
|
||||
.RI ( "cd filename/lslR://" ).
|
||||
.TP
|
||||
.B mailfs
|
||||
поддержка файлов формата mailbox
|
||||
.RI ( "cd mailbox/mailfs://" ).
|
||||
.TP
|
||||
.B patchfs
|
||||
поддержка diff\-файлов
|
||||
.RI ( "cd filename/patchfs://" ).
|
||||
.TP
|
||||
.B rpm
|
||||
поддержка файлов в формате RPM
|
||||
.RI ( "cd filename/rpm://" ).
|
||||
.TP
|
||||
.B rpms
|
||||
Управление установленными в системе RPM\-пакетами
|
||||
.RI ( "cd rpms://" ).
|
||||
.TP
|
||||
.B ulha, urar, uzip, uzoo, uar, uha
|
||||
архивы
|
||||
.RI ( "cd archive/xxxx://"
|
||||
где xxxx один из:
|
||||
.IR ulha ,
|
||||
.IR urar ,
|
||||
.IR uzip ,
|
||||
.IR uzoo ,
|
||||
.IR uar ,
|
||||
.IR uha ).
|
||||
.PP
|
||||
Вы можете назначить ВФС файлах по типу или расширению в секции
|
||||
.\"LINK2"
|
||||
Файл расширений
|
||||
.\"Extension File Edit"
|
||||
Например, для обработки пакетов Debian внесите:
|
||||
.PP
|
||||
.nf
|
||||
regex/\.deb$
|
||||
Open=%cd %p/deb://
|
||||
.fi
|
||||
.\"NODE "Colors"
|
||||
.SH "Цвета"
|
||||
@ -4391,7 +4505,7 @@ insert=\\e[Op
|
||||
.IP
|
||||
Используемый по умолчанию общесистемный файл расширений.
|
||||
.PP
|
||||
.I ~/.local/share/mc/bindings
|
||||
.I ~/.local/share/mc/mc.ext
|
||||
.IP
|
||||
Файл расширений пользователя. Если этот файл существует, он используется
|
||||
вместо общесистемного файла расширений.
|
||||
|
@ -1272,7 +1272,7 @@ awk '$9 ~! /incoming/ { print $9 }' < /var/log/xferlog
|
||||
.\"NODE " Extension File Edit"
|
||||
.SH " Уреди датотеку врста"
|
||||
Ово покреће ваш уређивач над датотеком
|
||||
.IR ~/.local/share/mc/bindings .
|
||||
.IR ~/.local/share/mc/mc.ext .
|
||||
Формат ове датотеке је следећи:
|
||||
.PP
|
||||
Сви редови који почињу на # или празни редови се одбацују.
|
||||
@ -2630,7 +2630,7 @@ if the
|
||||
.I cd (пром.дир.)
|
||||
на путању која изгледа овако:
|
||||
.PP
|
||||
.I /#ftp:[!][корисник[:лозинка]@]машина[:порт][удаљени\-дир]
|
||||
.I ftp://[!][корисник[:лозинка]@]машина[:порт][удаљени\-дир]
|
||||
.PP
|
||||
Елементи
|
||||
.IR корисник ,
|
||||
@ -2657,11 +2657,11 @@ if the
|
||||
Примери:
|
||||
.PP
|
||||
.nf
|
||||
/#ftp:ftp.nuclecu.unam.mx/linux/local
|
||||
/#ftp:tsx\-11.mit.edu/pub/linux/packages
|
||||
/#ftp:!iza.zast.zida.edu.cs/pub
|
||||
/#ftp:guest@udaljeni\-domacin.com:40/pub
|
||||
/#ftp:miguel:xxx@server/pub
|
||||
ftp://ftp.nuclecu.unam.mx/linux/local
|
||||
ftp://tsx\-11.mit.edu/pub/linux/packages
|
||||
ftp://!iza.zast.zida.edu.cs/pub
|
||||
ftp://guest@udaljeni\-domacin.com:40/pub
|
||||
ftp://miguel:xxx@server/pub
|
||||
.fi
|
||||
.PP
|
||||
Молим да ради избора ftpfs\-а погледате дијалог
|
||||
@ -2675,7 +2675,7 @@ if the
|
||||
директоријума). Да бисте прешли у датотеку врсте `tar', можете да
|
||||
користите наредбу промене текућег директоријума уз следећу синтаксу:
|
||||
.PP
|
||||
.I /datoteka.tar#utar/[дир\-унутар\-дат]
|
||||
.I /datoteka.tar/utar://[дир\-унутар\-дат]
|
||||
.PP
|
||||
Датотека `mc.ext' већ садржи пречицу за датотеке врсте `tar', што
|
||||
значи да можете само показати на датотеку врсте `tar' и притиснути
|
||||
@ -2688,8 +2688,8 @@ if the
|
||||
Примери:
|
||||
.PP
|
||||
.nf
|
||||
mc\-3.0.tar.gz#utar/mc\-3.0/vfs
|
||||
/ftp/GCC/gcc\-2.7.0.tar#utar
|
||||
mc\-3.0.tar.gz/utar://mc\-3.0/vfs
|
||||
/ftp/GCC/gcc\-2.7.0.tar/utar://
|
||||
.fi
|
||||
.PP
|
||||
Последњи ред задаје пуну путању архиве врсте `tar'.
|
||||
@ -2704,7 +2704,7 @@ if the
|
||||
текући директоријум на посебан директоријум чији назив је у следећем
|
||||
формату:
|
||||
.PP
|
||||
.I /#sh:[корисник@]машина[:избори]/[удаљени\-дир]
|
||||
.I sh://[корисник@]машина[:избори]/[удаљени\-дир]
|
||||
.PP
|
||||
Елементи
|
||||
.IR корисник ,
|
||||
@ -2727,9 +2727,9 @@ if the
|
||||
Примери:
|
||||
.PP
|
||||
.nf
|
||||
/#sh:onlyrsh.mx:r/linux/local
|
||||
/#sh:joe@hocu.komprimovanje.edu:C/private
|
||||
/#sh:joe@nekomprimovan.ssh.edu/private
|
||||
sh://onlyrsh.mx:r/linux/local
|
||||
sh://joe@hocu.komprimovanje.edu:C/private
|
||||
sh://joe@nekomprimovan.ssh.edu/private
|
||||
.fi
|
||||
.\"NODE " Undelete File System"
|
||||
.SH " Систем датотека за одбрисање"
|
||||
@ -2743,13 +2743,13 @@ if the
|
||||
.PP
|
||||
Да бисте користили овај систем датотека, морате да поставите текући
|
||||
директоријум на посебни назив датотеке који се састоји од префикса
|
||||
`/#undel' и назива датотеке у којој се налази систем датотека.
|
||||
`undel://' и назива датотеке у којој се налази систем датотека.
|
||||
.PP
|
||||
На пример, да бисте опоравили обрисане датотеке на другој партицији
|
||||
првог скази диска под ГНУ\-ом, можете да користите следећу путању:
|
||||
.PP
|
||||
.nf
|
||||
/#undel:sda2
|
||||
undel://sda2
|
||||
.fi
|
||||
.PP
|
||||
Учитавање тражених података пре него што можете да почнете разгледање
|
||||
@ -2765,7 +2765,7 @@ SMB\-ом...' (која је доступна преко реда менија),
|
||||
текућег директоријума) да бисте текући директоријум поставили на
|
||||
путању сличну овој:
|
||||
.PP
|
||||
.I /#smb:[корисник@]машина[/сервис][/удаљени\-дир]
|
||||
.I smb://[корисник@]машина[/сервис][/удаљени\-дир]
|
||||
.PP
|
||||
Елементи
|
||||
.IR корисник ,
|
||||
@ -2782,9 +2782,9 @@ SMB\-ом...' (која је доступна преко реда менија),
|
||||
Примери:
|
||||
.PP
|
||||
.nf
|
||||
/#smb:masina/Deljeno
|
||||
/#smb:druga_masina
|
||||
/#smb:guest@masina/Public/Irlex
|
||||
smb://masina/Deljeno
|
||||
smb://druga_masina
|
||||
smb://guest@masina/Public/Irlex
|
||||
.fi
|
||||
.\"NODE " EXTernal File System"
|
||||
.SH " Спољашњи системи датотека (EXTFS)"
|
||||
@ -2797,7 +2797,7 @@ SMB\-ом...' (која је доступна преко реда менија),
|
||||
1. Самостални системи датотека, који нису повезани ни са једном
|
||||
стварном датотеком. Они представљају извесне податке за цео систем у
|
||||
виду стабла директоријума. Можете их позвати куцајући
|
||||
.RI ' `cd #називсд' '
|
||||
.RI ' `cd називсд://' '
|
||||
где је `називсд' кратки назив система `extfs'\-а (погледајте доле).
|
||||
Примери оваквих система датотека су `audio' (наводи звучне траке на
|
||||
CD\-овима) или `apt' (списак свих Дебијанових пакета на систему).
|
||||
@ -2806,7 +2806,7 @@ CD\-овима) или `apt' (списак свих Дебијанових па
|
||||
уређаја за CD\-ROM\-ове, можете да откуцате
|
||||
.PP
|
||||
.nf
|
||||
cd #audio
|
||||
cd audio://
|
||||
.fi
|
||||
.PP
|
||||
2. `Архивни' системи датотека (као што су `rpm', `patchfs' и други),
|
||||
@ -2816,7 +2816,7 @@ CD\-овима) или `apt' (списак свих Дебијанових па
|
||||
сандучићима (`mailfs') или делови закрпе (`patchfs'). Да бисте
|
||||
приступили таквим системима датотека, требало би да на назив архиве
|
||||
надовежете
|
||||
.RI ` #називсд. '
|
||||
.RI ` називсд://. '
|
||||
Приметите да сама архива може да буде у другом виртуалном систему
|
||||
датотека.
|
||||
.PP
|
||||
@ -2824,7 +2824,7 @@ CD\-овима) или `apt' (списак свих Дебијанових па
|
||||
`dokumenti.zip', откуцајте
|
||||
.PP
|
||||
.nf
|
||||
cd dokumenti.zip#uzip
|
||||
cd dokumenti.zip/uzip://
|
||||
.fi
|
||||
.PP
|
||||
На више начина, можете да сматрате да су спољашњи системи датотека
|
||||
@ -2838,58 +2838,58 @@ CD\-овима) или `apt' (списак свих Дебијанових па
|
||||
.TP
|
||||
.B a
|
||||
приступа дискети ДОС\-а/Виндовса `A:'
|
||||
.RI ( "`cd #a'" ).
|
||||
.RI ( "`cd a://'" ).
|
||||
.TP
|
||||
.B apt
|
||||
љуска за Дебијанов систем управљања пакетима `APT'
|
||||
.RI ( "`cd #apt'" ).
|
||||
.RI ( "`cd apt://'" ).
|
||||
.TP
|
||||
.B audio
|
||||
скидање и пуштање звучних CD\-ова
|
||||
.RI ( "`cd #audio'"
|
||||
.RI ( "`cd audio://'"
|
||||
или
|
||||
.IR "`cd device#audio'" ).
|
||||
.IR "`cd device/audio://'" ).
|
||||
.TP
|
||||
.B bpp
|
||||
пакет дистрибуције ГНУ/Линукса Лош Пингвин (Bad Penguin)
|
||||
.IR ( "`cd file.bpp#bpp'" ).
|
||||
.IR ( "`cd file.bpp/bpp://'" ).
|
||||
.TP
|
||||
.B deb
|
||||
пакет дистрибуције ГНУ/Линукса Дебијан
|
||||
.RI ( "`cd file.deb#deb'" ).
|
||||
.RI ( "`cd file.deb/deb://'" ).
|
||||
.TP
|
||||
.B dpkg
|
||||
инсталирани пакети Дебијановог ГНУ/Линукса
|
||||
.RI ( "`cd #deb'" ).
|
||||
.RI ( "`cd deb://'" ).
|
||||
.TP
|
||||
.B hp48
|
||||
преглед и копирање датотека на/са калкулатора ХП48
|
||||
.RI ( "`cd #hp48'" ).
|
||||
.RI ( "`cd hp48://'" ).
|
||||
.TP
|
||||
.B lslR
|
||||
разгледање спискова `lslR' који се могу наћи на многим серверима FTP\-а
|
||||
.RI ( "`cd filename#lslR'" ).
|
||||
.RI ( "`cd filename/lslR://'" ).
|
||||
.TP
|
||||
.B mailfs
|
||||
подршка за сандучиће електронске поште врсте `mbox'
|
||||
.RI ( "`cd mailbox#mailfs'" ).
|
||||
.RI ( "`cd mailbox/mailfs://'" ).
|
||||
.TP
|
||||
.B patchfs
|
||||
спољашњи систем датотека за рад са унификованим и контекстним
|
||||
датотекама врсте `diff'
|
||||
.RI ( "`cd filename#patchfs'" ).
|
||||
.RI ( "`cd filename/patchfs://'" ).
|
||||
.TP
|
||||
.B rpm
|
||||
пакет врсте `RPM'
|
||||
.RI ( "`cd filename#rpm'" ).
|
||||
.RI ( "`cd filename/rpm://'" ).
|
||||
.TP
|
||||
.B rpms
|
||||
управљање базом пакета врсте `RPM'
|
||||
.RI ( "`cd #rpms'" ).
|
||||
.RI ( "`cd rpms://'" ).
|
||||
.TP
|
||||
.B ulha, urar, uzip, uzoo, uar, uha
|
||||
архивари
|
||||
.RI ( "`cd архива#xxxx'"
|
||||
.RI ( "`cd архива/xxxx://'"
|
||||
где xxxx може да буде:
|
||||
.IR ulha ,
|
||||
.IR urar ,
|
||||
@ -2907,7 +2907,7 @@ CD\-овима) или `apt' (списак свих Дебијанових па
|
||||
.PP
|
||||
.nf
|
||||
regex/\.deb$
|
||||
Отвори=%cd %p#deb
|
||||
Отвори=%cd %p/deb://
|
||||
.fi
|
||||
.\"NODE "Colors"
|
||||
.SH "Боје"
|
||||
@ -3186,7 +3186,7 @@ MC_DATADIR. Ако ова променљива није постављена, б
|
||||
.IP
|
||||
Подразумевана системска датотека врста.
|
||||
.PP
|
||||
.I ~/.local/share/mc/bindings
|
||||
.I ~/.local/share/mc/mc.ext
|
||||
.IP
|
||||
Корисничке датотеке врста, подешавања прегледача и уређивача. Уколико
|
||||
постоје, оне заобилазе системске датотеке.
|
||||
|
@ -43,6 +43,7 @@ libmc_la_SOURCES = \
|
||||
global.c global.h \
|
||||
keybind.c keybind.h \
|
||||
lock.c lock.h \
|
||||
serialize.c serialize.h \
|
||||
timefmt.c timefmt.h
|
||||
|
||||
if USE_MAINTAINER_MODE
|
||||
|
@ -52,7 +52,7 @@
|
||||
|
||||
#define MC_BASHRC_FILE "bashrc"
|
||||
#define MC_CONFIG_FILE "ini"
|
||||
#define MC_FILEBIND_FILE "bindings"
|
||||
#define MC_FILEBIND_FILE "mc.ext"
|
||||
#define MC_FILEPOS_FILE "filepos"
|
||||
#define MC_HISTORY_FILE "history"
|
||||
#define MC_HOTLIST_FILE "hotlist"
|
||||
|
@ -197,6 +197,7 @@ lock_file (const char *fname)
|
||||
struct stat statbuf;
|
||||
struct lock_s *lockinfo;
|
||||
gboolean symlink_ok;
|
||||
vfs_path_t *vpath;
|
||||
|
||||
/* Just to be sure (and don't lock new file) */
|
||||
if (fname == NULL || *fname == '\0')
|
||||
@ -204,12 +205,16 @@ lock_file (const char *fname)
|
||||
|
||||
fname = tilde_expand (fname);
|
||||
|
||||
vpath = vfs_path_from_str (fname);
|
||||
|
||||
/* Locking on VFS is not supported */
|
||||
if (!vfs_file_is_local (fname))
|
||||
if (!vfs_file_is_local (vpath))
|
||||
{
|
||||
g_free ((gpointer) fname);
|
||||
vfs_path_free (vpath);
|
||||
return 0;
|
||||
}
|
||||
vfs_path_free (vpath);
|
||||
|
||||
/* Check if already locked */
|
||||
lockfname = lock_build_symlink_name (fname);
|
||||
|
@ -31,7 +31,7 @@ void mc_config_deinit (mc_config_t *);
|
||||
gboolean mc_config_del_key (mc_config_t *, const char *, const gchar *);
|
||||
gboolean mc_config_del_group (mc_config_t *, const char *);
|
||||
|
||||
gboolean mc_config_has_param (mc_config_t *, const char *, const gchar *);
|
||||
gboolean mc_config_has_param (const mc_config_t *, const char *, const gchar *);
|
||||
gboolean mc_config_has_group (mc_config_t *, const char *);
|
||||
|
||||
gboolean mc_config_read_file (mc_config_t * mc_config, const gchar * ini_path,
|
||||
@ -44,13 +44,13 @@ gboolean mc_config_save_to_file (mc_config_t * config, const gchar * filename, G
|
||||
|
||||
/* mcconfig/get.c: */
|
||||
|
||||
gchar **mc_config_get_groups (mc_config_t *, gsize *);
|
||||
gchar **mc_config_get_groups (const mc_config_t *, gsize *);
|
||||
|
||||
gchar **mc_config_get_keys (mc_config_t *, const gchar *, gsize *);
|
||||
gchar **mc_config_get_keys (const mc_config_t *, const gchar *, gsize *);
|
||||
|
||||
gchar *mc_config_get_string (mc_config_t *, const gchar *, const gchar *, const gchar *);
|
||||
|
||||
gchar *mc_config_get_string_raw (mc_config_t *, const gchar *, const gchar *, const gchar *);
|
||||
gchar *mc_config_get_string_raw (const mc_config_t *, const gchar *, const gchar *, const gchar *);
|
||||
|
||||
gboolean mc_config_get_bool (mc_config_t *, const gchar *, const gchar *, gboolean);
|
||||
|
||||
@ -68,7 +68,7 @@ int *mc_config_get_int_list (mc_config_t *, const gchar *, const gchar *, gsize
|
||||
|
||||
void mc_config_set_string_raw (mc_config_t *, const gchar *, const gchar *, const gchar *);
|
||||
|
||||
void mc_config_set_string (mc_config_t *, const gchar *, const gchar *, const gchar *);
|
||||
void mc_config_set_string (const mc_config_t *, const gchar *, const gchar *, const gchar *);
|
||||
|
||||
void mc_config_set_bool (mc_config_t *, const gchar *, const gchar *, gboolean);
|
||||
|
||||
|
@ -137,7 +137,7 @@ mc_config_deinit (mc_config_t * mc_config)
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
gboolean
|
||||
mc_config_has_param (mc_config_t * mc_config, const char *group, const gchar * param)
|
||||
mc_config_has_param (const mc_config_t * mc_config, const char *group, const gchar * param)
|
||||
{
|
||||
if (!mc_config || !group || !param)
|
||||
return FALSE;
|
||||
|
@ -36,7 +36,7 @@
|
||||
/*** public functions **************************************************/
|
||||
|
||||
gchar **
|
||||
mc_config_get_groups (mc_config_t * mc_config, gsize * len)
|
||||
mc_config_get_groups (const mc_config_t * mc_config, gsize * len)
|
||||
{
|
||||
gchar **ret;
|
||||
|
||||
@ -58,7 +58,7 @@ mc_config_get_groups (mc_config_t * mc_config, gsize * len)
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
gchar **
|
||||
mc_config_get_keys (mc_config_t * mc_config, const gchar * group, gsize * len)
|
||||
mc_config_get_keys (const mc_config_t * mc_config, const gchar * group, gsize * len)
|
||||
{
|
||||
gchar **ret;
|
||||
|
||||
@ -126,7 +126,7 @@ mc_config_get_string (mc_config_t * mc_config, const gchar * group,
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
gchar *
|
||||
mc_config_get_string_raw (mc_config_t * mc_config, const gchar * group,
|
||||
mc_config_get_string_raw (const mc_config_t * mc_config, const gchar * group,
|
||||
const gchar * param, const gchar * def)
|
||||
{
|
||||
gchar *ret;
|
||||
|
@ -76,7 +76,7 @@ mc_config_set_string_raw (mc_config_t * mc_config, const gchar * group,
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
void
|
||||
mc_config_set_string (mc_config_t * mc_config, const gchar * group,
|
||||
mc_config_set_string (const mc_config_t * mc_config, const gchar * group,
|
||||
const gchar * param, const gchar * value)
|
||||
{
|
||||
gchar *buffer;
|
||||
|
346
lib/serialize.c
Обычный файл
346
lib/serialize.c
Обычный файл
@ -0,0 +1,346 @@
|
||||
/*
|
||||
Provides a serialize/unserialize functionality for INI-like formats.
|
||||
|
||||
Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
|
||||
Written:
|
||||
2011 Slava Zanko <slavazanko@gmail.com>.
|
||||
|
||||
This file is part of the Midnight Commander.
|
||||
|
||||
The Midnight Commander is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The Midnight Commander is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file serialize.c
|
||||
* \brief Source: serialize/unserialize functionality for INI-like formats.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "lib/global.h"
|
||||
|
||||
#include "lib/serialize.h"
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
#define SRLZ_DELIM_C ':'
|
||||
#define SRLZ_DELIM_S ":"
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
prepend_error_message (GError ** error, const char *format, ...)
|
||||
{
|
||||
char *prepend_str;
|
||||
char *split_str;
|
||||
va_list ap;
|
||||
|
||||
if ((error == NULL) || (*error == NULL))
|
||||
return;
|
||||
|
||||
va_start (ap, format);
|
||||
prepend_str = g_strdup_vprintf (format, ap);
|
||||
va_end (ap);
|
||||
|
||||
split_str = g_strdup_printf ("%s: %s", prepend_str, (*error)->message);
|
||||
g_free (prepend_str);
|
||||
g_free ((*error)->message);
|
||||
(*error)->message = split_str;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static const char *
|
||||
go_to_end_of_serialized_string (const char *non_serialized_data,
|
||||
const char *already_serialized_part, size_t * offset)
|
||||
{
|
||||
size_t calculated_offset;
|
||||
const char *semi_ptr = strchr (non_serialized_data + 1, SRLZ_DELIM_C);
|
||||
|
||||
calculated_offset = (semi_ptr - non_serialized_data) + 1 + strlen (already_serialized_part);
|
||||
if (calculated_offset >= strlen (non_serialized_data))
|
||||
return NULL;
|
||||
|
||||
non_serialized_data += calculated_offset;
|
||||
*offset += calculated_offset;
|
||||
|
||||
return non_serialized_data;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*** public functions ****************************************************************************/
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Serialize some string object to string
|
||||
*
|
||||
* @param prefix prefix for serailization
|
||||
* @param data data for serialization
|
||||
* @param error contain pointer to object for handle error code and message
|
||||
*
|
||||
* @return serialized data as newly allocated string
|
||||
*/
|
||||
|
||||
char *
|
||||
mc_serialize_str (const char prefix, const char *data, GError ** error)
|
||||
{
|
||||
if (data == NULL)
|
||||
{
|
||||
g_set_error (error, MC_ERROR, -1, "mc_serialize_str(): Input data is NULL.");
|
||||
return NULL;
|
||||
}
|
||||
return g_strdup_printf ("%c%zd" SRLZ_DELIM_S "%s", prefix, strlen (data), data);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Deserialize string to string object
|
||||
*
|
||||
* @param prefix prefix for deserailization
|
||||
* @param data data for deserialization
|
||||
* @param error contain pointer to object for handle error code and message
|
||||
*
|
||||
* @return newly allocated string
|
||||
*/
|
||||
|
||||
#define FUNC_NAME "mc_serialize_str()"
|
||||
char *
|
||||
mc_deserialize_str (const char prefix, const char *data, GError ** error)
|
||||
{
|
||||
size_t data_len;
|
||||
|
||||
if ((data == NULL) || (strlen (data) == 0))
|
||||
{
|
||||
g_set_error (error, MC_ERROR, -1, FUNC_NAME ": Input data is NULL or empty.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (*data != prefix)
|
||||
{
|
||||
g_set_error (error, MC_ERROR, -2, FUNC_NAME ": String prefix doesn't equal to '%c'",
|
||||
prefix);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[BUF_TINY];
|
||||
char *semi_ptr;
|
||||
size_t semi_offset;
|
||||
|
||||
semi_ptr = strchr (data + 1, SRLZ_DELIM_C);
|
||||
if (semi_ptr == NULL)
|
||||
{
|
||||
g_set_error (error, MC_ERROR, -3,
|
||||
FUNC_NAME ": Length delimiter '%c' doesn't exists", SRLZ_DELIM_C);
|
||||
return NULL;
|
||||
}
|
||||
semi_offset = semi_ptr - (data + 1);
|
||||
if (semi_offset >= BUF_TINY)
|
||||
{
|
||||
g_set_error (error, MC_ERROR, -3, FUNC_NAME ": Too big string length");
|
||||
return NULL;
|
||||
}
|
||||
strncpy (buffer, data + 1, semi_offset);
|
||||
buffer[semi_offset] = '\0';
|
||||
data_len = atol (buffer);
|
||||
data += semi_offset + 2;
|
||||
}
|
||||
|
||||
if (data_len > strlen (data))
|
||||
{
|
||||
g_set_error (error, MC_ERROR, -3,
|
||||
FUNC_NAME ": Specified data length (%zd) is greater than actual data length (%zd)",
|
||||
data_len, strlen (data));
|
||||
return NULL;
|
||||
}
|
||||
return g_strndup (data, data_len);
|
||||
}
|
||||
|
||||
#undef FUNC_NAME
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Serialize mc_config_t object to string
|
||||
*
|
||||
* @param data data for serialization
|
||||
* @param error contain pointer to object for handle error code and message
|
||||
*
|
||||
* @return serialized data as newly allocated string
|
||||
*/
|
||||
|
||||
char *
|
||||
mc_serialize_config (const mc_config_t * data, GError ** error)
|
||||
{
|
||||
gchar **groups, **group_iterator;
|
||||
size_t group_count;
|
||||
GString *buffer;
|
||||
|
||||
buffer = g_string_new ("");
|
||||
group_iterator = groups = mc_config_get_groups (data, &group_count);
|
||||
|
||||
while (group_count-- != 0)
|
||||
{
|
||||
char *serialized_str;
|
||||
gchar **params, **param_iterator;
|
||||
size_t param_count;
|
||||
|
||||
serialized_str = mc_serialize_str ('g', *group_iterator, error);
|
||||
if (serialized_str == NULL)
|
||||
{
|
||||
g_string_free (buffer, TRUE);
|
||||
g_strfreev (groups);
|
||||
return NULL;
|
||||
}
|
||||
g_string_append (buffer, serialized_str);
|
||||
g_free (serialized_str);
|
||||
|
||||
param_iterator = params = mc_config_get_keys (data, *group_iterator, ¶m_count);
|
||||
|
||||
while (param_count-- != 0)
|
||||
{
|
||||
char *value;
|
||||
serialized_str = mc_serialize_str ('p', *param_iterator, error);
|
||||
if (serialized_str == NULL)
|
||||
{
|
||||
g_string_free (buffer, TRUE);
|
||||
g_strfreev (params);
|
||||
g_strfreev (groups);
|
||||
return NULL;
|
||||
}
|
||||
g_string_append (buffer, serialized_str);
|
||||
g_free (serialized_str);
|
||||
|
||||
value = mc_config_get_string_raw (data, *group_iterator, *param_iterator, "");
|
||||
serialized_str = mc_serialize_str ('v', value, error);
|
||||
g_free (value);
|
||||
|
||||
if (serialized_str == NULL)
|
||||
{
|
||||
g_string_free (buffer, TRUE);
|
||||
g_strfreev (params);
|
||||
g_strfreev (groups);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_string_append (buffer, serialized_str);
|
||||
g_free (serialized_str);
|
||||
|
||||
param_iterator++;
|
||||
}
|
||||
|
||||
g_strfreev (params);
|
||||
|
||||
group_iterator++;
|
||||
}
|
||||
return g_string_free (buffer, FALSE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Deserialize string to mc_config_t object
|
||||
*
|
||||
* @param data data for serialization
|
||||
* @param error contain pointer to object for handle error code and message
|
||||
*
|
||||
* @return newly allocated mc_config_t object
|
||||
*/
|
||||
|
||||
#define FUNC_NAME "mc_deserialize_config()"
|
||||
#define prepend_error_and_exit() { \
|
||||
prepend_error_message (error, FUNC_NAME " at %lu", current_position + 1); \
|
||||
mc_config_deinit (ret_data); \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
mc_config_t *
|
||||
mc_deserialize_config (const char *data, GError ** error)
|
||||
{
|
||||
char *current_group = NULL, *current_param = NULL, *current_value = NULL;
|
||||
size_t current_position = 0;
|
||||
mc_config_t *ret_data = mc_config_init (NULL);
|
||||
enum automat_status
|
||||
{
|
||||
WAIT_GROUP,
|
||||
WAIT_PARAM,
|
||||
WAIT_VALUE
|
||||
} current_status = WAIT_GROUP;
|
||||
|
||||
while (data != NULL)
|
||||
{
|
||||
if ((current_status == WAIT_GROUP) && (*data == 'p') && (current_group != NULL))
|
||||
current_status = WAIT_PARAM;
|
||||
|
||||
switch (current_status)
|
||||
{
|
||||
case WAIT_GROUP:
|
||||
g_free (current_group);
|
||||
|
||||
current_group = mc_deserialize_str ('g', data, error);
|
||||
if (current_group == NULL)
|
||||
prepend_error_and_exit ();
|
||||
|
||||
data = go_to_end_of_serialized_string (data, current_group, ¤t_position);
|
||||
current_status = WAIT_PARAM;
|
||||
break;
|
||||
case WAIT_PARAM:
|
||||
g_free (current_param);
|
||||
|
||||
current_param = mc_deserialize_str ('p', data, error);
|
||||
if (current_param == NULL)
|
||||
{
|
||||
g_free (current_group);
|
||||
prepend_error_and_exit ();
|
||||
}
|
||||
|
||||
data = go_to_end_of_serialized_string (data, current_param, ¤t_position);
|
||||
current_status = WAIT_VALUE;
|
||||
break;
|
||||
case WAIT_VALUE:
|
||||
current_value = mc_deserialize_str ('v', data, error);
|
||||
if (current_param == NULL)
|
||||
{
|
||||
g_free (current_group);
|
||||
g_free (current_param);
|
||||
prepend_error_and_exit ();
|
||||
}
|
||||
mc_config_set_string (ret_data, current_group, current_param, current_value);
|
||||
|
||||
data = go_to_end_of_serialized_string (data, current_value, ¤t_position);
|
||||
g_free (current_value);
|
||||
current_status = WAIT_GROUP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_free (current_group);
|
||||
g_free (current_param);
|
||||
|
||||
return ret_data;
|
||||
}
|
||||
|
||||
#undef FUNC_NAME
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
27
lib/serialize.h
Обычный файл
27
lib/serialize.h
Обычный файл
@ -0,0 +1,27 @@
|
||||
#ifndef MC__SERIALIZE_H
|
||||
#define MC__SERIALIZE_H
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "lib/global.h"
|
||||
#include "lib/mcconfig.h"
|
||||
|
||||
/*** typedefs(not structures) and defined constants **********************************************/
|
||||
|
||||
/*** enums ***************************************************************************************/
|
||||
|
||||
/*** structures declarations (and typedefs of structures)*****************************************/
|
||||
|
||||
/*** global variables defined in .c file *********************************************************/
|
||||
|
||||
/*** declarations of public functions ************************************************************/
|
||||
|
||||
char *mc_serialize_str (const char prefix, const char *data, GError ** error);
|
||||
char *mc_deserialize_str (const char prefix, const char *data, GError ** error);
|
||||
|
||||
char *mc_serialize_config (const mc_config_t * data, GError ** error);
|
||||
mc_config_t *mc_deserialize_config (const char *data, GError ** error);
|
||||
|
||||
/*** inline functions ****************************************************************************/
|
||||
|
||||
#endif
|
@ -524,6 +524,12 @@ int str_verscmp (const char *s1, const char *s2);
|
||||
*/
|
||||
void str_msg_term_size (const char *text, int *lines, int *columns);
|
||||
|
||||
/**
|
||||
skip first <skip_count> needle's in haystack and returns pointer to
|
||||
<skip_count+1> needle (or NULL if not found).
|
||||
*/
|
||||
char *strrstr_skip_count (const char *haystack, const char *needle, size_t skip_count);
|
||||
|
||||
/*** inline functions ****************************************************************************/
|
||||
|
||||
static inline void
|
||||
|
@ -803,3 +803,26 @@ str_msg_term_size (const char *text, int *lines, int *columns)
|
||||
|
||||
g_free (tmp);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
char *
|
||||
strrstr_skip_count (const char *haystack, const char *needle, size_t skip_count)
|
||||
{
|
||||
char *semi;
|
||||
ssize_t len;
|
||||
|
||||
len = strlen (haystack);
|
||||
|
||||
do
|
||||
{
|
||||
semi = g_strrstr_len (haystack, len, needle);
|
||||
if (semi == NULL)
|
||||
return NULL;
|
||||
len = semi - haystack - 1;
|
||||
}
|
||||
while (skip_count-- != 0);
|
||||
return semi;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
@ -1,12 +1,24 @@
|
||||
SUBDIRS = . mcconfig
|
||||
SUBDIRS = . mcconfig vfs
|
||||
|
||||
AM_CFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) @CHECK_CFLAGS@
|
||||
LIBS=@CHECK_LIBS@ $(top_builddir)/lib/libmc.la
|
||||
|
||||
TESTS = \
|
||||
library_independ
|
||||
library_independ \
|
||||
mc_build_filename \
|
||||
serialize \
|
||||
x_basename
|
||||
|
||||
check_PROGRAMS = $(TESTS)
|
||||
|
||||
library_independ_SOURCES = \
|
||||
library_independ.c
|
||||
|
||||
mc_build_filename_SOURCES = \
|
||||
mc_build_filename.c
|
||||
|
||||
serialize_SOURCES = \
|
||||
serialize.c
|
||||
|
||||
x_basename_SOURCES = \
|
||||
x_basename.c
|
||||
|
100
lib/tests/mc_build_filename.c
Обычный файл
100
lib/tests/mc_build_filename.c
Обычный файл
@ -0,0 +1,100 @@
|
||||
/* lib/vfs - mc_build_filename() function testing
|
||||
|
||||
Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2011
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
as published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define TEST_SUITE_NAME "/lib"
|
||||
|
||||
#include <check.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lib/global.h"
|
||||
#include "lib/strutil.h"
|
||||
#include "lib/util.h"
|
||||
|
||||
|
||||
static void
|
||||
setup (void)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
teardown (void)
|
||||
{
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
#define check_mc_build_filename( inargs, etalon ) \
|
||||
{ \
|
||||
result = mc_build_filename inargs; \
|
||||
fail_unless( strcmp (result, etalon) == 0, \
|
||||
"\nactial (%s) not equal to\netalon (%s)", result, etalon); \
|
||||
g_free (result); \
|
||||
}
|
||||
|
||||
START_TEST (test_mc_build_filename)
|
||||
{
|
||||
char *result;
|
||||
|
||||
check_mc_build_filename(("test", "path", NULL), "/test/path");
|
||||
|
||||
check_mc_build_filename(("/test", "path/", NULL), "/test/path");
|
||||
|
||||
check_mc_build_filename(("/test", "pa/th", NULL), "/test/pa/th");
|
||||
|
||||
check_mc_build_filename(("/test", "#vfsprefix:", "path ", NULL), "/test/#vfsprefix:/path ");
|
||||
|
||||
check_mc_build_filename(("/test", "vfsprefix://", "path ", NULL), "/test/vfsprefix://path ");
|
||||
|
||||
check_mc_build_filename(("/test", "vfs/../prefix:///", "p\\///ath", NULL), "/test/prefix://p\\/ath");
|
||||
|
||||
check_mc_build_filename(("/test", "path", "..", "/test", "path/", NULL), "/test/test/path");
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int number_failed;
|
||||
|
||||
Suite *s = suite_create (TEST_SUITE_NAME);
|
||||
TCase *tc_core = tcase_create ("Core");
|
||||
SRunner *sr;
|
||||
|
||||
tcase_add_checked_fixture (tc_core, setup, teardown);
|
||||
|
||||
/* Add new tests here: *************** */
|
||||
tcase_add_test (tc_core, test_mc_build_filename);
|
||||
/* *********************************** */
|
||||
|
||||
suite_add_tcase (s, tc_core);
|
||||
sr = srunner_create (s);
|
||||
srunner_set_log (sr, "mc_build_filename.log");
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
number_failed = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
return (number_failed == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
258
lib/tests/serialize.c
Обычный файл
258
lib/tests/serialize.c
Обычный файл
@ -0,0 +1,258 @@
|
||||
/* lib/vfs - common serialize/deserialize functions
|
||||
|
||||
Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2011
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
as published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define TEST_SUITE_NAME "/lib"
|
||||
|
||||
#include <check.h>
|
||||
|
||||
|
||||
#include "lib/global.h"
|
||||
#include "lib/strutil.h"
|
||||
#include "lib/serialize.h"
|
||||
|
||||
|
||||
static void
|
||||
setup (void)
|
||||
{
|
||||
str_init_strings (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
teardown (void)
|
||||
{
|
||||
str_uninit_strings ();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
#define deserialize_check_incorrect( etalon_code, etalon_str ) { \
|
||||
if (actual != NULL) \
|
||||
{ \
|
||||
fail("actual value is '%s', but should be NULL", actual); \
|
||||
g_free(actual); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
fail_unless (error->code == etalon_code && strcmp(error->message, etalon_str) == 0, \
|
||||
"\nerror code is %d (should be %d);\nerror message is '%s' (should be '%s')", \
|
||||
error->code, etalon_code, error->message, etalon_str); \
|
||||
g_clear_error(&error); \
|
||||
} \
|
||||
}
|
||||
|
||||
START_TEST (test_serialize_deserialize_str)
|
||||
{
|
||||
GError *error = NULL;
|
||||
char *actual;
|
||||
|
||||
|
||||
actual = mc_serialize_str('s', "some test string", &error);
|
||||
|
||||
if (actual == NULL)
|
||||
{
|
||||
fail("actual value is NULL!\nError code is '%d'; error message is '%s'", error->code, error->message);
|
||||
g_clear_error(&error);
|
||||
return;
|
||||
}
|
||||
fail_unless (strcmp(actual,"s16:some test string") == 0, "Actual value(%s) doesn't equal to etalon(s16:some test string)", actual);
|
||||
g_free(actual);
|
||||
|
||||
actual = mc_deserialize_str('s', NULL, &error);
|
||||
deserialize_check_incorrect( -1, "mc_serialize_str(): Input data is NULL or empty." );
|
||||
|
||||
actual = mc_deserialize_str('s', "incorrect string", &error);
|
||||
deserialize_check_incorrect( -2, "mc_serialize_str(): String prefix doesn't equal to 's'" );
|
||||
|
||||
actual = mc_deserialize_str('s', "s12345string without delimiter", &error);
|
||||
deserialize_check_incorrect( -3, "mc_serialize_str(): Length delimiter ':' doesn't exists" );
|
||||
|
||||
actual = mc_deserialize_str('s', "s1234567890123456789012345678901234567890123456789012345678901234567890:too big number", &error);
|
||||
deserialize_check_incorrect( -3, "mc_serialize_str(): Too big string length" );
|
||||
|
||||
actual = mc_deserialize_str('s', "s500:actual string length less that specified length", &error);
|
||||
deserialize_check_incorrect( -3, "mc_serialize_str(): Specified data length (500) is greater than actual data length (47)" );
|
||||
|
||||
actual = mc_deserialize_str('s', "s10:actual string length great that specified length", &error);
|
||||
fail_unless (actual != NULL && strcmp(actual, "actual str") == 0, "actual (%s) doesn't equal to etalon(actual str)", actual);
|
||||
g_free(actual);
|
||||
|
||||
actual = mc_deserialize_str('s', "s21:The right test string", &error);
|
||||
fail_unless (actual != NULL && strcmp(actual, "The right test string") == 0, "actual (%s) doesn't equal to etalon(The right test string)", actual);
|
||||
g_free(actual);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define etalon_str "g6:group1p6:param1v10:some valuep6:param2v11:some value " \
|
||||
"g6:group2p6:param1v4:truep6:param2v6:123456" \
|
||||
"g6:group3p6:param1v11:::bla-bla::p6:param2v31:bla-:p1:w:v2:12:g3:123:bla-bla\n" \
|
||||
"g6:group4p6:param1v5:falsep6:param2v6:654321"
|
||||
|
||||
START_TEST (test_serialize_config)
|
||||
{
|
||||
mc_config_t *test_data;
|
||||
GError *error = NULL;
|
||||
char *actual;
|
||||
|
||||
test_data = mc_config_init (NULL);
|
||||
|
||||
mc_config_set_string_raw (test_data, "group1", "param1", "some value");
|
||||
mc_config_set_string (test_data, "group1", "param2", "some value ");
|
||||
|
||||
mc_config_set_bool (test_data, "group2", "param1", TRUE);
|
||||
mc_config_set_int (test_data, "group2", "param2", 123456);
|
||||
|
||||
mc_config_set_string_raw (test_data, "group3", "param1", "::bla-bla::");
|
||||
mc_config_set_string (test_data, "group3", "param2", "bla-:p1:w:v2:12:g3:123:bla-bla\n");
|
||||
|
||||
mc_config_set_bool (test_data, "group4", "param1", FALSE);
|
||||
mc_config_set_int (test_data, "group4", "param2", 654321);
|
||||
|
||||
actual = mc_serialize_config (test_data, &error);
|
||||
mc_config_deinit (test_data);
|
||||
|
||||
if (actual == NULL)
|
||||
{
|
||||
fail("actual value is NULL!\nError code is '%d'; error message is '%s'", error->code, error->message);
|
||||
g_clear_error(&error);
|
||||
return;
|
||||
}
|
||||
|
||||
fail_unless(strcmp(actual, etalon_str) == 0, "Not equal:\nactual (%s)\netalon (%s)", actual, etalon_str);
|
||||
g_free(actual);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
#undef deserialize_check_incorrect
|
||||
#define deserialize_check_incorrect( etalon_code, etalon_str ) { \
|
||||
if (actual != NULL) \
|
||||
{ \
|
||||
fail("actual value but should be NULL", actual); \
|
||||
mc_config_deinit(actual); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
fail_unless (error->code == etalon_code && strcmp(error->message, etalon_str) == 0, \
|
||||
"\nerror code is %d (should be %d);\nerror message is '%s' (should be '%s')", \
|
||||
error->code, etalon_code, error->message, etalon_str); \
|
||||
g_clear_error(&error); \
|
||||
} \
|
||||
}
|
||||
|
||||
START_TEST (test_deserialize_config)
|
||||
{
|
||||
mc_config_t *actual;
|
||||
GError *error = NULL;
|
||||
char *actual_value;
|
||||
|
||||
actual = mc_deserialize_config ("g123error in group name", &error);
|
||||
deserialize_check_incorrect( -3,
|
||||
"mc_deserialize_config() at 1: mc_serialize_str(): Length delimiter ':' doesn't exists");
|
||||
|
||||
actual = mc_deserialize_config ("p6:param1v10:some valuep6:param2v11:some value ", &error);
|
||||
deserialize_check_incorrect( -2,
|
||||
"mc_deserialize_config() at 1: mc_serialize_str(): String prefix doesn't equal to 'g'");
|
||||
|
||||
actual = mc_deserialize_config ("g6:group1v10:some valuep6:param2v11:some value ", &error);
|
||||
deserialize_check_incorrect( -2,
|
||||
"mc_deserialize_config() at 10: mc_serialize_str(): String prefix doesn't equal to 'p'");
|
||||
|
||||
actual = mc_deserialize_config ("g6:group1p6000:param2v11:some value ", &error);
|
||||
deserialize_check_incorrect( -3,
|
||||
"mc_deserialize_config() at 10: mc_serialize_str(): Specified data length (6000) is greater than actual data length (21)");
|
||||
|
||||
actual = mc_deserialize_config (etalon_str, &error);
|
||||
|
||||
if (actual == NULL)
|
||||
{
|
||||
fail("actual value is NULL!\nError code is '%d'; error message is '%s'", error->code, error->message);
|
||||
g_clear_error(&error);
|
||||
return;
|
||||
}
|
||||
|
||||
actual_value = mc_config_get_string_raw(actual, "group1", "param1", "");
|
||||
fail_unless( strcmp(actual_value, "some value") == 0,
|
||||
"group1->param1(%s) should be equal to 'some value'", actual_value);
|
||||
g_free(actual_value);
|
||||
|
||||
actual_value = mc_config_get_string(actual, "group1", "param2", "");
|
||||
fail_unless( strcmp(actual_value, "some value ") == 0,
|
||||
"group1->param2(%s) should be equal to 'some value '", actual_value);
|
||||
g_free(actual_value);
|
||||
|
||||
fail_unless( mc_config_get_bool(actual, "group2", "param1", FALSE) == TRUE,
|
||||
"group2->param1(FALSE) should be equal to TRUE");
|
||||
|
||||
fail_unless( mc_config_get_int(actual, "group2", "param2", 0) == 123456,
|
||||
"group2->param2(%d) should be equal to 123456", mc_config_get_int(actual, "group2", "param2", 0));
|
||||
|
||||
actual_value = mc_config_get_string_raw(actual, "group3", "param1", "");
|
||||
fail_unless( strcmp(actual_value, "::bla-bla::") == 0,
|
||||
"group3->param1(%s) should be equal to '::bla-bla::'", actual_value);
|
||||
g_free(actual_value);
|
||||
|
||||
actual_value = mc_config_get_string(actual, "group3", "param2", "");
|
||||
fail_unless( strcmp(actual_value, "bla-:p1:w:v2:12:g3:123:bla-bla\n") == 0,
|
||||
"group3->param2(%s) should be equal to 'bla-:p1:w:v2:12:g3:123:bla-bla\n'", actual_value);
|
||||
g_free(actual_value);
|
||||
|
||||
fail_unless( mc_config_get_bool(actual, "group4", "param1", TRUE) == FALSE,
|
||||
"group4->param1(TRUE) should be equal to FALSE");
|
||||
|
||||
fail_unless( mc_config_get_int(actual, "group4", "param2", 0) == 654321,
|
||||
"group4->param2(%d) should be equal to 654321", mc_config_get_int(actual, "group4", "param2", 0));
|
||||
|
||||
mc_config_deinit (actual);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int number_failed;
|
||||
|
||||
Suite *s = suite_create (TEST_SUITE_NAME);
|
||||
TCase *tc_core = tcase_create ("Core");
|
||||
SRunner *sr;
|
||||
|
||||
tcase_add_checked_fixture (tc_core, setup, teardown);
|
||||
|
||||
/* Add new tests here: *************** */
|
||||
tcase_add_test (tc_core, test_serialize_deserialize_str);
|
||||
tcase_add_test (tc_core, test_serialize_config);
|
||||
tcase_add_test (tc_core, test_deserialize_config);
|
||||
/* *********************************** */
|
||||
|
||||
suite_add_tcase (s, tc_core);
|
||||
sr = srunner_create (s);
|
||||
srunner_set_log (sr, "serialize.log");
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
number_failed = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
return (number_failed == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
39
lib/tests/vfs/Makefile.am
Обычный файл
39
lib/tests/vfs/Makefile.am
Обычный файл
@ -0,0 +1,39 @@
|
||||
AM_CFLAGS = -I$(top_srcdir)/lib/vfs $(GLIB_CFLAGS) -I$(top_srcdir) @CHECK_CFLAGS@ \
|
||||
-DTEST_SHARE_DIR=\"$(abs_srcdir)\" -z muldefs
|
||||
|
||||
AM_LDFLAGS = -z muldefs
|
||||
|
||||
LIBS=@CHECK_LIBS@ \
|
||||
$(top_builddir)/lib/libmc.la
|
||||
|
||||
TESTS = \
|
||||
canonicalize_pathname \
|
||||
current_dir \
|
||||
path_serialize \
|
||||
vfs_path_string_convert \
|
||||
vfs_prefix_to_class \
|
||||
vfs_split \
|
||||
vfs_s_get_path
|
||||
|
||||
check_PROGRAMS = $(TESTS)
|
||||
|
||||
canonicalize_pathname_SOURCES = \
|
||||
canonicalize_pathname.c
|
||||
|
||||
current_dir_SOURCES = \
|
||||
current_dir.c
|
||||
|
||||
path_serialize_SOURCES = \
|
||||
path_serialize.c
|
||||
|
||||
vfs_split_SOURCES = \
|
||||
vfs_split.c
|
||||
|
||||
vfs_prefix_to_class_SOURCES = \
|
||||
vfs_prefix_to_class.c
|
||||
|
||||
vfs_path_string_convert_SOURCES = \
|
||||
vfs_path_string_convert.c
|
||||
|
||||
vfs_s_get_path_SOURCES = \
|
||||
vfs_s_get_path.c
|
133
lib/tests/vfs/canonicalize_pathname.c
Обычный файл
133
lib/tests/vfs/canonicalize_pathname.c
Обычный файл
@ -0,0 +1,133 @@
|
||||
/* lib - canonicalize path
|
||||
|
||||
Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2011
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
as published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define TEST_SUITE_NAME "/lib/vfs"
|
||||
|
||||
#include <check.h>
|
||||
|
||||
|
||||
#include "lib/global.h"
|
||||
#include "lib/strutil.h"
|
||||
#include "lib/util.h"
|
||||
#include "lib/vfs/xdirentry.h"
|
||||
|
||||
#include "src/vfs/local/local.c"
|
||||
|
||||
static void
|
||||
setup (void)
|
||||
{
|
||||
str_init_strings (NULL);
|
||||
|
||||
vfs_init ();
|
||||
init_localfs ();
|
||||
vfs_setup_work_dir ();
|
||||
}
|
||||
|
||||
static void
|
||||
teardown (void)
|
||||
{
|
||||
vfs_shut ();
|
||||
str_uninit_strings ();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define check_canonicalize( input, etalon ) { \
|
||||
path = g_strdup(input); \
|
||||
canonicalize_pathname (path); \
|
||||
fail_unless ( \
|
||||
strcmp(path, etalon) == 0, \
|
||||
"\nactual value (%s)\nnot equal to etalon (%s)", path, etalon \
|
||||
); \
|
||||
g_free(path); \
|
||||
}
|
||||
|
||||
START_TEST (test_canonicalize_path)
|
||||
{
|
||||
char *path;
|
||||
static struct vfs_s_subclass test_subclass;
|
||||
static struct vfs_class vfs_test_ops;
|
||||
|
||||
vfs_s_init_class (&vfs_test_ops, &test_subclass);
|
||||
|
||||
vfs_test_ops.name = "testfs";
|
||||
vfs_test_ops.flags = VFSF_NOLINKS;
|
||||
vfs_test_ops.prefix = "ftp";
|
||||
test_subclass.flags = VFS_S_REMOTE;
|
||||
vfs_register_class (&vfs_test_ops);
|
||||
|
||||
/* UNC path */
|
||||
check_canonicalize ("//some_server/ww", "//some_server/ww");
|
||||
|
||||
/* join slashes */
|
||||
check_canonicalize ("///some_server/////////ww", "/some_server/ww");
|
||||
|
||||
/* Collapse "/./" -> "/" */
|
||||
check_canonicalize ("//some_server//.///////ww/./././.", "//some_server/ww");
|
||||
|
||||
/* Remove leading "./" */
|
||||
check_canonicalize ("./some_server/ww", "some_server/ww");
|
||||
|
||||
/* some/.. -> . */
|
||||
check_canonicalize ("some_server/..", ".");
|
||||
|
||||
/* Collapse "/.." with the previous part of path */
|
||||
check_canonicalize ("/some_server/ww/some_server/../ww/../some_server/..//ww/some_server/ww", "/some_server/ww/ww/some_server/ww");
|
||||
|
||||
/* URI style */
|
||||
check_canonicalize ("/some_server/ww/ftp://user:pass@host.net/path/", "/some_server/ww/ftp://user:pass@host.net/path");
|
||||
|
||||
check_canonicalize ("/some_server/ww/ftp://user:pass@host.net/path/../../", "/some_server/ww");
|
||||
|
||||
check_canonicalize ("ftp://user:pass@host.net/path/../../", ".");
|
||||
|
||||
check_canonicalize ("ftp://user/../../", "..");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int number_failed;
|
||||
|
||||
Suite *s = suite_create (TEST_SUITE_NAME);
|
||||
TCase *tc_core = tcase_create ("Core");
|
||||
SRunner *sr;
|
||||
|
||||
tcase_add_checked_fixture (tc_core, setup, teardown);
|
||||
|
||||
/* Add new tests here: *************** */
|
||||
tcase_add_test (tc_core, test_canonicalize_path);
|
||||
/* *********************************** */
|
||||
|
||||
suite_add_tcase (s, tc_core);
|
||||
sr = srunner_create (s);
|
||||
srunner_set_log (sr, "canonicalize_pathname.log");
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
number_failed = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
return (number_failed == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
177
lib/tests/vfs/current_dir.c
Обычный файл
177
lib/tests/vfs/current_dir.c
Обычный файл
@ -0,0 +1,177 @@
|
||||
/* lib/vfs - manipulate with current directory
|
||||
|
||||
Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2011
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
as published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define TEST_SUITE_NAME "/lib/vfs"
|
||||
|
||||
#include <check.h>
|
||||
|
||||
|
||||
#include "lib/global.h"
|
||||
#include "lib/strutil.h"
|
||||
#include "lib/vfs/xdirentry.h"
|
||||
|
||||
#include "src/vfs/local/local.c"
|
||||
|
||||
static void
|
||||
setup (void)
|
||||
{
|
||||
str_init_strings (NULL);
|
||||
|
||||
vfs_init ();
|
||||
init_localfs ();
|
||||
vfs_setup_work_dir ();
|
||||
}
|
||||
|
||||
static void
|
||||
teardown (void)
|
||||
{
|
||||
vfs_shut ();
|
||||
str_uninit_strings ();
|
||||
}
|
||||
|
||||
static int
|
||||
test_chdir(const vfs_path_t * vpath)
|
||||
{
|
||||
#if 0
|
||||
char *path = vfs_path_to_str(vpath);
|
||||
printf("test_chdir: %s\n", path);
|
||||
g_free(path);
|
||||
#else
|
||||
(void) vpath;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define cd_and_check( cd_dir, etalon ) \
|
||||
mc_chdir(cd_dir); \
|
||||
fail_unless( \
|
||||
strcmp(etalon, mc_get_current_wd(buffer,MC_MAXPATHLEN)) == 0, \
|
||||
"\n expected(%s) doesn't equal \nto actual(%s)", etalon, buffer);
|
||||
|
||||
START_TEST (set_up_current_dir)
|
||||
{
|
||||
static struct vfs_s_subclass test_subclass;
|
||||
static struct vfs_class vfs_test_ops;
|
||||
char buffer[MC_MAXPATHLEN];
|
||||
|
||||
vfs_s_init_class (&vfs_test_ops, &test_subclass);
|
||||
|
||||
vfs_test_ops.name = "testfs";
|
||||
vfs_test_ops.flags = VFSF_NOLINKS;
|
||||
vfs_test_ops.prefix = "test";
|
||||
vfs_test_ops.chdir = test_chdir;
|
||||
|
||||
vfs_register_class (&vfs_test_ops);
|
||||
|
||||
cd_and_check ("/dev/some.file#test", "/dev/some.file/test://");
|
||||
|
||||
cd_and_check ("/dev/some.file#test/bla-bla", "/dev/some.file/test://bla-bla");
|
||||
|
||||
cd_and_check ("..", "/dev/some.file/test://");
|
||||
|
||||
cd_and_check ("..", "/dev");
|
||||
|
||||
cd_and_check ("..", "/");
|
||||
|
||||
cd_and_check ("..", "/");
|
||||
|
||||
cd_and_check ("/dev/some.file/#test/bla-bla", "/dev/some.file/test://bla-bla");
|
||||
|
||||
cd_and_check ("..", "/dev/some.file/test://");
|
||||
|
||||
cd_and_check ("..", "/dev");
|
||||
|
||||
cd_and_check ("..", "/");
|
||||
|
||||
cd_and_check ("..", "/");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
START_TEST (set_up_current_dir_url)
|
||||
{
|
||||
static struct vfs_s_subclass test_subclass;
|
||||
static struct vfs_class vfs_test_ops;
|
||||
char buffer[MC_MAXPATHLEN];
|
||||
|
||||
vfs_s_init_class (&vfs_test_ops, &test_subclass);
|
||||
|
||||
vfs_test_ops.name = "testfs";
|
||||
vfs_test_ops.flags = VFSF_NOLINKS;
|
||||
vfs_test_ops.prefix = "test";
|
||||
vfs_test_ops.chdir = test_chdir;
|
||||
|
||||
vfs_register_class (&vfs_test_ops);
|
||||
|
||||
cd_and_check ("/dev/some.file/test://", "/dev/some.file/test://");
|
||||
|
||||
cd_and_check ("/dev/some.file/test://bla-bla", "/dev/some.file/test://bla-bla");
|
||||
|
||||
cd_and_check ("..", "/dev/some.file/test://");
|
||||
|
||||
cd_and_check ("..", "/dev");
|
||||
|
||||
cd_and_check ("..", "/");
|
||||
|
||||
cd_and_check ("..", "/");
|
||||
|
||||
test_subclass.flags = VFS_S_REMOTE;
|
||||
|
||||
cd_and_check ("/test://user:pass@host.net/path", "/test://user:pass@host.net/path");
|
||||
cd_and_check ("..", "/test://user:pass@host.net");
|
||||
|
||||
cd_and_check ("..", "/");
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int number_failed;
|
||||
|
||||
Suite *s = suite_create (TEST_SUITE_NAME);
|
||||
TCase *tc_core = tcase_create ("Core");
|
||||
SRunner *sr;
|
||||
|
||||
tcase_add_checked_fixture (tc_core, setup, teardown);
|
||||
|
||||
/* Add new tests here: *************** */
|
||||
tcase_add_test (tc_core, set_up_current_dir);
|
||||
tcase_add_test (tc_core, set_up_current_dir_url);
|
||||
/* *********************************** */
|
||||
|
||||
suite_add_tcase (s, tc_core);
|
||||
sr = srunner_create (s);
|
||||
srunner_set_log (sr, "current_dir.log");
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
number_failed = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
return (number_failed == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
5
lib/tests/vfs/mc.charsets
Обычный файл
5
lib/tests/vfs/mc.charsets
Обычный файл
@ -0,0 +1,5 @@
|
||||
ASCII 7-bit ASCII
|
||||
IBM866 CP 866
|
||||
KOI8-R KOI8-R
|
||||
KOI8-U KOI8-U
|
||||
UTF-8 UTF-8
|
181
lib/tests/vfs/path_serialize.c
Обычный файл
181
lib/tests/vfs/path_serialize.c
Обычный файл
@ -0,0 +1,181 @@
|
||||
/* lib/vfs - vfs_path_t serialize/deserialize functions
|
||||
|
||||
Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2011
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
as published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define TEST_SUITE_NAME "/lib/vfs"
|
||||
|
||||
#include <check.h>
|
||||
|
||||
#include "lib/global.c"
|
||||
|
||||
#ifndef HAVE_CHARSET
|
||||
#define HAVE_CHARSET 1
|
||||
#endif
|
||||
|
||||
#include "lib/charsets.h"
|
||||
|
||||
#include "lib/strutil.h"
|
||||
#include "lib/vfs/xdirentry.h"
|
||||
#include "lib/vfs/path.h"
|
||||
|
||||
#include "src/vfs/local/local.c"
|
||||
|
||||
|
||||
struct vfs_s_subclass test_subclass1, test_subclass2, test_subclass3;
|
||||
struct vfs_class vfs_test_ops1, vfs_test_ops2, vfs_test_ops3;
|
||||
|
||||
static void
|
||||
setup (void)
|
||||
{
|
||||
|
||||
str_init_strings (NULL);
|
||||
|
||||
vfs_init ();
|
||||
init_localfs ();
|
||||
vfs_setup_work_dir ();
|
||||
|
||||
|
||||
test_subclass1.flags = VFS_S_REMOTE;
|
||||
vfs_s_init_class (&vfs_test_ops1, &test_subclass1);
|
||||
|
||||
vfs_test_ops1.name = "testfs1";
|
||||
vfs_test_ops1.flags = VFSF_NOLINKS;
|
||||
vfs_test_ops1.prefix = "test1";
|
||||
vfs_register_class (&vfs_test_ops1);
|
||||
|
||||
vfs_s_init_class (&vfs_test_ops2, &test_subclass2);
|
||||
vfs_test_ops2.name = "testfs2";
|
||||
vfs_test_ops2.prefix = "test2";
|
||||
vfs_register_class (&vfs_test_ops2);
|
||||
|
||||
vfs_s_init_class (&vfs_test_ops3, &test_subclass3);
|
||||
vfs_test_ops3.name = "testfs3";
|
||||
vfs_test_ops3.prefix = "test3";
|
||||
vfs_register_class (&vfs_test_ops3);
|
||||
|
||||
mc_global.sysconfig_dir = (char *) TEST_SHARE_DIR;
|
||||
load_codepages_list ();
|
||||
}
|
||||
|
||||
static void
|
||||
teardown (void)
|
||||
{
|
||||
free_codepages_list ();
|
||||
|
||||
vfs_shut ();
|
||||
str_uninit_strings ();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
#define ETALON_PATH_STR "/local/path/#test1:user:pass@some.host:12345/bla-bla/some/path/#test2/#enc:KOI8-R/bla-bla/some/path#test3/111/22/33"
|
||||
#define ETALON_PATH_URL_STR "/local/path/test1://user:pass@some.host:12345/bla-bla/some/path/test2://#enc:KOI8-R/bla-bla/some/path/test3://111/22/33"
|
||||
#define ETALON_SERIALIZED_PATH \
|
||||
"g14:path-element-0" \
|
||||
"p4:pathv12:/local/path/" \
|
||||
"p10:class-namev7:localfs" \
|
||||
"g14:path-element-1" \
|
||||
"p4:pathv18:bla-bla/some/path/" \
|
||||
"p10:class-namev7:testfs1" \
|
||||
"p10:vfs_prefixv5:test1" \
|
||||
"p4:userv4:user" \
|
||||
"p8:passwordv4:pass" \
|
||||
"p4:hostv9:some.host" \
|
||||
"p4:portv5:12345" \
|
||||
"g14:path-element-2" \
|
||||
"p4:pathv17:bla-bla/some/path" \
|
||||
"p10:class-namev7:testfs2" \
|
||||
"p8:encodingv6:KOI8-R" \
|
||||
"p10:vfs_prefixv5:test2" \
|
||||
"g14:path-element-3" \
|
||||
"p4:pathv9:111/22/33" \
|
||||
"p10:class-namev7:testfs3" \
|
||||
"p10:vfs_prefixv5:test3"
|
||||
|
||||
START_TEST (test_path_serialize_deserialize)
|
||||
{
|
||||
vfs_path_t *vpath;
|
||||
char *serialized_vpath;
|
||||
GError *error = NULL;
|
||||
|
||||
vpath = vfs_path_from_str (ETALON_PATH_STR);
|
||||
serialized_vpath = vfs_path_serialize (vpath, &error);
|
||||
vfs_path_free (vpath);
|
||||
|
||||
if (serialized_vpath == NULL)
|
||||
{
|
||||
fail ("serialized_vpath is NULL!\nError code is '%d'; error message is '%s'", error->code, error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
fail_unless (
|
||||
strcmp (serialized_vpath, ETALON_SERIALIZED_PATH ) == 0,
|
||||
"\nserialized_vpath (%s)\nnot equal to etalon (%s)", serialized_vpath, ETALON_SERIALIZED_PATH
|
||||
);
|
||||
|
||||
vpath = vfs_path_deserialize (serialized_vpath, &error);
|
||||
g_free (serialized_vpath);
|
||||
|
||||
if (vpath == NULL)
|
||||
{
|
||||
fail ("vpath is NULL!\nError code is '%d'; error message is '%s'", error->code, error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
serialized_vpath = vfs_path_to_str (vpath);
|
||||
fail_unless (
|
||||
strcmp (serialized_vpath, ETALON_PATH_URL_STR) == 0,
|
||||
"\ndeserialized path (%s)\nnot equal to etalon (%s)", serialized_vpath, ETALON_PATH_URL_STR
|
||||
);
|
||||
vfs_path_free(vpath);
|
||||
g_free(serialized_vpath);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int number_failed;
|
||||
|
||||
Suite *s = suite_create (TEST_SUITE_NAME);
|
||||
TCase *tc_core = tcase_create ("Core");
|
||||
SRunner *sr;
|
||||
|
||||
tcase_add_checked_fixture (tc_core, setup, teardown);
|
||||
|
||||
/* Add new tests here: *************** */
|
||||
tcase_add_test (tc_core, test_path_serialize_deserialize);
|
||||
/* *********************************** */
|
||||
|
||||
suite_add_tcase (s, tc_core);
|
||||
sr = srunner_create (s);
|
||||
srunner_set_log (sr, "path_serialize.log");
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
number_failed = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
return (number_failed == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
336
lib/tests/vfs/vfs_path_string_convert.c
Обычный файл
336
lib/tests/vfs/vfs_path_string_convert.c
Обычный файл
@ -0,0 +1,336 @@
|
||||
/* lib/vfs - get vfs_path_t from string
|
||||
|
||||
Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2011
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
as published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define TEST_SUITE_NAME "/lib/vfs"
|
||||
|
||||
#include <check.h>
|
||||
|
||||
#include "lib/global.c"
|
||||
|
||||
#ifndef HAVE_CHARSET
|
||||
#define HAVE_CHARSET 1
|
||||
#endif
|
||||
|
||||
#include "lib/charsets.h"
|
||||
|
||||
#include "lib/strutil.h"
|
||||
#include "lib/vfs/xdirentry.h"
|
||||
#include "lib/vfs/path.c" /* for testing static methods */
|
||||
|
||||
#include "src/vfs/local/local.c"
|
||||
|
||||
struct vfs_s_subclass test_subclass1, test_subclass2, test_subclass3;
|
||||
struct vfs_class vfs_test_ops1, vfs_test_ops2, vfs_test_ops3;
|
||||
|
||||
static void
|
||||
setup (void)
|
||||
{
|
||||
|
||||
str_init_strings (NULL);
|
||||
|
||||
vfs_init ();
|
||||
init_localfs ();
|
||||
vfs_setup_work_dir ();
|
||||
|
||||
|
||||
vfs_s_init_class (&vfs_test_ops1, &test_subclass1);
|
||||
|
||||
vfs_test_ops1.name = "testfs1";
|
||||
vfs_test_ops1.flags = VFSF_NOLINKS;
|
||||
vfs_test_ops1.prefix = "test1";
|
||||
vfs_register_class (&vfs_test_ops1);
|
||||
|
||||
test_subclass2.flags = VFS_S_REMOTE;
|
||||
vfs_s_init_class (&vfs_test_ops2, &test_subclass2);
|
||||
vfs_test_ops2.name = "testfs2";
|
||||
vfs_test_ops2.prefix = "test2";
|
||||
vfs_register_class (&vfs_test_ops2);
|
||||
|
||||
vfs_s_init_class (&vfs_test_ops3, &test_subclass3);
|
||||
vfs_test_ops3.name = "testfs3";
|
||||
vfs_test_ops3.prefix = "test3";
|
||||
vfs_register_class (&vfs_test_ops3);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
teardown (void)
|
||||
{
|
||||
vfs_shut ();
|
||||
str_uninit_strings ();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
#define ETALON_PATH_STR "/#test1/bla-bla/some/path/#test2/bla-bla/some/path#test3/111/22/33"
|
||||
#define ETALON_PATH_URL_STR "/test1://bla-bla/some/path/test2://bla-bla/some/path/test3://111/22/33"
|
||||
START_TEST (test_vfs_path_from_to_string)
|
||||
{
|
||||
vfs_path_t *vpath;
|
||||
size_t vpath_len;
|
||||
char *result;
|
||||
vpath = vfs_path_from_str (ETALON_PATH_STR);
|
||||
|
||||
|
||||
vpath_len = vfs_path_elements_count(vpath);
|
||||
fail_unless(vpath_len == 4, "vpath length should be 4 (actial: %d)",vpath_len);
|
||||
|
||||
result = vfs_path_to_str(vpath);
|
||||
fail_unless(strcmp(ETALON_PATH_URL_STR, result) == 0, "expected(%s) doesn't equal to actual(%s)", ETALON_PATH_URL_STR, result);
|
||||
g_free(result);
|
||||
|
||||
vfs_path_free(vpath);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
START_TEST (test_vfs_path_from_to_string2)
|
||||
{
|
||||
vfs_path_t *vpath;
|
||||
size_t vpath_len;
|
||||
char *result;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
vpath = vfs_path_from_str ("/");
|
||||
|
||||
|
||||
vpath_len = vfs_path_elements_count(vpath);
|
||||
fail_unless(vpath_len == 1, "vpath length should be 1 (actial: %d)",vpath_len);
|
||||
|
||||
result = vfs_path_to_str(vpath);
|
||||
fail_unless(strcmp("/", result) == 0, "expected(%s) doesn't equal to actual(%s)", "/", result);
|
||||
g_free(result);
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
fail_unless(strcmp("/", path_element->path) == 0, "expected(%s) doesn't equal to actual(%s)", "/", path_element->path);
|
||||
|
||||
fail_unless(path_element->class == &vfs_local_ops , "actual vfs-class doesn't equal to localfs");
|
||||
|
||||
vfs_path_free(vpath);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
START_TEST (test_vfs_path_from_to_partial_string_by_class)
|
||||
{
|
||||
vfs_path_t *vpath;
|
||||
char *result;
|
||||
vpath = vfs_path_from_str (ETALON_PATH_STR);
|
||||
|
||||
|
||||
result = vfs_path_to_str_elements_count(vpath, -1);
|
||||
fail_unless(
|
||||
strcmp("/test1://bla-bla/some/path/test2://bla-bla/some/path", result) == 0,
|
||||
"expected(%s) doesn't equal to actual(%s)", "/test1://bla-bla/some/path/test2://bla-bla/some/path", result);
|
||||
g_free(result);
|
||||
|
||||
result = vfs_path_to_str_elements_count(vpath, -2);
|
||||
fail_unless(
|
||||
strcmp("/test1://bla-bla/some/path/", result) == 0,
|
||||
"expected(%s) doesn't equal to actual(%s)", "/test1://bla-bla/some/path/", result);
|
||||
g_free(result);
|
||||
|
||||
result = vfs_path_to_str_elements_count(vpath, -3);
|
||||
fail_unless(
|
||||
strcmp("/", result) == 0,
|
||||
"expected(%s) doesn't equal to actual(%s)", "/", result);
|
||||
g_free(result);
|
||||
|
||||
/* index out of bound*/
|
||||
result = vfs_path_to_str_elements_count(vpath, -4);
|
||||
fail_unless(
|
||||
strcmp("", result) == 0,
|
||||
"expected(%s) doesn't equal to actual(%s)", "", result);
|
||||
g_free(result);
|
||||
|
||||
|
||||
result = vfs_path_to_str_elements_count(vpath, 1);
|
||||
fail_unless(
|
||||
strcmp("/", result) == 0,
|
||||
"expected(%s) doesn't equal to actual(%s)", "/", result);
|
||||
g_free(result);
|
||||
|
||||
result = vfs_path_to_str_elements_count(vpath, 2);
|
||||
fail_unless(
|
||||
strcmp("/test1://bla-bla/some/path/", result) == 0,
|
||||
"expected(%s) doesn't equal to actual(%s)", "/test1://bla-bla/some/path/", result);
|
||||
g_free(result);
|
||||
|
||||
result = vfs_path_to_str_elements_count(vpath, 3);
|
||||
fail_unless(
|
||||
strcmp("/test1://bla-bla/some/path/test2://bla-bla/some/path", result) == 0,
|
||||
"expected(%s) doesn't equal to actual(%s)", "/test1://bla-bla/some/path/test2://bla-bla/some/path", result);
|
||||
g_free(result);
|
||||
|
||||
result = vfs_path_to_str_elements_count(vpath, 4);
|
||||
fail_unless(
|
||||
strcmp(ETALON_PATH_URL_STR, result) == 0,
|
||||
"expected(%s) doesn't equal to actual(%s)", ETALON_PATH_URL_STR, result);
|
||||
g_free(result);
|
||||
|
||||
/* index out of bound*/
|
||||
result = vfs_path_to_str_elements_count(vpath, 5);
|
||||
fail_unless(
|
||||
strcmp(ETALON_PATH_URL_STR, result) == 0,
|
||||
"expected(%s) doesn't equal to actual(%s)", ETALON_PATH_URL_STR, result);
|
||||
g_free(result);
|
||||
|
||||
vfs_path_free(vpath);
|
||||
}
|
||||
END_TEST
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define encoding_check( input , etalon ) \
|
||||
{ \
|
||||
vfs_path_t *vpath; \
|
||||
char *result; \
|
||||
\
|
||||
vpath = vfs_path_from_str (input); \
|
||||
result = vfs_path_to_str(vpath); \
|
||||
fail_unless( result != NULL && strcmp(result, etalon) ==0, \
|
||||
"\ninput : %s\nactual: %s\netalon: %s", input, result , etalon ); \
|
||||
\
|
||||
g_free(result); \
|
||||
vfs_path_free(vpath); \
|
||||
}
|
||||
|
||||
START_TEST (test_vfs_path_from_to_string_encoding)
|
||||
{
|
||||
mc_global.sysconfig_dir = (char *) TEST_SHARE_DIR;
|
||||
load_codepages_list ();
|
||||
|
||||
encoding_check (
|
||||
"/#test1/bla-bla1/some/path/#test2/bla-bla2/#enc:KOI8-R/some/path#test3/111/22/33",
|
||||
"/test1://bla-bla1/some/path/test2://#enc:KOI8-R/bla-bla2/some/path/test3://111/22/33"
|
||||
);
|
||||
|
||||
encoding_check (
|
||||
"/#test1/bla-bla1/#enc:IBM866/some/path/#test2/bla-bla2/#enc:KOI8-R/some/path#test3/111/22/33",
|
||||
"/test1://#enc:IBM866/bla-bla1/some/path/test2://#enc:KOI8-R/bla-bla2/some/path/test3://111/22/33"
|
||||
);
|
||||
|
||||
encoding_check (
|
||||
"/#test1/bla-bla1/some/path/#test2/bla-bla2/#enc:IBM866/#enc:KOI8-R/some/path#test3/111/22/33",
|
||||
"/test1://bla-bla1/some/path/test2://#enc:KOI8-R/bla-bla2/some/path/test3://111/22/33"
|
||||
);
|
||||
|
||||
encoding_check (
|
||||
"/#test1/bla-bla1/some/path/#test2/bla-bla2/#enc:IBM866/some/#enc:KOI8-R/path#test3/111/22/33",
|
||||
"/test1://bla-bla1/some/path/test2://#enc:KOI8-R/bla-bla2/some/path/test3://111/22/33"
|
||||
);
|
||||
|
||||
encoding_check (
|
||||
"/#test1/bla-bla1/some/path/#test2/#enc:IBM866/bla-bla2/#enc:KOI8-R/some/path#test3/111/22/33",
|
||||
"/test1://bla-bla1/some/path/test2://#enc:KOI8-R/bla-bla2/some/path/test3://111/22/33"
|
||||
);
|
||||
|
||||
encoding_check (
|
||||
"/#test1/bla-bla1/some/path/#enc:IBM866/#test2/bla-bla2/#enc:KOI8-R/some/path#test3/111/22/33",
|
||||
"/test1://#enc:IBM866/bla-bla1/some/path/test2://#enc:KOI8-R/bla-bla2/some/path/test3://111/22/33"
|
||||
);
|
||||
|
||||
free_codepages_list ();
|
||||
}
|
||||
|
||||
END_TEST
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
#define ETALON_STR "/path/to/file.ext/test1://#enc:KOI8-R"
|
||||
START_TEST (test_vfs_path_encoding_at_end)
|
||||
{
|
||||
vfs_path_t *vpath;
|
||||
char *result;
|
||||
vfs_path_element_t *element;
|
||||
|
||||
mc_global.sysconfig_dir = (char *) TEST_SHARE_DIR;
|
||||
load_codepages_list ();
|
||||
|
||||
vpath = vfs_path_from_str ("/path/to/file.ext#test1:/#enc:KOI8-R");
|
||||
result = vfs_path_to_str(vpath);
|
||||
|
||||
element = vfs_path_get_by_index(vpath, -1);
|
||||
fail_unless(*element->path == '\0', "element->path should be empty, but actual value is '%s'",element->path);
|
||||
fail_unless(element->encoding != NULL && strcmp(element->encoding, "KOI8-R") == 0,
|
||||
"element->encoding should be 'KOI8-R', but actual value is '%s'",element->encoding);
|
||||
|
||||
fail_unless( result != NULL && strcmp(result, ETALON_STR) ==0,
|
||||
"\nactual: %s\netalon: %s", result , ETALON_STR );
|
||||
|
||||
g_free(result);
|
||||
vfs_path_free(vpath);
|
||||
|
||||
free_codepages_list ();
|
||||
}
|
||||
|
||||
END_TEST
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
#undef ETALON_PATH_STR
|
||||
#define ETALON_PATH_STR "/test1://bla-bla/some/path/test2://user:passwd@some.host:1234/bla-bla/some/path/test3://111/22/33"
|
||||
START_TEST (test_vfs_path_from_to_string_uri)
|
||||
{
|
||||
vfs_path_t *vpath;
|
||||
size_t vpath_len;
|
||||
char *result;
|
||||
vpath = vfs_path_from_str (ETALON_PATH_STR);
|
||||
|
||||
vpath_len = vfs_path_elements_count(vpath);
|
||||
fail_unless(vpath_len == 4, "vpath length should be 4 (actial: %d)",vpath_len);
|
||||
|
||||
result = vfs_path_to_str(vpath);
|
||||
fail_unless(strcmp(ETALON_PATH_STR, result) == 0, "\nexpected(%s)\ndoesn't equal to actual(%s)", ETALON_PATH_STR, result);
|
||||
g_free(result);
|
||||
|
||||
vfs_path_free(vpath);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int number_failed;
|
||||
|
||||
Suite *s = suite_create (TEST_SUITE_NAME);
|
||||
TCase *tc_core = tcase_create ("Core");
|
||||
SRunner *sr;
|
||||
|
||||
tcase_add_checked_fixture (tc_core, setup, teardown);
|
||||
|
||||
/* Add new tests here: *************** */
|
||||
tcase_add_test (tc_core, test_vfs_path_from_to_string);
|
||||
tcase_add_test (tc_core, test_vfs_path_from_to_string2);
|
||||
tcase_add_test (tc_core, test_vfs_path_from_to_partial_string_by_class);
|
||||
tcase_add_test (tc_core, test_vfs_path_from_to_string_encoding);
|
||||
tcase_add_test (tc_core, test_vfs_path_encoding_at_end);
|
||||
tcase_add_test (tc_core, test_vfs_path_from_to_string_uri);
|
||||
/* *********************************** */
|
||||
|
||||
suite_add_tcase (s, tc_core);
|
||||
sr = srunner_create (s);
|
||||
srunner_set_log (sr, "vfs_path_string_convert.log");
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
number_failed = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
return (number_failed == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
144
lib/tests/vfs/vfs_prefix_to_class.c
Обычный файл
144
lib/tests/vfs/vfs_prefix_to_class.c
Обычный файл
@ -0,0 +1,144 @@
|
||||
/* lib/vfs - test vfs_prefix_to_class() functionality
|
||||
|
||||
Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2011
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
as published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define TEST_SUITE_NAME "/lib/vfs"
|
||||
|
||||
#include <check.h>
|
||||
|
||||
|
||||
#include "lib/global.h"
|
||||
#include "lib/strutil.h"
|
||||
#include "lib/vfs/xdirentry.h"
|
||||
#include "lib/vfs/vfs.c" /* for testing static methods */
|
||||
|
||||
#include "src/vfs/local/local.c"
|
||||
|
||||
struct vfs_s_subclass test_subclass1, test_subclass2, test_subclass3;
|
||||
struct vfs_class vfs_test_ops1, vfs_test_ops2, vfs_test_ops3;
|
||||
|
||||
|
||||
static int
|
||||
test_which (struct vfs_class *me, const char *path)
|
||||
{
|
||||
(void) me;
|
||||
|
||||
if (
|
||||
(strcmp(path, "test_1:") == 0) ||
|
||||
(strcmp(path, "test_2:") == 0) ||
|
||||
(strcmp(path, "test_3:") == 0) ||
|
||||
(strcmp(path, "test_4:") == 0)
|
||||
)
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
setup (void)
|
||||
{
|
||||
|
||||
str_init_strings (NULL);
|
||||
|
||||
vfs_init ();
|
||||
init_localfs ();
|
||||
vfs_setup_work_dir ();
|
||||
|
||||
|
||||
test_subclass1.flags = VFS_S_REMOTE;
|
||||
vfs_s_init_class (&vfs_test_ops1, &test_subclass1);
|
||||
vfs_test_ops1.name = "testfs1";
|
||||
vfs_test_ops1.flags = VFSF_NOLINKS;
|
||||
vfs_test_ops1.prefix = "test1:";
|
||||
vfs_test_ops1.which = test_which;
|
||||
vfs_register_class (&vfs_test_ops1);
|
||||
|
||||
vfs_s_init_class (&vfs_test_ops2, &test_subclass2);
|
||||
vfs_test_ops2.name = "testfs2";
|
||||
vfs_test_ops2.prefix = "test2:";
|
||||
vfs_register_class (&vfs_test_ops2);
|
||||
|
||||
vfs_s_init_class (&vfs_test_ops3, &test_subclass3);
|
||||
vfs_test_ops3.name = "testfs3";
|
||||
vfs_test_ops3.prefix = "test3:";
|
||||
vfs_register_class (&vfs_test_ops3);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
teardown (void)
|
||||
{
|
||||
vfs_shut ();
|
||||
str_uninit_strings ();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
START_TEST (test_vfs_prefix_to_class_valid)
|
||||
{
|
||||
fail_unless(vfs_prefix_to_class((char *) "test_1:") == &vfs_test_ops1, "'test_1:' doesn't transform to vfs_test_ops1");
|
||||
fail_unless(vfs_prefix_to_class((char *) "test_2:") == &vfs_test_ops1, "'test_2:' doesn't transform to vfs_test_ops1");
|
||||
fail_unless(vfs_prefix_to_class((char *) "test_3:") == &vfs_test_ops1, "'test_3:' doesn't transform to vfs_test_ops1");
|
||||
fail_unless(vfs_prefix_to_class((char *) "test_4:") == &vfs_test_ops1, "'test_4:' doesn't transform to vfs_test_ops1");
|
||||
|
||||
fail_unless(vfs_prefix_to_class((char *) "test2:") == &vfs_test_ops2, "'test2:' doesn't transform to vfs_test_ops2");
|
||||
|
||||
fail_unless(vfs_prefix_to_class((char *) "test3:") == &vfs_test_ops3, "'test3:' doesn't transform to vfs_test_ops3");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
START_TEST (test_vfs_prefix_to_class_invalid)
|
||||
{
|
||||
fail_unless(vfs_prefix_to_class((char *) "test1:") == NULL, "'test1:' doesn't transform to NULL");
|
||||
fail_unless(vfs_prefix_to_class((char *) "test_5:") == NULL, "'test_5:' doesn't transform to NULL");
|
||||
fail_unless(vfs_prefix_to_class((char *) "test4:") == NULL, "'test4:' doesn't transform to NULL");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int number_failed;
|
||||
|
||||
Suite *s = suite_create (TEST_SUITE_NAME);
|
||||
TCase *tc_core = tcase_create ("Core");
|
||||
SRunner *sr;
|
||||
|
||||
tcase_add_checked_fixture (tc_core, setup, teardown);
|
||||
|
||||
/* Add new tests here: *************** */
|
||||
tcase_add_test (tc_core, test_vfs_prefix_to_class_valid);
|
||||
tcase_add_test (tc_core, test_vfs_prefix_to_class_invalid);
|
||||
/* *********************************** */
|
||||
|
||||
suite_add_tcase (s, tc_core);
|
||||
sr = srunner_create (s);
|
||||
srunner_set_log (sr, "vfs_prefix_to_class.log");
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
number_failed = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
return (number_failed == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
169
lib/tests/vfs/vfs_s_get_path.c
Обычный файл
169
lib/tests/vfs/vfs_s_get_path.c
Обычный файл
@ -0,0 +1,169 @@
|
||||
/* lib/vfs - test vfs_s_get_path() function
|
||||
|
||||
Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2011
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
as published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define TEST_SUITE_NAME "/lib/vfs"
|
||||
|
||||
#include <check.h>
|
||||
|
||||
|
||||
#include "lib/global.h"
|
||||
#include "lib/strutil.h"
|
||||
#include "lib/vfs/direntry.c" /* for testing static methods */
|
||||
|
||||
#include "src/vfs/local/local.c"
|
||||
|
||||
#define ARCH_NAME "/path/to/some/file.ext"
|
||||
#define ETALON_PATH "path/to/test1_file.ext"
|
||||
#define ETALON_VFS_NAME "#test2:user:pass@host.net"
|
||||
#define ETALON_VFS_URL_NAME "test2://user:pass@host.net"
|
||||
|
||||
struct vfs_s_subclass test_subclass1, test_subclass2, test_subclass3;
|
||||
struct vfs_class vfs_test_ops1, vfs_test_ops2, vfs_test_ops3;
|
||||
|
||||
static int
|
||||
test1_mock_open_archive(struct vfs_s_super *super, const vfs_path_t *vpath, const vfs_path_element_t *vpath_element)
|
||||
{
|
||||
struct vfs_s_inode *root;
|
||||
char *spath = vfs_path_to_str (vpath);
|
||||
|
||||
fail_unless(strcmp("/" ETALON_VFS_URL_NAME ARCH_NAME, spath) == 0,
|
||||
"etalon(%s) doesn't equal to actual(%s)", "/" ETALON_VFS_URL_NAME ARCH_NAME, spath);
|
||||
|
||||
super->name = g_strdup (spath);
|
||||
super->data = g_new (char *, 1);
|
||||
root = vfs_s_new_inode (vpath_element->class, super, NULL);
|
||||
super->root = root;
|
||||
g_free(spath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
test1_mock_archive_same (const vfs_path_element_t *vpath_element, struct vfs_s_super *super,
|
||||
const vfs_path_t *vpath, void *cookie)
|
||||
{
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index(vpath, -1);
|
||||
|
||||
(void) vpath_element;
|
||||
(void) super;
|
||||
(void) cookie;
|
||||
|
||||
if (strcmp(ARCH_NAME, path_element->path) != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
setup (void)
|
||||
{
|
||||
|
||||
str_init_strings (NULL);
|
||||
|
||||
vfs_init ();
|
||||
init_localfs ();
|
||||
vfs_setup_work_dir ();
|
||||
|
||||
|
||||
test_subclass1.flags = VFS_S_REMOTE;
|
||||
vfs_s_init_class (&vfs_test_ops1, &test_subclass1);
|
||||
|
||||
vfs_test_ops1.name = "testfs1";
|
||||
vfs_test_ops1.flags = VFSF_NOLINKS;
|
||||
vfs_test_ops1.prefix = "test1:";
|
||||
vfs_register_class (&vfs_test_ops1);
|
||||
test_subclass1.open_archive = test1_mock_open_archive;
|
||||
test_subclass1.archive_same = test1_mock_archive_same;
|
||||
test_subclass1.archive_check = NULL;
|
||||
|
||||
vfs_s_init_class (&vfs_test_ops2, &test_subclass2);
|
||||
vfs_test_ops2.name = "testfs2";
|
||||
vfs_test_ops2.prefix = "test2:";
|
||||
vfs_register_class (&vfs_test_ops2);
|
||||
|
||||
vfs_s_init_class (&vfs_test_ops3, &test_subclass3);
|
||||
vfs_test_ops3.name = "testfs3";
|
||||
vfs_test_ops3.prefix = "test3:";
|
||||
vfs_register_class (&vfs_test_ops3);
|
||||
}
|
||||
|
||||
static void
|
||||
teardown (void)
|
||||
{
|
||||
vfs_shut ();
|
||||
str_uninit_strings ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
vfs_die (const char *m)
|
||||
{
|
||||
printf("VFS_DIE: '%s'\n", m);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
START_TEST (test_vfs_s_get_path)
|
||||
{
|
||||
struct vfs_s_super *archive;
|
||||
|
||||
const char *result;
|
||||
vfs_path_t *vpath = vfs_path_from_str("/" ETALON_VFS_NAME ARCH_NAME "#test1:/" ETALON_PATH);
|
||||
|
||||
result = vfs_s_get_path (vpath, &archive, 0);
|
||||
|
||||
fail_unless(strcmp(ETALON_PATH, result) == 0,
|
||||
"expected(%s) doesn't equal to actual(%s)", ETALON_PATH, result);
|
||||
|
||||
fail_unless(strcmp("/" ETALON_VFS_URL_NAME ARCH_NAME,archive->name) == 0,
|
||||
"expected(%s) doesn't equal to actual(%s)", "/" ETALON_VFS_URL_NAME ARCH_NAME, archive->name);
|
||||
|
||||
g_free(vpath);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int number_failed;
|
||||
|
||||
Suite *s = suite_create (TEST_SUITE_NAME);
|
||||
TCase *tc_core = tcase_create ("Core");
|
||||
SRunner *sr;
|
||||
|
||||
tcase_add_checked_fixture (tc_core, setup, teardown);
|
||||
|
||||
/* Add new tests here: *************** */
|
||||
tcase_add_test (tc_core, test_vfs_s_get_path);
|
||||
/* *********************************** */
|
||||
|
||||
suite_add_tcase (s, tc_core);
|
||||
sr = srunner_create (s);
|
||||
srunner_set_log (sr, "vfs_s_get_path.log");
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
number_failed = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
return (number_failed == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
267
lib/tests/vfs/vfs_split.c
Обычный файл
267
lib/tests/vfs/vfs_split.c
Обычный файл
@ -0,0 +1,267 @@
|
||||
/* lib/vfs - test vfs_split() functionality
|
||||
|
||||
Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2011
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
as published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define TEST_SUITE_NAME "/lib/vfs"
|
||||
|
||||
#include <check.h>
|
||||
|
||||
|
||||
#include "lib/global.h"
|
||||
#include "lib/strutil.h"
|
||||
#include "lib/vfs/xdirentry.h"
|
||||
#include "lib/vfs/path.c" /* for testing static methods */
|
||||
|
||||
#include "src/vfs/local/local.c"
|
||||
|
||||
struct vfs_s_subclass test_subclass1, test_subclass2, test_subclass3;
|
||||
struct vfs_class vfs_test_ops1, vfs_test_ops2, vfs_test_ops3;
|
||||
|
||||
static void
|
||||
setup (void)
|
||||
{
|
||||
|
||||
str_init_strings (NULL);
|
||||
|
||||
vfs_init ();
|
||||
init_localfs ();
|
||||
vfs_setup_work_dir ();
|
||||
|
||||
|
||||
test_subclass1.flags = VFS_S_REMOTE;
|
||||
vfs_s_init_class (&vfs_test_ops1, &test_subclass1);
|
||||
|
||||
vfs_test_ops1.name = "testfs1";
|
||||
vfs_test_ops1.flags = VFSF_NOLINKS;
|
||||
vfs_test_ops1.prefix = "test1:";
|
||||
vfs_register_class (&vfs_test_ops1);
|
||||
|
||||
vfs_s_init_class (&vfs_test_ops2, &test_subclass2);
|
||||
vfs_test_ops2.name = "testfs2";
|
||||
vfs_test_ops2.prefix = "test2:";
|
||||
vfs_register_class (&vfs_test_ops2);
|
||||
|
||||
vfs_s_init_class (&vfs_test_ops3, &test_subclass3);
|
||||
vfs_test_ops3.name = "testfs3";
|
||||
vfs_test_ops3.prefix = "test3:";
|
||||
vfs_register_class (&vfs_test_ops3);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
teardown (void)
|
||||
{
|
||||
vfs_shut ();
|
||||
str_uninit_strings ();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
START_TEST (test_vfs_split)
|
||||
{
|
||||
char *path;
|
||||
const char *local, *op, *etalon_path, *etalon_local, *etalon_op;
|
||||
struct vfs_class *result;
|
||||
|
||||
path = g_strdup("#test1:/bla-bla/some/path/#test2:/bla-bla/some/path2/#test3:/qqq/www/eee.rr");
|
||||
|
||||
etalon_path = "#test1:/bla-bla/some/path/#test2:/bla-bla/some/path2/";
|
||||
etalon_local = "qqq/www/eee.rr";
|
||||
etalon_op = "test3:";
|
||||
result = _vfs_split_with_semi_skip_count (path, &local, &op, 0);
|
||||
fail_unless(result == &vfs_test_ops3, "Result(%p) doesn't match to vfs_test_ops3(%p)", result, &vfs_test_ops3);
|
||||
fail_unless(strcmp (path, etalon_path) == 0, "path('%s') doesn't match to '%s'", path, etalon_path);
|
||||
fail_unless(strcmp (local, etalon_local) == 0, "parsed local path('%s') doesn't match to '%s'", local, etalon_local);
|
||||
fail_unless(strcmp (op, etalon_op) == 0, "parsed VFS name ('%s') doesn't match to '%s'", op, etalon_op);
|
||||
|
||||
etalon_path = "#test1:/bla-bla/some/path/";
|
||||
etalon_local = "bla-bla/some/path2/";
|
||||
etalon_op = "test2:";
|
||||
result = _vfs_split_with_semi_skip_count (path, &local, &op, 0);
|
||||
fail_unless(result == &vfs_test_ops2, "Result(%p) doesn't match to vfs_test_ops2(%p)", result, &vfs_test_ops2);
|
||||
fail_unless(strcmp (path, etalon_path) == 0, "path('%s') doesn't match to '%s'", path, etalon_path);
|
||||
fail_unless(strcmp (local, etalon_local) == 0, "parsed local path('%s') doesn't match to '%s'", local, etalon_local);
|
||||
fail_unless(strcmp (op, etalon_op) == 0, "parsed VFS name ('%s') doesn't match to '%s'", op, etalon_op);
|
||||
|
||||
etalon_path = "";
|
||||
etalon_local = "bla-bla/some/path/";
|
||||
etalon_op = "test1:";
|
||||
result = _vfs_split_with_semi_skip_count (path, &local, &op, 0);
|
||||
fail_unless(result == &vfs_test_ops1, "Result(%p) doesn't match to vfs_test_ops1(%p)", result, &vfs_test_ops2);
|
||||
fail_unless(strcmp (path, etalon_path) == 0, "path('%s') doesn't match to '%s'", path, etalon_path);
|
||||
fail_unless(strcmp (local, etalon_local) == 0, "parsed local path('%s') doesn't match to '%s'", local, etalon_local);
|
||||
fail_unless(strcmp (op, etalon_op) == 0, "parsed VFS name ('%s') doesn't match to '%s'", op, etalon_op);
|
||||
|
||||
result = _vfs_split_with_semi_skip_count (path, &local, &op, 0);
|
||||
fail_unless(result == NULL, "Result(%p) doesn't match to vfs_test_ops1(NULL)", result);
|
||||
fail_unless(strcmp (path, etalon_path) == 0, "path('%s') doesn't match to '%s'", path, etalon_path);
|
||||
fail_unless(strcmp (local, etalon_local) == 0, "parsed local path('%s') doesn't match to '%s'", local, etalon_local);
|
||||
fail_unless(strcmp (op, etalon_op) == 0, "parsed VFS name ('%s') doesn't match to '%s'", op, etalon_op);
|
||||
|
||||
g_free(path);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
START_TEST (test_vfs_split_with_local)
|
||||
{
|
||||
char *path;
|
||||
const char *local, *op, *etalon_path, *etalon_local, *etalon_op;
|
||||
struct vfs_class *result;
|
||||
|
||||
path = g_strdup("/local/path/#test1:/bla-bla/some/path/#test2:/bla-bla/some/path2#test3:/qqq/www/eee.rr");
|
||||
|
||||
etalon_path = "/local/path/#test1:/bla-bla/some/path/#test2:/bla-bla/some/path2";
|
||||
etalon_local = "qqq/www/eee.rr";
|
||||
etalon_op = "test3:";
|
||||
result = _vfs_split_with_semi_skip_count (path, &local, &op, 0);
|
||||
fail_unless(result == &vfs_test_ops3, "Result(%p) doesn't match to vfs_test_ops3(%p)", result, &vfs_test_ops3);
|
||||
fail_unless(strcmp (path, etalon_path) == 0, "path('%s') doesn't match to '%s'", path, etalon_path);
|
||||
fail_unless(strcmp (local, etalon_local) == 0, "parsed local path('%s') doesn't match to '%s'", local, etalon_local);
|
||||
fail_unless(strcmp (op, etalon_op) == 0, "parsed VFS name ('%s') doesn't match to '%s'", op, etalon_op);
|
||||
|
||||
etalon_path = "/local/path/#test1:/bla-bla/some/path/";
|
||||
etalon_local = "bla-bla/some/path2";
|
||||
etalon_op = "test2:";
|
||||
result = _vfs_split_with_semi_skip_count (path, &local, &op, 0);
|
||||
fail_unless(result == &vfs_test_ops2, "Result(%p) doesn't match to vfs_test_ops2(%p)", result, &vfs_test_ops2);
|
||||
fail_unless(strcmp (path, etalon_path) == 0, "path('%s') doesn't match to '%s'", path, etalon_path);
|
||||
fail_unless(strcmp (local, etalon_local) == 0, "parsed local path('%s') doesn't match to '%s'", local, etalon_local);
|
||||
fail_unless(strcmp (op, etalon_op) == 0, "parsed VFS name ('%s') doesn't match to '%s'", op, etalon_op);
|
||||
|
||||
etalon_path = "/local/path/";
|
||||
etalon_local = "bla-bla/some/path/";
|
||||
etalon_op = "test1:";
|
||||
result = _vfs_split_with_semi_skip_count (path, &local, &op, 0);
|
||||
fail_unless(result == &vfs_test_ops1, "Result(%p) doesn't match to vfs_test_ops1(%p)", result, &vfs_test_ops2);
|
||||
fail_unless(strcmp (path, etalon_path) == 0, "path('%s') doesn't match to '%s'", path, etalon_path);
|
||||
fail_unless(strcmp (local, etalon_local) == 0, "parsed local path('%s') doesn't match to '%s'", local, etalon_local);
|
||||
fail_unless(strcmp (op, etalon_op) == 0, "parsed VFS name ('%s') doesn't match to '%s'", op, etalon_op);
|
||||
|
||||
result = _vfs_split_with_semi_skip_count (path, &local, &op, 0);
|
||||
fail_unless(result == NULL, "Result(%p) doesn't match to vfs_test_ops1(NULL)", result);
|
||||
|
||||
g_free(path);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
START_TEST (test_vfs_split_url)
|
||||
{
|
||||
char *path;
|
||||
const char *local, *op, *etalon_path, *etalon_local, *etalon_op;
|
||||
struct vfs_class *result;
|
||||
|
||||
path = g_strdup("#test2:username:passwd@somehost.net/bla-bla/some/path2");
|
||||
|
||||
etalon_path = "";
|
||||
etalon_local = "bla-bla/some/path2";
|
||||
etalon_op = "test2:username:passwd@somehost.net";
|
||||
result = _vfs_split_with_semi_skip_count (path, &local, &op, 0);
|
||||
fail_unless(result == &vfs_test_ops2, "Result(%p) doesn't match to vfs_test_ops2(%p)", result, &vfs_test_ops2);
|
||||
fail_unless(path != NULL && strcmp (path, etalon_path) == 0, "path('%s') doesn't match to '%s'", path, etalon_path);
|
||||
fail_unless(local != NULL && strcmp (local, etalon_local) == 0, "parsed local path('%s') doesn't match to '%s'", local, etalon_local);
|
||||
fail_unless(op != NULL && strcmp (op, etalon_op) == 0, "parsed VFS name ('%s') doesn't match to '%s'", op, etalon_op);
|
||||
|
||||
g_free(path);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
START_TEST (test_vfs_split_url_with_semi)
|
||||
{
|
||||
char *path;
|
||||
const char *local, *op, *etalon_path, *etalon_local, *etalon_op;
|
||||
struct vfs_class *result;
|
||||
|
||||
|
||||
path = g_strdup("/local/path/#test1:/bla-bla/some/path/#test2:username:p!a@s#s$w%d@somehost.net/bla-bla/some/path2");
|
||||
|
||||
etalon_path = "/local/path/#test1:/bla-bla/some/path/";
|
||||
etalon_local = "bla-bla/some/path2";
|
||||
etalon_op = "test2:username:p!a@s#s$w%d@somehost.net";
|
||||
result = _vfs_split_with_semi_skip_count (path, &local, &op, 0);
|
||||
fail_unless(result == &vfs_test_ops2, "Result(%p) doesn't match to vfs_test_ops2(%p)", result, &vfs_test_ops2);
|
||||
fail_unless(path != NULL && strcmp (path, etalon_path) == 0, "path('%s') doesn't match to '%s'", path, etalon_path);
|
||||
fail_unless(local != NULL && strcmp (local, etalon_local) == 0, "parsed local path('%s') doesn't match to '%s'", local, etalon_local);
|
||||
fail_unless(op != NULL && strcmp (op, etalon_op) == 0, "parsed VFS name ('%s') doesn't match to '%s'", op, etalon_op);
|
||||
|
||||
g_free(path);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
START_TEST (test_vfs_split_with_semi_in_path)
|
||||
{
|
||||
char *path;
|
||||
const char *local, *op, *etalon_path, *etalon_local, *etalon_op;
|
||||
struct vfs_class *result;
|
||||
|
||||
path = g_strdup("#test2:/bl#a-bl#a/so#me/pa#th2");
|
||||
|
||||
etalon_path = "";
|
||||
etalon_local = "bl#a-bl#a/so#me/pa#th2";
|
||||
etalon_op = "test2:";
|
||||
result = _vfs_split_with_semi_skip_count (path, &local, &op, 0);
|
||||
fail_unless(result == &vfs_test_ops2, "Result(%p) doesn't match to vfs_test_ops2(%p)", result, &vfs_test_ops2);
|
||||
fail_unless(path != NULL && strcmp (path, etalon_path) == 0, "path('%s') doesn't match to '%s'", path, etalon_path);
|
||||
fail_unless(local != NULL && strcmp (local, etalon_local) == 0, "parsed local path('%s') doesn't match to '%s'", local, etalon_local);
|
||||
fail_unless(op != NULL && strcmp (op, etalon_op) == 0, "parsed VFS name ('%s') doesn't match to '%s'", op, etalon_op);
|
||||
|
||||
g_free(path);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int number_failed;
|
||||
|
||||
Suite *s = suite_create (TEST_SUITE_NAME);
|
||||
TCase *tc_core = tcase_create ("Core");
|
||||
SRunner *sr;
|
||||
|
||||
tcase_add_checked_fixture (tc_core, setup, teardown);
|
||||
|
||||
/* Add new tests here: *************** */
|
||||
tcase_add_test (tc_core, test_vfs_split);
|
||||
tcase_add_test (tc_core, test_vfs_split_with_local);
|
||||
tcase_add_test (tc_core, test_vfs_split_url);
|
||||
tcase_add_test (tc_core, test_vfs_split_url_with_semi);
|
||||
tcase_add_test (tc_core, test_vfs_split_with_semi_in_path);
|
||||
/* *********************************** */
|
||||
|
||||
suite_add_tcase (s, tc_core);
|
||||
sr = srunner_create (s);
|
||||
srunner_set_log (sr, "vfs_split.log");
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
number_failed = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
return (number_failed == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
98
lib/tests/x_basename.c
Обычный файл
98
lib/tests/x_basename.c
Обычный файл
@ -0,0 +1,98 @@
|
||||
/* lib/vfs - x_basename() function testing
|
||||
|
||||
Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2011
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
as published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define TEST_SUITE_NAME "/lib"
|
||||
|
||||
#include <check.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lib/global.h"
|
||||
#include "lib/strutil.h"
|
||||
#include "lib/util.h"
|
||||
|
||||
|
||||
static void
|
||||
setup (void)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
teardown (void)
|
||||
{
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
#define check_x_basename( input, etalon ) \
|
||||
{ \
|
||||
result = x_basename ( input ); \
|
||||
fail_unless(strcmp(result, etalon) == 0, \
|
||||
"\ninput (%s)\nactial (%s) not equal to\netalon (%s)", input, result, etalon); \
|
||||
}
|
||||
|
||||
START_TEST (test_x_basename)
|
||||
{
|
||||
const char *result;
|
||||
check_x_basename ("/test/path/test2/path2", "path2");
|
||||
|
||||
check_x_basename ("/test/path/test2/path2#vfsprefix", "path2#vfsprefix");
|
||||
|
||||
check_x_basename ("/test/path/test2/path2/vfsprefix://", "path2/vfsprefix://");
|
||||
|
||||
|
||||
check_x_basename ("/test/path/test2/path2/vfsprefix://subdir", "subdir");
|
||||
|
||||
check_x_basename ("/test/path/test2/path2/vfsprefix://subdir/", "subdir/");
|
||||
|
||||
check_x_basename ("/test/path/test2/path2/vfsprefix://subdir/subdir2", "subdir2");
|
||||
|
||||
check_x_basename ("/test/path/test2/path2/vfsprefix:///", "/");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int number_failed;
|
||||
|
||||
Suite *s = suite_create (TEST_SUITE_NAME);
|
||||
TCase *tc_core = tcase_create ("Core");
|
||||
SRunner *sr;
|
||||
|
||||
tcase_add_checked_fixture (tc_core, setup, teardown);
|
||||
|
||||
/* Add new tests here: *************** */
|
||||
tcase_add_test (tc_core, test_x_basename);
|
||||
/* *********************************** */
|
||||
|
||||
suite_add_tcase (s, tc_core);
|
||||
sr = srunner_create (s);
|
||||
srunner_set_log (sr, "x_basename.log");
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
number_failed = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
return (number_failed == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
35
lib/util.c
35
lib/util.c
@ -668,8 +668,29 @@ extract_line (const char *s, const char *top)
|
||||
const char *
|
||||
x_basename (const char *s)
|
||||
{
|
||||
const char *where;
|
||||
return ((where = strrchr (s, PATH_SEP))) ? where + 1 : s;
|
||||
const char *url_delim, *path_sep;
|
||||
|
||||
url_delim = g_strrstr (s, VFS_PATH_URL_DELIMITER);
|
||||
path_sep = strrchr (s, PATH_SEP);
|
||||
|
||||
if (url_delim == NULL
|
||||
|| url_delim < path_sep - strlen (VFS_PATH_URL_DELIMITER)
|
||||
|| url_delim - s + strlen (VFS_PATH_URL_DELIMITER) < strlen (s))
|
||||
{
|
||||
/* avoid trailing PATH_SEP, if present */
|
||||
if (s[strlen (s) - 1] == PATH_SEP)
|
||||
{
|
||||
while (--path_sep > s && *path_sep != PATH_SEP);
|
||||
return (path_sep != s) ? path_sep + 1 : s;
|
||||
}
|
||||
else
|
||||
return (path_sep != NULL) ? path_sep + 1 : s;
|
||||
}
|
||||
|
||||
while (--url_delim > s && *url_delim != PATH_SEP);
|
||||
while (--url_delim > s && *url_delim != PATH_SEP);
|
||||
|
||||
return (url_delim == s) ? s : url_delim + 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -890,15 +911,15 @@ decompress_extension (int type)
|
||||
switch (type)
|
||||
{
|
||||
case COMPRESSION_GZIP:
|
||||
return "#ugz";
|
||||
return "/ugz" VFS_PATH_URL_DELIMITER;
|
||||
case COMPRESSION_BZIP:
|
||||
return "#ubz";
|
||||
return "/ubz" VFS_PATH_URL_DELIMITER;
|
||||
case COMPRESSION_BZIP2:
|
||||
return "#ubz2";
|
||||
return "/ubz2" VFS_PATH_URL_DELIMITER;
|
||||
case COMPRESSION_LZMA:
|
||||
return "#ulzma";
|
||||
return "/ulzma" VFS_PATH_URL_DELIMITER;
|
||||
case COMPRESSION_XZ:
|
||||
return "#uxz";
|
||||
return "/uxz" VFS_PATH_URL_DELIMITER;
|
||||
}
|
||||
/* Should never reach this place */
|
||||
fprintf (stderr, "Fatal: decompress_extension called with an unknown argument\n");
|
||||
|
@ -205,6 +205,8 @@ gboolean mc_util_unlink_backup_if_possible (const char *, const char *);
|
||||
|
||||
char *guess_message_value (void);
|
||||
|
||||
char *mc_build_filename (const char *first_element, ...);
|
||||
|
||||
/*** inline functions **************************************************/
|
||||
|
||||
static inline gboolean
|
||||
|
139
lib/utilunix.c
139
lib/utilunix.c
@ -56,6 +56,7 @@
|
||||
#include "lib/strutil.h" /* str_move() */
|
||||
#include "lib/util.h"
|
||||
#include "lib/widget.h" /* message() */
|
||||
#include "lib/vfs/xdirentry.h"
|
||||
|
||||
#ifdef HAVE_CHARSET
|
||||
#include "lib/charsets.h"
|
||||
@ -543,8 +544,9 @@ void
|
||||
custom_canonicalize_pathname (char *path, CANON_PATH_FLAGS flags)
|
||||
{
|
||||
char *p, *s;
|
||||
int len;
|
||||
size_t len;
|
||||
char *lpath = path; /* path without leading UNC part */
|
||||
const size_t url_delim_len = strlen (VFS_PATH_URL_DELIMITER);
|
||||
|
||||
/* Detect and preserve UNC paths: //server/... */
|
||||
if ((flags & CANON_PATH_GUARDUNC) && path[0] == PATH_SEP && path[1] == PATH_SEP)
|
||||
@ -565,7 +567,7 @@ custom_canonicalize_pathname (char *path, CANON_PATH_FLAGS flags)
|
||||
p = lpath;
|
||||
while (*p)
|
||||
{
|
||||
if (p[0] == PATH_SEP && p[1] == PATH_SEP)
|
||||
if (p[0] == PATH_SEP && p[1] == PATH_SEP && (p == lpath || *(p - 1) != ':'))
|
||||
{
|
||||
s = p + 1;
|
||||
while (*(++s) == PATH_SEP);
|
||||
@ -593,7 +595,12 @@ custom_canonicalize_pathname (char *path, CANON_PATH_FLAGS flags)
|
||||
/* Remove trailing slashes */
|
||||
p = lpath + strlen (lpath) - 1;
|
||||
while (p > lpath && *p == PATH_SEP)
|
||||
{
|
||||
if (p >= lpath - (url_delim_len + 1)
|
||||
&& strncmp (p - url_delim_len + 1, VFS_PATH_URL_DELIMITER, url_delim_len) == 0)
|
||||
break;
|
||||
*p-- = 0;
|
||||
}
|
||||
|
||||
/* Remove leading "./" */
|
||||
if (lpath[0] == '.' && lpath[1] == PATH_SEP)
|
||||
@ -613,9 +620,12 @@ custom_canonicalize_pathname (char *path, CANON_PATH_FLAGS flags)
|
||||
len = strlen (lpath);
|
||||
if (len < 2)
|
||||
return;
|
||||
if (lpath[len - 1] == PATH_SEP)
|
||||
if (lpath[len - 1] == PATH_SEP
|
||||
&& (len < url_delim_len
|
||||
|| strncmp (lpath + len - url_delim_len, VFS_PATH_URL_DELIMITER,
|
||||
url_delim_len) != 0))
|
||||
{
|
||||
lpath[len - 1] = 0;
|
||||
lpath[len - 1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -623,12 +633,12 @@ custom_canonicalize_pathname (char *path, CANON_PATH_FLAGS flags)
|
||||
{
|
||||
if (len == 2)
|
||||
{
|
||||
lpath[1] = 0;
|
||||
lpath[1] = '\0';
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
lpath[len - 2] = 0;
|
||||
lpath[len - 2] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -650,8 +660,63 @@ custom_canonicalize_pathname (char *path, CANON_PATH_FLAGS flags)
|
||||
|
||||
/* search for the previous token */
|
||||
s = p - 1;
|
||||
while (s >= lpath && *s != PATH_SEP)
|
||||
if (s >= lpath + url_delim_len - 2
|
||||
&& strncmp (s - url_delim_len + 2, VFS_PATH_URL_DELIMITER, url_delim_len) == 0)
|
||||
{
|
||||
s -= (url_delim_len - 2);
|
||||
while (s >= lpath && *s-- != PATH_SEP);
|
||||
}
|
||||
|
||||
while (s >= lpath)
|
||||
{
|
||||
if (s - url_delim_len > lpath
|
||||
&& strncmp (s - url_delim_len, VFS_PATH_URL_DELIMITER, url_delim_len) == 0)
|
||||
{
|
||||
char *vfs_prefix = s - url_delim_len;
|
||||
struct vfs_class *vclass;
|
||||
|
||||
while (vfs_prefix > lpath && *--vfs_prefix != PATH_SEP);
|
||||
if (*vfs_prefix == PATH_SEP)
|
||||
vfs_prefix++;
|
||||
*(s - url_delim_len) = '\0';
|
||||
|
||||
vclass = vfs_prefix_to_class (vfs_prefix);
|
||||
*(s - url_delim_len) = *VFS_PATH_URL_DELIMITER;
|
||||
|
||||
if (vclass != NULL)
|
||||
{
|
||||
struct vfs_s_subclass *sub = (struct vfs_s_subclass *) vclass->data;
|
||||
if (sub != NULL && sub->flags & VFS_S_REMOTE)
|
||||
{
|
||||
s = vfs_prefix;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*s == PATH_SEP)
|
||||
{
|
||||
/* skip VFS prefix */
|
||||
char *path_sep;
|
||||
struct vfs_class *vclass;
|
||||
|
||||
/* old parser mode */
|
||||
if (*(s + 1) != '#')
|
||||
break;
|
||||
|
||||
path_sep = strchr (s + 1, PATH_SEP);
|
||||
if (path_sep != NULL)
|
||||
*path_sep = '\0';
|
||||
|
||||
vclass = vfs_prefix_to_class (s + 2);
|
||||
if (path_sep != NULL)
|
||||
*path_sep = PATH_SEP;
|
||||
|
||||
if (vclass == NULL)
|
||||
break;
|
||||
}
|
||||
s--;
|
||||
}
|
||||
|
||||
s++;
|
||||
|
||||
@ -720,7 +785,13 @@ custom_canonicalize_pathname (char *path, CANON_PATH_FLAGS flags)
|
||||
}
|
||||
#endif /* HAVE_CHARSET */
|
||||
else
|
||||
s[-1] = 0;
|
||||
{
|
||||
if (s >= lpath + url_delim_len
|
||||
&& strncmp (s - url_delim_len, VFS_PATH_URL_DELIMITER, url_delim_len) == 0)
|
||||
*s = '\0';
|
||||
else
|
||||
s[-1] = '\0';
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -945,3 +1016,55 @@ get_user_permissions (struct stat *st)
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Build filename from arguments.
|
||||
* Like to g_build_filename(), but respect VFS_PATH_URL_DELIMITER
|
||||
*/
|
||||
|
||||
char *
|
||||
mc_build_filename (const char *first_element, ...)
|
||||
{
|
||||
va_list args;
|
||||
const char *element = first_element;
|
||||
GString *path;
|
||||
char *ret;
|
||||
|
||||
if (element == NULL)
|
||||
return NULL;
|
||||
|
||||
path = g_string_new ("");
|
||||
va_start (args, first_element);
|
||||
|
||||
do
|
||||
{
|
||||
char *tmp_element;
|
||||
size_t len;
|
||||
const char *start;
|
||||
|
||||
tmp_element = g_strdup (element);
|
||||
|
||||
element = va_arg (args, char *);
|
||||
|
||||
canonicalize_pathname (tmp_element);
|
||||
len = strlen (tmp_element);
|
||||
start = (tmp_element[0] == PATH_SEP) ? tmp_element + 1 : tmp_element;
|
||||
|
||||
g_string_append (path, start);
|
||||
if (tmp_element[len - 1] != PATH_SEP && element != NULL)
|
||||
g_string_append_c (path, PATH_SEP);
|
||||
|
||||
g_free (tmp_element);
|
||||
}
|
||||
while (element != NULL);
|
||||
|
||||
va_end (args);
|
||||
|
||||
g_string_prepend_c (path, PATH_SEP);
|
||||
|
||||
ret = g_string_free (path, FALSE);
|
||||
canonicalize_pathname (ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
@ -3,10 +3,13 @@ noinst_LTLIBRARIES = libmcvfs.la
|
||||
AM_CFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir)
|
||||
|
||||
libmcvfs_la_SOURCES = \
|
||||
direntry.c \
|
||||
gc.c gc.h \
|
||||
interface.c \
|
||||
path.c path.h \
|
||||
vfs.c vfs.h \
|
||||
direntry.c xdirentry.h \
|
||||
utilvfs.c utilvfs.h \
|
||||
gc.c gc.h
|
||||
xdirentry.h
|
||||
|
||||
if ENABLE_VFS_NET
|
||||
libmcvfs_la_SOURCES += netutil.c netutil.h
|
||||
|
@ -384,72 +384,70 @@ vfs_s_free_super (struct vfs_class *me, struct vfs_s_super *super)
|
||||
MEDATA->supers = g_list_remove (MEDATA->supers, super);
|
||||
|
||||
CALL (free_archive) (me, super);
|
||||
#ifdef ENABLE_VFS_NET
|
||||
vfs_path_element_free (super->path_element);
|
||||
#endif
|
||||
g_free (super->name);
|
||||
g_free (super);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Dissect the path and create corresponding superblock.
|
||||
* The result should be freed.
|
||||
*/
|
||||
|
||||
static char *
|
||||
vfs_s_get_path (struct vfs_class *me, const char *inname, struct vfs_s_super **archive, int flags)
|
||||
{
|
||||
char *buf, *retval;
|
||||
|
||||
buf = g_strdup (inname);
|
||||
retval = g_strdup (vfs_s_get_path_mangle (me, buf, archive, flags));
|
||||
g_free (buf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/* Support of archives */
|
||||
/* ------------------------ readdir & friends ----------------------------- */
|
||||
|
||||
static struct vfs_s_inode *
|
||||
vfs_s_inode_from_path (struct vfs_class *me, const char *name, int flags)
|
||||
vfs_s_inode_from_path (const vfs_path_t * vpath, int flags)
|
||||
{
|
||||
struct vfs_s_super *super;
|
||||
struct vfs_s_inode *ino;
|
||||
char *q;
|
||||
const char *q;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
if (!(q = vfs_s_get_path (me, name, &super, 0)))
|
||||
q = vfs_s_get_path (vpath, &super, 0);
|
||||
if (q == NULL)
|
||||
return NULL;
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
ino =
|
||||
vfs_s_find_inode (me, super, q,
|
||||
vfs_s_find_inode (path_element->class, super, q,
|
||||
flags & FL_FOLLOW ? LINK_FOLLOW : LINK_NO_FOLLOW, flags & ~FL_FOLLOW);
|
||||
if ((!ino) && (!*q))
|
||||
/* We are asking about / directory of ftp server: assume it exists */
|
||||
ino =
|
||||
vfs_s_find_inode (me, super, q,
|
||||
vfs_s_find_inode (path_element->class, super, q,
|
||||
flags & FL_FOLLOW ? LINK_FOLLOW :
|
||||
LINK_NO_FOLLOW, FL_DIR | (flags & ~FL_FOLLOW));
|
||||
g_free (q);
|
||||
return ino;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void *
|
||||
vfs_s_opendir (struct vfs_class *me, const char *dirname)
|
||||
vfs_s_opendir (const vfs_path_t * vpath)
|
||||
{
|
||||
struct vfs_s_inode *dir;
|
||||
struct dirhandle *info;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
dir = vfs_s_inode_from_path (me, dirname, FL_DIR | FL_FOLLOW);
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
dir = vfs_s_inode_from_path (vpath, FL_DIR | FL_FOLLOW);
|
||||
if (dir == NULL)
|
||||
return NULL;
|
||||
if (!S_ISDIR (dir->st.st_mode))
|
||||
ERRNOR (ENOTDIR, NULL);
|
||||
{
|
||||
path_element->class->verrno = ENOTDIR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dir->st.st_nlink++;
|
||||
#if 0
|
||||
if (dir->subdir == NULL) /* This can actually happen if we allow empty directories */
|
||||
ERRNOR (EAGAIN, NULL);
|
||||
{
|
||||
path_element->class->verrno = EAGAIN;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
info = g_new (struct dirhandle, 1);
|
||||
info->cur = dir->subdir;
|
||||
@ -498,11 +496,11 @@ vfs_s_closedir (void *data)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
vfs_s_chdir (struct vfs_class *me, const char *path)
|
||||
vfs_s_chdir (const vfs_path_t * vpath)
|
||||
{
|
||||
void *data;
|
||||
|
||||
data = vfs_s_opendir (me, path);
|
||||
data = vfs_s_opendir (vpath);
|
||||
if (data == NULL)
|
||||
return -1;
|
||||
vfs_s_closedir (data);
|
||||
@ -513,11 +511,11 @@ vfs_s_chdir (struct vfs_class *me, const char *path)
|
||||
/* --------------------------- stat and friends ---------------------------- */
|
||||
|
||||
static int
|
||||
vfs_s_internal_stat (struct vfs_class *me, const char *path, struct stat *buf, int flag)
|
||||
vfs_s_internal_stat (const vfs_path_t * vpath, struct stat *buf, int flag)
|
||||
{
|
||||
struct vfs_s_inode *ino;
|
||||
|
||||
ino = vfs_s_inode_from_path (me, path, flag);
|
||||
ino = vfs_s_inode_from_path (vpath, flag);
|
||||
if (ino == NULL)
|
||||
return -1;
|
||||
*buf = ino->st;
|
||||
@ -527,17 +525,17 @@ vfs_s_internal_stat (struct vfs_class *me, const char *path, struct stat *buf, i
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
vfs_s_stat (struct vfs_class *me, const char *path, struct stat *buf)
|
||||
vfs_s_stat (const vfs_path_t * vpath, struct stat *buf)
|
||||
{
|
||||
return vfs_s_internal_stat (me, path, buf, FL_FOLLOW);
|
||||
return vfs_s_internal_stat (vpath, buf, FL_FOLLOW);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
vfs_s_lstat (struct vfs_class *me, const char *path, struct stat *buf)
|
||||
vfs_s_lstat (const vfs_path_t * vpath, struct stat *buf)
|
||||
{
|
||||
return vfs_s_internal_stat (me, path, buf, FL_NONE);
|
||||
return vfs_s_internal_stat (vpath, buf, FL_NONE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -552,20 +550,29 @@ vfs_s_fstat (void *fh, struct stat *buf)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
vfs_s_readlink (struct vfs_class *me, const char *path, char *buf, size_t size)
|
||||
vfs_s_readlink (const vfs_path_t * vpath, char *buf, size_t size)
|
||||
{
|
||||
struct vfs_s_inode *ino;
|
||||
size_t len;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
ino = vfs_s_inode_from_path (me, path, 0);
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
ino = vfs_s_inode_from_path (vpath, 0);
|
||||
if (!ino)
|
||||
return -1;
|
||||
|
||||
if (!S_ISLNK (ino->st.st_mode))
|
||||
ERRNOR (EINVAL, -1);
|
||||
{
|
||||
path_element->class->verrno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ino->linkname == NULL)
|
||||
ERRNOR (EFAULT, -1);
|
||||
{
|
||||
path_element->class->verrno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = strlen (ino->linkname);
|
||||
if (size < len)
|
||||
@ -738,7 +745,7 @@ vfs_s_fill_names (struct vfs_class *me, fill_names_f func)
|
||||
const struct vfs_s_super *super = (const struct vfs_s_super *) iter->data;
|
||||
char *name;
|
||||
|
||||
name = g_strconcat (super->name, "#", me->prefix, "/",
|
||||
name = g_strconcat (super->name, "/", me->prefix, VFS_PATH_URL_DELIMITER,
|
||||
/* super->current_dir->name, */ (char *) NULL);
|
||||
func (name);
|
||||
g_free (name);
|
||||
@ -760,12 +767,12 @@ vfs_s_ferrno (struct vfs_class *me)
|
||||
*/
|
||||
|
||||
static char *
|
||||
vfs_s_getlocalcopy (struct vfs_class *me, const char *path)
|
||||
vfs_s_getlocalcopy (const vfs_path_t * vpath)
|
||||
{
|
||||
vfs_file_handler_t *fh;
|
||||
char *local = NULL;
|
||||
|
||||
fh = vfs_s_open (me, path, O_RDONLY, 0);
|
||||
fh = vfs_s_open (vpath, O_RDONLY, 0);
|
||||
|
||||
if (fh != NULL)
|
||||
{
|
||||
@ -785,10 +792,9 @@ vfs_s_getlocalcopy (struct vfs_class *me, const char *path)
|
||||
*/
|
||||
|
||||
static int
|
||||
vfs_s_ungetlocalcopy (struct vfs_class *me, const char *path, const char *local, int has_changed)
|
||||
vfs_s_ungetlocalcopy (const vfs_path_t * vpath, const char *local, int has_changed)
|
||||
{
|
||||
(void) me;
|
||||
(void) path;
|
||||
(void) vpath;
|
||||
(void) local;
|
||||
(void) has_changed;
|
||||
return 0;
|
||||
@ -797,13 +803,16 @@ vfs_s_ungetlocalcopy (struct vfs_class *me, const char *path, const char *local,
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
vfs_s_setctl (struct vfs_class *me, const char *path, int ctlop, void *arg)
|
||||
vfs_s_setctl (const vfs_path_t * vpath, int ctlop, void *arg)
|
||||
{
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
switch (ctlop)
|
||||
{
|
||||
case VFS_SETCTL_STALE_DATA:
|
||||
{
|
||||
struct vfs_s_inode *ino = vfs_s_inode_from_path (me, path, 0);
|
||||
struct vfs_s_inode *ino = vfs_s_inode_from_path (vpath, 0);
|
||||
|
||||
if (ino == NULL)
|
||||
return 0;
|
||||
@ -812,15 +821,15 @@ vfs_s_setctl (struct vfs_class *me, const char *path, int ctlop, void *arg)
|
||||
else
|
||||
{
|
||||
ino->super->want_stale = 0;
|
||||
vfs_s_invalidate (me, ino->super);
|
||||
vfs_s_invalidate (path_element->class, ino->super);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
case VFS_SETCTL_LOGFILE:
|
||||
MEDATA->logfile = fopen ((char *) arg, "w");
|
||||
((struct vfs_s_subclass *) path_element->class->data)->logfile = fopen ((char *) arg, "w");
|
||||
return 1;
|
||||
case VFS_SETCTL_FLUSH:
|
||||
MEDATA->flush = 1;
|
||||
((struct vfs_s_subclass *) path_element->class->data)->flush = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -830,15 +839,15 @@ vfs_s_setctl (struct vfs_class *me, const char *path, int ctlop, void *arg)
|
||||
/* ----------------------------- Stamping support -------------------------- */
|
||||
|
||||
static vfsid
|
||||
vfs_s_getid (struct vfs_class *me, const char *path)
|
||||
vfs_s_getid (const vfs_path_t * vpath)
|
||||
{
|
||||
struct vfs_s_super *archive = NULL;
|
||||
char *p;
|
||||
const char *p;
|
||||
|
||||
p = vfs_s_get_path (me, path, &archive, FL_NO_OPEN);
|
||||
p = vfs_s_get_path (vpath, &archive, FL_NO_OPEN);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
g_free (p);
|
||||
|
||||
return (vfsid) archive;
|
||||
}
|
||||
|
||||
@ -1020,41 +1029,53 @@ vfs_s_find_inode (struct vfs_class *me, const struct vfs_s_super *super,
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/* Ook, these were functions around directory entries / inodes */
|
||||
/* -------------------------------- superblock games -------------------------- */
|
||||
|
||||
/*
|
||||
* Dissect the path and create corresponding superblock. Note that inname
|
||||
* can be changed and the result may point inside the original string.
|
||||
/**
|
||||
* get path from last VFS-element and create corresponding superblock
|
||||
*
|
||||
* @param vpath source path object
|
||||
* @param archive pointer to object for store newly created superblock
|
||||
* @param flags flags
|
||||
*
|
||||
* @return path from last VFS-element
|
||||
*/
|
||||
const char *
|
||||
vfs_s_get_path_mangle (struct vfs_class *me, char *inname, struct vfs_s_super **archive, int flags)
|
||||
vfs_s_get_path (const vfs_path_t * vpath, struct vfs_s_super **archive, int flags)
|
||||
{
|
||||
GList *iter;
|
||||
const char *retval;
|
||||
char *local, *op;
|
||||
const char *archive_name;
|
||||
int result = -1;
|
||||
struct vfs_s_super *super;
|
||||
void *cookie = NULL;
|
||||
vfs_path_element_t *path_element;
|
||||
vfs_path_t *vpath_archive;
|
||||
struct vfs_s_subclass *subclass;
|
||||
|
||||
archive_name = inname;
|
||||
vfs_split (inname, &local, &op);
|
||||
retval = (local != NULL) ? local : "";
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
subclass = ((struct vfs_s_subclass *) path_element->class->data);
|
||||
|
||||
if (MEDATA->archive_check != NULL)
|
||||
vpath_archive = vfs_path_clone (vpath);
|
||||
vfs_path_remove_element_by_index (vpath_archive, -1);
|
||||
|
||||
retval = (path_element->path != NULL) ? path_element->path : "";
|
||||
|
||||
if (subclass->archive_check != NULL)
|
||||
{
|
||||
cookie = MEDATA->archive_check (me, archive_name, op);
|
||||
cookie = subclass->archive_check (vpath_archive);
|
||||
if (cookie == NULL)
|
||||
{
|
||||
vfs_path_free (vpath_archive);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (iter = MEDATA->supers; iter != NULL; iter = g_list_next (iter))
|
||||
for (iter = subclass->supers; iter != NULL; iter = g_list_next (iter))
|
||||
{
|
||||
int i;
|
||||
|
||||
super = (struct vfs_s_super *) iter->data;
|
||||
|
||||
/* 0 == other, 1 == same, return it, 2 == other but stop scanning */
|
||||
i = MEDATA->archive_same (me, super, archive_name, op, cookie);
|
||||
i = subclass->archive_same (path_element, super, vpath_archive, cookie);
|
||||
if (i != 0)
|
||||
{
|
||||
if (i == 1)
|
||||
@ -1064,26 +1085,33 @@ vfs_s_get_path_mangle (struct vfs_class *me, char *inname, struct vfs_s_super **
|
||||
}
|
||||
|
||||
if (flags & FL_NO_OPEN)
|
||||
ERRNOR (EIO, NULL);
|
||||
{
|
||||
path_element->class->verrno = EIO;
|
||||
vfs_path_free (vpath_archive);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
super = vfs_s_new_super (me);
|
||||
if (MEDATA->open_archive != NULL)
|
||||
result = MEDATA->open_archive (me, super, archive_name, op);
|
||||
super = vfs_s_new_super (path_element->class);
|
||||
if (subclass->open_archive != NULL)
|
||||
result = subclass->open_archive (super, vpath_archive, path_element);
|
||||
if (result == -1)
|
||||
{
|
||||
vfs_s_free_super (me, super);
|
||||
ERRNOR (EIO, NULL);
|
||||
vfs_s_free_super (path_element->class, super);
|
||||
path_element->class->verrno = EIO;
|
||||
vfs_path_free (vpath_archive);
|
||||
return NULL;
|
||||
}
|
||||
if (!super->name)
|
||||
vfs_die ("You have to fill name\n");
|
||||
if (!super->root)
|
||||
vfs_die ("You have to fill root inode\n");
|
||||
|
||||
vfs_s_insert_super (me, super);
|
||||
vfs_stamp_create (me, super);
|
||||
vfs_s_insert_super (path_element->class, super);
|
||||
vfs_stamp_create (path_element->class, super);
|
||||
|
||||
return_success:
|
||||
*archive = super;
|
||||
vfs_path_free (vpath_archive);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -1135,63 +1163,64 @@ vfs_s_fullpath (struct vfs_class *me, struct vfs_s_inode *ino)
|
||||
/* --------------------------- stat and friends ---------------------------- */
|
||||
|
||||
void *
|
||||
vfs_s_open (struct vfs_class *me, const char *file, int flags, mode_t mode)
|
||||
vfs_s_open (const vfs_path_t * vpath, int flags, mode_t mode)
|
||||
{
|
||||
int was_changed = 0;
|
||||
vfs_file_handler_t *fh;
|
||||
struct vfs_s_super *super;
|
||||
char *q;
|
||||
const char *q;
|
||||
struct vfs_s_inode *ino;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
q = vfs_s_get_path (me, file, &super, 0);
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
q = vfs_s_get_path (vpath, &super, 0);
|
||||
if (q == NULL)
|
||||
return NULL;
|
||||
ino = vfs_s_find_inode (me, super, q, LINK_FOLLOW, FL_NONE);
|
||||
ino = vfs_s_find_inode (path_element->class, super, q, LINK_FOLLOW, FL_NONE);
|
||||
if (ino && ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)))
|
||||
{
|
||||
g_free (q);
|
||||
ERRNOR (EEXIST, NULL);
|
||||
path_element->class->verrno = EEXIST;
|
||||
return NULL;
|
||||
}
|
||||
if (!ino)
|
||||
{
|
||||
char *dirname, *name, *save;
|
||||
char *dirname, *name, *save, *q_mangle;
|
||||
struct vfs_s_entry *ent;
|
||||
struct vfs_s_inode *dir;
|
||||
int tmp_handle;
|
||||
|
||||
/* If the filesystem is read-only, disable file creation */
|
||||
if (!(flags & O_CREAT) || !(me->write))
|
||||
{
|
||||
g_free (q);
|
||||
if (!(flags & O_CREAT) || !(path_element->class->write))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
split_dir_name (me, q, &dirname, &name, &save);
|
||||
dir = vfs_s_find_inode (me, super, dirname, LINK_FOLLOW, FL_DIR);
|
||||
q_mangle = g_strdup (q);
|
||||
split_dir_name (path_element->class, q_mangle, &dirname, &name, &save);
|
||||
dir = vfs_s_find_inode (path_element->class, super, dirname, LINK_FOLLOW, FL_DIR);
|
||||
if (dir == NULL)
|
||||
{
|
||||
g_free (q);
|
||||
g_free (q_mangle);
|
||||
return NULL;
|
||||
}
|
||||
if (save)
|
||||
*save = PATH_SEP;
|
||||
ent = vfs_s_generate_entry (me, name, dir, 0755);
|
||||
ent = vfs_s_generate_entry (path_element->class, name, dir, 0755);
|
||||
ino = ent->ino;
|
||||
vfs_s_insert_entry (me, dir, ent);
|
||||
tmp_handle = vfs_mkstemps (&ino->localname, me->name, name);
|
||||
vfs_s_insert_entry (path_element->class, dir, ent);
|
||||
tmp_handle = vfs_mkstemps (&ino->localname, path_element->class->name, name);
|
||||
g_free (q_mangle);
|
||||
if (tmp_handle == -1)
|
||||
{
|
||||
g_free (q);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
close (tmp_handle);
|
||||
was_changed = 1;
|
||||
}
|
||||
|
||||
g_free (q);
|
||||
|
||||
if (S_ISDIR (ino->st.st_mode))
|
||||
ERRNOR (EISDIR, NULL);
|
||||
{
|
||||
path_element->class->verrno = EISDIR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fh = g_new (vfs_file_handler_t, 1);
|
||||
fh->pos = 0;
|
||||
@ -1203,13 +1232,14 @@ vfs_s_open (struct vfs_class *me, const char *file, int flags, mode_t mode)
|
||||
|
||||
if (IS_LINEAR (flags))
|
||||
{
|
||||
if (MEDATA->linear_start)
|
||||
if (VFSDATA (path_element)->linear_start)
|
||||
{
|
||||
vfs_print_message (_("Starting linear transfer..."));
|
||||
fh->linear = LS_LINEAR_PREOPEN;
|
||||
}
|
||||
}
|
||||
else if ((MEDATA->fh_open != NULL) && (MEDATA->fh_open (me, fh, flags, mode) != 0))
|
||||
else if ((VFSDATA (path_element)->fh_open != NULL)
|
||||
&& (VFSDATA (path_element)->fh_open (path_element->class, fh, flags, mode) != 0))
|
||||
{
|
||||
g_free (fh);
|
||||
return NULL;
|
||||
@ -1221,12 +1251,13 @@ vfs_s_open (struct vfs_class *me, const char *file, int flags, mode_t mode)
|
||||
if (fh->handle == -1)
|
||||
{
|
||||
g_free (fh);
|
||||
ERRNOR (errno, NULL);
|
||||
path_element->class->verrno = errno;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* i.e. we had no open files and now we have one */
|
||||
vfs_rmstamp (me, (vfsid) super);
|
||||
vfs_rmstamp (path_element->class, (vfsid) super);
|
||||
super->fd_usage++;
|
||||
fh->ino->st.st_nlink++;
|
||||
return fh;
|
||||
@ -1350,18 +1381,15 @@ vfs_s_init_class (struct vfs_class *vclass, struct vfs_s_subclass *sub)
|
||||
/** Find VFS id for given directory name */
|
||||
|
||||
vfsid
|
||||
vfs_getid (struct vfs_class *vclass, const char *dir)
|
||||
vfs_getid (const vfs_path_t * vpath)
|
||||
{
|
||||
char *dir1;
|
||||
vfsid id = NULL;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
/* append slash if needed */
|
||||
dir1 = concat_dir_and_file (dir, "");
|
||||
if (vclass->getid)
|
||||
id = (*vclass->getid) (vclass, dir1);
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
if (!vfs_path_element_valid (path_element) || path_element->class->getid == NULL)
|
||||
return NULL;
|
||||
|
||||
g_free (dir1);
|
||||
return id;
|
||||
return (*path_element->class->getid) (vpath);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
49
lib/vfs/gc.c
49
lib/vfs/gc.c
@ -153,12 +153,16 @@ vfs_rmstamp (struct vfs_class *v, vfsid id)
|
||||
void
|
||||
vfs_stamp_path (const char *path)
|
||||
{
|
||||
struct vfs_class *vfs;
|
||||
vfsid id;
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
vfs = vfs_get_class (path);
|
||||
id = vfs_getid (vfs, path);
|
||||
vfs_addstamp (vfs, id);
|
||||
vpath = vfs_path_from_str (path);
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
id = vfs_getid (vpath);
|
||||
vfs_addstamp (path_element->class, id);
|
||||
vfs_path_free (vpath);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -169,10 +173,11 @@ vfs_stamp_path (const char *path)
|
||||
void
|
||||
vfs_stamp_create (struct vfs_class *vclass, vfsid id)
|
||||
{
|
||||
struct vfs_class *nvfs;
|
||||
vfsid nvfsid;
|
||||
|
||||
ev_vfs_stamp_create_t event_data = { vclass, id, FALSE };
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
/* There are three directories we have to take care of: current_dir,
|
||||
current_panel->cwd and other_panel->cwd. Athough most of the time either
|
||||
@ -182,20 +187,20 @@ vfs_stamp_create (struct vfs_class *vclass, vfsid id)
|
||||
if (!mc_event_present (MCEVENT_GROUP_CORE, "vfs_timestamp"))
|
||||
return;
|
||||
|
||||
nvfs = vfs_get_class (vfs_get_current_dir ());
|
||||
nvfsid = vfs_getid (nvfs, vfs_get_current_dir ());
|
||||
vfs_rmstamp (nvfs, nvfsid);
|
||||
vpath = vfs_get_raw_current_dir ();
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
if (id == NULL || (nvfs == vclass && nvfsid == id))
|
||||
return;
|
||||
nvfsid = vfs_getid (vpath);
|
||||
vfs_rmstamp (path_element->class, nvfsid);
|
||||
|
||||
mc_event_raise (MCEVENT_GROUP_CORE, "vfs_timestamp", (gpointer) &event_data);
|
||||
if (!(id == NULL || (path_element->class == vclass && nvfsid == id)))
|
||||
{
|
||||
mc_event_raise (MCEVENT_GROUP_CORE, "vfs_timestamp", (gpointer) & event_data);
|
||||
|
||||
if (event_data.ret)
|
||||
return;
|
||||
|
||||
if (vclass != NULL && vclass->nothingisopen != NULL && vclass->nothingisopen (id) != 0)
|
||||
vfs_addstamp (vclass, id);
|
||||
if (!event_data.ret && vclass != NULL && vclass->nothingisopen != NULL
|
||||
&& vclass->nothingisopen (id) != 0)
|
||||
vfs_addstamp (vclass, id);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -260,12 +265,14 @@ vfs_timeout_handler (void)
|
||||
void
|
||||
vfs_release_path (const char *dir)
|
||||
{
|
||||
struct vfs_class *oldvfs;
|
||||
vfsid oldvfsid;
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
oldvfs = vfs_get_class (dir);
|
||||
oldvfsid = vfs_getid (oldvfs, dir);
|
||||
vfs_stamp_create (oldvfs, oldvfsid);
|
||||
vpath = vfs_path_from_str (dir);
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
vfs_stamp_create (path_element->class, vfs_getid (vpath));
|
||||
vfs_path_free (vpath);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
@ -29,7 +29,6 @@ struct vfs_stamping
|
||||
void vfs_stamp (struct vfs_class *vclass, vfsid id);
|
||||
void vfs_rmstamp (struct vfs_class *vclass, vfsid id);
|
||||
void vfs_stamp_create (struct vfs_class *vclass, vfsid id);
|
||||
vfsid vfs_getid (struct vfs_class *vclass, const char *dir);
|
||||
void vfs_gc_done (void);
|
||||
|
||||
/*** inline functions ****************************************************************************/
|
||||
|
778
lib/vfs/interface.c
Обычный файл
778
lib/vfs/interface.c
Обычный файл
@ -0,0 +1,778 @@
|
||||
/* Virtual File System: interface functions
|
||||
Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2011
|
||||
|
||||
This file is part of the Midnight Commander.
|
||||
|
||||
The Midnight Commander is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The Midnight Commander is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \brief Source: Virtual File System: path handlers
|
||||
* \author Slava Zanko
|
||||
* \date 2011
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* For atol() */
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h> /* is_digit() */
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "lib/global.h"
|
||||
|
||||
#include "lib/widget.h" /* message() */
|
||||
#include "lib/strutil.h" /* str_crt_conv_from() */
|
||||
|
||||
#include "vfs.h"
|
||||
#include "utilvfs.h"
|
||||
#include "path.h"
|
||||
#include "gc.h"
|
||||
|
||||
extern GString *vfs_str_buffer;
|
||||
extern struct vfs_class *current_vfs;
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
struct dirent *mc_readdir_result = NULL;
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static char *
|
||||
mc_def_getlocalcopy (const char *filename)
|
||||
{
|
||||
char *tmp;
|
||||
int fdin, fdout;
|
||||
ssize_t i;
|
||||
char buffer[8192];
|
||||
struct stat mystat;
|
||||
|
||||
fdin = mc_open (filename, O_RDONLY | O_LINEAR);
|
||||
if (fdin == -1)
|
||||
return NULL;
|
||||
|
||||
fdout = vfs_mkstemps (&tmp, "vfs", filename);
|
||||
|
||||
if (fdout == -1)
|
||||
goto fail;
|
||||
while ((i = mc_read (fdin, buffer, sizeof (buffer))) > 0)
|
||||
{
|
||||
if (write (fdout, buffer, i) != i)
|
||||
goto fail;
|
||||
}
|
||||
if (i == -1)
|
||||
goto fail;
|
||||
i = mc_close (fdin);
|
||||
fdin = -1;
|
||||
if (i == -1)
|
||||
goto fail;
|
||||
if (close (fdout) == -1)
|
||||
{
|
||||
fdout = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (mc_stat (filename, &mystat) != -1)
|
||||
chmod (tmp, mystat.st_mode);
|
||||
|
||||
return tmp;
|
||||
|
||||
fail:
|
||||
if (fdout != -1)
|
||||
close (fdout);
|
||||
if (fdin != -1)
|
||||
mc_close (fdin);
|
||||
g_free (tmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
mc_def_ungetlocalcopy (struct vfs_class *vfs, const char *filename,
|
||||
const char *local, int has_changed)
|
||||
{
|
||||
int fdin = -1, fdout = -1;
|
||||
if (has_changed)
|
||||
{
|
||||
char buffer[8192];
|
||||
ssize_t i;
|
||||
|
||||
if (!vfs->write)
|
||||
goto failed;
|
||||
|
||||
fdin = open (local, O_RDONLY);
|
||||
if (fdin == -1)
|
||||
goto failed;
|
||||
fdout = mc_open (filename, O_WRONLY | O_TRUNC);
|
||||
if (fdout == -1)
|
||||
goto failed;
|
||||
while ((i = read (fdin, buffer, sizeof (buffer))) > 0)
|
||||
if (mc_write (fdout, buffer, (size_t) i) != i)
|
||||
goto failed;
|
||||
if (i == -1)
|
||||
goto failed;
|
||||
|
||||
if (close (fdin) == -1)
|
||||
{
|
||||
fdin = -1;
|
||||
goto failed;
|
||||
}
|
||||
fdin = -1;
|
||||
if (mc_close (fdout) == -1)
|
||||
{
|
||||
fdout = -1;
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
unlink (local);
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
message (D_ERROR, _("Changes to file lost"), "%s", filename);
|
||||
if (fdout != -1)
|
||||
mc_close (fdout);
|
||||
if (fdin != -1)
|
||||
close (fdin);
|
||||
unlink (local);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*** public functions ****************************************************************************/
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
mc_open (const char *filename, int flags, ...)
|
||||
{
|
||||
int mode = 0, result = -1;
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
vpath = vfs_path_from_str (filename);
|
||||
if (vpath == NULL)
|
||||
return -1;
|
||||
|
||||
/* Get the mode flag */
|
||||
if (flags & O_CREAT)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, flags);
|
||||
mode = va_arg (ap, int);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
if (vfs_path_element_valid (path_element) && path_element->class->open != NULL)
|
||||
{
|
||||
void *info;
|
||||
/* open must be supported */
|
||||
info = path_element->class->open (vpath, flags, mode);
|
||||
if (info == NULL)
|
||||
errno = vfs_ferrno (path_element->class);
|
||||
else
|
||||
result = vfs_new_handle (path_element->class, info);
|
||||
}
|
||||
else
|
||||
errno = -EOPNOTSUPP;
|
||||
|
||||
vfs_path_free (vpath);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
|
||||
#define MC_NAMEOP(name, inarg, callarg) \
|
||||
int mc_##name inarg \
|
||||
{ \
|
||||
int result; \
|
||||
vfs_path_t *vpath; \
|
||||
vfs_path_element_t *path_element; \
|
||||
\
|
||||
vpath = vfs_path_from_str (path); \
|
||||
if (vpath == NULL) \
|
||||
return -1; \
|
||||
\
|
||||
path_element = vfs_path_get_by_index (vpath, -1); \
|
||||
if (!vfs_path_element_valid (path_element)) \
|
||||
{ \
|
||||
vfs_path_free(vpath); \
|
||||
return -1; \
|
||||
} \
|
||||
\
|
||||
result = path_element->class->name != NULL ? path_element->class->name callarg : -1; \
|
||||
if (result == -1) \
|
||||
errno = path_element->class->name != NULL ? vfs_ferrno (path_element->class) : E_NOTSUPP; \
|
||||
vfs_path_free(vpath); \
|
||||
return result; \
|
||||
}
|
||||
|
||||
MC_NAMEOP (chmod, (const char *path, mode_t mode), (vpath, mode))
|
||||
MC_NAMEOP (chown, (const char *path, uid_t owner, gid_t group), (vpath, owner, group))
|
||||
MC_NAMEOP (utime, (const char *path, struct utimbuf * times), (vpath, times))
|
||||
MC_NAMEOP (readlink, (const char *path, char *buf, size_t bufsiz), (vpath, buf, bufsiz))
|
||||
MC_NAMEOP (unlink, (const char *path), (vpath))
|
||||
MC_NAMEOP (mkdir, (const char *path, mode_t mode), (vpath, mode))
|
||||
MC_NAMEOP (rmdir, (const char *path), (vpath))
|
||||
MC_NAMEOP (mknod, (const char *path, mode_t mode, dev_t dev), (vpath, mode, dev))
|
||||
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
mc_symlink (const char *name1, const char *path)
|
||||
{
|
||||
int result = -1;
|
||||
vfs_path_t *vpath1, *vpath2;
|
||||
|
||||
vpath1 = vfs_path_from_str (path);
|
||||
if (vpath1 == NULL)
|
||||
return -1;
|
||||
|
||||
vpath2 = vfs_path_from_str (name1);
|
||||
|
||||
if (vpath2 != NULL)
|
||||
{
|
||||
vfs_path_element_t *path_element =
|
||||
vfs_path_get_by_index (vpath1, vfs_path_elements_count (vpath1) - 1);
|
||||
if (vfs_path_element_valid (path_element))
|
||||
{
|
||||
result =
|
||||
path_element->class->symlink !=
|
||||
NULL ? path_element->class->symlink (vpath2, vpath1) : -1;
|
||||
|
||||
if (result == -1)
|
||||
errno =
|
||||
path_element->class->symlink !=
|
||||
NULL ? vfs_ferrno (path_element->class) : E_NOTSUPP;
|
||||
}
|
||||
}
|
||||
vfs_path_free (vpath1);
|
||||
vfs_path_free (vpath2);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
|
||||
#define MC_HANDLEOP(name, inarg, callarg) \
|
||||
ssize_t mc_##name inarg \
|
||||
{ \
|
||||
struct vfs_class *vfs; \
|
||||
int result; \
|
||||
if (handle == -1) \
|
||||
return -1; \
|
||||
vfs = vfs_class_find_by_handle (handle); \
|
||||
if (vfs == NULL) \
|
||||
return -1; \
|
||||
result = vfs->name != NULL ? vfs->name callarg : -1; \
|
||||
if (result == -1) \
|
||||
errno = vfs->name != NULL ? vfs_ferrno (vfs) : E_NOTSUPP; \
|
||||
return result; \
|
||||
}
|
||||
|
||||
MC_HANDLEOP (read, (int handle, void *buffer, size_t count), (vfs_class_data_find_by_handle (handle), buffer, count))
|
||||
MC_HANDLEOP (write, (int handle, const void *buf, size_t nbyte), (vfs_class_data_find_by_handle (handle), buf, nbyte))
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
#define MC_RENAMEOP(name) \
|
||||
int mc_##name (const char *fname1, const char *fname2) \
|
||||
{ \
|
||||
int result; \
|
||||
vfs_path_t *vpath1, *vpath2; \
|
||||
vfs_path_element_t *path_element1, *path_element2; \
|
||||
\
|
||||
vpath1 = vfs_path_from_str (fname1); \
|
||||
if (vpath1 == NULL) \
|
||||
return -1; \
|
||||
\
|
||||
vpath2 = vfs_path_from_str (fname2); \
|
||||
if (vpath2 == NULL) \
|
||||
{ \
|
||||
vfs_path_free(vpath1); \
|
||||
return -1; \
|
||||
}\
|
||||
path_element1 = vfs_path_get_by_index (vpath1, vfs_path_elements_count (vpath1) - 1); \
|
||||
path_element2 = vfs_path_get_by_index (vpath2, vfs_path_elements_count (vpath2) - 1); \
|
||||
\
|
||||
if (!vfs_path_element_valid (path_element1) || !vfs_path_element_valid (path_element2) || \
|
||||
path_element1->class != path_element2->class) \
|
||||
{ \
|
||||
errno = EXDEV; \
|
||||
vfs_path_free(vpath1); \
|
||||
vfs_path_free(vpath2); \
|
||||
return -1; \
|
||||
}\
|
||||
\
|
||||
result = path_element1->class->name != NULL \
|
||||
? path_element1->class->name (vpath1, vpath2) \
|
||||
: -1; \
|
||||
if (result == -1) \
|
||||
errno = path_element1->class->name != NULL ? vfs_ferrno (path_element1->class) : E_NOTSUPP; \
|
||||
vfs_path_free(vpath1); \
|
||||
vfs_path_free(vpath2); \
|
||||
return result; \
|
||||
}
|
||||
|
||||
MC_RENAMEOP (link)
|
||||
MC_RENAMEOP (rename)
|
||||
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
mc_ctl (int handle, int ctlop, void *arg)
|
||||
{
|
||||
struct vfs_class *vfs = vfs_class_find_by_handle (handle);
|
||||
|
||||
if (vfs == NULL)
|
||||
return 0;
|
||||
|
||||
return vfs->ctl ? (*vfs->ctl) (vfs_class_data_find_by_handle (handle), ctlop, arg) : 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
mc_setctl (const char *path, int ctlop, void *arg)
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
vpath = vfs_path_from_str (path);
|
||||
if (vpath == NULL)
|
||||
vfs_die ("You don't want to pass NULL to mc_setctl.");
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
if (vfs_path_element_valid (path_element))
|
||||
result =
|
||||
path_element->class->setctl != NULL ? path_element->class->setctl (vpath,
|
||||
ctlop, arg) : 0;
|
||||
|
||||
vfs_path_free (vpath);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
mc_close (int handle)
|
||||
{
|
||||
struct vfs_class *vfs;
|
||||
int result;
|
||||
|
||||
if (handle == -1 || !vfs_class_data_find_by_handle (handle))
|
||||
return -1;
|
||||
|
||||
vfs = vfs_class_find_by_handle (handle);
|
||||
if (vfs == NULL)
|
||||
return -1;
|
||||
|
||||
if (handle < 3)
|
||||
return close (handle);
|
||||
|
||||
if (!vfs->close)
|
||||
vfs_die ("VFS must support close.\n");
|
||||
result = (*vfs->close) (vfs_class_data_find_by_handle (handle));
|
||||
vfs_free_handle (handle);
|
||||
if (result == -1)
|
||||
errno = vfs_ferrno (vfs);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
DIR *
|
||||
mc_opendir (const char *dirname)
|
||||
{
|
||||
int handle, *handlep;
|
||||
void *info;
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
vpath = vfs_path_from_str (dirname);
|
||||
|
||||
if (vpath == NULL)
|
||||
return NULL;
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
if (!vfs_path_element_valid (path_element))
|
||||
{
|
||||
errno = E_NOTSUPP;
|
||||
vfs_path_free (vpath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info = path_element->class->opendir ? (*path_element->class->opendir) (vpath) : NULL;
|
||||
|
||||
if (info == NULL)
|
||||
{
|
||||
errno = path_element->class->opendir ? vfs_ferrno (path_element->class) : E_NOTSUPP;
|
||||
vfs_path_free (vpath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path_element->dir.info = info;
|
||||
|
||||
path_element->dir.converter =
|
||||
(path_element->encoding !=
|
||||
NULL) ? str_crt_conv_from (path_element->encoding) : str_cnv_from_term;
|
||||
if (path_element->dir.converter == INVALID_CONV)
|
||||
path_element->dir.converter = str_cnv_from_term;
|
||||
|
||||
handle = vfs_new_handle (path_element->class, vfs_path_element_clone (path_element));
|
||||
|
||||
handlep = g_new (int, 1);
|
||||
*handlep = handle;
|
||||
vfs_path_free (vpath);
|
||||
return (DIR *) handlep;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
struct dirent *
|
||||
mc_readdir (DIR * dirp)
|
||||
{
|
||||
int handle;
|
||||
struct vfs_class *vfs;
|
||||
struct dirent *entry = NULL;
|
||||
vfs_path_element_t *vfs_path_element;
|
||||
estr_t state;
|
||||
|
||||
if (!mc_readdir_result)
|
||||
{
|
||||
/* We can't just allocate struct dirent as (see man dirent.h)
|
||||
* struct dirent has VERY nonnaive semantics of allocating
|
||||
* d_name in it. Moreover, linux's glibc-2.9 allocates dirents _less_,
|
||||
* than 'sizeof (struct dirent)' making full bitwise (sizeof dirent) copy
|
||||
* heap corrupter. So, allocate longliving dirent with at least
|
||||
* (MAXNAMLEN + 1) for d_name in it.
|
||||
* Strictly saying resulting dirent is unusable as we don't adjust internal
|
||||
* structures, holding dirent size. But we don't use it in libc infrastructure.
|
||||
* TODO: to make simpler homemade dirent-alike structure.
|
||||
*/
|
||||
mc_readdir_result = (struct dirent *) g_malloc (sizeof (struct dirent) + MAXNAMLEN + 1);
|
||||
}
|
||||
|
||||
if (!dirp)
|
||||
{
|
||||
errno = EFAULT;
|
||||
return NULL;
|
||||
}
|
||||
handle = *(int *) dirp;
|
||||
|
||||
vfs = vfs_class_find_by_handle (handle);
|
||||
if (vfs == NULL)
|
||||
return NULL;
|
||||
|
||||
vfs_path_element = vfs_class_data_find_by_handle (handle);
|
||||
if (vfs->readdir)
|
||||
{
|
||||
entry = (*vfs->readdir) (vfs_path_element->dir.info);
|
||||
if (entry == NULL)
|
||||
return NULL;
|
||||
g_string_set_size (vfs_str_buffer, 0);
|
||||
state =
|
||||
str_vfs_convert_from (vfs_path_element->dir.converter, entry->d_name, vfs_str_buffer);
|
||||
mc_readdir_result->d_ino = entry->d_ino;
|
||||
g_strlcpy (mc_readdir_result->d_name, vfs_str_buffer->str, MAXNAMLEN + 1);
|
||||
}
|
||||
if (entry == NULL)
|
||||
errno = vfs->readdir ? vfs_ferrno (vfs) : E_NOTSUPP;
|
||||
return (entry != NULL) ? mc_readdir_result : NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
mc_closedir (DIR * dirp)
|
||||
{
|
||||
int handle = *(int *) dirp;
|
||||
struct vfs_class *vfs;
|
||||
int result = -1;
|
||||
|
||||
vfs = vfs_class_find_by_handle (handle);
|
||||
if (vfs != NULL)
|
||||
{
|
||||
vfs_path_element_t *vfs_path_element;
|
||||
vfs_path_element = vfs_class_data_find_by_handle (handle);
|
||||
if (vfs_path_element->dir.converter != str_cnv_from_term)
|
||||
{
|
||||
str_close_conv (vfs_path_element->dir.converter);
|
||||
vfs_path_element->dir.converter = INVALID_CONV;
|
||||
}
|
||||
|
||||
result = vfs->closedir ? (*vfs->closedir) (vfs_path_element->dir.info) : -1;
|
||||
vfs_free_handle (handle);
|
||||
vfs_path_element_free (vfs_path_element);
|
||||
}
|
||||
g_free (dirp);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
mc_stat (const char *filename, struct stat *buf)
|
||||
{
|
||||
int result = -1;
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
vpath = vfs_path_from_str (filename);
|
||||
if (vpath == NULL)
|
||||
return -1;
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
if (vfs_path_element_valid (path_element))
|
||||
{
|
||||
result = path_element->class->stat ? (*path_element->class->stat) (vpath, buf) : -1;
|
||||
if (result == -1)
|
||||
errno = path_element->class->name ? vfs_ferrno (path_element->class) : E_NOTSUPP;
|
||||
}
|
||||
|
||||
vfs_path_free (vpath);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
mc_lstat (const char *filename, struct stat *buf)
|
||||
{
|
||||
int result = -1;
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
vpath = vfs_path_from_str (filename);
|
||||
if (vpath == NULL)
|
||||
return -1;
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
if (vfs_path_element_valid (path_element))
|
||||
{
|
||||
result = path_element->class->lstat ? (*path_element->class->lstat) (vpath, buf) : -1;
|
||||
if (result == -1)
|
||||
errno = path_element->class->name ? vfs_ferrno (path_element->class) : E_NOTSUPP;
|
||||
}
|
||||
|
||||
vfs_path_free (vpath);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
mc_fstat (int handle, struct stat *buf)
|
||||
{
|
||||
struct vfs_class *vfs;
|
||||
int result;
|
||||
|
||||
if (handle == -1)
|
||||
return -1;
|
||||
|
||||
vfs = vfs_class_find_by_handle (handle);
|
||||
if (vfs == NULL)
|
||||
return -1;
|
||||
|
||||
result = vfs->fstat ? (*vfs->fstat) (vfs_class_data_find_by_handle (handle), buf) : -1;
|
||||
if (result == -1)
|
||||
errno = vfs->name ? vfs_ferrno (vfs) : E_NOTSUPP;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Return current directory. If it's local, reread the current directory
|
||||
* from the OS. Put directory to the provided buffer.
|
||||
*/
|
||||
|
||||
char *
|
||||
mc_get_current_wd (char *buffer, size_t size)
|
||||
{
|
||||
char *cwd = _vfs_get_cwd ();
|
||||
|
||||
g_strlcpy (buffer, cwd, size);
|
||||
g_free (cwd);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
char *
|
||||
mc_getlocalcopy (const char *pathname)
|
||||
{
|
||||
char *result = NULL;
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
vpath = vfs_path_from_str (pathname);
|
||||
if (vpath == NULL)
|
||||
return NULL;
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
if (vfs_path_element_valid (path_element))
|
||||
{
|
||||
result = path_element->class->getlocalcopy != NULL ?
|
||||
path_element->class->getlocalcopy (vpath) : mc_def_getlocalcopy (pathname);
|
||||
if (result == NULL)
|
||||
errno = vfs_ferrno (path_element->class);
|
||||
}
|
||||
vfs_path_free (vpath);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
mc_ungetlocalcopy (const char *pathname, const char *local, int has_changed)
|
||||
{
|
||||
int return_value = -1;
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
vpath = vfs_path_from_str (pathname);
|
||||
if (vpath == NULL)
|
||||
return -1;
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
if (vfs_path_element_valid (path_element))
|
||||
{
|
||||
return_value = path_element->class->ungetlocalcopy != NULL ?
|
||||
path_element->class->ungetlocalcopy (vpath, local,
|
||||
has_changed) :
|
||||
mc_def_ungetlocalcopy (path_element->class, path_element->path, local, has_changed);
|
||||
}
|
||||
vfs_path_free (vpath);
|
||||
return return_value;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* VFS chdir.
|
||||
* Return 0 on success, -1 on failure.
|
||||
*/
|
||||
|
||||
int
|
||||
mc_chdir (const char *path)
|
||||
{
|
||||
struct vfs_class *old_vfs;
|
||||
vfsid old_vfsid;
|
||||
int result;
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
vpath = vfs_path_from_str (path);
|
||||
|
||||
if (vpath == NULL)
|
||||
return -1;
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
if (!vfs_path_element_valid (path_element) || path_element->class->chdir == NULL)
|
||||
{
|
||||
vfs_path_free (vpath);
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = (*path_element->class->chdir) (vpath);
|
||||
|
||||
if (result == -1)
|
||||
{
|
||||
errno = vfs_ferrno (path_element->class);
|
||||
vfs_path_free (vpath);
|
||||
return -1;
|
||||
}
|
||||
|
||||
old_vfsid = vfs_getid (vfs_get_raw_current_dir ());
|
||||
old_vfs = current_vfs;
|
||||
|
||||
/* Actually change directory */
|
||||
vfs_set_raw_current_dir (vpath);
|
||||
current_vfs = path_element->class;
|
||||
|
||||
/* This function uses the new current_dir implicitly */
|
||||
vfs_stamp_create (old_vfs, old_vfsid);
|
||||
|
||||
/* Sometimes we assume no trailing slash on cwd */
|
||||
path_element = vfs_path_get_by_index (vfs_get_raw_current_dir (), -1);
|
||||
if (vfs_path_element_valid (path_element) && (*path_element->path != '\0'))
|
||||
{
|
||||
char *p;
|
||||
p = strchr (path_element->path, 0) - 1;
|
||||
if (*p == PATH_SEP && p > path_element->path)
|
||||
*p = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
off_t
|
||||
mc_lseek (int fd, off_t offset, int whence)
|
||||
{
|
||||
struct vfs_class *vfs;
|
||||
off_t result;
|
||||
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
vfs = vfs_class_find_by_handle (fd);
|
||||
if (vfs == NULL)
|
||||
return -1;
|
||||
|
||||
result = vfs->lseek ? (*vfs->lseek) (vfs_class_data_find_by_handle (fd), offset, whence) : -1;
|
||||
if (result == -1)
|
||||
errno = vfs->lseek ? vfs_ferrno (vfs) : E_NOTSUPP;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
999
lib/vfs/path.c
Обычный файл
999
lib/vfs/path.c
Обычный файл
@ -0,0 +1,999 @@
|
||||
/* Virtual File System path handlers
|
||||
Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2011
|
||||
|
||||
This file is part of the Midnight Commander.
|
||||
|
||||
The Midnight Commander is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The Midnight Commander is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \brief Source: Virtual File System: path handlers
|
||||
* \author Slava Zanko
|
||||
* \date 2011
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "lib/global.h"
|
||||
#include "lib/strutil.h"
|
||||
#include "lib/util.h" /* concat_dir_and_file */
|
||||
#include "lib/serialize.h"
|
||||
|
||||
#include "vfs.h"
|
||||
#include "utilvfs.h"
|
||||
#include "xdirentry.h"
|
||||
#include "path.h"
|
||||
|
||||
extern GPtrArray *vfs__classes_list;
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static gboolean
|
||||
path_magic (const char *path)
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
return (stat (path, &buf) != 0);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Splits path extracting vfs part.
|
||||
*
|
||||
* Splits path
|
||||
* \verbatim /p1#op/inpath \endverbatim
|
||||
* into
|
||||
* \verbatim inpath,op; \endverbatim
|
||||
* returns which vfs it is.
|
||||
* What is left in path is p1. You still want to g_free(path), you DON'T
|
||||
* want to free neither *inpath nor *op
|
||||
*/
|
||||
|
||||
static struct vfs_class *
|
||||
_vfs_split_with_semi_skip_count (char *path, const char **inpath, const char **op,
|
||||
size_t skip_count)
|
||||
{
|
||||
char *semi;
|
||||
char *slash;
|
||||
struct vfs_class *ret;
|
||||
|
||||
if (path == NULL)
|
||||
vfs_die ("Cannot split NULL");
|
||||
|
||||
semi = strrstr_skip_count (path, "#", skip_count);
|
||||
|
||||
if ((semi == NULL) || (!path_magic (path)))
|
||||
return NULL;
|
||||
|
||||
slash = strchr (semi, PATH_SEP);
|
||||
*semi = '\0';
|
||||
|
||||
if (op != NULL)
|
||||
*op = NULL;
|
||||
|
||||
if (inpath != NULL)
|
||||
*inpath = NULL;
|
||||
|
||||
if (slash != NULL)
|
||||
*slash = '\0';
|
||||
|
||||
ret = vfs_prefix_to_class (semi + 1);
|
||||
if (ret != NULL)
|
||||
{
|
||||
if (op != NULL)
|
||||
*op = semi + 1;
|
||||
if (inpath != NULL)
|
||||
*inpath = slash != NULL ? slash + 1 : NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (slash != NULL)
|
||||
*slash = PATH_SEP;
|
||||
|
||||
*semi = '#';
|
||||
ret = _vfs_split_with_semi_skip_count (path, inpath, op, skip_count + 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* remove //, /./ and /../
|
||||
*
|
||||
* @return newly allocated string
|
||||
*/
|
||||
|
||||
static char *
|
||||
vfs_canon (const char *path)
|
||||
{
|
||||
if (!path)
|
||||
vfs_die ("Cannot canonicalize NULL");
|
||||
|
||||
/* Relative to current directory */
|
||||
if (*path != PATH_SEP)
|
||||
{
|
||||
char *local, *result, *curr_dir;
|
||||
|
||||
curr_dir = vfs_get_current_dir ();
|
||||
local = concat_dir_and_file (curr_dir, path);
|
||||
g_free (curr_dir);
|
||||
|
||||
result = vfs_canon (local);
|
||||
g_free (local);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* So we have path of following form:
|
||||
* /p1/p2#op/.././././p3#op/p4. Good luck.
|
||||
*/
|
||||
{
|
||||
char *result = g_strdup (path);
|
||||
canonicalize_pathname (result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Build URL parameters (such as user:pass@host:port) from one path element object
|
||||
*
|
||||
* @param element path element
|
||||
*
|
||||
* @return newly allocated string
|
||||
*/
|
||||
|
||||
static char *
|
||||
vfs_path_build_url_params_str (vfs_path_element_t * element)
|
||||
{
|
||||
GString *buffer;
|
||||
|
||||
if (element == NULL)
|
||||
return NULL;
|
||||
|
||||
buffer = g_string_new ("");
|
||||
|
||||
if (element->user != NULL)
|
||||
g_string_append (buffer, element->user);
|
||||
|
||||
if (element->password != NULL)
|
||||
{
|
||||
g_string_append_c (buffer, ':');
|
||||
g_string_append (buffer, element->password);
|
||||
}
|
||||
|
||||
if (element->host != NULL)
|
||||
{
|
||||
if ((element->user != NULL) || (element->password != NULL))
|
||||
g_string_append_c (buffer, '@');
|
||||
g_string_append (buffer, element->host);
|
||||
}
|
||||
|
||||
if ((element->port) != 0 && (element->host != NULL))
|
||||
{
|
||||
g_string_append_c (buffer, ':');
|
||||
g_string_append_printf (buffer, "%d", element->port);
|
||||
}
|
||||
|
||||
return g_string_free (buffer, FALSE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/** get encoding after last #enc: or NULL, if part does not contain #enc:
|
||||
*
|
||||
* @param path string
|
||||
*
|
||||
* @return newly allocated string.
|
||||
*/
|
||||
|
||||
static char *
|
||||
vfs_get_encoding (const char *path)
|
||||
{
|
||||
char result[16];
|
||||
char *work;
|
||||
char *semi;
|
||||
char *slash;
|
||||
work = g_strdup (path);
|
||||
|
||||
/* try found #enc: */
|
||||
semi = g_strrstr (work, VFS_ENCODING_PREFIX);
|
||||
|
||||
if (semi != NULL && (semi == work || *(semi - 1) == PATH_SEP))
|
||||
{
|
||||
semi += strlen (VFS_ENCODING_PREFIX); /* skip "#enc:" */
|
||||
slash = strchr (semi, PATH_SEP);
|
||||
if (slash != NULL)
|
||||
slash[0] = '\0';
|
||||
|
||||
g_strlcpy (result, semi, sizeof (result));
|
||||
g_free (work);
|
||||
return g_strdup (result);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free (work);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/** Extract the hostname and username from the path
|
||||
*
|
||||
* Format of the path is [user@]hostname:port/remote-dir, e.g.:
|
||||
*
|
||||
* ftp://sunsite.unc.edu/pub/linux
|
||||
* ftp://miguel@sphinx.nuclecu.unam.mx/c/nc
|
||||
* ftp://tsx-11.mit.edu:8192/
|
||||
* ftp://joe@foo.edu:11321/private
|
||||
* ftp://joe:password@foo.se
|
||||
*
|
||||
* @param path_element is an input string to be parsed
|
||||
* @param path is an input string to be parsed
|
||||
*
|
||||
* @return g_malloc()ed url info.
|
||||
* If the user is empty, e.g. ftp://@roxanne/private, and URL_USE_ANONYMOUS
|
||||
* is not set, then the current login name is supplied.
|
||||
* Return value is a g_malloc()ed structure with the pathname relative to the
|
||||
* host.
|
||||
*/
|
||||
|
||||
static void
|
||||
vfs_path_url_split (vfs_path_element_t * path_element, const char *path)
|
||||
{
|
||||
char *pcopy;
|
||||
const char *pend;
|
||||
char *dir, *colon, *inner_colon, *at, *rest;
|
||||
|
||||
path_element->port = 0;
|
||||
|
||||
pcopy = g_strdup (path);
|
||||
pend = pcopy + strlen (pcopy);
|
||||
dir = pcopy;
|
||||
|
||||
/* search for any possible user */
|
||||
at = strrchr (pcopy, '@');
|
||||
|
||||
/* We have a username */
|
||||
if (at == NULL)
|
||||
rest = pcopy;
|
||||
else
|
||||
{
|
||||
*at = '\0';
|
||||
inner_colon = strchr (pcopy, ':');
|
||||
if (inner_colon != NULL)
|
||||
{
|
||||
*inner_colon = '\0';
|
||||
inner_colon++;
|
||||
path_element->password = g_strdup (inner_colon);
|
||||
}
|
||||
|
||||
if (*pcopy != '\0')
|
||||
path_element->user = g_strdup (pcopy);
|
||||
|
||||
if (pend == at + 1)
|
||||
rest = at;
|
||||
else
|
||||
rest = at + 1;
|
||||
}
|
||||
|
||||
/* Check if the host comes with a port spec, if so, chop it */
|
||||
if (*rest != '[')
|
||||
colon = strchr (rest, ':');
|
||||
else
|
||||
{
|
||||
colon = strchr (++rest, ']');
|
||||
if (colon != NULL)
|
||||
{
|
||||
colon[0] = '\0';
|
||||
colon[1] = '\0';
|
||||
colon++;
|
||||
}
|
||||
}
|
||||
|
||||
if (colon != NULL)
|
||||
{
|
||||
*colon = '\0';
|
||||
if (sscanf (colon + 1, "%d", &path_element->port) == 1)
|
||||
{
|
||||
if (path_element->port <= 0 || path_element->port >= 65536)
|
||||
path_element->port = 0;
|
||||
}
|
||||
else
|
||||
while (*(++colon) != '\0')
|
||||
{
|
||||
switch (*colon)
|
||||
{
|
||||
case 'C':
|
||||
path_element->port = 1;
|
||||
break;
|
||||
case 'r':
|
||||
path_element->port = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
path_element->host = g_strdup (rest);
|
||||
g_free (pcopy);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* get VFS class for the given name
|
||||
*
|
||||
* @param class_name name of class
|
||||
*
|
||||
* @return pointer to class structure or NULL if class not found
|
||||
*/
|
||||
|
||||
static struct vfs_class *
|
||||
vfs_get_class_by_name (const char *class_name)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (class_name == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < vfs__classes_list->len; i++)
|
||||
{
|
||||
struct vfs_class *vfs = (struct vfs_class *) g_ptr_array_index (vfs__classes_list, i);
|
||||
if ((vfs->name != NULL) && (strcmp (vfs->name, class_name) == 0))
|
||||
return vfs;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Check if path string contain URL-like elements
|
||||
*
|
||||
* @param path_str path
|
||||
*
|
||||
* @return TRUE if path is deprecated or FALSE otherwise
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
vfs_path_is_str_path_deprecated (const char *path_str)
|
||||
{
|
||||
return strstr (path_str, VFS_PATH_URL_DELIMITER) == NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/** Split path string to path elements by deprecated algorithm.
|
||||
*
|
||||
* @param path_str VFS-path
|
||||
*
|
||||
* @return pointer to newly created vfs_path_t object with filled path elements array.
|
||||
*/
|
||||
|
||||
static vfs_path_t *
|
||||
vfs_path_from_str_deprecated_parser (char *path)
|
||||
{
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *element;
|
||||
struct vfs_class *class;
|
||||
const char *local, *op;
|
||||
|
||||
vpath = vfs_path_new ();
|
||||
|
||||
while ((class = _vfs_split_with_semi_skip_count (path, &local, &op, 0)) != NULL)
|
||||
{
|
||||
char *url_params;
|
||||
element = g_new0 (vfs_path_element_t, 1);
|
||||
element->class = class;
|
||||
if (local == NULL)
|
||||
local = "";
|
||||
element->path = vfs_translate_path_n (local);
|
||||
|
||||
element->encoding = vfs_get_encoding (local);
|
||||
element->dir.converter = INVALID_CONV;
|
||||
|
||||
url_params = strchr (op, ':'); /* skip VFS prefix */
|
||||
if (url_params != NULL)
|
||||
{
|
||||
*url_params = '\0';
|
||||
url_params++;
|
||||
vfs_path_url_split (element, url_params);
|
||||
}
|
||||
|
||||
if (*op != '\0')
|
||||
element->vfs_prefix = g_strdup (op);
|
||||
|
||||
vpath->path = g_list_prepend (vpath->path, element);
|
||||
}
|
||||
if (path[0] != '\0')
|
||||
{
|
||||
element = g_new0 (vfs_path_element_t, 1);
|
||||
element->class = g_ptr_array_index (vfs__classes_list, 0);
|
||||
element->path = vfs_translate_path_n (path);
|
||||
|
||||
element->encoding = vfs_get_encoding (path);
|
||||
element->dir.converter = INVALID_CONV;
|
||||
vpath->path = g_list_prepend (vpath->path, element);
|
||||
}
|
||||
|
||||
return vpath;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/** Split path string to path elements by URL algorithm.
|
||||
*
|
||||
* @param path_str VFS-path
|
||||
*
|
||||
* @return pointer to newly created vfs_path_t object with filled path elements array.
|
||||
*/
|
||||
|
||||
static vfs_path_t *
|
||||
vfs_path_from_str_uri_parser (char *path)
|
||||
{
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *element;
|
||||
|
||||
char *url_delimiter;
|
||||
|
||||
vpath = vfs_path_new ();
|
||||
|
||||
while ((url_delimiter = g_strrstr (path, VFS_PATH_URL_DELIMITER)) != NULL)
|
||||
{
|
||||
char *vfs_prefix_start;
|
||||
char *real_vfs_prefix_start = url_delimiter;
|
||||
char *slash_pointer;
|
||||
struct vfs_s_subclass *sub = NULL;
|
||||
|
||||
while (real_vfs_prefix_start > path && *(real_vfs_prefix_start) != PATH_SEP)
|
||||
real_vfs_prefix_start--;
|
||||
vfs_prefix_start = real_vfs_prefix_start;
|
||||
|
||||
if (*(vfs_prefix_start) == PATH_SEP)
|
||||
vfs_prefix_start += 1;
|
||||
|
||||
*url_delimiter = '\0';
|
||||
|
||||
element = g_new0 (vfs_path_element_t, 1);
|
||||
element->class = vfs_prefix_to_class (vfs_prefix_start);
|
||||
element->vfs_prefix = g_strdup (vfs_prefix_start);
|
||||
|
||||
element->dir.converter = INVALID_CONV;
|
||||
|
||||
url_delimiter += strlen (VFS_PATH_URL_DELIMITER);
|
||||
sub = VFSDATA (element);
|
||||
if (sub != NULL && sub->flags & VFS_S_REMOTE)
|
||||
{
|
||||
slash_pointer = strchr (url_delimiter, PATH_SEP);
|
||||
if (slash_pointer == NULL)
|
||||
{
|
||||
element->path = g_strdup ("");
|
||||
}
|
||||
else
|
||||
{
|
||||
element->path = vfs_translate_path_n (slash_pointer + 1);
|
||||
element->encoding = vfs_get_encoding (slash_pointer);
|
||||
*slash_pointer = '\0';
|
||||
}
|
||||
vfs_path_url_split (element, url_delimiter);
|
||||
}
|
||||
else
|
||||
{
|
||||
element->path = vfs_translate_path_n (url_delimiter);
|
||||
element->encoding = vfs_get_encoding (url_delimiter);
|
||||
}
|
||||
vpath->path = g_list_prepend (vpath->path, element);
|
||||
|
||||
if (real_vfs_prefix_start > path && *(real_vfs_prefix_start) == PATH_SEP)
|
||||
*real_vfs_prefix_start = '\0';
|
||||
else
|
||||
*(real_vfs_prefix_start + 1) = '\0';
|
||||
}
|
||||
|
||||
if (path[0] != '\0')
|
||||
{
|
||||
element = g_new0 (vfs_path_element_t, 1);
|
||||
element->class = g_ptr_array_index (vfs__classes_list, 0);
|
||||
element->path = vfs_translate_path_n (path);
|
||||
element->encoding = vfs_get_encoding (path);
|
||||
element->dir.converter = INVALID_CONV;
|
||||
vpath->path = g_list_prepend (vpath->path, element);
|
||||
}
|
||||
|
||||
return vpath;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*** public functions ****************************************************************************/
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Convert first elements_count elements from vfs_path_t to string representation.
|
||||
*
|
||||
* @param vpath pointer to vfs_path_t object
|
||||
* @param elements_count count of first elements for convert
|
||||
*
|
||||
* @return pointer to newly created string.
|
||||
*/
|
||||
|
||||
char *
|
||||
vfs_path_to_str_elements_count (const vfs_path_t * vpath, int elements_count)
|
||||
{
|
||||
int element_index;
|
||||
GString *buffer;
|
||||
|
||||
if (vpath == NULL)
|
||||
return NULL;
|
||||
|
||||
if (elements_count > vfs_path_elements_count (vpath))
|
||||
elements_count = vfs_path_elements_count (vpath);
|
||||
|
||||
if (elements_count < 0)
|
||||
elements_count = vfs_path_elements_count (vpath) + elements_count;
|
||||
|
||||
buffer = g_string_new ("");
|
||||
|
||||
for (element_index = 0; element_index < elements_count; element_index++)
|
||||
{
|
||||
vfs_path_element_t *element = vfs_path_get_by_index (vpath, element_index);
|
||||
|
||||
if (element->vfs_prefix != NULL)
|
||||
{
|
||||
char *url_str;
|
||||
|
||||
if (buffer->str[buffer->len - 1] != '/')
|
||||
g_string_append_c (buffer, '/');
|
||||
|
||||
g_string_append (buffer, element->vfs_prefix);
|
||||
g_string_append (buffer, VFS_PATH_URL_DELIMITER);
|
||||
|
||||
url_str = vfs_path_build_url_params_str (element);
|
||||
if (*url_str != '\0')
|
||||
g_string_append (buffer, url_str);
|
||||
|
||||
g_free (url_str);
|
||||
}
|
||||
|
||||
if (element->encoding != NULL)
|
||||
{
|
||||
if (buffer->str[buffer->len - 1] != PATH_SEP)
|
||||
g_string_append (buffer, PATH_SEP_STR);
|
||||
g_string_append (buffer, VFS_ENCODING_PREFIX);
|
||||
g_string_append (buffer, element->encoding);
|
||||
}
|
||||
if ((*element->path != PATH_SEP) && (*element->path != '\0')
|
||||
&& (buffer->str[buffer->len - 1] != PATH_SEP))
|
||||
g_string_append_c (buffer, PATH_SEP);
|
||||
|
||||
g_string_append (buffer, element->path);
|
||||
}
|
||||
return g_string_free (buffer, FALSE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Convert vfs_path_t to string representation.
|
||||
*
|
||||
* @param vpath pointer to vfs_path_t object
|
||||
*
|
||||
* @return pointer to newly created string.
|
||||
*/
|
||||
char *
|
||||
vfs_path_to_str (const vfs_path_t * vpath)
|
||||
{
|
||||
return vfs_path_to_str_elements_count (vpath, vfs_path_elements_count (vpath));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Split path string to path elements.
|
||||
*
|
||||
* @param path_str VFS-path
|
||||
*
|
||||
* @return pointer to newly created vfs_path_t object with filled path elements array.
|
||||
*/
|
||||
|
||||
vfs_path_t *
|
||||
vfs_path_from_str (const char *path_str)
|
||||
{
|
||||
vfs_path_t *vpath;
|
||||
char *path;
|
||||
|
||||
if (path_str == NULL)
|
||||
return NULL;
|
||||
|
||||
path = vfs_canon (path_str);
|
||||
if (path == NULL)
|
||||
return NULL;
|
||||
|
||||
if (vfs_path_is_str_path_deprecated (path))
|
||||
vpath = vfs_path_from_str_deprecated_parser (path);
|
||||
else
|
||||
vpath = vfs_path_from_str_uri_parser (path);
|
||||
|
||||
g_free (path);
|
||||
|
||||
return vpath;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*
|
||||
* Create new vfs_path_t object.
|
||||
*
|
||||
* @return pointer to newly created vfs_path_t object.
|
||||
*/
|
||||
|
||||
vfs_path_t *
|
||||
vfs_path_new (void)
|
||||
{
|
||||
vfs_path_t *vpath;
|
||||
vpath = g_new0 (vfs_path_t, 1);
|
||||
return vpath;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*
|
||||
* Get count of path elements.
|
||||
*
|
||||
* @param vpath pointer to vfs_path_t object
|
||||
*
|
||||
* @return count of path elements.
|
||||
*/
|
||||
|
||||
int
|
||||
vfs_path_elements_count (const vfs_path_t * vpath)
|
||||
{
|
||||
if (vpath == NULL)
|
||||
return 0;
|
||||
|
||||
return (vpath->path != NULL) ? g_list_length (vpath->path) : 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*
|
||||
* Get one path element by index.
|
||||
*
|
||||
* @param vpath pointer to vfs_path_t object
|
||||
* @param element_index element index. May have negative value (in this case count was started at the end of list).
|
||||
*
|
||||
* @return path element.
|
||||
*/
|
||||
|
||||
vfs_path_element_t *
|
||||
vfs_path_get_by_index (const vfs_path_t * vpath, int element_index)
|
||||
{
|
||||
vfs_path_element_t *element;
|
||||
|
||||
if (vpath == NULL)
|
||||
return NULL;
|
||||
|
||||
if (element_index < 0)
|
||||
element_index = vfs_path_elements_count (vpath) + element_index;
|
||||
|
||||
element = g_list_nth_data (vpath->path, element_index);
|
||||
if (element == NULL)
|
||||
vfs_die ("vfs_path_get_by_index: incorrect index!");
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*
|
||||
* Clone one path element
|
||||
*
|
||||
* @param element pointer to vfs_path_element_t object
|
||||
*
|
||||
* @return Newly allocated path element
|
||||
*/
|
||||
|
||||
vfs_path_element_t *
|
||||
vfs_path_element_clone (const vfs_path_element_t * element)
|
||||
{
|
||||
vfs_path_element_t *new_element = g_new0 (vfs_path_element_t, 1);
|
||||
memcpy (new_element, element, sizeof (vfs_path_element_t));
|
||||
|
||||
new_element->user = g_strdup (element->user);
|
||||
new_element->password = g_strdup (element->password);
|
||||
new_element->host = g_strdup (element->host);
|
||||
new_element->path = g_strdup (element->path);
|
||||
new_element->encoding = g_strdup (element->encoding);
|
||||
if (vfs_path_element_need_cleanup_converter (element) && new_element->encoding != NULL)
|
||||
new_element->dir.converter = str_crt_conv_from (new_element->encoding);
|
||||
new_element->vfs_prefix = g_strdup (element->vfs_prefix);
|
||||
|
||||
return new_element;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*
|
||||
* Free one path element.
|
||||
*
|
||||
* @param element pointer to vfs_path_element_t object
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
vfs_path_element_free (vfs_path_element_t * element)
|
||||
{
|
||||
if (element == NULL)
|
||||
return;
|
||||
|
||||
g_free (element->user);
|
||||
g_free (element->password);
|
||||
g_free (element->host);
|
||||
g_free (element->path);
|
||||
g_free (element->encoding);
|
||||
g_free (element->vfs_prefix);
|
||||
|
||||
if (vfs_path_element_need_cleanup_converter (element))
|
||||
{
|
||||
str_close_conv (element->dir.converter);
|
||||
}
|
||||
|
||||
g_free (element);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*
|
||||
* Clone path
|
||||
*
|
||||
* @param vpath pointer to vfs_path_t object
|
||||
*
|
||||
* @return Newly allocated path object
|
||||
*/
|
||||
|
||||
vfs_path_t *
|
||||
vfs_path_clone (const vfs_path_t * vpath)
|
||||
{
|
||||
vfs_path_t *new_vpath;
|
||||
int vpath_element_index;
|
||||
if (vpath == NULL)
|
||||
return NULL;
|
||||
|
||||
new_vpath = vfs_path_new ();
|
||||
for (vpath_element_index = 0; vpath_element_index < vfs_path_elements_count (vpath);
|
||||
vpath_element_index++)
|
||||
{
|
||||
new_vpath->path =
|
||||
g_list_append (new_vpath->path,
|
||||
vfs_path_element_clone (vfs_path_get_by_index
|
||||
(vpath, vpath_element_index)));
|
||||
}
|
||||
|
||||
return new_vpath;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*
|
||||
* Free vfs_path_t object.
|
||||
*
|
||||
* @param vpath pointer to vfs_path_t object
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
vfs_path_free (vfs_path_t * path)
|
||||
{
|
||||
if (path == NULL)
|
||||
return;
|
||||
g_list_foreach (path->path, (GFunc) vfs_path_element_free, NULL);
|
||||
g_list_free (path->path);
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*
|
||||
* Remove one path element by index
|
||||
*
|
||||
* @param vpath pointer to vfs_path_t object
|
||||
* @param element_index element index. May have negative value (in this case count was started at the end of list).
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
vfs_path_remove_element_by_index (vfs_path_t * vpath, int element_index)
|
||||
{
|
||||
vfs_path_element_t *element;
|
||||
|
||||
if ((vpath == NULL) || (vfs_path_elements_count (vpath) == 1))
|
||||
return;
|
||||
|
||||
if (element_index < 0)
|
||||
element_index = vfs_path_elements_count (vpath) + element_index;
|
||||
|
||||
element = g_list_nth_data (vpath->path, element_index);
|
||||
vpath->path = g_list_remove (vpath->path, element);
|
||||
vfs_path_element_free (element);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/** Return VFS class for the given prefix */
|
||||
|
||||
struct vfs_class *
|
||||
vfs_prefix_to_class (const char *prefix)
|
||||
{
|
||||
guint i;
|
||||
|
||||
/* Avoid first class (localfs) that would accept any prefix */
|
||||
for (i = 1; i < vfs__classes_list->len; i++)
|
||||
{
|
||||
struct vfs_class *vfs = (struct vfs_class *) g_ptr_array_index (vfs__classes_list, i);
|
||||
if (vfs->which != NULL)
|
||||
{
|
||||
if (vfs->which (vfs, prefix) == -1)
|
||||
continue;
|
||||
return vfs;
|
||||
}
|
||||
|
||||
if (vfs->prefix != NULL && strncmp (prefix, vfs->prefix, strlen (vfs->prefix)) == 0)
|
||||
return vfs;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Check if need cleanup charset converter for vfs_path_element_t
|
||||
*
|
||||
* @param element part of path
|
||||
*
|
||||
* @return TRUE if need cleanup converter or FALSE otherwise
|
||||
*/
|
||||
|
||||
gboolean
|
||||
vfs_path_element_need_cleanup_converter (const vfs_path_element_t * element)
|
||||
{
|
||||
return (element->dir.converter != str_cnv_from_term && element->dir.converter != INVALID_CONV);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Serialize vfs_path_t object to string
|
||||
*
|
||||
* @param vpath data for serialization
|
||||
* @param error contain pointer to object for handle error code and message
|
||||
*
|
||||
* @return serialized vpath as newly allocated string
|
||||
*/
|
||||
|
||||
char *
|
||||
vfs_path_serialize (const vfs_path_t * vpath, GError ** error)
|
||||
{
|
||||
mc_config_t *cpath = mc_config_init (NULL);
|
||||
ssize_t element_index;
|
||||
char *ret_value;
|
||||
|
||||
if ((vpath == NULL) || (vfs_path_elements_count (vpath) == 0))
|
||||
{
|
||||
g_set_error (error, MC_ERROR, -1, "vpath object is empty");
|
||||
return NULL;
|
||||
|
||||
}
|
||||
for (element_index = 0; element_index < vfs_path_elements_count (vpath); element_index++)
|
||||
{
|
||||
char *groupname = g_strdup_printf ("path-element-%zd", element_index);
|
||||
vfs_path_element_t *element = vfs_path_get_by_index (vpath, element_index);
|
||||
|
||||
/* convert one element to config group */
|
||||
|
||||
mc_config_set_string_raw (cpath, groupname, "path", element->path);
|
||||
mc_config_set_string_raw (cpath, groupname, "class-name", element->class->name);
|
||||
mc_config_set_string_raw (cpath, groupname, "encoding", element->encoding);
|
||||
|
||||
mc_config_set_string_raw (cpath, groupname, "vfs_prefix", element->vfs_prefix);
|
||||
|
||||
mc_config_set_string_raw (cpath, groupname, "user", element->user);
|
||||
mc_config_set_string_raw (cpath, groupname, "password", element->password);
|
||||
mc_config_set_string_raw (cpath, groupname, "host", element->host);
|
||||
if (element->port != 0)
|
||||
mc_config_set_int (cpath, groupname, "port", element->port);
|
||||
|
||||
g_free (groupname);
|
||||
}
|
||||
|
||||
ret_value = mc_serialize_config (cpath, error);
|
||||
mc_config_deinit (cpath);
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Deserialize string to vfs_path_t object
|
||||
*
|
||||
* @param data data for serialization
|
||||
* @param error contain pointer to object for handle error code and message
|
||||
*
|
||||
* @return newly allocated vfs_path_t object
|
||||
*/
|
||||
|
||||
vfs_path_t *
|
||||
vfs_path_deserialize (const char *data, GError ** error)
|
||||
{
|
||||
mc_config_t *cpath = mc_deserialize_config (data, error);
|
||||
size_t element_index = 0;
|
||||
vfs_path_t *vpath;
|
||||
|
||||
if (cpath == NULL)
|
||||
return NULL;
|
||||
|
||||
vpath = vfs_path_new ();
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
vfs_path_element_t *element;
|
||||
char *cfg_value;
|
||||
char *groupname;
|
||||
|
||||
groupname = g_strdup_printf ("path-element-%zd", element_index);
|
||||
if (!mc_config_has_group (cpath, groupname))
|
||||
{
|
||||
g_free (groupname);
|
||||
break;
|
||||
}
|
||||
|
||||
element = g_new0 (vfs_path_element_t, 1);
|
||||
element->dir.converter = INVALID_CONV;
|
||||
|
||||
cfg_value = mc_config_get_string_raw (cpath, groupname, "class-name", NULL);
|
||||
element->class = vfs_get_class_by_name (cfg_value);
|
||||
if (element->class == NULL)
|
||||
{
|
||||
g_free (element);
|
||||
vfs_path_free (vpath);
|
||||
g_set_error (error, MC_ERROR, -1, "Unable to find VFS class by name '%s'", cfg_value);
|
||||
g_free (cfg_value);
|
||||
mc_config_deinit (cpath);
|
||||
return NULL;
|
||||
}
|
||||
g_free (cfg_value);
|
||||
|
||||
element->path = mc_config_get_string_raw (cpath, groupname, "path", NULL);
|
||||
element->encoding = mc_config_get_string_raw (cpath, groupname, "encoding", NULL);
|
||||
|
||||
element->vfs_prefix = mc_config_get_string_raw (cpath, groupname, "vfs_prefix", NULL);
|
||||
|
||||
element->user = mc_config_get_string_raw (cpath, groupname, "user", NULL);
|
||||
element->password = mc_config_get_string_raw (cpath, groupname, "password", NULL);
|
||||
element->host = mc_config_get_string_raw (cpath, groupname, "host", NULL);
|
||||
element->port = mc_config_get_int (cpath, groupname, "port", 0);
|
||||
|
||||
vpath->path = g_list_append (vpath->path, element);
|
||||
|
||||
g_free (groupname);
|
||||
element_index++;
|
||||
}
|
||||
|
||||
mc_config_deinit (cpath);
|
||||
if (vfs_path_elements_count (vpath) == 0)
|
||||
{
|
||||
vfs_path_free (vpath);
|
||||
g_set_error (error, MC_ERROR, -1, "No any path elements found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return vpath;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
73
lib/vfs/path.h
Обычный файл
73
lib/vfs/path.h
Обычный файл
@ -0,0 +1,73 @@
|
||||
#ifndef MC__VFS_PATH_H
|
||||
#define MC__VFS_PATH_H
|
||||
|
||||
/*** typedefs(not structures) and defined constants **********************************************/
|
||||
|
||||
#define VFS_PATH_URL_DELIMITER "://"
|
||||
|
||||
/*** enums ***************************************************************************************/
|
||||
|
||||
/*** structures declarations (and typedefs of structures)*****************************************/
|
||||
|
||||
struct vfs_class;
|
||||
struct vfs_url_struct;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GList *path;
|
||||
} vfs_path_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *user;
|
||||
char *password;
|
||||
char *host;
|
||||
int port;
|
||||
char *path;
|
||||
struct vfs_class *class;
|
||||
char *encoding;
|
||||
char *vfs_prefix;
|
||||
|
||||
struct
|
||||
{
|
||||
GIConv converter;
|
||||
DIR *info;
|
||||
} dir;
|
||||
|
||||
struct vfs_s_super *current_super_block;
|
||||
} vfs_path_element_t;
|
||||
|
||||
/*** global variables defined in .c file *********************************************************/
|
||||
|
||||
/*** declarations of public functions ************************************************************/
|
||||
|
||||
vfs_path_t *vfs_path_new (void);
|
||||
vfs_path_t *vfs_path_clone (const vfs_path_t * vpath);
|
||||
void vfs_path_remove_element_by_index (vfs_path_t * vpath, int element_index);
|
||||
void vfs_path_free (vfs_path_t * path);
|
||||
int vfs_path_elements_count (const vfs_path_t * path);
|
||||
|
||||
char *vfs_path_to_str (const vfs_path_t * path);
|
||||
char *vfs_path_to_str_elements_count (const vfs_path_t * path, int elements_count);
|
||||
vfs_path_t *vfs_path_from_str (const char *path_str);
|
||||
|
||||
vfs_path_element_t *vfs_path_get_by_index (const vfs_path_t * path, int element_index);
|
||||
vfs_path_element_t *vfs_path_element_clone (const vfs_path_element_t * element);
|
||||
void vfs_path_element_free (vfs_path_element_t * element);
|
||||
|
||||
struct vfs_class *vfs_prefix_to_class (const char *prefix);
|
||||
|
||||
gboolean vfs_path_element_need_cleanup_converter (const vfs_path_element_t * element);
|
||||
|
||||
char *vfs_path_serialize (const vfs_path_t * vpath, GError ** error);
|
||||
vfs_path_t *vfs_path_deserialize (const char *data, GError ** error);
|
||||
|
||||
/*** inline functions ****************************************************************************/
|
||||
|
||||
static inline gboolean
|
||||
vfs_path_element_valid (const vfs_path_element_t * element)
|
||||
{
|
||||
return (element != NULL && element->class != NULL);
|
||||
}
|
||||
|
||||
#endif
|
@ -373,85 +373,82 @@ vfs_mkstemps (char **pname, const char *prefix, const char *param_basename)
|
||||
* ftp://joe:password@foo.se
|
||||
*
|
||||
* @param path is an input string to be parsed
|
||||
* @param host is an outptun g_malloc()ed hostname
|
||||
* @param user is an outptut g_malloc()ed username
|
||||
* (NULL if not specified)
|
||||
* @param port is an outptut integer port number
|
||||
* @param pass is an outptut g_malloc()ed password
|
||||
* @param default_port is an input default port
|
||||
* @param flags are parsing modifier flags (@see VFS_URL_FLAGS)
|
||||
* @param flags are parsing modifier flags (@see vfs_url_flags_t)
|
||||
*
|
||||
* @return g_malloc()ed host, user and pass if they are present.
|
||||
* @return g_malloc()ed url info.
|
||||
* If the user is empty, e.g. ftp://@roxanne/private, and URL_USE_ANONYMOUS
|
||||
* is not set, then the current login name is supplied.
|
||||
* Return value is a g_malloc()ed string with the pathname relative to the
|
||||
* Return value is a g_malloc()ed structure with the pathname relative to the
|
||||
* host.
|
||||
*/
|
||||
|
||||
char *
|
||||
vfs_split_url (const char *path, char **host, char **user, int *port,
|
||||
char **pass, int default_port, enum VFS_URL_FLAGS flags)
|
||||
vfs_path_element_t *
|
||||
vfs_url_split (const char *path, int default_port, vfs_url_flags_t flags)
|
||||
{
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
char *pcopy;
|
||||
const char *pend;
|
||||
char *dir, *colon, *inner_colon, *at, *rest;
|
||||
char *retval;
|
||||
char *const pcopy = g_strdup (path);
|
||||
const char *pend = pcopy + strlen (pcopy);
|
||||
|
||||
if (pass)
|
||||
*pass = NULL;
|
||||
*port = default_port;
|
||||
*user = NULL;
|
||||
retval = NULL;
|
||||
path_element = g_new0 (vfs_path_element_t, 1);
|
||||
path_element->port = default_port;
|
||||
|
||||
pcopy = g_strdup (path);
|
||||
pend = pcopy + strlen (pcopy);
|
||||
dir = pcopy;
|
||||
if (!(flags & URL_NOSLASH))
|
||||
|
||||
if ((flags & URL_NOSLASH) == 0)
|
||||
{
|
||||
/* locate path component */
|
||||
while (*dir != PATH_SEP && *dir)
|
||||
while (*dir != PATH_SEP && *dir != '\0')
|
||||
dir++;
|
||||
if (*dir)
|
||||
{
|
||||
retval = g_strdup (dir);
|
||||
*dir = 0;
|
||||
}
|
||||
if (*dir == '\0')
|
||||
path_element->path = g_strdup (PATH_SEP_STR);
|
||||
else
|
||||
retval = g_strdup (PATH_SEP_STR);
|
||||
{
|
||||
path_element->path = g_strdup (dir);
|
||||
*dir = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* search for any possible user */
|
||||
at = strrchr (pcopy, '@');
|
||||
|
||||
/* We have a username */
|
||||
if (at)
|
||||
if (at == NULL)
|
||||
rest = pcopy;
|
||||
else
|
||||
{
|
||||
*at = 0;
|
||||
*at = '\0';
|
||||
inner_colon = strchr (pcopy, ':');
|
||||
if (inner_colon)
|
||||
if (inner_colon != NULL)
|
||||
{
|
||||
*inner_colon = 0;
|
||||
*inner_colon = '\0';
|
||||
inner_colon++;
|
||||
if (pass)
|
||||
*pass = g_strdup (inner_colon);
|
||||
path_element->password = g_strdup (inner_colon);
|
||||
}
|
||||
if (*pcopy != 0)
|
||||
*user = g_strdup (pcopy);
|
||||
|
||||
if (*pcopy != '\0')
|
||||
path_element->user = g_strdup (pcopy);
|
||||
|
||||
if (pend == at + 1)
|
||||
rest = at;
|
||||
else
|
||||
rest = at + 1;
|
||||
}
|
||||
else
|
||||
rest = pcopy;
|
||||
|
||||
if (!*user && !(flags & URL_USE_ANONYMOUS))
|
||||
*user = vfs_get_local_username ();
|
||||
if ((flags & URL_USE_ANONYMOUS) == 0)
|
||||
path_element->user = vfs_get_local_username ();
|
||||
|
||||
/* Check if the host comes with a port spec, if so, chop it */
|
||||
if ('[' == *rest)
|
||||
if (*rest != '[')
|
||||
colon = strchr (rest, ':');
|
||||
else
|
||||
{
|
||||
colon = strchr (++rest, ']');
|
||||
if (colon)
|
||||
if (colon != NULL)
|
||||
{
|
||||
colon[0] = '\0';
|
||||
colon[1] = '\0';
|
||||
@ -459,45 +456,37 @@ vfs_split_url (const char *path, char **host, char **user, int *port,
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free (pcopy);
|
||||
g_free (retval);
|
||||
*host = NULL;
|
||||
*port = 0;
|
||||
vfs_path_element_free (path_element);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
colon = strchr (rest, ':');
|
||||
|
||||
if (colon)
|
||||
if (colon != NULL)
|
||||
{
|
||||
*colon = 0;
|
||||
if (sscanf (colon + 1, "%d", port) == 1)
|
||||
*colon = '\0';
|
||||
if (sscanf (colon + 1, "%d", &path_element->port) == 1)
|
||||
{
|
||||
if (*port <= 0 || *port >= 65536)
|
||||
*port = default_port;
|
||||
if (path_element->port <= 0 || path_element->port >= 65536)
|
||||
path_element->port = default_port;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (*(++colon))
|
||||
while (*(++colon) != '\0')
|
||||
{
|
||||
switch (*colon)
|
||||
{
|
||||
case 'C':
|
||||
*port = 1;
|
||||
path_element->port = 1;
|
||||
break;
|
||||
case 'r':
|
||||
*port = 2;
|
||||
path_element->port = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (host)
|
||||
*host = g_strdup (rest);
|
||||
|
||||
g_free (pcopy);
|
||||
return retval;
|
||||
path_element->host = g_strdup (rest);
|
||||
|
||||
return path_element;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
@ -12,21 +12,23 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "lib/global.h"
|
||||
#include "path.h"
|
||||
|
||||
/*** typedefs(not structures) and defined constants **********************************************/
|
||||
|
||||
/*** enums ***************************************************************************************/
|
||||
|
||||
/** Bit flags for vfs_split_url()
|
||||
/** Bit flags for vfs_url_split()
|
||||
*
|
||||
* Modify parsing parameters according to flag meaning.
|
||||
* @see vfs_split_url()
|
||||
* @see vfs_url_split()
|
||||
*/
|
||||
enum VFS_URL_FLAGS
|
||||
typedef enum
|
||||
{
|
||||
URL_FLAGS_NONE = 0,
|
||||
URL_USE_ANONYMOUS = 1, /**< if set, empty *user will contain NULL instead of current */
|
||||
URL_NOSLASH = 2 /**< if set, 'proto://' part in url is not searched */
|
||||
};
|
||||
} vfs_url_flags_t;
|
||||
|
||||
/*** structures declarations (and typedefs of structures)*****************************************/
|
||||
|
||||
@ -37,8 +39,7 @@ enum VFS_URL_FLAGS
|
||||
int vfs_finduid (const char *name);
|
||||
int vfs_findgid (const char *name);
|
||||
|
||||
char *vfs_split_url (const char *path, char **host, char **user, int *port,
|
||||
char **pass, int default_port, enum VFS_URL_FLAGS flags);
|
||||
vfs_path_element_t *vfs_url_split (const char *path, int default_port, vfs_url_flags_t flags);
|
||||
int vfs_split_text (char *p);
|
||||
|
||||
int vfs_mkstemps (char **pname, const char *prefix, const char *basename);
|
||||
|
1512
lib/vfs/vfs.c
1512
lib/vfs/vfs.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
121
lib/vfs/vfs.h
121
lib/vfs/vfs.h
@ -19,6 +19,8 @@
|
||||
#include "lib/global.h"
|
||||
#include "lib/fs.h" /* MC_MAXPATHLEN */
|
||||
|
||||
#include "path.h"
|
||||
|
||||
/*** typedefs(not structures) and defined constants **********************************************/
|
||||
|
||||
#if defined (ENABLE_VFS_FTP) || defined (ENABLE_VFS_FISH) || defined (ENABLE_VFS_SMB)
|
||||
@ -148,47 +150,46 @@ typedef struct vfs_class
|
||||
*/
|
||||
int (*which) (struct vfs_class * me, const char *path);
|
||||
|
||||
void *(*open) (struct vfs_class * me, const char *fname, int flags, mode_t mode);
|
||||
void *(*open) (const vfs_path_t * vpath, int flags, mode_t mode);
|
||||
int (*close) (void *vfs_info);
|
||||
ssize_t (*read) (void *vfs_info, char *buffer, size_t count);
|
||||
ssize_t (*write) (void *vfs_info, const char *buf, size_t count);
|
||||
|
||||
void *(*opendir) (struct vfs_class * me, const char *dirname);
|
||||
void *(*opendir) (const vfs_path_t * vpath);
|
||||
void *(*readdir) (void *vfs_info);
|
||||
int (*closedir) (void *vfs_info);
|
||||
|
||||
int (*stat) (struct vfs_class * me, const char *path, struct stat * buf);
|
||||
int (*lstat) (struct vfs_class * me, const char *path, struct stat * buf);
|
||||
int (*stat) (const vfs_path_t * vpath, struct stat * buf);
|
||||
int (*lstat) (const vfs_path_t * vpath, struct stat * buf);
|
||||
int (*fstat) (void *vfs_info, struct stat * buf);
|
||||
|
||||
int (*chmod) (struct vfs_class * me, const char *path, int mode);
|
||||
int (*chown) (struct vfs_class * me, const char *path, uid_t owner, gid_t group);
|
||||
int (*utime) (struct vfs_class * me, const char *path, struct utimbuf * times);
|
||||
int (*chmod) (const vfs_path_t * vpath, int mode);
|
||||
int (*chown) (const vfs_path_t * vpath, uid_t owner, gid_t group);
|
||||
int (*utime) (const vfs_path_t * vpath, struct utimbuf * times);
|
||||
|
||||
int (*readlink) (struct vfs_class * me, const char *path, char *buf, size_t size);
|
||||
int (*symlink) (struct vfs_class * me, const char *n1, const char *n2);
|
||||
int (*link) (struct vfs_class * me, const char *p1, const char *p2);
|
||||
int (*unlink) (struct vfs_class * me, const char *path);
|
||||
int (*rename) (struct vfs_class * me, const char *p1, const char *p2);
|
||||
int (*chdir) (struct vfs_class * me, const char *path);
|
||||
int (*readlink) (const vfs_path_t * vpath, char *buf, size_t size);
|
||||
int (*symlink) (const vfs_path_t * vpath1, const vfs_path_t * vpath2);
|
||||
int (*link) (const vfs_path_t * vpath1, const vfs_path_t * vpath2);
|
||||
int (*unlink) (const vfs_path_t * vpath);
|
||||
int (*rename) (const vfs_path_t * vpath1, const vfs_path_t * vpath2);
|
||||
int (*chdir) (const vfs_path_t * vpath);
|
||||
int (*ferrno) (struct vfs_class * me);
|
||||
off_t (*lseek) (void *vfs_info, off_t offset, int whence);
|
||||
int (*mknod) (struct vfs_class * me, const char *path, mode_t mode, dev_t dev);
|
||||
int (*mknod) (const vfs_path_t * vpath, mode_t mode, dev_t dev);
|
||||
|
||||
vfsid (*getid) (struct vfs_class * me, const char *path);
|
||||
vfsid (*getid) (const vfs_path_t * vpath);
|
||||
|
||||
int (*nothingisopen) (vfsid id);
|
||||
void (*free) (vfsid id);
|
||||
|
||||
char *(*getlocalcopy) (struct vfs_class * me, const char *filename);
|
||||
int (*ungetlocalcopy) (struct vfs_class * me, const char *filename,
|
||||
const char *local, int has_changed);
|
||||
char *(*getlocalcopy) (const vfs_path_t * vpath);
|
||||
int (*ungetlocalcopy) (const vfs_path_t * vpath, const char *local, int has_changed);
|
||||
|
||||
int (*mkdir) (struct vfs_class * me, const char *path, mode_t mode);
|
||||
int (*rmdir) (struct vfs_class * me, const char *path);
|
||||
int (*mkdir) (const vfs_path_t * vpath, mode_t mode);
|
||||
int (*rmdir) (const vfs_path_t * vpath);
|
||||
|
||||
int (*ctl) (void *vfs_info, int ctlop, void *arg);
|
||||
int (*setctl) (struct vfs_class * me, const char *path, int ctlop, void *arg);
|
||||
int (*setctl) (const vfs_path_t * vpath, int ctlop, void *arg);
|
||||
} vfs_class;
|
||||
|
||||
/*
|
||||
@ -212,9 +213,9 @@ extern int use_netrc;
|
||||
/*** declarations of public functions ************************************************************/
|
||||
|
||||
/* lib/vfs/direntry.c: */
|
||||
void *vfs_s_open (struct vfs_class *me, const char *file, int flags, mode_t mode);
|
||||
void *vfs_s_open (const vfs_path_t * vpath, int flags, mode_t mode);
|
||||
|
||||
vfsid vfs_getid (struct vfs_class *vclass, const char *dir);
|
||||
vfsid vfs_getid (const vfs_path_t * vpath);
|
||||
|
||||
void vfs_init (void);
|
||||
void vfs_shut (void);
|
||||
@ -228,14 +229,52 @@ int vfs_timeouts (void);
|
||||
void vfs_expire (int now);
|
||||
|
||||
char *vfs_get_current_dir (void);
|
||||
gboolean vfs_current_is_local (void);
|
||||
gboolean vfs_file_is_local (const char *filename);
|
||||
vfs_path_t *vfs_get_raw_current_dir (void);
|
||||
void vfs_set_raw_current_dir (const vfs_path_t * vpath);
|
||||
|
||||
gboolean vfs_current_is_local (void);
|
||||
gboolean vfs_file_is_local (const vfs_path_t * vpath);
|
||||
|
||||
char *vfs_strip_suffix_from_filename (const char *filename);
|
||||
|
||||
vfs_class_flags_t vfs_file_class_flags (const vfs_path_t * vpath);
|
||||
|
||||
/* translate path back to terminal encoding, remove all #enc:
|
||||
* every invalid character is replaced with question mark
|
||||
* return static buffer */
|
||||
char *vfs_translate_path (const char *path);
|
||||
/* return new string */
|
||||
char *vfs_translate_path_n (const char *path);
|
||||
|
||||
void vfs_stamp_path (const char *path);
|
||||
|
||||
void vfs_release_path (const char *dir);
|
||||
|
||||
void vfs_fill_names (fill_names_f);
|
||||
|
||||
void vfs_print_message (const char *msg, ...) __attribute__ ((format (__printf__, 1, 2)));
|
||||
|
||||
int vfs_ferrno (struct vfs_class *vfs);
|
||||
|
||||
int vfs_new_handle (struct vfs_class *vclass, void *fsinfo);
|
||||
|
||||
struct vfs_class *vfs_class_find_by_handle (int handle);
|
||||
|
||||
void *vfs_class_data_find_by_handle (int handle);
|
||||
|
||||
void vfs_free_handle (int handle);
|
||||
|
||||
char *_vfs_get_cwd (void);
|
||||
|
||||
vfs_path_t *vfs_change_encoding (vfs_path_t * vpath, const char *encoding);
|
||||
|
||||
/**
|
||||
* Interface functions described in interface.c
|
||||
*/
|
||||
ssize_t mc_read (int handle, void *buffer, size_t count);
|
||||
ssize_t mc_write (int handle, const void *buffer, size_t count);
|
||||
int mc_utime (const char *path, struct utimbuf *times);
|
||||
int mc_readlink (const char *path, char *buf, size_t bufsiz);
|
||||
int mc_ungetlocalcopy (const char *pathname, const char *local, int has_changed);
|
||||
int mc_close (int handle);
|
||||
off_t mc_lseek (int fd, off_t offset, int whence);
|
||||
DIR *mc_opendir (const char *dirname);
|
||||
@ -258,37 +297,9 @@ int mc_ctl (int fd, int ctlop, void *arg);
|
||||
int mc_setctl (const char *path, int ctlop, void *arg);
|
||||
int mc_open (const char *filename, int flags, ...);
|
||||
char *mc_get_current_wd (char *buffer, size_t bufsize);
|
||||
char *vfs_canon (const char *path);
|
||||
char *mc_getlocalcopy (const char *pathname);
|
||||
char *vfs_strip_suffix_from_filename (const char *filename);
|
||||
char *vfs_translate_url (const char *url);
|
||||
int mc_ungetlocalcopy (const char *pathname, const char *local, int has_changed);
|
||||
|
||||
struct vfs_class *vfs_split (char *path, char **inpath, char **op);
|
||||
char *vfs_path (const char *path);
|
||||
|
||||
struct vfs_class *vfs_get_class (const char *path);
|
||||
vfs_class_flags_t vfs_file_class_flags (const char *filename);
|
||||
|
||||
/* return encoding after last #enc: or NULL, if part does not contain #enc:
|
||||
* return static buffer */
|
||||
const char *vfs_get_encoding (const char *path);
|
||||
|
||||
/* canonize and translate path, return new string */
|
||||
char *vfs_canon_and_translate (const char *path);
|
||||
/* translate path back to terminal encoding, remove all #enc:
|
||||
* every invalid character is replaced with question mark
|
||||
* return static buffer */
|
||||
char *vfs_translate_path (const char *path);
|
||||
/* return new string */
|
||||
char *vfs_translate_path_n (const char *path);
|
||||
|
||||
void vfs_stamp_path (const char *path);
|
||||
|
||||
void vfs_release_path (const char *dir);
|
||||
|
||||
void vfs_fill_names (fill_names_f);
|
||||
|
||||
void vfs_print_message (const char *msg, ...) __attribute__ ((format (__printf__, 1, 2)));
|
||||
|
||||
/*** inline functions ****************************************************************************/
|
||||
#endif /* MC_VFS_VFS_H */
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "lib/global.h" /* GList */
|
||||
#include "lib/vfs/path.h" /* vfs_path_t */
|
||||
|
||||
/*** typedefs(not structures) and defined constants **********************************************/
|
||||
|
||||
@ -39,6 +40,8 @@
|
||||
|
||||
#define MEDATA ((struct vfs_s_subclass *) me->data)
|
||||
|
||||
#define VFSDATA(a) ((a->class != NULL) ? (struct vfs_s_subclass *) a->class->data : NULL)
|
||||
|
||||
#define FH ((vfs_file_handler_t *) fh)
|
||||
#define FH_SUPER FH->ino->super
|
||||
|
||||
@ -60,6 +63,10 @@ struct vfs_s_super
|
||||
int fd_usage; /* Number of open files */
|
||||
int ino_usage; /* Usage count of this superblock */
|
||||
int want_stale; /* If set, we do not flush cache properly */
|
||||
#ifdef ENABLE_VFS_NET
|
||||
vfs_path_element_t *path_element;
|
||||
#endif /* ENABLE_VFS_NET */
|
||||
|
||||
void *data; /* This is for filesystem-specific use */
|
||||
};
|
||||
|
||||
@ -117,11 +124,11 @@ struct vfs_s_subclass
|
||||
void (*free_inode) (struct vfs_class * me, struct vfs_s_inode * ino); /* optional */
|
||||
int (*init_entry) (struct vfs_class * me, struct vfs_s_entry * entry); /* optional */
|
||||
|
||||
void *(*archive_check) (struct vfs_class * me, const char *name, char *op); /* optional */
|
||||
int (*archive_same) (struct vfs_class * me, struct vfs_s_super * psup,
|
||||
const char *archive_name, char *op, void *cookie);
|
||||
int (*open_archive) (struct vfs_class * me, struct vfs_s_super * psup,
|
||||
const char *archive_name, char *op);
|
||||
void *(*archive_check) (const vfs_path_t * vpath); /* optional */
|
||||
int (*archive_same) (const vfs_path_element_t * vpath_element, struct vfs_s_super * psup,
|
||||
const vfs_path_t * vpath, void *cookie);
|
||||
int (*open_archive) (struct vfs_s_super * psup,
|
||||
const vfs_path_t * vpath, const vfs_path_element_t * vpath_element);
|
||||
void (*free_archive) (struct vfs_class * me, struct vfs_s_super * psup);
|
||||
|
||||
int (*fh_open) (struct vfs_class * me, vfs_file_handler_t * fh, int flags, mode_t mode);
|
||||
@ -161,8 +168,9 @@ struct vfs_s_inode *vfs_s_find_root (struct vfs_class *me, struct vfs_s_entry *e
|
||||
|
||||
/* outside interface */
|
||||
void vfs_s_init_class (struct vfs_class *vclass, struct vfs_s_subclass *sub);
|
||||
const char *vfs_s_get_path_mangle (struct vfs_class *me, char *inname,
|
||||
struct vfs_s_super **archive, int flags);
|
||||
const char *vfs_s_get_path (const vfs_path_t * vpath, struct vfs_s_super **archive,
|
||||
int flags);
|
||||
|
||||
void vfs_s_invalidate (struct vfs_class *me, struct vfs_s_super *super);
|
||||
char *vfs_s_fullpath (struct vfs_class *me, struct vfs_s_inode *ino);
|
||||
|
||||
|
@ -108,149 +108,149 @@
|
||||
|
||||
# .tgz, .tpz, .tar.gz, .tar.z, .tar.Z, .ipk
|
||||
regex/\.t([gp]?z|ar\.g?[zZ])$|\.ipk$
|
||||
Open=%cd %p#utar
|
||||
Open=%cd %p/utar://
|
||||
View=%view{ascii} gzip -dc %f 2>/dev/null | tar tvvf -
|
||||
|
||||
regex/\.tar\.bz$
|
||||
# Open=%cd %p#utar
|
||||
# Open=%cd %p/utar://
|
||||
View=%view{ascii} bzip -dc %f 2>/dev/null | tar tvvf -
|
||||
|
||||
regex/\.t(ar\.bz2|bz2?|b2)$
|
||||
Open=%cd %p#utar
|
||||
Open=%cd %p/utar://
|
||||
View=%view{ascii} bzip2 -dc %f 2>/dev/null | tar tvvf -
|
||||
|
||||
# .tar.lzma, .tlz
|
||||
regex/\.t(ar\.lzma|lz)$
|
||||
Open=%cd %p#utar
|
||||
Open=%cd %p/utar://
|
||||
View=%view{ascii} lzma -dc %f 2>/dev/null | tar tvvf -
|
||||
|
||||
# .tar.xz, .txz
|
||||
regex/\.t(ar\.xz|xz)$
|
||||
Open=%cd %p#utar
|
||||
Open=%cd %p/utar://
|
||||
View=%view{ascii} xz -dc %f 2>/dev/null | tar tvvf -
|
||||
|
||||
# .tar.F - used in QNX
|
||||
regex/\.tar\.F$
|
||||
# Open=%cd %p#utar
|
||||
# Open=%cd %p/utar://
|
||||
View=%view{ascii} freeze -dc %f 2>/dev/null | tar tvvf -
|
||||
|
||||
# .qpr/.qpk - QNX Neutrino package installer files
|
||||
regex/\.(qp[rk])$
|
||||
Open=%cd %p#utar
|
||||
Open=%cd %p/utar://
|
||||
View=%view{ascii} gzip -dc %f 2>/dev/null | tar tvvf -
|
||||
|
||||
# tar
|
||||
regex/\.(tar|TAR)$
|
||||
Open=%cd %p#utar
|
||||
Open=%cd %p/utar://
|
||||
View=%view{ascii} tar tvvf - < %f
|
||||
|
||||
# lha
|
||||
type/^LHa\ .*archive
|
||||
Open=%cd %p#ulha
|
||||
Open=%cd %p/ulha://
|
||||
View=%view{ascii} lha l %f
|
||||
|
||||
# arj
|
||||
regex/\.a(rj|[0-9][0-9])$
|
||||
Open=%cd %p#uarj
|
||||
Open=%cd %p/uarj://
|
||||
View=%view{ascii} unarj l %f
|
||||
|
||||
# cab
|
||||
regex/\.([cC][aA][bB])$
|
||||
Open=%cd %p#ucab
|
||||
Open=%cd %p/ucab://
|
||||
View=%view{ascii} cabextract -l %f
|
||||
|
||||
# ha
|
||||
regex/\.([Hh][Aa])$
|
||||
Open=%cd %p#uha
|
||||
Open=%cd %p/uha://
|
||||
View=%view{ascii} ha lf %f
|
||||
|
||||
# rar
|
||||
regex/\.[rR]([aA][rR]|[0-9][0-9])$
|
||||
Open=%cd %p#urar
|
||||
Open=%cd %p/urar://
|
||||
View=%view{ascii} rar v -c- %f
|
||||
|
||||
# ALZip
|
||||
regex/\.(alz|ALZ)$
|
||||
Open=%cd %p#ualz
|
||||
Open=%cd %p/ualz://
|
||||
View=%view{ascii} unalz -l %f
|
||||
|
||||
# cpio
|
||||
shell/.cpio.Z
|
||||
Open=%cd %p#ucpio
|
||||
Open=%cd %p/ucpio://
|
||||
View=%view{ascii} gzip -dc %f | cpio -itv 2>/dev/null
|
||||
|
||||
shell/.cpio.gz
|
||||
Open=%cd %p#ucpio
|
||||
Open=%cd %p/ucpio://
|
||||
View=%view{ascii} gzip -dc %f | cpio -itv 2>/dev/null
|
||||
|
||||
shell/.cpio
|
||||
Open=%cd %p#ucpio
|
||||
Open=%cd %p/ucpio://
|
||||
View=%view{ascii} cpio -itv < %f 2>/dev/null
|
||||
|
||||
# ls-lR
|
||||
regex/(^|\.)ls-?lR(\.gz|Z|bz2)$
|
||||
Open=%cd %p#lslR
|
||||
Open=%cd %p/lslR://
|
||||
|
||||
# patch
|
||||
regex/\.(diff|patch)(\.bz2)$
|
||||
Open=%cd %p#patchfs
|
||||
Open=%cd %p/patchfs://
|
||||
View=%view{ascii} bzip2 -dc %f 2>/dev/null
|
||||
|
||||
regex/\.(diff|patch)(\.(gz|Z))$
|
||||
Open=%cd %p#patchfs
|
||||
Open=%cd %p/patchfs://
|
||||
View=%view{ascii} gzip -dc %f 2>/dev/null
|
||||
|
||||
regex/\.(diff|patch)$
|
||||
Open=%cd %p#patchfs
|
||||
Open=%cd %p/patchfs://
|
||||
View=%view{ascii} /bin/cat %f 2>/dev/null
|
||||
|
||||
# ar library
|
||||
regex/\.s?a$
|
||||
Open=%cd %p#uar
|
||||
Open=%cd %p/uar://
|
||||
#Open=%view{ascii} ar tv %f
|
||||
View=%view{ascii} file %f && nm -C %f
|
||||
|
||||
# trpm
|
||||
regex/\.trpm$
|
||||
Open=%cd %p#trpm
|
||||
Open=%cd %p/trpm://
|
||||
View=%view{ascii} rpm -qivl --scripts `basename %p .trpm`
|
||||
|
||||
# RPM packages (SuSE uses *.spm for source packages)
|
||||
regex/\.(src\.rpm|spm)$
|
||||
Open=%cd %p#rpm
|
||||
Open=%cd %p/rpm://
|
||||
View=%view{ascii} if rpm --nosignature --version >/dev/null 2>&1; then RPM="rpm --nosignature" ; else RPM="rpm" ; fi ; $RPM -qivlp --scripts %f
|
||||
|
||||
regex/\.rpm$
|
||||
Open=%cd %p#rpm
|
||||
Open=%cd %p/rpm://
|
||||
View=%view{ascii} if rpm --nosignature --version >/dev/null 2>&1; then RPM="rpm --nosignature" ; else RPM="rpm" ; fi ; $RPM -qivlp --scripts %f
|
||||
|
||||
# deb
|
||||
regex/\.u?deb$
|
||||
Open=%cd %p#deb
|
||||
Open=%cd %p/deb://
|
||||
View=%view{ascii} dpkg-deb -I %f && echo && dpkg-deb -c %f
|
||||
|
||||
# dpkg
|
||||
shell/.debd
|
||||
Open=%cd %p#debd
|
||||
Open=%cd %p/debd://
|
||||
View=%view{ascii} dpkg -s `echo %p | sed 's/\([0-9a-z.-]*\).*/\1/'`
|
||||
# apt
|
||||
shell/.deba
|
||||
Open=%cd %p#deba
|
||||
Open=%cd %p/deba://
|
||||
View=%view{ascii} apt-cache show `echo %p | sed 's/\([0-9a-z.-]*\).*/\1/'`
|
||||
|
||||
# ISO9660
|
||||
regex/\.([iI][sS][oO])$
|
||||
Open=%cd %p#iso9660
|
||||
Open=%cd %p/iso9660://
|
||||
View=%view{ascii} isoinfo -l -i %f
|
||||
|
||||
# 7zip archives (they are not man pages)
|
||||
regex/\.(7z|7Z)$
|
||||
Open=%cd %p#u7z
|
||||
Open=%cd %p/u7z://
|
||||
View=%view{ascii} 7za l %f 2>/dev/null
|
||||
|
||||
# Mailboxes
|
||||
type/^ASCII\ mail\ text
|
||||
Open=%cd %p#mailfs
|
||||
Open=%cd %p/mailfs://
|
||||
|
||||
|
||||
### Sources ###
|
||||
@ -574,7 +574,7 @@ regex/\.(rexx?|cmd)$
|
||||
|
||||
# Disk images for Commodore computers (VIC20, C64, C128)
|
||||
regex/\.(d64|D64)$
|
||||
Open=%cd %p#uc1541
|
||||
Open=%cd %p/uc1541://
|
||||
View=%view{ascii} c1541 %f -list
|
||||
Extract=c1541 %f -extract
|
||||
|
||||
@ -595,25 +595,25 @@ regex/\.(lyx|LYX)$
|
||||
|
||||
# ace
|
||||
regex/\.(ace|ACE)$
|
||||
Open=%cd %p#uace
|
||||
Open=%cd %p/uace://
|
||||
View=%view{ascii} unace l %f
|
||||
Extract=unace x %f
|
||||
|
||||
# arc
|
||||
regex/\.(arc|ARC)$
|
||||
Open=%cd %p#uarc
|
||||
Open=%cd %p/uarc://
|
||||
View=%view{ascii} arc l %f
|
||||
Extract=arc x %f '*'
|
||||
Extract (with flags)=I=%{Enter any Arc flags:}; if test -n "$I"; then arc x $I %f; fi
|
||||
|
||||
# zip
|
||||
type/^([Zz][Ii][Pp])\ archive
|
||||
Open=%cd %p#uzip
|
||||
Open=%cd %p/uzip://
|
||||
View=%view{ascii} unzip -v %f
|
||||
|
||||
# zoo
|
||||
regex/\.([Zz][Oo][Oo])$
|
||||
Open=%cd %p#uzoo
|
||||
Open=%cd %p/uzoo://
|
||||
View=%view{ascii} zoo l %f
|
||||
|
||||
# gzip
|
||||
|
@ -3332,9 +3332,10 @@ diff_view (const char *file1, const char *file2, const char *label1, const char
|
||||
#define GET_FILE_AND_STAMP(n) \
|
||||
do \
|
||||
{ \
|
||||
vfs_path_t *vpath = vfs_path_from_str(file##n); \
|
||||
use_copy##n = 0; \
|
||||
real_file##n = file##n; \
|
||||
if (!vfs_file_is_local (file##n)) \
|
||||
if (!vfs_file_is_local (vpath)) \
|
||||
{ \
|
||||
real_file##n = mc_getlocalcopy (file##n); \
|
||||
if (real_file##n != NULL) \
|
||||
@ -3344,6 +3345,7 @@ do \
|
||||
use_copy##n = -1; \
|
||||
} \
|
||||
} \
|
||||
vfs_path_free(vpath); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
|
@ -432,6 +432,7 @@ static int
|
||||
edit_load_file (WEdit * edit)
|
||||
{
|
||||
int fast_load = 1;
|
||||
vfs_path_t *vpath = vfs_path_from_str (edit->filename);
|
||||
|
||||
/* Cannot do fast load if a filter is used */
|
||||
if (edit_find_filter (edit->filename) >= 0)
|
||||
@ -441,8 +442,9 @@ edit_load_file (WEdit * edit)
|
||||
* VFS may report file size incorrectly, and slow load is not a big
|
||||
* deal considering overhead in VFS.
|
||||
*/
|
||||
if (!vfs_file_is_local (edit->filename))
|
||||
if (!vfs_file_is_local (vpath))
|
||||
fast_load = 0;
|
||||
vfs_path_free (vpath);
|
||||
|
||||
/*
|
||||
* FIXME: line end translation should disable fast loading as well
|
||||
@ -497,12 +499,15 @@ edit_load_position (WEdit * edit)
|
||||
char *filename;
|
||||
long line, column;
|
||||
off_t offset;
|
||||
vfs_path_t *vpath;
|
||||
|
||||
if (!edit->filename || !*edit->filename)
|
||||
return;
|
||||
|
||||
filename = vfs_canon (edit->filename);
|
||||
vpath = vfs_path_from_str (edit->filename);
|
||||
filename = vfs_path_to_str (vpath);
|
||||
load_file_position (filename, &line, &column, &offset, &edit->serialized_bookmarks);
|
||||
vfs_path_free (vpath);
|
||||
g_free (filename);
|
||||
|
||||
if (line > 0)
|
||||
@ -530,11 +535,13 @@ static void
|
||||
edit_save_position (WEdit * edit)
|
||||
{
|
||||
char *filename;
|
||||
vfs_path_t *vpath;
|
||||
|
||||
if (edit->filename == NULL || *edit->filename == '\0')
|
||||
return;
|
||||
|
||||
filename = vfs_canon (edit->filename);
|
||||
vpath = vfs_path_from_str (edit->filename);
|
||||
filename = vfs_path_to_str (vpath);
|
||||
|
||||
book_mark_serialize (edit, BOOK_MARK_COLOR);
|
||||
save_file_position (filename, edit->curs_line + 1, edit->curs_col, edit->curs1,
|
||||
@ -542,6 +549,7 @@ edit_save_position (WEdit * edit)
|
||||
edit->serialized_bookmarks = NULL;
|
||||
|
||||
g_free (filename);
|
||||
vfs_path_free (vpath);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -1599,7 +1607,7 @@ edit_get_bracket (WEdit * edit, int in_screen, unsigned long furthest_bracket_se
|
||||
break;
|
||||
/* count lines if searching downward */
|
||||
if (inc > 0 && a == '\n')
|
||||
if (n++ >= edit->widget.lines - edit->curs_row) /* out of screen */
|
||||
if (n++ >= edit->widget.lines - edit->curs_row) /* out of screen */
|
||||
break;
|
||||
}
|
||||
/* count bracket depth */
|
||||
@ -2320,7 +2328,9 @@ edit_set_codeset (WEdit * edit)
|
||||
#ifdef HAVE_CHARSET
|
||||
const char *cp_id;
|
||||
|
||||
cp_id = get_codepage_id (mc_global.source_codepage >= 0 ? mc_global.source_codepage : mc_global.display_codepage);
|
||||
cp_id =
|
||||
get_codepage_id (mc_global.source_codepage >=
|
||||
0 ? mc_global.source_codepage : mc_global.display_codepage);
|
||||
|
||||
if (cp_id != NULL)
|
||||
{
|
||||
@ -3427,7 +3437,7 @@ edit_execute_cmd (WEdit * edit, unsigned long command, int char_for_insertion)
|
||||
|
||||
switch (command)
|
||||
{
|
||||
/* a mark command with shift-arrow */
|
||||
/* a mark command with shift-arrow */
|
||||
case CK_MarkLeft:
|
||||
case CK_MarkRight:
|
||||
case CK_MarkToWordBegin:
|
||||
@ -3446,7 +3456,7 @@ edit_execute_cmd (WEdit * edit, unsigned long command, int char_for_insertion)
|
||||
case CK_MarkScrollDown:
|
||||
case CK_MarkParagraphUp:
|
||||
case CK_MarkParagraphDown:
|
||||
/* a mark command with alt-arrow */
|
||||
/* a mark command with alt-arrow */
|
||||
case CK_MarkColumnPageUp:
|
||||
case CK_MarkColumnPageDown:
|
||||
case CK_MarkColumnLeft:
|
||||
@ -3466,7 +3476,7 @@ edit_execute_cmd (WEdit * edit, unsigned long command, int char_for_insertion)
|
||||
edit->highlight = 1;
|
||||
break;
|
||||
|
||||
/* any other command */
|
||||
/* any other command */
|
||||
default:
|
||||
if (edit->highlight)
|
||||
edit_mark_cmd (edit, 0); /* clear */
|
||||
@ -3914,8 +3924,7 @@ edit_execute_cmd (WEdit * edit, unsigned long command, int char_for_insertion)
|
||||
if (p->next)
|
||||
{
|
||||
p = p->next;
|
||||
if (p->line >= edit->start_line + edit->widget.lines
|
||||
|| p->line < edit->start_line)
|
||||
if (p->line >= edit->start_line + edit->widget.lines || p->line < edit->start_line)
|
||||
edit_move_display (edit, p->line - edit->widget.lines / 2);
|
||||
edit_move_to_line (edit, p->line);
|
||||
}
|
||||
@ -3931,8 +3940,7 @@ edit_execute_cmd (WEdit * edit, unsigned long command, int char_for_insertion)
|
||||
p = p->prev;
|
||||
if (p->line >= 0)
|
||||
{
|
||||
if (p->line >= edit->start_line + edit->widget.lines
|
||||
|| p->line < edit->start_line)
|
||||
if (p->line >= edit->start_line + edit->widget.lines || p->line < edit->start_line)
|
||||
edit_move_display (edit, p->line - edit->widget.lines / 2);
|
||||
edit_move_to_line (edit, p->line);
|
||||
}
|
||||
@ -4267,7 +4275,7 @@ edit_unlock_file (WEdit * edit)
|
||||
char *fullpath;
|
||||
unsigned int ret;
|
||||
|
||||
fullpath = g_build_filename (edit->dir, edit->filename, (char *) NULL);
|
||||
fullpath = mc_build_filename (edit->dir, edit->filename, (char *) NULL);
|
||||
ret = unlock_file (fullpath);
|
||||
g_free (fullpath);
|
||||
|
||||
@ -4282,7 +4290,7 @@ edit_lock_file (WEdit * edit)
|
||||
char *fullpath;
|
||||
unsigned int ret;
|
||||
|
||||
fullpath = g_build_filename (edit->dir, edit->filename, (char *) NULL);
|
||||
fullpath = mc_build_filename (edit->dir, edit->filename, (char *) NULL);
|
||||
ret = lock_file (fullpath);
|
||||
g_free (fullpath);
|
||||
|
||||
|
@ -143,8 +143,8 @@ edit_save_file (WEdit * edit, const char *filename)
|
||||
this_save_mode = option_save_mode;
|
||||
if (this_save_mode != EDIT_QUICK_SAVE)
|
||||
{
|
||||
if (!vfs_file_is_local (real_filename) ||
|
||||
(fd = mc_open (real_filename, O_RDONLY | O_BINARY)) == -1)
|
||||
vfs_path_t *vpath = vfs_path_from_str (real_filename);
|
||||
if (!vfs_file_is_local (vpath) || (fd = mc_open (real_filename, O_RDONLY | O_BINARY)) == -1)
|
||||
{
|
||||
/*
|
||||
* The file does not exists yet, so no safe save or
|
||||
@ -152,6 +152,7 @@ edit_save_file (WEdit * edit, const char *filename)
|
||||
*/
|
||||
this_save_mode = EDIT_QUICK_SAVE;
|
||||
}
|
||||
vfs_path_free (vpath);
|
||||
if (fd != -1)
|
||||
mc_close (fd);
|
||||
}
|
||||
@ -491,7 +492,7 @@ edit_load_file_from_filename (WEdit * edit, char *exp)
|
||||
{
|
||||
char *fullpath;
|
||||
|
||||
fullpath = g_build_filename (edit->dir, prev_filename, (char *) NULL);
|
||||
fullpath = mc_build_filename (edit->dir, prev_filename, (char *) NULL);
|
||||
unlock_file (fullpath);
|
||||
g_free (fullpath);
|
||||
}
|
||||
@ -1259,7 +1260,7 @@ edit_set_filename (WEdit * edit, const char *name)
|
||||
|
||||
edit->filename = tilde_expand (name);
|
||||
if (edit->dir == NULL && !g_path_is_absolute (name))
|
||||
edit->dir = g_strdup (vfs_get_current_dir ());
|
||||
edit->dir = vfs_get_current_dir ();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -1382,7 +1383,7 @@ edit_save_as_cmd (WEdit * edit)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
edit_macro_comparator (gconstpointer *macro1, gconstpointer *macro2)
|
||||
edit_macro_comparator (gconstpointer * macro1, gconstpointer * macro2)
|
||||
{
|
||||
const macros_t *m1 = (const macros_t *) macro1;
|
||||
const macros_t *m2 = (const macros_t *) macro2;
|
||||
@ -1402,7 +1403,7 @@ edit_macro_sort_by_hotkey (void)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static gboolean
|
||||
edit_get_macro (WEdit * edit, int hotkey, const macros_t **macros, guint *indx)
|
||||
edit_get_macro (WEdit * edit, int hotkey, const macros_t ** macros, guint * indx)
|
||||
{
|
||||
const macros_t *array_start = &g_array_index (macros_list, struct macros_t, 0);
|
||||
macros_t *result;
|
||||
@ -1522,7 +1523,7 @@ edit_store_macro_cmd (WEdit * edit)
|
||||
mc_config_t *macros_config = NULL;
|
||||
const char *section_name = "editor";
|
||||
gchar *macros_fname;
|
||||
GArray *macros; /* current macro */
|
||||
GArray *macros; /* current macro */
|
||||
int tmp_act;
|
||||
gboolean have_macro = FALSE;
|
||||
char *keyname = NULL;
|
||||
@ -1535,8 +1536,7 @@ edit_store_macro_cmd (WEdit * edit)
|
||||
|
||||
/* return FALSE if try assign macro into restricted hotkeys */
|
||||
if (tmp_act == CK_MacroStartRecord
|
||||
|| tmp_act == CK_MacroStopRecord
|
||||
|| tmp_act == CK_MacroStartStopRecord)
|
||||
|| tmp_act == CK_MacroStopRecord || tmp_act == CK_MacroStartStopRecord)
|
||||
return FALSE;
|
||||
|
||||
edit_delete_macro (edit, hotkey);
|
||||
@ -1569,7 +1569,8 @@ edit_store_macro_cmd (WEdit * edit)
|
||||
m_act.ch = record_macro_buf[i].ch;
|
||||
g_array_append_val (macros, m_act);
|
||||
have_macro = TRUE;
|
||||
g_string_append_printf (marcros_string, "%s:%i;", action_name, (int) record_macro_buf[i].ch);
|
||||
g_string_append_printf (marcros_string, "%s:%i;", action_name,
|
||||
(int) record_macro_buf[i].ch);
|
||||
}
|
||||
if (have_macro)
|
||||
{
|
||||
@ -3192,7 +3193,7 @@ edit_get_match_keyword_cmd (WEdit * edit)
|
||||
g_free (path);
|
||||
path = ptr;
|
||||
g_free (tagfile);
|
||||
tagfile = g_build_filename (path, TAGS_NAME, (char *) NULL);
|
||||
tagfile = mc_build_filename (path, TAGS_NAME, (char *) NULL);
|
||||
if (exist_file (tagfile))
|
||||
break;
|
||||
}
|
||||
|
@ -225,7 +225,7 @@ etags_set_definition_hash (const char *tagfile, const char *start_path,
|
||||
if (num < MAX_DEFINITIONS - 1)
|
||||
{
|
||||
def_hash[num].filename_len = strlen (filename);
|
||||
def_hash[num].fullpath = g_build_filename (start_path, filename, (char *) NULL);
|
||||
def_hash[num].fullpath = mc_build_filename (start_path, filename, (char *) NULL);
|
||||
|
||||
canonicalize_pathname (def_hash[num].fullpath);
|
||||
def_hash[num].filename = g_strdup (filename);
|
||||
|
@ -130,7 +130,7 @@ do_execute (const char *lc_shell, const char *command, int flags)
|
||||
char *old_vfs_dir = 0;
|
||||
|
||||
if (!vfs_current_is_local ())
|
||||
old_vfs_dir = g_strdup (vfs_get_current_dir ());
|
||||
old_vfs_dir = vfs_get_current_dir ();
|
||||
|
||||
if (mc_global.mc_run_mode == MC_RUN_FULL)
|
||||
save_cwds_stat ();
|
||||
@ -432,15 +432,18 @@ execute_with_vfs_arg (const char *command, const char *filename)
|
||||
char *fn;
|
||||
struct stat st;
|
||||
time_t mtime;
|
||||
vfs_path_t *vpath = vfs_path_from_str (filename);
|
||||
|
||||
/* Simplest case, this file is local */
|
||||
if (!filename || vfs_file_is_local (filename))
|
||||
if (!filename || vfs_file_is_local (vpath))
|
||||
{
|
||||
fn = vfs_canon_and_translate (filename);
|
||||
fn = vfs_path_to_str (vpath);
|
||||
do_execute (command, fn, EXECUTE_INTERNAL);
|
||||
g_free (fn);
|
||||
vfs_path_free (vpath);
|
||||
return;
|
||||
}
|
||||
vfs_path_free (vpath);
|
||||
|
||||
/* FIXME: Creation of new files on VFS is not supported */
|
||||
if (!*filename)
|
||||
|
@ -485,6 +485,23 @@ do_link (link_type_t link_type, const char *fname)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
#if defined(ENABLE_VFS_UNDELFS) || defined(ENABLE_VFS_NET)
|
||||
|
||||
static const char *
|
||||
transform_prefix (const char *prefix)
|
||||
{
|
||||
static char buffer[BUF_TINY];
|
||||
size_t prefix_len = strlen (prefix);
|
||||
|
||||
if (prefix_len < 3)
|
||||
return prefix;
|
||||
|
||||
strcpy (buffer, prefix + 2);
|
||||
strcpy (buffer + prefix_len - 3, VFS_PATH_URL_DELIMITER);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
nice_cd (const char *text, const char *xtext, const char *help,
|
||||
const char *history_name, const char *prefix, int to_home)
|
||||
@ -502,11 +519,22 @@ nice_cd (const char *text, const char *xtext, const char *help,
|
||||
to_home = 0; /* FIXME: how to solve going to home nicely? /~/ is
|
||||
ugly as hell and leads to problems in vfs layer */
|
||||
|
||||
/* default prefix in old-style format. */
|
||||
if (strncmp (prefix, machine, strlen (prefix)) != 0)
|
||||
prefix = transform_prefix (prefix); /* Convert prefix to URL-style format */
|
||||
|
||||
if (strncmp (prefix, machine, strlen (prefix)) == 0)
|
||||
cd_path = g_strconcat (machine, to_home ? "/~/" : (char *) NULL, (char *) NULL);
|
||||
else
|
||||
cd_path = g_strconcat (prefix, machine, to_home ? "/~/" : (char *) NULL, (char *) NULL);
|
||||
|
||||
if (*cd_path != PATH_SEP)
|
||||
{
|
||||
char *tmp = cd_path;
|
||||
cd_path = g_strconcat (PATH_SEP_STR, tmp, (char *) NULL);
|
||||
g_free (tmp);
|
||||
}
|
||||
|
||||
if (!do_panel_cd (MENU_PANEL, cd_path, cd_parse_command))
|
||||
message (D_ERROR, MSG_ERROR, _("Cannot chdir to \"%s\""), cd_path);
|
||||
g_free (cd_path);
|
||||
|
@ -106,12 +106,15 @@ exec_extension (const char *filename, const char *lc_data, int *move_dir, int st
|
||||
time_t localmtime = 0;
|
||||
struct stat mystat;
|
||||
quote_func_t quote_func = name_quote;
|
||||
vfs_path_t *vpath;
|
||||
|
||||
g_return_if_fail (filename != NULL);
|
||||
g_return_if_fail (lc_data != NULL);
|
||||
|
||||
vpath = vfs_path_from_str (filename);
|
||||
|
||||
/* Avoid making a local copy if we are doing a cd */
|
||||
if (!vfs_file_is_local (filename))
|
||||
if (!vfs_file_is_local (vpath))
|
||||
do_local_copy = 1;
|
||||
else
|
||||
do_local_copy = 0;
|
||||
@ -156,6 +159,7 @@ exec_extension (const char *filename, const char *lc_data, int *move_dir, int st
|
||||
g_free (localcopy);
|
||||
}
|
||||
g_free (file_name);
|
||||
vfs_path_free (vpath);
|
||||
return;
|
||||
}
|
||||
fputs (parameter, cmd_file);
|
||||
@ -225,6 +229,7 @@ exec_extension (const char *filename, const char *lc_data, int *move_dir, int st
|
||||
fclose (cmd_file);
|
||||
unlink (file_name);
|
||||
g_free (file_name);
|
||||
vfs_path_free (vpath);
|
||||
return;
|
||||
}
|
||||
mc_stat (localcopy, &mystat);
|
||||
@ -233,7 +238,7 @@ exec_extension (const char *filename, const char *lc_data, int *move_dir, int st
|
||||
}
|
||||
else
|
||||
{
|
||||
fn = vfs_canon_and_translate (filename);
|
||||
fn = vfs_path_to_str (vpath);
|
||||
text = quote_func (fn, 0);
|
||||
g_free (fn);
|
||||
}
|
||||
@ -371,6 +376,7 @@ exec_extension (const char *filename, const char *lc_data, int *move_dir, int st
|
||||
mc_ungetlocalcopy (filename, localcopy, localmtime != mystat.st_mtime);
|
||||
g_free (localcopy);
|
||||
}
|
||||
vfs_path_free (vpath);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -683,7 +689,8 @@ regex_command (const char *filename, const char *action, int *move_dir)
|
||||
_("The format of the %s%s%s file has "
|
||||
"changed with version 3.0. You may either want to copy "
|
||||
"it from %smc.ext or use that file as an example of how to write it."),
|
||||
mc_config_get_data_path (), PATH_SEP_STR, MC_FILEBIND_FILE, mc_global.sysconfig_dir);
|
||||
mc_config_get_data_path (), PATH_SEP_STR, MC_FILEBIND_FILE,
|
||||
mc_global.sysconfig_dir);
|
||||
g_free (title);
|
||||
}
|
||||
}
|
||||
|
@ -234,58 +234,91 @@ free_linklist (struct link **lc_linklist)
|
||||
static int
|
||||
is_in_linklist (struct link *lp, const char *path, struct stat *sb)
|
||||
{
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *vpath_element;
|
||||
ino_t ino = sb->st_ino;
|
||||
dev_t dev = sb->st_dev;
|
||||
struct vfs_class *vfs = vfs_get_class (path);
|
||||
|
||||
vpath = vfs_path_from_str (path);
|
||||
vpath_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
while (lp != NULL)
|
||||
{
|
||||
if (lp->vfs == vfs)
|
||||
if (lp->vfs == vpath_element->class)
|
||||
if (lp->ino == ino && lp->dev == dev)
|
||||
return 1;
|
||||
lp = lp->next;
|
||||
}
|
||||
vfs_path_free (vpath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Returns 0 if the inode wasn't found in the cache and 1 if it was found
|
||||
* Check and made hardlink
|
||||
*
|
||||
* @return FALSE if the inode wasn't found in the cache and TRUE if it was found
|
||||
* and a hardlink was succesfully made
|
||||
*/
|
||||
|
||||
static int
|
||||
static gboolean
|
||||
check_hardlinks (const char *src_name, const char *dst_name, struct stat *pstat)
|
||||
{
|
||||
struct link *lp;
|
||||
struct vfs_class *my_vfs = vfs_get_class (src_name);
|
||||
vfs_path_t *vpath;
|
||||
|
||||
struct vfs_class *my_vfs;
|
||||
ino_t ino = pstat->st_ino;
|
||||
dev_t dev = pstat->st_dev;
|
||||
struct stat link_stat;
|
||||
const char *p;
|
||||
|
||||
if ((vfs_file_class_flags (src_name) & VFSF_NOLINKS) != 0)
|
||||
return 0;
|
||||
vpath = vfs_path_from_str (src_name);
|
||||
|
||||
if ((vfs_file_class_flags (vpath) & VFSF_NOLINKS) != 0)
|
||||
{
|
||||
vfs_path_free (vpath);
|
||||
return FALSE;
|
||||
}
|
||||
my_vfs = vfs_path_get_by_index (vpath, -1)->class;
|
||||
vfs_path_free (vpath);
|
||||
|
||||
for (lp = linklist; lp != NULL; lp = lp->next)
|
||||
if (lp->vfs == my_vfs && lp->ino == ino && lp->dev == dev)
|
||||
{
|
||||
struct vfs_class *lp_name_class;
|
||||
|
||||
vpath = vfs_path_from_str (lp->name);
|
||||
lp_name_class = vfs_path_get_by_index (vpath, -1)->class;
|
||||
vfs_path_free (vpath);
|
||||
|
||||
if (!mc_stat (lp->name, &link_stat) && link_stat.st_ino == ino
|
||||
&& link_stat.st_dev == dev && vfs_get_class (lp->name) == my_vfs)
|
||||
&& link_stat.st_dev == dev && lp_name_class == my_vfs)
|
||||
{
|
||||
struct vfs_class *p_class, *dst_name_class;
|
||||
|
||||
p = strchr (lp->name, 0) + 1; /* i.e. where the `name' file
|
||||
was copied to */
|
||||
if (vfs_get_class (dst_name) == vfs_get_class (p))
|
||||
|
||||
vpath = vfs_path_from_str (p);
|
||||
p_class = vfs_path_get_by_index (vpath, -1)->class;
|
||||
vfs_path_free (vpath);
|
||||
|
||||
vpath = vfs_path_from_str (dst_name);
|
||||
dst_name_class = vfs_path_get_by_index (vpath, -1)->class;
|
||||
vfs_path_free (vpath);
|
||||
|
||||
if (dst_name_class == p_class)
|
||||
{
|
||||
if (!mc_stat (p, &link_stat))
|
||||
{
|
||||
if (!mc_link (p, dst_name))
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
message (D_ERROR, MSG_ERROR, _("Cannot make the hardlink"));
|
||||
return 0;
|
||||
return FALSE;
|
||||
}
|
||||
lp = (struct link *) g_try_malloc (sizeof (struct link) + strlen (src_name)
|
||||
+ strlen (dst_name) + 1);
|
||||
@ -301,7 +334,7 @@ check_hardlinks (const char *src_name, const char *dst_name, struct stat *pstat)
|
||||
lp->next = linklist;
|
||||
linklist = lp;
|
||||
}
|
||||
return 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -336,13 +369,20 @@ make_symlink (FileOpContext * ctx, const char *src_path, const char *dst_path)
|
||||
link_target[len] = 0;
|
||||
|
||||
if (ctx->stable_symlinks)
|
||||
if (!vfs_file_is_local (src_path) || !vfs_file_is_local (dst_path))
|
||||
{
|
||||
vfs_path_t *vpath1 = vfs_path_from_str (src_path);
|
||||
vfs_path_t *vpath2 = vfs_path_from_str (dst_path);
|
||||
|
||||
if (!vfs_file_is_local (vpath1) || !vfs_file_is_local (vpath2))
|
||||
{
|
||||
message (D_ERROR, MSG_ERROR,
|
||||
_("Cannot make stable symlinks across"
|
||||
"non-local filesystems:\n\nOption Stable Symlinks will be disabled"));
|
||||
ctx->stable_symlinks = FALSE;
|
||||
}
|
||||
vfs_path_free (vpath1);
|
||||
vfs_path_free (vpath2);
|
||||
}
|
||||
|
||||
if (ctx->stable_symlinks && !g_path_is_absolute (link_target))
|
||||
{
|
||||
@ -650,6 +690,7 @@ files_error (const char *format, const char *file1, const char *file2)
|
||||
|
||||
return do_file_error (buf);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -1318,7 +1359,7 @@ copy_file_file (FileOpTotalContext * tctx, FileOpContext * ctx,
|
||||
if (!ctx->do_append)
|
||||
{
|
||||
/* Check the hardlinks */
|
||||
if (!ctx->follow_links && sb.st_nlink > 1 && check_hardlinks (src_path, dst_path, &sb) == 1)
|
||||
if (!ctx->follow_links && sb.st_nlink > 1 && check_hardlinks (src_path, dst_path, &sb))
|
||||
{
|
||||
/* We have made a hardlink - no more processing is necessary */
|
||||
return FILE_CONT;
|
||||
@ -1712,7 +1753,7 @@ copy_dir_dir (FileOpTotalContext * tctx, FileOpContext * ctx, const char *s, con
|
||||
/* FIXME: In this step we should do something
|
||||
in case the destination already exist */
|
||||
/* Check the hardlinks */
|
||||
if (ctx->preserve && cbuf.st_nlink > 1 && check_hardlinks (s, d, &cbuf) == 1)
|
||||
if (ctx->preserve && cbuf.st_nlink > 1 && check_hardlinks (s, d, &cbuf))
|
||||
{
|
||||
/* We have made a hardlink - no more processing is necessary */
|
||||
goto ret_fast;
|
||||
@ -1735,7 +1776,11 @@ copy_dir_dir (FileOpTotalContext * tctx, FileOpContext * ctx, const char *s, con
|
||||
}
|
||||
|
||||
lp = g_new (struct link, 1);
|
||||
lp->vfs = vfs_get_class (s);
|
||||
{
|
||||
vfs_path_t *vpath = vfs_path_from_str (s);
|
||||
lp->vfs = vfs_path_get_by_index (vpath, -1)->class;
|
||||
vfs_path_free (vpath);
|
||||
}
|
||||
lp->ino = cbuf.st_ino;
|
||||
lp->dev = cbuf.st_dev;
|
||||
lp->next = parent_dirs;
|
||||
@ -1795,7 +1840,11 @@ copy_dir_dir (FileOpTotalContext * tctx, FileOpContext * ctx, const char *s, con
|
||||
|
||||
lp = g_new (struct link, 1);
|
||||
mc_stat (dest_dir, &buf);
|
||||
lp->vfs = vfs_get_class (dest_dir);
|
||||
{
|
||||
vfs_path_t *vpath = vfs_path_from_str (dest_dir);
|
||||
lp->vfs = vfs_path_get_by_index (vpath, -1)->class;
|
||||
vfs_path_free (vpath);
|
||||
}
|
||||
lp->ino = buf.st_ino;
|
||||
lp->dev = buf.st_dev;
|
||||
lp->next = dest_dirs;
|
||||
@ -2498,7 +2547,7 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl
|
||||
if (g_path_is_absolute (source))
|
||||
source_with_path = g_strdup (source);
|
||||
else
|
||||
source_with_path = g_build_filename (panel->cwd, source, (char *) NULL);
|
||||
source_with_path = mc_build_filename (panel->cwd, source, (char *) NULL);
|
||||
#endif /* WITH_FULL_PATHS */
|
||||
|
||||
if (panel_operate_init_totals (operation, panel, source_with_path, ctx) == FILE_CONT)
|
||||
@ -2592,7 +2641,7 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl
|
||||
if (g_path_is_absolute (source))
|
||||
source_with_path = g_strdup (source);
|
||||
else
|
||||
source_with_path = g_build_filename (panel->cwd, source, (char *) NULL);
|
||||
source_with_path = mc_build_filename (panel->cwd, source, (char *) NULL);
|
||||
#endif /* WITH_FULL_PATHS */
|
||||
|
||||
if (operation == OP_DELETE)
|
||||
|
@ -75,8 +75,15 @@ my_mkdir_rec (char *s, mode_t mode)
|
||||
return -1;
|
||||
|
||||
/* FIXME: should check instead if s is at the root of that filesystem */
|
||||
if (!vfs_file_is_local (s))
|
||||
return -1;
|
||||
{
|
||||
vfs_path_t *vpath = vfs_path_from_str (s);
|
||||
if (!vfs_file_is_local (vpath))
|
||||
{
|
||||
vfs_path_free (vpath);
|
||||
return -1;
|
||||
}
|
||||
vfs_path_free (vpath);
|
||||
}
|
||||
|
||||
if (!strcmp (s, PATH_SEP_STR))
|
||||
{
|
||||
@ -85,7 +92,11 @@ my_mkdir_rec (char *s, mode_t mode)
|
||||
}
|
||||
|
||||
p = concat_dir_and_file (s, "..");
|
||||
q = vfs_canon (p);
|
||||
{
|
||||
vfs_path_t *vpath = vfs_path_from_str (p);
|
||||
q = vfs_path_to_str (vpath);
|
||||
vfs_path_free (vpath);
|
||||
}
|
||||
g_free (p);
|
||||
|
||||
result = my_mkdir_rec (q, mode);
|
||||
@ -109,9 +120,13 @@ my_mkdir (const char *s, mode_t mode)
|
||||
result = mc_mkdir (s, mode);
|
||||
if (result)
|
||||
{
|
||||
char *p = vfs_canon (s);
|
||||
vfs_path_t *vpath;
|
||||
char *p;
|
||||
vpath = vfs_path_from_str (s);
|
||||
p = vfs_path_to_str (vpath);
|
||||
|
||||
result = my_mkdir_rec (p, mode);
|
||||
vfs_path_free (vpath);
|
||||
g_free (p);
|
||||
}
|
||||
if (result == 0)
|
||||
|
@ -714,7 +714,7 @@ find_parameters (char **start_dir, char **ignore_dirs, char **pattern, char **co
|
||||
else if (g_path_is_absolute (*start_dir))
|
||||
*start_dir = g_strdup (*start_dir);
|
||||
else
|
||||
*start_dir = g_build_filename (current_panel->cwd, *start_dir, (char *) NULL);
|
||||
*start_dir = mc_build_filename (current_panel->cwd, *start_dir, (char *) NULL);
|
||||
|
||||
canonicalize_pathname (*start_dir);
|
||||
|
||||
@ -1246,7 +1246,7 @@ do_search (Dlg_head * h)
|
||||
{
|
||||
char *tmp_name;
|
||||
|
||||
tmp_name = g_build_filename (directory, dp->d_name, (char *) NULL);
|
||||
tmp_name = mc_build_filename (directory, dp->d_name, (char *) NULL);
|
||||
|
||||
if (mc_lstat (tmp_name, &tmp_stat) == 0 && S_ISDIR (tmp_stat.st_mode))
|
||||
{
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include "lib/tty/key.h"
|
||||
#include "lib/tty/mouse.h"
|
||||
#include "lib/mcconfig.h"
|
||||
#include "lib/vfs/vfs.h" /* For vfs_translate_url() */
|
||||
#include "lib/vfs/vfs.h" /* For mc_get_current_wd() */
|
||||
#include "lib/strutil.h"
|
||||
#include "lib/widget.h"
|
||||
#include "lib/event.h"
|
||||
@ -1185,7 +1185,7 @@ save_panel_dir (int idx)
|
||||
|
||||
g_free (panels[idx].last_saved_dir); /* last path no needed */
|
||||
/* Because path can be nonlocal */
|
||||
panels[idx].last_saved_dir = vfs_translate_url (widget_work_dir);
|
||||
panels[idx].last_saved_dir = g_strdup (widget_work_dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@
|
||||
#include "lib/skin.h"
|
||||
#include "lib/util.h"
|
||||
|
||||
#include "lib/vfs/vfs.h" /* vfs_translate_url() */
|
||||
#include "lib/vfs/vfs.h"
|
||||
|
||||
#include "src/args.h"
|
||||
#include "src/subshell.h"
|
||||
@ -465,23 +465,6 @@ toggle_panels_split (void)
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Just a hack for allowing url-like pathnames to be accepted from the
|
||||
* command line.
|
||||
*/
|
||||
static void
|
||||
translated_mc_chdir (char *dir)
|
||||
{
|
||||
char *newdir;
|
||||
int ret;
|
||||
|
||||
newdir = vfs_translate_url (dir);
|
||||
ret = mc_chdir (newdir);
|
||||
g_free (newdir);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
#if ENABLE_VFS
|
||||
|
||||
/* event helper */
|
||||
@ -491,15 +474,24 @@ check_panel_timestamp (const WPanel * panel, panel_view_mode_t mode, struct vfs_
|
||||
{
|
||||
if (mode == view_listing)
|
||||
{
|
||||
struct vfs_class *nvfs;
|
||||
vfsid nvfsid;
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
nvfs = vfs_get_class (panel->cwd);
|
||||
if (nvfs != vclass)
|
||||
vpath = vfs_path_from_str (panel->cwd);
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
if (path_element->class != vclass)
|
||||
{
|
||||
vfs_path_free (vpath);
|
||||
return FALSE;
|
||||
nvfsid = vfs_getid (nvfs, panel->cwd);
|
||||
if (nvfsid != id)
|
||||
}
|
||||
|
||||
if (vfs_getid (vpath) != id)
|
||||
{
|
||||
vfs_path_free (vpath);
|
||||
return FALSE;
|
||||
}
|
||||
vfs_path_free (vpath);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@ -622,7 +614,7 @@ create_panels (void)
|
||||
*/
|
||||
mc_get_current_wd (original_dir, sizeof (original_dir) - 2);
|
||||
}
|
||||
translated_mc_chdir (mc_run_param0);
|
||||
mc_chdir (mc_run_param0);
|
||||
}
|
||||
set_display_type (current_index, current_mode);
|
||||
|
||||
@ -630,8 +622,8 @@ create_panels (void)
|
||||
if (mc_run_param1 != NULL)
|
||||
{
|
||||
if (original_dir[0] != '\0')
|
||||
translated_mc_chdir (original_dir);
|
||||
translated_mc_chdir (mc_run_param1);
|
||||
mc_chdir (original_dir);
|
||||
mc_chdir (mc_run_param1);
|
||||
}
|
||||
set_display_type (other_index, other_mode);
|
||||
|
||||
@ -952,7 +944,11 @@ done_mc (void)
|
||||
save_setup (auto_save_setup, panels_options.auto_save_setup);
|
||||
done_screen ();
|
||||
|
||||
vfs_stamp_path (vfs_get_current_dir ());
|
||||
{
|
||||
char *curr_dir = vfs_get_current_dir ();
|
||||
vfs_stamp_path (curr_dir);
|
||||
g_free (curr_dir);
|
||||
}
|
||||
|
||||
if ((current_panel != NULL) && (get_current_type () == view_listing))
|
||||
vfs_stamp_path (current_panel->cwd);
|
||||
@ -996,9 +992,15 @@ prepend_cwd_on_local (const char *filename)
|
||||
{
|
||||
char *d;
|
||||
size_t l;
|
||||
vfs_path_t *vpath;
|
||||
|
||||
if (!vfs_file_is_local (filename) || g_path_is_absolute (filename))
|
||||
vpath = vfs_path_from_str (filename);
|
||||
if (!vfs_file_is_local (vpath) || g_path_is_absolute (filename))
|
||||
{
|
||||
vfs_path_free (vpath);
|
||||
return g_strdup (filename);
|
||||
}
|
||||
vfs_path_free (vpath);
|
||||
|
||||
d = g_malloc (MC_MAXPATHLEN + strlen (filename) + 2);
|
||||
mc_get_current_wd (d, MC_MAXPATHLEN);
|
||||
|
@ -1015,10 +1015,15 @@ show_free_space (WPanel * panel)
|
||||
static struct my_statfs myfs_stats;
|
||||
/* Old current working directory for displaying free space */
|
||||
static char *old_cwd = NULL;
|
||||
vfs_path_t *vpath = vfs_path_from_str (panel->cwd);
|
||||
|
||||
/* Don't try to stat non-local fs */
|
||||
if (!vfs_file_is_local (panel->cwd) || !free_space)
|
||||
if (!vfs_file_is_local (vpath) || !free_space)
|
||||
{
|
||||
vfs_path_free (vpath);
|
||||
return;
|
||||
}
|
||||
vfs_path_free (vpath);
|
||||
|
||||
if (old_cwd == NULL || strcmp (old_cwd, panel->cwd) != 0)
|
||||
{
|
||||
@ -1142,39 +1147,6 @@ adjust_top_file (WPanel * panel)
|
||||
* retun new string
|
||||
*/
|
||||
|
||||
static char *
|
||||
add_encoding_to_path (const char *path, const char *encoding)
|
||||
{
|
||||
char *result;
|
||||
char *semi;
|
||||
char *slash;
|
||||
|
||||
semi = g_strrstr (path, VFS_ENCODING_PREFIX);
|
||||
|
||||
if (semi != NULL)
|
||||
{
|
||||
slash = strchr (semi, PATH_SEP);
|
||||
if (slash != NULL)
|
||||
{
|
||||
result = g_strconcat (path, PATH_SEP_STR VFS_ENCODING_PREFIX, encoding, (char *) NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
*semi = '\0';
|
||||
result = g_strconcat (path, PATH_SEP_STR VFS_ENCODING_PREFIX, encoding, (char *) NULL);
|
||||
*semi = '#';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = g_strconcat (path, PATH_SEP_STR VFS_ENCODING_PREFIX, encoding, (char *) NULL);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static char *
|
||||
panel_save_name (WPanel * panel)
|
||||
{
|
||||
@ -2288,10 +2260,12 @@ do_enter_on_file_entry (file_entry * fe)
|
||||
|
||||
if (!vfs_current_is_local ())
|
||||
{
|
||||
char *tmp;
|
||||
char *tmp, *tmp_curr_dir;
|
||||
int ret;
|
||||
|
||||
tmp = concat_dir_and_file (vfs_get_current_dir (), fe->fname);
|
||||
tmp_curr_dir = vfs_get_current_dir ();
|
||||
tmp = concat_dir_and_file (tmp_curr_dir, fe->fname);
|
||||
g_free (tmp_curr_dir);
|
||||
ret = mc_setctl (tmp, VFS_SETCTL_RUN, NULL);
|
||||
g_free (tmp);
|
||||
/* We took action only if the dialog was shown or the execution
|
||||
@ -2608,14 +2582,18 @@ static const char *
|
||||
get_parent_dir_name (const char *cwd, const char *lwd)
|
||||
{
|
||||
size_t llen, clen;
|
||||
const char *p;
|
||||
|
||||
llen = strlen (lwd);
|
||||
clen = strlen (cwd);
|
||||
|
||||
if (llen > clen)
|
||||
{
|
||||
const char *p;
|
||||
if (llen <= clen)
|
||||
return NULL;
|
||||
|
||||
p = g_strrstr (lwd, VFS_PATH_URL_DELIMITER);
|
||||
|
||||
if (p == NULL)
|
||||
{
|
||||
p = strrchr (lwd, PATH_SEP);
|
||||
|
||||
if ((p != NULL)
|
||||
@ -2623,9 +2601,14 @@ get_parent_dir_name (const char *cwd, const char *lwd)
|
||||
&& (clen == (size_t) (p - lwd)
|
||||
|| ((p == lwd) && (cwd[0] == PATH_SEP) && (cwd[1] == '\0'))))
|
||||
return (p + 1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
while (--p > lwd && *p != PATH_SEP);
|
||||
while (--p > lwd && *p != PATH_SEP);
|
||||
|
||||
return (p != lwd) ? p + 1 : NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -2652,7 +2635,6 @@ _do_panel_cd (WPanel * panel, const char *new_dir, enum cd_enum cd_type)
|
||||
const char *directory;
|
||||
char *olddir;
|
||||
char temp[MC_MAXPATHLEN];
|
||||
char *translated_url;
|
||||
|
||||
if (cd_type == cd_parse_command)
|
||||
{
|
||||
@ -2661,7 +2643,6 @@ _do_panel_cd (WPanel * panel, const char *new_dir, enum cd_enum cd_type)
|
||||
}
|
||||
|
||||
olddir = g_strdup (panel->cwd);
|
||||
new_dir = translated_url = vfs_translate_url (new_dir);
|
||||
|
||||
/* Convert *new_path to a suitable pathname, handle ~user */
|
||||
|
||||
@ -2679,10 +2660,8 @@ _do_panel_cd (WPanel * panel, const char *new_dir, enum cd_enum cd_type)
|
||||
{
|
||||
strcpy (panel->cwd, olddir);
|
||||
g_free (olddir);
|
||||
g_free (translated_url);
|
||||
return FALSE;
|
||||
}
|
||||
g_free (translated_url);
|
||||
|
||||
/* Success: save previous directory, shutdown status of previous dir */
|
||||
strcpy (panel->lwd, olddir);
|
||||
@ -3386,12 +3365,17 @@ remove_encoding_from_path (const char *path)
|
||||
|
||||
while ((tmp = g_strrstr (tmp_path->str, PATH_SEP_STR VFS_ENCODING_PREFIX)) != NULL)
|
||||
{
|
||||
const char *enc;
|
||||
GIConv converter;
|
||||
char *tmp2;
|
||||
|
||||
enc = vfs_get_encoding ((const char *) tmp);
|
||||
converter = enc != NULL ? str_crt_conv_to (enc) : str_cnv_to_term;
|
||||
vfs_path_t *vpath = vfs_path_from_str (tmp);
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
converter =
|
||||
path_element->encoding !=
|
||||
NULL ? str_crt_conv_to (path_element->encoding) : str_cnv_to_term;
|
||||
vfs_path_free (vpath);
|
||||
|
||||
if (converter == INVALID_CONV)
|
||||
converter = str_cnv_to_term;
|
||||
|
||||
@ -3655,9 +3639,13 @@ panel_new_with_dir (const char *panel_name, const char *wpath)
|
||||
|
||||
#ifdef HAVE_CHARSET
|
||||
{
|
||||
const char *enc = vfs_get_encoding (panel->cwd);
|
||||
if (enc != NULL)
|
||||
panel->codepage = get_codepage_index (enc);
|
||||
vfs_path_t *vpath = vfs_path_from_str (panel->cwd);
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
if (path_element->encoding != NULL)
|
||||
panel->codepage = get_codepage_index (path_element->encoding);
|
||||
|
||||
vfs_path_free (vpath);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -4034,18 +4022,16 @@ panel_change_encoding (WPanel * panel)
|
||||
#endif
|
||||
if (encoding != NULL)
|
||||
{
|
||||
const char *enc;
|
||||
vfs_path_t *vpath = vfs_path_from_str (panel->cwd);
|
||||
|
||||
enc = vfs_get_encoding (panel->cwd);
|
||||
vfs_change_encoding (vpath, encoding);
|
||||
|
||||
/* don't add current encoding */
|
||||
if ((enc == NULL) || (strcmp (encoding, enc) != 0))
|
||||
{
|
||||
cd_path = add_encoding_to_path (panel->cwd, encoding);
|
||||
if (!do_panel_cd (panel, cd_path, cd_parse_command))
|
||||
message (D_ERROR, MSG_ERROR, _("Cannot chdir to \"%s\""), cd_path);
|
||||
g_free (cd_path);
|
||||
}
|
||||
cd_path = vfs_path_to_str (vpath);
|
||||
if (!do_panel_cd (panel, cd_path, cd_parse_command))
|
||||
message (D_ERROR, MSG_ERROR, _("Cannot chdir to \"%s\""), cd_path);
|
||||
g_free (cd_path);
|
||||
|
||||
vfs_path_free (vpath);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,22 +248,26 @@ tree_store_load_from (char *name)
|
||||
different = strtok (NULL, "");
|
||||
if (different)
|
||||
{
|
||||
vfs_path_t *vpath = vfs_path_from_str (oldname);
|
||||
strcpy (oldname + common, different);
|
||||
if (vfs_file_is_local (oldname))
|
||||
if (vfs_file_is_local (vpath))
|
||||
{
|
||||
e = tree_store_add_entry (oldname);
|
||||
e->scanned = scanned;
|
||||
}
|
||||
vfs_path_free (vpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vfs_file_is_local (lc_name))
|
||||
vfs_path_t *vpath = vfs_path_from_str (lc_name);
|
||||
if (vfs_file_is_local (vpath))
|
||||
{
|
||||
e = tree_store_add_entry (lc_name);
|
||||
e->scanned = scanned;
|
||||
}
|
||||
vfs_path_free (vpath);
|
||||
strcpy (oldname, lc_name);
|
||||
}
|
||||
g_free (lc_name);
|
||||
@ -343,8 +347,9 @@ tree_store_save_to (char *name)
|
||||
while (current)
|
||||
{
|
||||
int i, common;
|
||||
vfs_path_t *vpath = vfs_path_from_str (current->name);
|
||||
|
||||
if (vfs_file_is_local (current->name))
|
||||
if (vfs_file_is_local (vpath))
|
||||
{
|
||||
/* Clear-text compression */
|
||||
if (current->prev && (common = str_common (current->prev->name, current->name)) > 2)
|
||||
@ -366,9 +371,11 @@ tree_store_save_to (char *name)
|
||||
{
|
||||
fprintf (stderr, _("Cannot write to the %s file:\n%s\n"),
|
||||
name, unix_error_string (errno));
|
||||
vfs_path_free (vpath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
vfs_path_free (vpath);
|
||||
current = current->next;
|
||||
}
|
||||
tree_store_dirty (FALSE);
|
||||
|
10
src/main.c
10
src/main.c
@ -262,13 +262,15 @@ do_cd (const char *new_dir, enum cd_enum exact)
|
||||
#if HAVE_CHARSET
|
||||
if (res)
|
||||
{
|
||||
const char *enc_name;
|
||||
vfs_path_t *vpath = vfs_path_from_str (current_panel->cwd);
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
enc_name = vfs_get_encoding (current_panel->cwd);
|
||||
if (enc_name != NULL)
|
||||
current_panel->codepage = get_codepage_index (enc_name);
|
||||
if (path_element->encoding != NULL)
|
||||
current_panel->codepage = get_codepage_index (path_element->encoding);
|
||||
else
|
||||
current_panel->codepage = SELECT_CHARSET_NO_TRANSLATE;
|
||||
|
||||
vfs_path_free (vpath);
|
||||
}
|
||||
#endif /* HAVE_CHARSET */
|
||||
|
||||
|
@ -899,11 +899,14 @@ load_setup (void)
|
||||
|
||||
if (mc_run_param1 == NULL)
|
||||
{
|
||||
vfs_path_t *vpath;
|
||||
buffer = mc_config_get_string (mc_panels_config, "Dirs", "other_dir", ".");
|
||||
if (vfs_file_is_local (buffer))
|
||||
vpath = vfs_path_from_str (buffer);
|
||||
if (vfs_file_is_local (vpath))
|
||||
mc_run_param1 = buffer;
|
||||
else
|
||||
g_free (buffer);
|
||||
vfs_path_free (vpath);
|
||||
}
|
||||
|
||||
boot_current_is_left = mc_config_get_bool (mc_panels_config, "Dirs", "current_is_left", TRUE);
|
||||
|
@ -392,7 +392,7 @@ cpio_create_entry (struct vfs_class *me, struct vfs_s_super *super, struct stat
|
||||
|
||||
if ((st->st_nlink > 1) && ((arch->type == CPIO_NEWC) || (arch->type == CPIO_CRC)))
|
||||
{ /* For case of hardlinked files */
|
||||
defer_inode i = {st->st_ino, st->st_dev, NULL};
|
||||
defer_inode i = { st->st_ino, st->st_dev, NULL };
|
||||
GSList *l;
|
||||
|
||||
l = g_slist_find_custom (arch->deferred, &i, cpio_defer_find);
|
||||
@ -714,23 +714,28 @@ cpio_read_crc_head (struct vfs_class *me, struct vfs_s_super *super)
|
||||
/** Need to CPIO_SEEK_CUR to skip the file at the end of add entry!!!! */
|
||||
|
||||
static int
|
||||
cpio_open_archive (struct vfs_class *me, struct vfs_s_super *super, const char *name, char *op)
|
||||
cpio_open_archive (struct vfs_s_super *super, const vfs_path_t * vpath,
|
||||
const vfs_path_element_t * vpath_element)
|
||||
{
|
||||
int status = STATUS_START;
|
||||
char *archive_name = vfs_path_to_str (vpath);
|
||||
|
||||
(void) op;
|
||||
(void) vpath_element;
|
||||
|
||||
if (cpio_open_cpio_file (me, super, name) == -1)
|
||||
if (cpio_open_cpio_file (vpath_element->class, super, archive_name) == -1)
|
||||
{
|
||||
g_free (archive_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
status = cpio_read_head (me, super);
|
||||
status = cpio_read_head (vpath_element->class, super);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case STATUS_EOF:
|
||||
message (D_ERROR, MSG_ERROR, _("Unexpected end of file\n%s"), name);
|
||||
message (D_ERROR, MSG_ERROR, _("Unexpected end of file\n%s"), archive_name);
|
||||
return 0;
|
||||
case STATUS_OK:
|
||||
continue;
|
||||
@ -740,6 +745,7 @@ cpio_open_archive (struct vfs_class *me, struct vfs_s_super *super, const char *
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (archive_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -747,29 +753,34 @@ cpio_open_archive (struct vfs_class *me, struct vfs_s_super *super, const char *
|
||||
/** Remaining functions are exactly same as for tarfs (and were in fact just copied) */
|
||||
|
||||
static void *
|
||||
cpio_super_check (struct vfs_class *me, const char *archive_name, char *op)
|
||||
cpio_super_check (const vfs_path_t * vpath)
|
||||
{
|
||||
static struct stat sb;
|
||||
char *archive_name = vfs_path_to_str (vpath);
|
||||
int stat_result;
|
||||
|
||||
(void) me;
|
||||
(void) op;
|
||||
|
||||
return (mc_stat (archive_name, &sb) == 0 ? &sb : NULL);
|
||||
stat_result = mc_stat (archive_name, &sb);
|
||||
g_free (archive_name);
|
||||
return (stat_result == 0 ? &sb : NULL);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
cpio_super_same (struct vfs_class *me, struct vfs_s_super *parc,
|
||||
const char *archive_name, char *op, void *cookie)
|
||||
cpio_super_same (const vfs_path_element_t * vpath_element, struct vfs_s_super *parc,
|
||||
const vfs_path_t * vpath, void *cookie)
|
||||
{
|
||||
struct stat *archive_stat = cookie; /* stat of main archive */
|
||||
char *archive_name = vfs_path_to_str (vpath);
|
||||
|
||||
(void) me;
|
||||
(void) op;
|
||||
(void) vpath_element;
|
||||
|
||||
if (strcmp (parc->name, archive_name))
|
||||
{
|
||||
g_free (archive_name);
|
||||
return 0;
|
||||
}
|
||||
g_free (archive_name);
|
||||
|
||||
/* Has the cached archive been changed on the disk? */
|
||||
if (((cpio_super_data_t *) parc->data)->st.st_mtime < archive_stat->st_mtime)
|
||||
@ -810,7 +821,7 @@ cpio_read (void *fh, char *buffer, size_t count)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
cpio_fh_open (struct vfs_class *me, vfs_file_handler_t *fh, int flags, mode_t mode)
|
||||
cpio_fh_open (struct vfs_class *me, vfs_file_handler_t * fh, int flags, mode_t mode)
|
||||
{
|
||||
(void) mode;
|
||||
|
||||
|
@ -350,7 +350,9 @@ extfs_fill_names (struct vfs_class *me, fill_names_f func)
|
||||
char *name;
|
||||
|
||||
info = &g_array_index (extfs_plugins, extfs_plugin_info_t, a->fstype);
|
||||
name = g_strconcat (a->name ? a->name : "", "#", info->prefix, (char *) NULL);
|
||||
name =
|
||||
g_strconcat (a->name ? a->name : "", "/", info->prefix, VFS_PATH_URL_DELIMITER,
|
||||
(char *) NULL);
|
||||
func (name);
|
||||
g_free (name);
|
||||
a = a->next;
|
||||
@ -395,15 +397,17 @@ extfs_open_archive (int fstype, const char *name, struct archive **pparc)
|
||||
|
||||
if (info->need_archive)
|
||||
{
|
||||
vfs_path_t *vpath = vfs_path_from_str (name);
|
||||
if (mc_stat (name, &mystat) == -1)
|
||||
return NULL;
|
||||
|
||||
if (!vfs_file_is_local (name))
|
||||
if (!vfs_file_is_local (vpath))
|
||||
{
|
||||
local_name = mc_getlocalcopy (name);
|
||||
if (local_name == NULL)
|
||||
return NULL;
|
||||
}
|
||||
vfs_path_free (vpath);
|
||||
|
||||
tmp = name_quote (name, 0);
|
||||
}
|
||||
@ -644,24 +648,25 @@ extfs_which (struct vfs_class *me, const char *path)
|
||||
*/
|
||||
|
||||
static char *
|
||||
extfs_get_path_mangle (struct vfs_class *me, char *inname, struct archive **archive,
|
||||
gboolean do_not_open)
|
||||
extfs_get_path_mangle (const vfs_path_t * vpath, struct archive **archive, gboolean do_not_open)
|
||||
{
|
||||
char *local, *op;
|
||||
const char *archive_name;
|
||||
char *archive_name;
|
||||
int result = -1;
|
||||
struct archive *parc;
|
||||
int fstype;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
archive_name = inname;
|
||||
vfs_split (inname, &local, &op);
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
fstype = extfs_which (me, op);
|
||||
archive_name = vfs_path_to_str_elements_count (vpath, -1);
|
||||
|
||||
fstype = extfs_which (path_element->class, path_element->vfs_prefix);
|
||||
|
||||
if (fstype == -1)
|
||||
{
|
||||
g_free (archive_name);
|
||||
return NULL;
|
||||
if (local == NULL)
|
||||
local = inname + strlen (inname);
|
||||
}
|
||||
|
||||
/*
|
||||
* All filesystems should have some local archive, at least
|
||||
@ -679,11 +684,16 @@ extfs_get_path_mangle (struct vfs_class *me, char *inname, struct archive **arch
|
||||
|
||||
result = do_not_open ? -1 : extfs_read_archive (fstype, archive_name, &parc);
|
||||
if (result == -1)
|
||||
ERRNOR (EIO, NULL);
|
||||
{
|
||||
path_element->class->verrno = EIO;
|
||||
g_free (archive_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return_success:
|
||||
*archive = parc;
|
||||
return local;
|
||||
g_free (archive_name);
|
||||
return path_element->path;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -693,16 +703,9 @@ extfs_get_path_mangle (struct vfs_class *me, char *inname, struct archive **arch
|
||||
*/
|
||||
|
||||
static char *
|
||||
extfs_get_path (struct vfs_class *me, const char *inname,
|
||||
struct archive **archive, gboolean do_not_open)
|
||||
extfs_get_path (const vfs_path_t * vpath, struct archive **archive, gboolean do_not_open)
|
||||
{
|
||||
char *buf, *res, *res2;
|
||||
|
||||
buf = g_strdup (inname);
|
||||
res = extfs_get_path_mangle (me, buf, archive, do_not_open);
|
||||
res2 = g_strdup (res);
|
||||
g_free (buf);
|
||||
return res2;
|
||||
return g_strdup (extfs_get_path_mangle (vpath, archive, do_not_open));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -832,14 +835,14 @@ extfs_cmd (const char *str_extfs_cmd, struct archive *archive,
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
extfs_run (struct vfs_class *me, const char *file)
|
||||
extfs_run (const vfs_path_t * vpath)
|
||||
{
|
||||
struct archive *archive = NULL;
|
||||
char *p, *q, *archive_name;
|
||||
char *cmd;
|
||||
const extfs_plugin_info_t *info;
|
||||
|
||||
p = extfs_get_path (me, file, &archive, FALSE);
|
||||
p = extfs_get_path (vpath, &archive, FALSE);
|
||||
if (p == NULL)
|
||||
return;
|
||||
q = name_quote (p, 0);
|
||||
@ -857,7 +860,7 @@ extfs_run (struct vfs_class *me, const char *file)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void *
|
||||
extfs_open (struct vfs_class *me, const char *file, int flags, mode_t mode)
|
||||
extfs_open (const vfs_path_t * vpath, int flags, mode_t mode)
|
||||
{
|
||||
struct pseudofile *extfs_info;
|
||||
struct archive *archive = NULL;
|
||||
@ -866,7 +869,7 @@ extfs_open (struct vfs_class *me, const char *file, int flags, mode_t mode)
|
||||
int local_handle;
|
||||
gboolean created = FALSE;
|
||||
|
||||
q = extfs_get_path (me, file, &archive, FALSE);
|
||||
q = extfs_get_path (vpath, &archive, FALSE);
|
||||
if (q == NULL)
|
||||
return NULL;
|
||||
entry = extfs_find_entry (archive->root_entry, q, FALSE, FALSE);
|
||||
@ -990,14 +993,14 @@ extfs_errno (struct vfs_class *me)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void *
|
||||
extfs_opendir (struct vfs_class *me, const char *dirname)
|
||||
extfs_opendir (const vfs_path_t * vpath)
|
||||
{
|
||||
struct archive *archive = NULL;
|
||||
char *q;
|
||||
struct entry *entry;
|
||||
struct entry **info;
|
||||
|
||||
q = extfs_get_path (me, dirname, &archive, FALSE);
|
||||
q = extfs_get_path (vpath, &archive, FALSE);
|
||||
if (q == NULL)
|
||||
return NULL;
|
||||
entry = extfs_find_entry (archive->root_entry, q, FALSE, FALSE);
|
||||
@ -1074,16 +1077,14 @@ extfs_stat_move (struct stat *buf, const struct inode *inode)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
extfs_internal_stat (struct vfs_class *me, const char *path, struct stat *buf, gboolean resolve)
|
||||
extfs_internal_stat (const vfs_path_t * vpath, struct stat *buf, gboolean resolve)
|
||||
{
|
||||
struct archive *archive;
|
||||
char *q, *mpath;
|
||||
char *q;
|
||||
struct entry *entry;
|
||||
int result = -1;
|
||||
|
||||
mpath = g_strdup (path);
|
||||
|
||||
q = extfs_get_path_mangle (me, mpath, &archive, FALSE);
|
||||
q = extfs_get_path_mangle (vpath, &archive, FALSE);
|
||||
if (q == NULL)
|
||||
goto cleanup;
|
||||
entry = extfs_find_entry (archive->root_entry, q, FALSE, FALSE);
|
||||
@ -1098,24 +1099,23 @@ extfs_internal_stat (struct vfs_class *me, const char *path, struct stat *buf, g
|
||||
extfs_stat_move (buf, entry->inode);
|
||||
result = 0;
|
||||
cleanup:
|
||||
g_free (mpath);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
extfs_stat (struct vfs_class *me, const char *path, struct stat *buf)
|
||||
extfs_stat (const vfs_path_t * vpath, struct stat *buf)
|
||||
{
|
||||
return extfs_internal_stat (me, path, buf, TRUE);
|
||||
return extfs_internal_stat (vpath, buf, TRUE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
extfs_lstat (struct vfs_class *me, const char *path, struct stat *buf)
|
||||
extfs_lstat (const vfs_path_t * vpath, struct stat *buf)
|
||||
{
|
||||
return extfs_internal_stat (me, path, buf, FALSE);
|
||||
return extfs_internal_stat (vpath, buf, FALSE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -1132,17 +1132,15 @@ extfs_fstat (void *data, struct stat *buf)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
extfs_readlink (struct vfs_class *me, const char *path, char *buf, size_t size)
|
||||
extfs_readlink (const vfs_path_t * vpath, char *buf, size_t size)
|
||||
{
|
||||
struct archive *archive;
|
||||
char *q, *mpath;
|
||||
char *q;
|
||||
size_t len;
|
||||
struct entry *entry;
|
||||
int result = -1;
|
||||
|
||||
mpath = g_strdup (path);
|
||||
|
||||
q = extfs_get_path_mangle (me, mpath, &archive, FALSE);
|
||||
q = extfs_get_path_mangle (vpath, &archive, FALSE);
|
||||
if (q == NULL)
|
||||
goto cleanup;
|
||||
entry = extfs_find_entry (archive->root_entry, q, FALSE, FALSE);
|
||||
@ -1150,7 +1148,9 @@ extfs_readlink (struct vfs_class *me, const char *path, char *buf, size_t size)
|
||||
goto cleanup;
|
||||
if (!S_ISLNK (entry->inode->mode))
|
||||
{
|
||||
me->verrno = EINVAL;
|
||||
vfs_path_element_t *path_element;
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
path_element->class->verrno = EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
len = strlen (entry->inode->linkname);
|
||||
@ -1160,17 +1160,15 @@ extfs_readlink (struct vfs_class *me, const char *path, char *buf, size_t size)
|
||||
result = len;
|
||||
memcpy (buf, entry->inode->linkname, result);
|
||||
cleanup:
|
||||
g_free (mpath);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
extfs_chown (struct vfs_class *me, const char *path, uid_t owner, gid_t group)
|
||||
extfs_chown (const vfs_path_t * vpath, uid_t owner, gid_t group)
|
||||
{
|
||||
(void) me;
|
||||
(void) path;
|
||||
(void) vpath;
|
||||
(void) owner;
|
||||
(void) group;
|
||||
return 0;
|
||||
@ -1179,10 +1177,9 @@ extfs_chown (struct vfs_class *me, const char *path, uid_t owner, gid_t group)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
extfs_chmod (struct vfs_class *me, const char *path, int mode)
|
||||
extfs_chmod (const vfs_path_t * vpath, int mode)
|
||||
{
|
||||
(void) me;
|
||||
(void) path;
|
||||
(void) vpath;
|
||||
(void) mode;
|
||||
return 0;
|
||||
}
|
||||
@ -1201,16 +1198,14 @@ extfs_write (void *data, const char *buf, size_t nbyte)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
extfs_unlink (struct vfs_class *me, const char *file)
|
||||
extfs_unlink (const vfs_path_t * vpath)
|
||||
{
|
||||
struct archive *archive;
|
||||
char *q, *mpath;
|
||||
char *q;
|
||||
struct entry *entry;
|
||||
int result = -1;
|
||||
|
||||
mpath = g_strdup (file);
|
||||
|
||||
q = extfs_get_path_mangle (me, mpath, &archive, FALSE);
|
||||
q = extfs_get_path_mangle (vpath, &archive, FALSE);
|
||||
if (q == NULL)
|
||||
goto cleanup;
|
||||
entry = extfs_find_entry (archive->root_entry, q, FALSE, FALSE);
|
||||
@ -1221,7 +1216,8 @@ extfs_unlink (struct vfs_class *me, const char *file)
|
||||
goto cleanup;
|
||||
if (S_ISDIR (entry->inode->mode))
|
||||
{
|
||||
me->verrno = EISDIR;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
path_element->class->verrno = EISDIR;
|
||||
goto cleanup;
|
||||
}
|
||||
if (extfs_cmd (" rm ", archive, entry, ""))
|
||||
@ -1232,31 +1228,29 @@ extfs_unlink (struct vfs_class *me, const char *file)
|
||||
extfs_remove_entry (entry);
|
||||
result = 0;
|
||||
cleanup:
|
||||
g_free (mpath);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
extfs_mkdir (struct vfs_class *me, const char *path, mode_t mode)
|
||||
extfs_mkdir (const vfs_path_t * vpath, mode_t mode)
|
||||
{
|
||||
struct archive *archive;
|
||||
char *q, *mpath;
|
||||
char *q;
|
||||
struct entry *entry;
|
||||
int result = -1;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
(void) mode;
|
||||
|
||||
mpath = g_strdup (path);
|
||||
|
||||
q = extfs_get_path_mangle (me, mpath, &archive, FALSE);
|
||||
q = extfs_get_path_mangle (vpath, &archive, FALSE);
|
||||
if (q == NULL)
|
||||
goto cleanup;
|
||||
entry = extfs_find_entry (archive->root_entry, q, FALSE, FALSE);
|
||||
if (entry != NULL)
|
||||
{
|
||||
me->verrno = EEXIST;
|
||||
path_element->class->verrno = EEXIST;
|
||||
goto cleanup;
|
||||
}
|
||||
entry = extfs_find_entry (archive->root_entry, q, TRUE, FALSE);
|
||||
@ -1267,7 +1261,7 @@ extfs_mkdir (struct vfs_class *me, const char *path, mode_t mode)
|
||||
goto cleanup;
|
||||
if (!S_ISDIR (entry->inode->mode))
|
||||
{
|
||||
me->verrno = ENOTDIR;
|
||||
path_element->class->verrno = ENOTDIR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -1279,23 +1273,20 @@ extfs_mkdir (struct vfs_class *me, const char *path, mode_t mode)
|
||||
}
|
||||
result = 0;
|
||||
cleanup:
|
||||
g_free (mpath);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
extfs_rmdir (struct vfs_class *me, const char *path)
|
||||
extfs_rmdir (const vfs_path_t * vpath)
|
||||
{
|
||||
struct archive *archive;
|
||||
char *q, *mpath;
|
||||
char *q;
|
||||
struct entry *entry;
|
||||
int result = -1;
|
||||
|
||||
mpath = g_strdup (path);
|
||||
|
||||
q = extfs_get_path_mangle (me, mpath, &archive, FALSE);
|
||||
q = extfs_get_path_mangle (vpath, &archive, FALSE);
|
||||
if (q == NULL)
|
||||
goto cleanup;
|
||||
entry = extfs_find_entry (archive->root_entry, q, FALSE, FALSE);
|
||||
@ -1306,7 +1297,8 @@ extfs_rmdir (struct vfs_class *me, const char *path)
|
||||
goto cleanup;
|
||||
if (!S_ISDIR (entry->inode->mode))
|
||||
{
|
||||
me->verrno = ENOTDIR;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
path_element->class->verrno = ENOTDIR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -1318,21 +1310,20 @@ extfs_rmdir (struct vfs_class *me, const char *path)
|
||||
extfs_remove_entry (entry);
|
||||
result = 0;
|
||||
cleanup:
|
||||
g_free (mpath);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
extfs_chdir (struct vfs_class *me, const char *path)
|
||||
extfs_chdir (const vfs_path_t * vpath)
|
||||
{
|
||||
struct archive *archive = NULL;
|
||||
char *q;
|
||||
struct entry *entry;
|
||||
|
||||
my_errno = ENOTDIR;
|
||||
q = extfs_get_path (me, path, &archive, FALSE);
|
||||
q = extfs_get_path (vpath, &archive, FALSE);
|
||||
if (q == NULL)
|
||||
return -1;
|
||||
entry = extfs_find_entry (archive->root_entry, q, FALSE, FALSE);
|
||||
@ -1359,12 +1350,12 @@ extfs_lseek (void *data, off_t offset, int whence)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static vfsid
|
||||
extfs_getid (struct vfs_class *me, const char *path)
|
||||
extfs_getid (const vfs_path_t * vpath)
|
||||
{
|
||||
struct archive *archive = NULL;
|
||||
char *p;
|
||||
|
||||
p = extfs_get_path (me, path, &archive, TRUE);
|
||||
p = extfs_get_path (vpath, &archive, TRUE);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
g_free (p);
|
||||
@ -1481,12 +1472,12 @@ extfs_free (vfsid id)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static char *
|
||||
extfs_getlocalcopy (struct vfs_class *me, const char *path)
|
||||
extfs_getlocalcopy (const vfs_path_t * vpath)
|
||||
{
|
||||
struct pseudofile *fp;
|
||||
char *p;
|
||||
|
||||
fp = (struct pseudofile *) extfs_open (me, path, O_RDONLY, 0);
|
||||
fp = (struct pseudofile *) extfs_open (vpath, O_RDONLY, 0);
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
if (fp->entry->inode->local_filename == NULL)
|
||||
@ -1503,11 +1494,11 @@ extfs_getlocalcopy (struct vfs_class *me, const char *path)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
extfs_ungetlocalcopy (struct vfs_class *me, const char *path, const char *local, int has_changed)
|
||||
extfs_ungetlocalcopy (const vfs_path_t * vpath, const char *local, int has_changed)
|
||||
{
|
||||
struct pseudofile *fp;
|
||||
|
||||
fp = (struct pseudofile *) extfs_open (me, path, O_RDONLY, 0);
|
||||
fp = (struct pseudofile *) extfs_open (vpath, O_RDONLY, 0);
|
||||
if (fp == NULL)
|
||||
return 0;
|
||||
|
||||
@ -1676,13 +1667,13 @@ extfs_done (struct vfs_class *me)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
extfs_setctl (struct vfs_class *me, const char *path, int ctlop, void *arg)
|
||||
extfs_setctl (const vfs_path_t * vpath, int ctlop, void *arg)
|
||||
{
|
||||
(void) arg;
|
||||
|
||||
if (ctlop == VFS_SETCTL_RUN)
|
||||
{
|
||||
extfs_run (me, path);
|
||||
extfs_run (vpath);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
/*** declarations of public functions ************************************************************/
|
||||
|
||||
void init_extfs(void);
|
||||
void init_extfs (void);
|
||||
|
||||
/*** inline functions ****************************************************************************/
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
shell connections.
|
||||
|
||||
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
|
||||
2007 Free Software Foundation, Inc.
|
||||
2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
|
||||
Written by: 1998 Pavel Machek
|
||||
Spaces fix: 2000 Michal Svec
|
||||
@ -115,30 +115,12 @@ int fish_directory_timeout = 900;
|
||||
|
||||
#define SUP ((fish_super_data_t *) super->data)
|
||||
|
||||
#define PREFIX \
|
||||
char buf[BUF_LARGE]; \
|
||||
const char *crpath; \
|
||||
char *rpath, *mpath; \
|
||||
struct vfs_s_super *super; \
|
||||
mpath = g_strdup (path); \
|
||||
crpath = vfs_s_get_path_mangle (me, mpath, &super, 0); \
|
||||
if (crpath == NULL) \
|
||||
{ \
|
||||
g_free (mpath); \
|
||||
return -1; \
|
||||
} \
|
||||
rpath = strutils_shell_escape (crpath); \
|
||||
g_free (mpath)
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int sockr, sockw;
|
||||
char *cwdir;
|
||||
char *host, *user;
|
||||
char *password;
|
||||
int flags;
|
||||
int sockr;
|
||||
int sockw;
|
||||
char *scr_ls;
|
||||
char *scr_chmod;
|
||||
char *scr_exists;
|
||||
@ -253,7 +235,7 @@ fish_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply, c
|
||||
{
|
||||
va_list ap;
|
||||
char *str;
|
||||
int status;
|
||||
ssize_t status;
|
||||
FILE *logfile = MEDATA->logfile;
|
||||
|
||||
va_start (ap, fmt);
|
||||
@ -297,10 +279,6 @@ fish_free_archive (struct vfs_class *me, struct vfs_s_super *super)
|
||||
close (SUP->sockr);
|
||||
SUP->sockw = SUP->sockr = -1;
|
||||
}
|
||||
g_free (SUP->host);
|
||||
g_free (SUP->user);
|
||||
g_free (SUP->cwdir);
|
||||
g_free (SUP->password);
|
||||
g_free (SUP->scr_ls);
|
||||
g_free (SUP->scr_exists);
|
||||
g_free (SUP->scr_mkdir);
|
||||
@ -437,17 +415,17 @@ fish_open_archive_pipeopen (struct vfs_s_super *super)
|
||||
{
|
||||
char gbuf[10];
|
||||
const char *argv[10]; /* All of 10 is used now */
|
||||
const char *xsh = (SUP->flags == FISH_FLAG_RSH ? "rsh" : "ssh");
|
||||
const char *xsh = (super->path_element->port == FISH_FLAG_RSH ? "rsh" : "ssh");
|
||||
int i = 0;
|
||||
|
||||
argv[i++] = xsh;
|
||||
if (SUP->flags == FISH_FLAG_COMPRESSED)
|
||||
if (super->path_element->port == FISH_FLAG_COMPRESSED)
|
||||
argv[i++] = "-C";
|
||||
|
||||
if (SUP->flags > FISH_FLAG_RSH)
|
||||
if (super->path_element->port > FISH_FLAG_RSH)
|
||||
{
|
||||
argv[i++] = "-p";
|
||||
g_snprintf (gbuf, sizeof (gbuf), "%d", SUP->flags);
|
||||
g_snprintf (gbuf, sizeof (gbuf), "%d", super->path_element->port);
|
||||
argv[i++] = gbuf;
|
||||
}
|
||||
|
||||
@ -458,18 +436,18 @@ fish_open_archive_pipeopen (struct vfs_s_super *super)
|
||||
* option breaks it for some)
|
||||
*/
|
||||
|
||||
if (SUP->user)
|
||||
if (super->path_element->user != NULL)
|
||||
{
|
||||
argv[i++] = "-l";
|
||||
argv[i++] = SUP->user;
|
||||
argv[i++] = super->path_element->user;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The rest of the code assumes it to be a valid username */
|
||||
SUP->user = vfs_get_local_username ();
|
||||
super->path_element->user = vfs_get_local_username ();
|
||||
}
|
||||
|
||||
argv[i++] = SUP->host;
|
||||
argv[i++] = super->path_element->host;
|
||||
argv[i++] = "echo FISH:; /bin/sh";
|
||||
argv[i++] = NULL;
|
||||
|
||||
@ -488,7 +466,7 @@ fish_open_archive_talk (struct vfs_class *me, struct vfs_s_super *super)
|
||||
if (!vfs_s_get_line (me, SUP->sockr, answer, sizeof (answer), ':'))
|
||||
return FALSE;
|
||||
|
||||
if (strstr (answer, "assword"))
|
||||
if (strstr (answer, "assword") != NULL)
|
||||
{
|
||||
/* Currently, this does not work. ssh reads passwords from
|
||||
/dev/tty, not from stdin :-(. */
|
||||
@ -497,25 +475,27 @@ fish_open_archive_talk (struct vfs_class *me, struct vfs_s_super *super)
|
||||
|
||||
return FALSE;
|
||||
#if 0
|
||||
if (!SUP->password)
|
||||
if (super->path_element->password == NULL)
|
||||
{
|
||||
char *p, *op;
|
||||
p = g_strdup_printf (_("fish: Password is required for %s"), SUP->user);
|
||||
p = g_strdup_printf (_("fish: Password is required for %s"), super->path_element->user);
|
||||
op = vfs_get_password (p);
|
||||
g_free (p);
|
||||
if (op == NULL)
|
||||
return FALSE;
|
||||
SUP->password = op;
|
||||
super->path_element->password = op;
|
||||
|
||||
}
|
||||
|
||||
printf ("\n%s\n", _("fish: Sending password..."));
|
||||
|
||||
{
|
||||
size_t str_len;
|
||||
str_len = strlen (SUP->password);
|
||||
if ((write (SUP->sockw, SUP->password, str_len) != (ssize_t) str_len)
|
||||
|
||||
str_len = strlen (super->path_element->password);
|
||||
if ((write (SUP.sockw, super->path_element->password, str_len) != (ssize_t) str_len)
|
||||
|| (write (SUP->sockw, "\n", 1) != 1))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -569,12 +549,15 @@ fish_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
|
||||
SUP->scr_env = fish_set_env (SUP->host_flags);
|
||||
|
||||
vfs_print_message (_("fish: Setting up current directory..."));
|
||||
SUP->cwdir = fish_getcwd (me, super);
|
||||
vfs_print_message (_("fish: Connected, home %s."), SUP->cwdir);
|
||||
super->path_element->path = fish_getcwd (me, super);
|
||||
vfs_print_message (_("fish: Connected, home %s."), super->path_element->path);
|
||||
#if 0
|
||||
super->name = g_strconcat ("/#sh:", SUP->user, "@", SUP->host, "/", (char *) NULL);
|
||||
#endif
|
||||
super->name =
|
||||
g_strconcat ("/#sh:", super->path_element->user, "@", super->path_element->host, "/",
|
||||
(char *) NULL);
|
||||
#else
|
||||
super->name = g_strdup (PATH_SEP_STR);
|
||||
#endif
|
||||
|
||||
super->root = vfs_s_new_inode (me, super, vfs_s_default_stat (me, S_IFDIR | 0755));
|
||||
return 0;
|
||||
@ -583,74 +566,81 @@ fish_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
fish_open_archive (struct vfs_class *me, struct vfs_s_super *super,
|
||||
const char *archive_name, char *op)
|
||||
fish_open_archive (struct vfs_s_super *super,
|
||||
const vfs_path_t * vpath, const vfs_path_element_t * vpath_element)
|
||||
{
|
||||
char *host, *user, *password, *p;
|
||||
int flags;
|
||||
|
||||
(void) archive_name;
|
||||
(void) vpath;
|
||||
|
||||
super->data = g_new0 (fish_super_data_t, 1);
|
||||
p = vfs_split_url (strchr (op, ':') + 1, &host, &user, &flags,
|
||||
&password, 0, URL_NOSLASH | URL_USE_ANONYMOUS);
|
||||
super->path_element = vfs_path_element_clone (vpath_element);
|
||||
|
||||
g_free (p);
|
||||
if (strncmp (vpath_element->vfs_prefix, "rsh", 3) == 0)
|
||||
super->path_element->port = FISH_FLAG_RSH;
|
||||
|
||||
super->data = g_new0 (fish_super_data_t, 1);
|
||||
SUP->host = host;
|
||||
SUP->user = user;
|
||||
SUP->flags = flags;
|
||||
if (strncmp (op, "rsh:", 4) == 0)
|
||||
SUP->flags = FISH_FLAG_RSH;
|
||||
SUP->cwdir = NULL;
|
||||
if (password != NULL)
|
||||
SUP->password = password;
|
||||
SUP->scr_ls = fish_load_script_from_file (host, FISH_LS_FILE, FISH_LS_DEF_CONTENT);
|
||||
SUP->scr_exists = fish_load_script_from_file (host, FISH_EXISTS_FILE, FISH_EXISTS_DEF_CONTENT);
|
||||
SUP->scr_mkdir = fish_load_script_from_file (host, FISH_MKDIR_FILE, FISH_MKDIR_DEF_CONTENT);
|
||||
SUP->scr_unlink = fish_load_script_from_file (host, FISH_UNLINK_FILE, FISH_UNLINK_DEF_CONTENT);
|
||||
SUP->scr_chown = fish_load_script_from_file (host, FISH_CHOWN_FILE, FISH_CHOWN_DEF_CONTENT);
|
||||
SUP->scr_chmod = fish_load_script_from_file (host, FISH_CHMOD_FILE, FISH_CHMOD_DEF_CONTENT);
|
||||
SUP->scr_rmdir = fish_load_script_from_file (host, FISH_RMDIR_FILE, FISH_RMDIR_DEF_CONTENT);
|
||||
SUP->scr_ln = fish_load_script_from_file (host, FISH_LN_FILE, FISH_LN_DEF_CONTENT);
|
||||
SUP->scr_mv = fish_load_script_from_file (host, FISH_MV_FILE, FISH_MV_DEF_CONTENT);
|
||||
SUP->scr_ls =
|
||||
fish_load_script_from_file (super->path_element->host, FISH_LS_FILE, FISH_LS_DEF_CONTENT);
|
||||
SUP->scr_exists =
|
||||
fish_load_script_from_file (super->path_element->host, FISH_EXISTS_FILE,
|
||||
FISH_EXISTS_DEF_CONTENT);
|
||||
SUP->scr_mkdir =
|
||||
fish_load_script_from_file (super->path_element->host, FISH_MKDIR_FILE,
|
||||
FISH_MKDIR_DEF_CONTENT);
|
||||
SUP->scr_unlink =
|
||||
fish_load_script_from_file (super->path_element->host, FISH_UNLINK_FILE,
|
||||
FISH_UNLINK_DEF_CONTENT);
|
||||
SUP->scr_chown =
|
||||
fish_load_script_from_file (super->path_element->host, FISH_CHOWN_FILE,
|
||||
FISH_CHOWN_DEF_CONTENT);
|
||||
SUP->scr_chmod =
|
||||
fish_load_script_from_file (super->path_element->host, FISH_CHMOD_FILE,
|
||||
FISH_CHMOD_DEF_CONTENT);
|
||||
SUP->scr_rmdir =
|
||||
fish_load_script_from_file (super->path_element->host, FISH_RMDIR_FILE,
|
||||
FISH_RMDIR_DEF_CONTENT);
|
||||
SUP->scr_ln =
|
||||
fish_load_script_from_file (super->path_element->host, FISH_LN_FILE, FISH_LN_DEF_CONTENT);
|
||||
SUP->scr_mv =
|
||||
fish_load_script_from_file (super->path_element->host, FISH_MV_FILE, FISH_MV_DEF_CONTENT);
|
||||
SUP->scr_hardlink =
|
||||
fish_load_script_from_file (host, FISH_HARDLINK_FILE, FISH_HARDLINK_DEF_CONTENT);
|
||||
SUP->scr_get = fish_load_script_from_file (host, FISH_GET_FILE, FISH_GET_DEF_CONTENT);
|
||||
SUP->scr_send = fish_load_script_from_file (host, FISH_SEND_FILE, FISH_SEND_DEF_CONTENT);
|
||||
SUP->scr_append = fish_load_script_from_file (host, FISH_APPEND_FILE, FISH_APPEND_DEF_CONTENT);
|
||||
SUP->scr_info = fish_load_script_from_file (host, FISH_INFO_FILE, FISH_INFO_DEF_CONTENT);
|
||||
return fish_open_archive_int (me, super);
|
||||
fish_load_script_from_file (super->path_element->host, FISH_HARDLINK_FILE,
|
||||
FISH_HARDLINK_DEF_CONTENT);
|
||||
SUP->scr_get =
|
||||
fish_load_script_from_file (super->path_element->host, FISH_GET_FILE, FISH_GET_DEF_CONTENT);
|
||||
SUP->scr_send =
|
||||
fish_load_script_from_file (super->path_element->host, FISH_SEND_FILE,
|
||||
FISH_SEND_DEF_CONTENT);
|
||||
SUP->scr_append =
|
||||
fish_load_script_from_file (super->path_element->host, FISH_APPEND_FILE,
|
||||
FISH_APPEND_DEF_CONTENT);
|
||||
SUP->scr_info =
|
||||
fish_load_script_from_file (super->path_element->host, FISH_INFO_FILE,
|
||||
FISH_INFO_DEF_CONTENT);
|
||||
|
||||
return fish_open_archive_int (vpath_element->class, super);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
fish_archive_same (struct vfs_class *me, struct vfs_s_super *super,
|
||||
const char *archive_name, char *op, void *cookie)
|
||||
fish_archive_same (const vfs_path_element_t * vpath_element, struct vfs_s_super *super,
|
||||
const vfs_path_t * vpath, void *cookie)
|
||||
{
|
||||
char *host, *user;
|
||||
int flags;
|
||||
vfs_path_element_t *path_element;
|
||||
int result;
|
||||
|
||||
(void) me;
|
||||
(void) archive_name;
|
||||
(void) vpath;
|
||||
(void) cookie;
|
||||
|
||||
op = vfs_split_url (strchr (op, ':') + 1, &host, &user, &flags, 0, 0,
|
||||
URL_NOSLASH | URL_USE_ANONYMOUS);
|
||||
path_element = vfs_path_element_clone (vpath_element);
|
||||
|
||||
g_free (op);
|
||||
if (path_element->user == NULL)
|
||||
path_element->user = vfs_get_local_username ();
|
||||
|
||||
if (user == NULL)
|
||||
user = vfs_get_local_username ();
|
||||
result = ((strcmp (path_element->host, super->path_element->host) == 0)
|
||||
&& (strcmp (path_element->user, super->path_element->user) == 0)
|
||||
&& (path_element->port == super->path_element->port)) ? 1 : 0;
|
||||
|
||||
result = ((strcmp (host, SUP->host) == 0)
|
||||
&& (strcmp (user, SUP->user) == 0) && (flags == SUP->flags));
|
||||
|
||||
g_free (host);
|
||||
g_free (user);
|
||||
vfs_path_element_free (path_element);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -843,19 +833,13 @@ fish_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
|
||||
reply_code = fish_decode_reply (buffer + 4, 0);
|
||||
if (reply_code == COMPLETE)
|
||||
{
|
||||
g_free (SUP->cwdir);
|
||||
SUP->cwdir = g_strdup (remote_path);
|
||||
g_free (super->path_element->path);
|
||||
super->path_element->path = g_strdup (remote_path);
|
||||
vfs_print_message (_("%s: done."), me->name);
|
||||
return 0;
|
||||
}
|
||||
else if (reply_code == ERROR)
|
||||
{
|
||||
me->verrno = EACCES;
|
||||
}
|
||||
else
|
||||
{
|
||||
me->verrno = E_REMOTE;
|
||||
}
|
||||
|
||||
me->verrno = reply_code == ERROR ? EACCES : E_REMOTE;
|
||||
|
||||
error:
|
||||
vfs_print_message (_("%s: failure"), me->name);
|
||||
@ -865,7 +849,7 @@ fish_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
fish_file_store (struct vfs_class *me, vfs_file_handler_t *fh, char *name, char *localname)
|
||||
fish_file_store (struct vfs_class *me, vfs_file_handler_t * fh, char *name, char *localname)
|
||||
{
|
||||
fish_fh_data_t *fish = (fish_fh_data_t *) fh->data;
|
||||
gchar *shell_commands = NULL;
|
||||
@ -878,7 +862,6 @@ fish_file_store (struct vfs_class *me, vfs_file_handler_t *fh, char *name, char
|
||||
char *quoted_name;
|
||||
|
||||
h = open (localname, O_RDONLY);
|
||||
|
||||
if (h == -1)
|
||||
ERRNOR (EIO, -1);
|
||||
if (fstat (h, &s) < 0)
|
||||
@ -925,6 +908,7 @@ fish_file_store (struct vfs_class *me, vfs_file_handler_t *fh, char *name, char
|
||||
shell_commands =
|
||||
g_strconcat (SUP->scr_env, "FISH_FILENAME=%s FISH_FILESIZE=%" PRIuMAX ";\n",
|
||||
SUP->scr_append, (char *) NULL);
|
||||
|
||||
n = fish_command (me, super, WAIT_REPLY, shell_commands, quoted_name,
|
||||
(uintmax_t) s.st_size);
|
||||
g_free (shell_commands);
|
||||
@ -978,9 +962,11 @@ fish_file_store (struct vfs_class *me, vfs_file_handler_t *fh, char *name, char
|
||||
}
|
||||
close (h);
|
||||
g_free (quoted_name);
|
||||
|
||||
if ((fish_get_reply (me, SUP->sockr, NULL, 0) != COMPLETE) || was_error)
|
||||
ERRNOR (E_REMOTE, -1);
|
||||
return 0;
|
||||
|
||||
error_return:
|
||||
close (h);
|
||||
fish_get_reply (me, SUP->sockr, NULL, 0);
|
||||
@ -991,7 +977,7 @@ fish_file_store (struct vfs_class *me, vfs_file_handler_t *fh, char *name, char
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
fish_linear_start (struct vfs_class *me, vfs_file_handler_t *fh, off_t offset)
|
||||
fish_linear_start (struct vfs_class *me, vfs_file_handler_t * fh, off_t offset)
|
||||
{
|
||||
fish_fh_data_t *fish;
|
||||
gchar *shell_commands = NULL;
|
||||
@ -1042,7 +1028,7 @@ fish_linear_start (struct vfs_class *me, vfs_file_handler_t *fh, off_t offset)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
fish_linear_abort (struct vfs_class *me, vfs_file_handler_t *fh)
|
||||
fish_linear_abort (struct vfs_class *me, vfs_file_handler_t * fh)
|
||||
{
|
||||
fish_fh_data_t *fish = (fish_fh_data_t *) fh->data;
|
||||
struct vfs_s_super *super = FH_SUPER;
|
||||
@ -1050,6 +1036,7 @@ fish_linear_abort (struct vfs_class *me, vfs_file_handler_t *fh)
|
||||
int n;
|
||||
|
||||
vfs_print_message (_("Aborting transfer..."));
|
||||
|
||||
do
|
||||
{
|
||||
n = MIN (sizeof (buffer), (size_t) (fish->total - fish->got));
|
||||
@ -1072,7 +1059,7 @@ fish_linear_abort (struct vfs_class *me, vfs_file_handler_t *fh)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
fish_linear_read (struct vfs_class *me, vfs_file_handler_t *fh, void *buf, size_t len)
|
||||
fish_linear_read (struct vfs_class *me, vfs_file_handler_t * fh, void *buf, size_t len)
|
||||
{
|
||||
fish_fh_data_t *fish = (fish_fh_data_t *) fh->data;
|
||||
struct vfs_s_super *super = FH_SUPER;
|
||||
@ -1101,7 +1088,7 @@ fish_linear_read (struct vfs_class *me, vfs_file_handler_t *fh, void *buf, size_
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
fish_linear_close (struct vfs_class *me, vfs_file_handler_t *fh)
|
||||
fish_linear_close (struct vfs_class *me, vfs_file_handler_t * fh)
|
||||
{
|
||||
fish_fh_data_t *fish = (fish_fh_data_t *) fh->data;
|
||||
|
||||
@ -1160,135 +1147,131 @@ fish_send_command (struct vfs_class *me, struct vfs_s_super *super, const char *
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
fish_rename (struct vfs_class *me, const char *path1, const char *path2)
|
||||
fish_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
|
||||
{
|
||||
gchar *shell_commands = NULL;
|
||||
char buf[BUF_LARGE];
|
||||
const char *crpath1, *crpath2;
|
||||
char *rpath1, *rpath2, *mpath1, *mpath2;
|
||||
char *rpath1, *rpath2;
|
||||
struct vfs_s_super *super, *super2;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath1, -1);
|
||||
|
||||
mpath1 = g_strdup (path1);
|
||||
crpath1 = vfs_s_get_path_mangle (me, mpath1, &super, 0);
|
||||
crpath1 = vfs_s_get_path (vpath1, &super, 0);
|
||||
if (crpath1 == NULL)
|
||||
{
|
||||
g_free (mpath1);
|
||||
return -1;
|
||||
}
|
||||
mpath2 = g_strdup (path2);
|
||||
crpath2 = vfs_s_get_path_mangle (me, mpath2, &super2, 0);
|
||||
|
||||
crpath2 = vfs_s_get_path (vpath2, &super2, 0);
|
||||
if (crpath2 == NULL)
|
||||
{
|
||||
g_free (mpath1);
|
||||
g_free (mpath2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rpath1 = strutils_shell_escape (crpath1);
|
||||
g_free (mpath1);
|
||||
rpath2 = strutils_shell_escape (crpath2);
|
||||
g_free (mpath2);
|
||||
shell_commands = g_strconcat (SUP->scr_env, "FISH_FILEFROM=%s FISH_FILETO=%s;\n",
|
||||
SUP->scr_mv, (char *) NULL);
|
||||
g_snprintf (buf, sizeof (buf), shell_commands, rpath1, rpath2);
|
||||
g_free (shell_commands);
|
||||
g_free (rpath1);
|
||||
g_free (rpath2);
|
||||
return fish_send_command (me, super2, buf, OPT_FLUSH);
|
||||
return fish_send_command (path_element->class, super2, buf, OPT_FLUSH);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
fish_link (struct vfs_class *me, const char *path1, const char *path2)
|
||||
fish_link (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
|
||||
{
|
||||
gchar *shell_commands = NULL;
|
||||
char buf[BUF_LARGE];
|
||||
const char *crpath1, *crpath2;
|
||||
char *rpath1, *rpath2, *mpath1, *mpath2;
|
||||
char *rpath1, *rpath2;
|
||||
struct vfs_s_super *super, *super2;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
mpath1 = g_strdup (path1);
|
||||
crpath1 = vfs_s_get_path_mangle (me, mpath1, &super, 0);
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath1, -1);
|
||||
|
||||
crpath1 = vfs_s_get_path (vpath1, &super, 0);
|
||||
if (crpath1 == NULL)
|
||||
{
|
||||
g_free (mpath1);
|
||||
return -1;
|
||||
}
|
||||
mpath2 = g_strdup (path2);
|
||||
crpath2 = vfs_s_get_path_mangle (me, mpath2, &super2, 0);
|
||||
|
||||
crpath2 = vfs_s_get_path (vpath2, &super2, 0);
|
||||
if (crpath2 == NULL)
|
||||
{
|
||||
g_free (mpath1);
|
||||
g_free (mpath2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rpath1 = strutils_shell_escape (crpath1);
|
||||
g_free (mpath1);
|
||||
rpath2 = strutils_shell_escape (crpath2);
|
||||
g_free (mpath2);
|
||||
shell_commands = g_strconcat (SUP->scr_env, "FISH_FILEFROM=%s FISH_FILETO=%s;\n",
|
||||
SUP->scr_hardlink, (char *) NULL);
|
||||
g_snprintf (buf, sizeof (buf), shell_commands, rpath1, rpath2);
|
||||
g_free (shell_commands);
|
||||
g_free (rpath1);
|
||||
g_free (rpath2);
|
||||
return fish_send_command (me, super2, buf, OPT_FLUSH);
|
||||
return fish_send_command (path_element->class, super2, buf, OPT_FLUSH);
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
fish_symlink (struct vfs_class *me, const char *setto, const char *path)
|
||||
fish_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
|
||||
{
|
||||
char *qsetto;
|
||||
gchar *shell_commands = NULL;
|
||||
char buf[BUF_LARGE];
|
||||
const char *crpath;
|
||||
char *rpath, *mpath;
|
||||
char *rpath, *str_path;
|
||||
struct vfs_s_super *super;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath1, -1);
|
||||
|
||||
mpath = g_strdup (path);
|
||||
crpath = vfs_s_get_path_mangle (me, mpath, &super, 0);
|
||||
crpath = vfs_s_get_path (vpath2, &super, 0);
|
||||
if (crpath == NULL)
|
||||
{
|
||||
g_free (mpath);
|
||||
return -1;
|
||||
}
|
||||
rpath = strutils_shell_escape (crpath);
|
||||
g_free (mpath);
|
||||
|
||||
qsetto = strutils_shell_escape (setto);
|
||||
str_path = vfs_path_to_str (vpath1);
|
||||
qsetto = strutils_shell_escape (str_path);
|
||||
g_free (str_path);
|
||||
|
||||
shell_commands = g_strconcat (SUP->scr_env, "FISH_FILEFROM=%s FISH_FILETO=%s;\n",
|
||||
SUP->scr_ln, (char *) NULL);
|
||||
g_snprintf (buf, sizeof (buf), shell_commands, qsetto, rpath);
|
||||
g_free (shell_commands);
|
||||
g_free (qsetto);
|
||||
g_free (rpath);
|
||||
return fish_send_command (me, super, buf, OPT_FLUSH);
|
||||
return fish_send_command (path_element->class, super, buf, OPT_FLUSH);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
fish_chmod (struct vfs_class *me, const char *path, int mode)
|
||||
fish_chmod (const vfs_path_t * vpath, int mode)
|
||||
{
|
||||
gchar *shell_commands = NULL;
|
||||
char buf[BUF_LARGE];
|
||||
const char *crpath;
|
||||
char *rpath;
|
||||
struct vfs_s_super *super;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
PREFIX;
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
crpath = vfs_s_get_path (vpath, &super, 0);
|
||||
if (crpath == NULL)
|
||||
return -1;
|
||||
rpath = strutils_shell_escape (crpath);
|
||||
|
||||
shell_commands = g_strconcat (SUP->scr_env, "FISH_FILENAME=%s FISH_FILEMODE=%4.4o;\n",
|
||||
SUP->scr_chmod, (char *) NULL);
|
||||
g_snprintf (buf, sizeof (buf), shell_commands, rpath, mode & 07777);
|
||||
g_free (shell_commands);
|
||||
g_free (rpath);
|
||||
return fish_send_command (me, super, buf, OPT_FLUSH);
|
||||
return fish_send_command (path_element->class, super, buf, OPT_FLUSH);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
fish_chown (struct vfs_class *me, const char *path, uid_t owner, gid_t group)
|
||||
fish_chown (const vfs_path_t * vpath, uid_t owner, gid_t group)
|
||||
{
|
||||
char *sowner, *sgroup;
|
||||
struct passwd *pw;
|
||||
@ -1304,49 +1287,81 @@ fish_chown (struct vfs_class *me, const char *path, uid_t owner, gid_t group)
|
||||
|
||||
sowner = pw->pw_name;
|
||||
sgroup = gr->gr_name;
|
||||
|
||||
{
|
||||
gchar *shell_commands = NULL;
|
||||
char buf[BUF_LARGE];
|
||||
const char *crpath;
|
||||
char *rpath;
|
||||
struct vfs_s_super *super;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
PREFIX;
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
|
||||
crpath = vfs_s_get_path (vpath, &super, 0);
|
||||
if (crpath == NULL)
|
||||
return -1;
|
||||
rpath = strutils_shell_escape (crpath);
|
||||
|
||||
shell_commands = g_strconcat (SUP->scr_env,
|
||||
"FISH_FILENAME=%s FISH_FILEOWNER=%s FISH_FILEGROUP=%s;\n",
|
||||
SUP->scr_chown, (char *) NULL);
|
||||
g_snprintf (buf, sizeof (buf), shell_commands, rpath, sowner, sgroup);
|
||||
g_free (shell_commands);
|
||||
fish_send_command (me, super, buf, OPT_FLUSH);
|
||||
fish_send_command (path_element->class, super, buf, OPT_FLUSH);
|
||||
/* FIXME: what should we report if chgrp succeeds but chown fails? */
|
||||
/* fish_send_command(me, super, buf, OPT_FLUSH); */
|
||||
g_free (rpath);
|
||||
return fish_send_command (me, super, buf, OPT_FLUSH);
|
||||
return fish_send_command (path_element->class, super, buf, OPT_FLUSH);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
fish_unlink (struct vfs_class *me, const char *path)
|
||||
fish_unlink (const vfs_path_t * vpath)
|
||||
{
|
||||
gchar *shell_commands = NULL;
|
||||
|
||||
PREFIX;
|
||||
char buf[BUF_LARGE];
|
||||
const char *crpath;
|
||||
char *rpath;
|
||||
struct vfs_s_super *super;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
crpath = vfs_s_get_path (vpath, &super, 0);
|
||||
if (crpath == NULL)
|
||||
return -1;
|
||||
rpath = strutils_shell_escape (crpath);
|
||||
|
||||
shell_commands =
|
||||
g_strconcat (SUP->scr_env, "FISH_FILENAME=%s;\n", SUP->scr_unlink, (char *) NULL);
|
||||
g_snprintf (buf, sizeof (buf), shell_commands, rpath);
|
||||
g_free (shell_commands);
|
||||
g_free (rpath);
|
||||
return fish_send_command (me, super, buf, OPT_FLUSH);
|
||||
return fish_send_command (path_element->class, super, buf, OPT_FLUSH);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
fish_exists (struct vfs_class *me, const char *path)
|
||||
fish_exists (const vfs_path_t * vpath)
|
||||
{
|
||||
gchar *shell_commands = NULL;
|
||||
|
||||
PREFIX;
|
||||
char buf[BUF_LARGE];
|
||||
const char *crpath;
|
||||
char *rpath;
|
||||
struct vfs_s_super *super;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
crpath = vfs_s_get_path (vpath, &super, 0);
|
||||
if (crpath == NULL)
|
||||
return -1;
|
||||
rpath = strutils_shell_escape (crpath);
|
||||
|
||||
shell_commands =
|
||||
g_strconcat (SUP->scr_env, "FISH_FILENAME=%s;\n", SUP->scr_exists, (char *) NULL);
|
||||
@ -1354,36 +1369,46 @@ fish_exists (struct vfs_class *me, const char *path)
|
||||
g_free (shell_commands);
|
||||
g_free (rpath);
|
||||
|
||||
return (fish_send_command (me, super, buf, OPT_FLUSH) == 0) ? 1 : 0;
|
||||
return (fish_send_command (path_element->class, super, buf, OPT_FLUSH) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
fish_mkdir (struct vfs_class *me, const char *path, mode_t mode)
|
||||
fish_mkdir (const vfs_path_t * vpath, mode_t mode)
|
||||
{
|
||||
gchar *shell_commands = NULL;
|
||||
int ret_code;
|
||||
|
||||
PREFIX;
|
||||
char buf[BUF_LARGE];
|
||||
const char *crpath;
|
||||
char *rpath;
|
||||
struct vfs_s_super *super;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
(void) mode;
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
crpath = vfs_s_get_path (vpath, &super, 0);
|
||||
if (crpath == NULL)
|
||||
return -1;
|
||||
rpath = strutils_shell_escape (crpath);
|
||||
|
||||
shell_commands =
|
||||
g_strconcat (SUP->scr_env, "FISH_FILENAME=%s;\n", SUP->scr_mkdir, (char *) NULL);
|
||||
g_snprintf (buf, sizeof (buf), shell_commands, rpath);
|
||||
g_free (shell_commands);
|
||||
|
||||
g_free (rpath);
|
||||
ret_code = fish_send_command (me, super, buf, OPT_FLUSH);
|
||||
ret_code = fish_send_command (path_element->class, super, buf, OPT_FLUSH);
|
||||
|
||||
if (ret_code != 0)
|
||||
return ret_code;
|
||||
|
||||
if (!fish_exists (me, path))
|
||||
if (!fish_exists (vpath))
|
||||
{
|
||||
ERRNOR (EACCES, -1);
|
||||
path_element->class->verrno = EACCES;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1391,24 +1416,34 @@ fish_mkdir (struct vfs_class *me, const char *path, mode_t mode)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
fish_rmdir (struct vfs_class *me, const char *path)
|
||||
fish_rmdir (const vfs_path_t * vpath)
|
||||
{
|
||||
gchar *shell_commands = NULL;
|
||||
char buf[BUF_LARGE];
|
||||
const char *crpath;
|
||||
char *rpath;
|
||||
struct vfs_s_super *super;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
PREFIX;
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
crpath = vfs_s_get_path (vpath, &super, 0);
|
||||
if (crpath == NULL)
|
||||
return -1;
|
||||
rpath = strutils_shell_escape (crpath);
|
||||
|
||||
shell_commands =
|
||||
g_strconcat (SUP->scr_env, "FISH_FILENAME=%s;\n", SUP->scr_rmdir, (char *) NULL);
|
||||
g_snprintf (buf, sizeof (buf), shell_commands, rpath);
|
||||
g_free (shell_commands);
|
||||
g_free (rpath);
|
||||
return fish_send_command (me, super, buf, OPT_FLUSH);
|
||||
return fish_send_command (path_element->class, super, buf, OPT_FLUSH);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
fish_fh_open (struct vfs_class *me, vfs_file_handler_t *fh, int flags, mode_t mode)
|
||||
fish_fh_open (struct vfs_class *me, vfs_file_handler_t * fh, int flags, mode_t mode)
|
||||
{
|
||||
fish_fh_data_t *fish;
|
||||
|
||||
@ -1445,7 +1480,7 @@ fish_fh_open (struct vfs_class *me, vfs_file_handler_t *fh, int flags, mode_t mo
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
fish_fh_close (struct vfs_class *me, vfs_file_handler_t *fh)
|
||||
fish_fh_close (struct vfs_class *me, vfs_file_handler_t * fh)
|
||||
{
|
||||
(void) me;
|
||||
|
||||
@ -1468,7 +1503,7 @@ fish_fill_names (struct vfs_class *me, fill_names_f func)
|
||||
char gbuf[10];
|
||||
const char *flags = "";
|
||||
|
||||
switch (SUP->flags)
|
||||
switch (super->path_element->port)
|
||||
{
|
||||
case FISH_FLAG_RSH:
|
||||
flags = ":r";
|
||||
@ -1477,16 +1512,18 @@ fish_fill_names (struct vfs_class *me, fill_names_f func)
|
||||
flags = ":C";
|
||||
break;
|
||||
default:
|
||||
if (SUP->flags > FISH_FLAG_RSH)
|
||||
if (super->path_element->port > FISH_FLAG_RSH)
|
||||
{
|
||||
g_snprintf (gbuf, sizeof (gbuf), ":%d", SUP->flags);
|
||||
g_snprintf (gbuf, sizeof (gbuf), ":%d", super->path_element->port);
|
||||
flags = gbuf;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
name =
|
||||
g_strconcat ("/#sh:", SUP->user, "@", SUP->host, flags, "/", SUP->cwdir, (char *) NULL);
|
||||
g_strconcat (vfs_fish_ops.prefix, VFS_PATH_URL_DELIMITER,
|
||||
super->path_element->user, "@", super->path_element->host, flags, "/",
|
||||
super->path_element->path, (char *) NULL);
|
||||
func (name);
|
||||
g_free (name);
|
||||
}
|
||||
@ -1495,14 +1532,14 @@ fish_fill_names (struct vfs_class *me, fill_names_f func)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void *
|
||||
fish_open (struct vfs_class *me, const char *file, int flags, mode_t mode)
|
||||
fish_open (const vfs_path_t * vpath, int flags, mode_t mode)
|
||||
{
|
||||
/*
|
||||
sorry, i've places hack here
|
||||
cause fish don't able to open files with O_EXCL flag
|
||||
*/
|
||||
flags &= ~O_EXCL;
|
||||
return vfs_s_open (me, file, flags, mode);
|
||||
return vfs_s_open (vpath, flags, mode);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -1530,7 +1567,7 @@ init_fish (void)
|
||||
|
||||
vfs_s_init_class (&vfs_fish_ops, &fish_subclass);
|
||||
vfs_fish_ops.name = "fish";
|
||||
vfs_fish_ops.prefix = "sh:";
|
||||
vfs_fish_ops.prefix = "sh";
|
||||
vfs_fish_ops.fill_names = fish_fill_names;
|
||||
vfs_fish_ops.chmod = fish_chmod;
|
||||
vfs_fish_ops.chown = fish_chown;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Virtual File System: FTP file system.
|
||||
Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
||||
2006, 2007 Free Software Foundation, Inc.
|
||||
2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
1995 Ching Hui
|
||||
@ -9,6 +9,8 @@
|
||||
1997 Norbert Warmuth
|
||||
1998 Pavel Machek
|
||||
2010 Yury V. Zaytsev
|
||||
2010 Slava Zanko
|
||||
2010 Andrew Borodin
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
@ -197,11 +199,6 @@ typedef enum
|
||||
typedef struct
|
||||
{
|
||||
int sock;
|
||||
char *cwdir;
|
||||
char *host;
|
||||
char *user;
|
||||
char *password;
|
||||
int port;
|
||||
|
||||
char *proxy; /* proxy server, NULL if no proxy */
|
||||
int failed_on_login; /* used to pass the failure reason to upper levels */
|
||||
@ -322,43 +319,45 @@ ftpfs_translate_path (struct vfs_class *me, struct vfs_s_super *super, const cha
|
||||
* ftp://joe@foo.edu:11321/private
|
||||
* If the user is empty, e.g. ftp://@roxanne/private, then your login name
|
||||
* is supplied.
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
ftpfs_split_url (char *path, char **host, char **user, int *port, char **pass)
|
||||
static vfs_path_element_t *
|
||||
ftpfs_correct_url_parameters (const vfs_path_element_t * velement)
|
||||
{
|
||||
char *p;
|
||||
vfs_path_element_t *path_element = vfs_path_element_clone (velement);
|
||||
|
||||
p = vfs_split_url (path, host, user, port, pass, FTP_COMMAND_PORT, URL_USE_ANONYMOUS);
|
||||
if (path_element->port == 0)
|
||||
path_element->port = FTP_COMMAND_PORT;
|
||||
|
||||
if (!*user)
|
||||
if (path_element->user == NULL)
|
||||
{
|
||||
/* Look up user and password in netrc */
|
||||
if (ftpfs_use_netrc)
|
||||
ftpfs_netrc_lookup (*host, user, pass);
|
||||
if (!*user)
|
||||
*user = g_strdup ("anonymous");
|
||||
ftpfs_netrc_lookup (path_element->host, &path_element->user, &path_element->password);
|
||||
}
|
||||
if (path_element->user == NULL)
|
||||
path_element->user = g_strdup ("anonymous");
|
||||
|
||||
/* Look up password in netrc for known user */
|
||||
if (ftpfs_use_netrc && *user && pass && !*pass)
|
||||
if (ftpfs_use_netrc && path_element->user != NULL && path_element->password != NULL)
|
||||
{
|
||||
char *new_user;
|
||||
char *new_user = NULL;
|
||||
char *new_passwd = NULL;
|
||||
|
||||
ftpfs_netrc_lookup (*host, &new_user, pass);
|
||||
ftpfs_netrc_lookup (path_element->host, &new_user, &new_passwd);
|
||||
|
||||
/* If user is different, remove password */
|
||||
if (new_user && strcmp (*user, new_user))
|
||||
if (new_user != NULL && strcmp (path_element->user, new_user) != 0)
|
||||
{
|
||||
g_free (*pass);
|
||||
*pass = NULL;
|
||||
g_free (path_element->password);
|
||||
path_element->password = NULL;
|
||||
}
|
||||
|
||||
g_free (new_user);
|
||||
g_free (new_passwd);
|
||||
}
|
||||
|
||||
g_free (p);
|
||||
return path_element;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -414,23 +413,30 @@ ftpfs_get_reply (struct vfs_class *me, int sock, char *string_buf, int string_le
|
||||
static int
|
||||
ftpfs_reconnect (struct vfs_class *me, struct vfs_s_super *super)
|
||||
{
|
||||
int sock = ftpfs_open_socket (me, super);
|
||||
int sock;
|
||||
|
||||
sock = ftpfs_open_socket (me, super);
|
||||
if (sock != -1)
|
||||
{
|
||||
char *cwdir = SUP->cwdir;
|
||||
char *cwdir = super->path_element->path;
|
||||
|
||||
close (SUP->sock);
|
||||
SUP->sock = sock;
|
||||
SUP->cwdir = NULL;
|
||||
if (ftpfs_login_server (me, super, SUP->password))
|
||||
super->path_element->path = NULL;
|
||||
|
||||
|
||||
if (ftpfs_login_server (me, super, super->path_element->password) != 0)
|
||||
{
|
||||
if (!cwdir)
|
||||
if (cwdir == NULL)
|
||||
return 1;
|
||||
sock = ftpfs_chdir_internal (me, super, cwdir);
|
||||
g_free (cwdir);
|
||||
return sock == COMPLETE;
|
||||
return sock == COMPLETE ? 1 : 0;
|
||||
}
|
||||
SUP->cwdir = cwdir;
|
||||
|
||||
super->path_element->path = cwdir;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -532,14 +538,10 @@ ftpfs_free_archive (struct vfs_class *me, struct vfs_s_super *super)
|
||||
{
|
||||
if (SUP->sock != -1)
|
||||
{
|
||||
vfs_print_message (_("ftpfs: Disconnecting from %s"), SUP->host);
|
||||
vfs_print_message (_("ftpfs: Disconnecting from %s"), super->path_element->host);
|
||||
ftpfs_command (me, super, NONE, "QUIT");
|
||||
close (SUP->sock);
|
||||
}
|
||||
g_free (SUP->host);
|
||||
g_free (SUP->user);
|
||||
g_free (SUP->cwdir);
|
||||
g_free (SUP->password);
|
||||
g_free (super->data);
|
||||
super->data = NULL;
|
||||
}
|
||||
@ -572,13 +574,14 @@ ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char
|
||||
|
||||
SUP->isbinary = TYPE_UNKNOWN;
|
||||
|
||||
if (SUP->password != NULL) /* explicit password */
|
||||
op = g_strdup (SUP->password);
|
||||
if (super->path_element->password != NULL) /* explicit password */
|
||||
op = g_strdup (super->path_element->password);
|
||||
else if (netrcpass != NULL) /* password from netrc */
|
||||
op = g_strdup (netrcpass);
|
||||
else if (strcmp (SUP->user, "anonymous") == 0 || strcmp (SUP->user, "ftp") == 0)
|
||||
else if (strcmp (super->path_element->user, "anonymous") == 0
|
||||
|| strcmp (super->path_element->user, "ftp") == 0)
|
||||
{
|
||||
if (!ftpfs_anonymous_passwd) /* default anonymous password */
|
||||
if (ftpfs_anonymous_passwd == NULL) /* default anonymous password */
|
||||
ftpfs_init_passwd ();
|
||||
op = g_strdup (ftpfs_anonymous_passwd);
|
||||
anon = 1;
|
||||
@ -587,12 +590,12 @@ ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char
|
||||
{ /* ask user */
|
||||
char *p;
|
||||
|
||||
p = g_strdup_printf (_("FTP: Password required for %s"), SUP->user);
|
||||
p = g_strdup_printf (_("FTP: Password required for %s"), super->path_element->user);
|
||||
op = vfs_get_password (p);
|
||||
g_free (p);
|
||||
if (op == NULL)
|
||||
ERRNOR (EPERM, 0);
|
||||
SUP->password = g_strdup (op);
|
||||
super->path_element->password = g_strdup (op);
|
||||
}
|
||||
|
||||
if (!anon || MEDATA->logfile)
|
||||
@ -605,13 +608,13 @@ ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char
|
||||
|
||||
/* Proxy server accepts: username@host-we-want-to-connect */
|
||||
if (SUP->proxy)
|
||||
{
|
||||
name =
|
||||
g_strconcat (SUP->user, "@",
|
||||
SUP->host[0] == '!' ? SUP->host + 1 : SUP->host, (char *) NULL);
|
||||
}
|
||||
g_strconcat (super->path_element->user, "@",
|
||||
super->path_element->host[0] ==
|
||||
'!' ? super->path_element->host + 1 : super->path_element->host,
|
||||
(char *) NULL);
|
||||
else
|
||||
name = g_strdup (SUP->user);
|
||||
name = g_strdup (super->path_element->user);
|
||||
|
||||
if (ftpfs_get_reply (me, SUP->sock, reply_string, sizeof (reply_string) - 1) == COMPLETE)
|
||||
{
|
||||
@ -638,7 +641,8 @@ ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = g_strdup_printf (_("FTP: Account required for user %s"), SUP->user);
|
||||
p = g_strdup_printf (_("FTP: Account required for user %s"),
|
||||
super->path_element->user);
|
||||
op = input_dialog (p, _("Account:"), MC_HISTORY_FTPFS_ACCOUNT, "");
|
||||
g_free (p);
|
||||
if (op == NULL)
|
||||
@ -659,14 +663,16 @@ ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char
|
||||
|
||||
default:
|
||||
SUP->failed_on_login = 1;
|
||||
if (SUP->password)
|
||||
wipe_password (SUP->password);
|
||||
SUP->password = 0;
|
||||
wipe_password (super->path_element->password);
|
||||
super->path_element->password = NULL;
|
||||
|
||||
goto login_fail;
|
||||
}
|
||||
}
|
||||
message (D_ERROR, MSG_ERROR, _("ftpfs: Login incorrect for user %s "), SUP->user);
|
||||
|
||||
message (D_ERROR, MSG_ERROR, _("ftpfs: Login incorrect for user %s "),
|
||||
super->path_element->user);
|
||||
|
||||
login_fail:
|
||||
wipe_password (pass);
|
||||
g_free (name);
|
||||
@ -764,11 +770,12 @@ ftpfs_check_proxy (const char *host)
|
||||
static void
|
||||
ftpfs_get_proxy_host_and_port (const char *proxy, char **host, int *port)
|
||||
{
|
||||
char *user, *dir;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
dir = vfs_split_url (proxy, host, &user, port, 0, FTP_COMMAND_PORT, URL_USE_ANONYMOUS);
|
||||
g_free (user);
|
||||
g_free (dir);
|
||||
path_element = vfs_url_split (proxy, FTP_COMMAND_PORT, URL_USE_ANONYMOUS);
|
||||
*host = g_strdup (path_element->host);
|
||||
*port = path_element->port;
|
||||
vfs_path_element_free (path_element);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -779,16 +786,16 @@ ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super)
|
||||
struct addrinfo hints, *res, *curr_res;
|
||||
int my_socket = 0;
|
||||
char *host = NULL;
|
||||
char *port = NULL;
|
||||
char port[8];
|
||||
int tmp_port;
|
||||
int e;
|
||||
|
||||
(void) me;
|
||||
|
||||
/* Use a proxy host? */
|
||||
host = g_strdup (SUP->host);
|
||||
host = g_strdup (super->path_element->host);
|
||||
|
||||
if (!host || !*host)
|
||||
if (host == NULL || *host == '\0')
|
||||
{
|
||||
vfs_print_message (_("ftpfs: Invalid host name."));
|
||||
ftpfs_errno = EINVAL;
|
||||
@ -797,15 +804,13 @@ ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super)
|
||||
}
|
||||
|
||||
/* Hosts to connect to that start with a ! should use proxy */
|
||||
tmp_port = SUP->port;
|
||||
tmp_port = super->path_element->port;
|
||||
|
||||
if (SUP->proxy)
|
||||
{
|
||||
if (SUP->proxy != NULL)
|
||||
ftpfs_get_proxy_host_and_port (ftpfs_proxy_host, &host, &tmp_port);
|
||||
}
|
||||
|
||||
port = g_strdup_printf ("%hu", (unsigned short) tmp_port);
|
||||
if (port == NULL)
|
||||
g_snprintf (port, sizeof (port), "%hu", (unsigned short) tmp_port);
|
||||
if (port[0] == '\0')
|
||||
{
|
||||
g_free (host);
|
||||
ftpfs_errno = errno;
|
||||
@ -836,8 +841,7 @@ ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super)
|
||||
}
|
||||
#endif
|
||||
|
||||
g_free (port);
|
||||
port = NULL;
|
||||
*port = '\0';
|
||||
|
||||
if (e != 0)
|
||||
{
|
||||
@ -850,12 +854,10 @@ ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super)
|
||||
|
||||
for (curr_res = res; curr_res != NULL; curr_res = curr_res->ai_next)
|
||||
{
|
||||
|
||||
my_socket = socket (curr_res->ai_family, curr_res->ai_socktype, curr_res->ai_protocol);
|
||||
|
||||
if (my_socket < 0)
|
||||
{
|
||||
|
||||
if (curr_res->ai_next != NULL)
|
||||
continue;
|
||||
|
||||
@ -878,18 +880,12 @@ ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super)
|
||||
close (my_socket);
|
||||
|
||||
if (errno == EINTR && tty_got_interrupt ())
|
||||
{
|
||||
vfs_print_message (_("ftpfs: connection interrupted by user"));
|
||||
}
|
||||
else if (res->ai_next == NULL)
|
||||
{
|
||||
vfs_print_message (_("ftpfs: connection to server failed: %s"),
|
||||
unix_error_string (errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
freeaddrinfo (res);
|
||||
tty_disable_interrupt_key ();
|
||||
@ -906,13 +902,13 @@ ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super)
|
||||
static int
|
||||
ftpfs_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
|
||||
{
|
||||
int retry_seconds, count_down;
|
||||
int retry_seconds = 0;
|
||||
int count_down;
|
||||
|
||||
/* We do not want to use the passive if we are using proxies */
|
||||
if (SUP->proxy)
|
||||
SUP->use_passive_connection = ftpfs_use_passive_connections_over_proxy;
|
||||
|
||||
retry_seconds = 0;
|
||||
do
|
||||
{
|
||||
SUP->failed_on_login = 0;
|
||||
@ -921,29 +917,26 @@ ftpfs_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
|
||||
if (SUP->sock == -1)
|
||||
return -1;
|
||||
|
||||
if (ftpfs_login_server (me, super, NULL))
|
||||
if (ftpfs_login_server (me, super, NULL) != 0)
|
||||
{
|
||||
/* Logged in, no need to retry the connection */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SUP->failed_on_login)
|
||||
{
|
||||
/* Close only the socket descriptor */
|
||||
close (SUP->sock);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!SUP->failed_on_login)
|
||||
return -1;
|
||||
}
|
||||
if (ftpfs_retry_seconds)
|
||||
|
||||
/* Close only the socket descriptor */
|
||||
close (SUP->sock);
|
||||
|
||||
if (ftpfs_retry_seconds != 0)
|
||||
{
|
||||
retry_seconds = ftpfs_retry_seconds;
|
||||
tty_enable_interrupt_key ();
|
||||
for (count_down = retry_seconds; count_down; count_down--)
|
||||
{
|
||||
vfs_print_message (_("Waiting to retry... %d (Control-C to cancel)"),
|
||||
vfs_print_message (_("Waiting to retry... %d (Control-G to cancel)"),
|
||||
count_down);
|
||||
sleep (1);
|
||||
if (tty_got_interrupt ())
|
||||
@ -957,68 +950,61 @@ ftpfs_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
|
||||
}
|
||||
}
|
||||
}
|
||||
while (retry_seconds);
|
||||
while (retry_seconds != 0);
|
||||
|
||||
super->path_element->path = ftpfs_get_current_directory (me, super);
|
||||
if (super->path_element->path == NULL)
|
||||
super->path_element->path = g_strdup (PATH_SEP_STR);
|
||||
|
||||
SUP->cwdir = ftpfs_get_current_directory (me, super);
|
||||
if (!SUP->cwdir)
|
||||
SUP->cwdir = g_strdup (PATH_SEP_STR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
ftpfs_open_archive (struct vfs_class *me, struct vfs_s_super *super,
|
||||
const char *archive_name, char *op)
|
||||
ftpfs_open_archive (struct vfs_s_super *super,
|
||||
const vfs_path_t * vpath, const vfs_path_element_t * vpath_element)
|
||||
{
|
||||
char *host, *user, *password;
|
||||
int port;
|
||||
|
||||
(void) archive_name;
|
||||
|
||||
ftpfs_split_url (strchr (op, ':') + 1, &host, &user, &port, &password);
|
||||
(void) vpath;
|
||||
|
||||
super->data = g_new0 (ftp_super_data_t, 1);
|
||||
SUP->host = host;
|
||||
SUP->user = user;
|
||||
SUP->port = port;
|
||||
SUP->cwdir = NULL;
|
||||
SUP->proxy = 0;
|
||||
if (ftpfs_check_proxy (host))
|
||||
|
||||
super->path_element = ftpfs_correct_url_parameters (vpath_element);
|
||||
SUP->proxy = NULL;
|
||||
if (ftpfs_check_proxy (super->path_element->host))
|
||||
SUP->proxy = ftpfs_proxy_host;
|
||||
SUP->password = password;
|
||||
SUP->use_passive_connection = ftpfs_use_passive_connections;
|
||||
SUP->strict = ftpfs_use_unix_list_options ? RFC_AUTODETECT : RFC_STRICT;
|
||||
SUP->isbinary = TYPE_UNKNOWN;
|
||||
SUP->remote_is_amiga = 0;
|
||||
super->name = g_strdup ("/");
|
||||
super->root = vfs_s_new_inode (me, super, vfs_s_default_stat (me, S_IFDIR | 0755));
|
||||
super->root =
|
||||
vfs_s_new_inode (vpath_element->class, super,
|
||||
vfs_s_default_stat (vpath_element->class, S_IFDIR | 0755));
|
||||
|
||||
return ftpfs_open_archive_int (me, super);
|
||||
return ftpfs_open_archive_int (vpath_element->class, super);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
ftpfs_archive_same (struct vfs_class *me, struct vfs_s_super *super,
|
||||
const char *archive_name, char *op, void *cookie)
|
||||
ftpfs_archive_same (const vfs_path_element_t * vpath_element, struct vfs_s_super *super,
|
||||
const vfs_path_t * vpath, void *cookie)
|
||||
{
|
||||
char *host, *user;
|
||||
int port;
|
||||
vfs_path_element_t *path_element;
|
||||
int result;
|
||||
|
||||
(void) me;
|
||||
(void) archive_name;
|
||||
(void) vpath;
|
||||
(void) cookie;
|
||||
|
||||
ftpfs_split_url (strchr (op, ':') + 1, &host, &user, &port, 0);
|
||||
path_element = ftpfs_correct_url_parameters (vpath_element);
|
||||
|
||||
port = ((strcmp (host, SUP->host) == 0) && (strcmp (user, SUP->user) == 0)
|
||||
&& (port == SUP->port));
|
||||
result = ((strcmp (path_element->host, super->path_element->host) == 0)
|
||||
&& (strcmp (path_element->user, super->path_element->user) == 0)
|
||||
&& (path_element->port == super->path_element->port)) ? 1 : 0;
|
||||
|
||||
g_free (host);
|
||||
g_free (user);
|
||||
|
||||
return port;
|
||||
vfs_path_element_free (path_element);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -1149,10 +1135,7 @@ ftpfs_setup_passive_epsv (struct vfs_class *me, struct vfs_s_super *super,
|
||||
break;
|
||||
}
|
||||
|
||||
if (connect (my_socket, (struct sockaddr *) sa, *salen) < 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
return (connect (my_socket, (struct sockaddr *) sa, *salen) < 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -1292,8 +1275,8 @@ ftpfs_init_data_socket (struct vfs_class *me, struct vfs_s_super *super,
|
||||
vfs_print_message (_("ftpfs: could not create socket: %s"), unix_error_string (errno));
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -1315,8 +1298,8 @@ ftpfs_initconn (struct vfs_class *me, struct vfs_s_super *super)
|
||||
if (SUP->use_passive_connection)
|
||||
{
|
||||
int data_sock;
|
||||
data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
|
||||
|
||||
data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
|
||||
if (data_sock < 0)
|
||||
return -1;
|
||||
|
||||
@ -1333,24 +1316,22 @@ ftpfs_initconn (struct vfs_class *me, struct vfs_s_super *super)
|
||||
if (!SUP->use_passive_connection)
|
||||
{
|
||||
int data_sock;
|
||||
data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
|
||||
|
||||
data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
|
||||
if (data_sock < 0)
|
||||
return -1;
|
||||
|
||||
if ((bind (data_sock, (struct sockaddr *) &data_addr, data_addrlen) == 0) &&
|
||||
(getsockname (data_sock, (struct sockaddr *) &data_addr, &data_addrlen) == 0) &&
|
||||
(listen (data_sock, 1) == 0))
|
||||
{
|
||||
if (ftpfs_setup_active (me, super, data_addr, data_addrlen))
|
||||
return data_sock;
|
||||
}
|
||||
(listen (data_sock, 1) == 0) &&
|
||||
(ftpfs_setup_active (me, super, data_addr, data_addrlen) != 0))
|
||||
return data_sock;
|
||||
|
||||
close (data_sock);
|
||||
}
|
||||
|
||||
/* Restore the initial value of use_passive_connection (for subsequent retries) */
|
||||
SUP->use_passive_connection = SUP->proxy ? ftpfs_use_passive_connections_over_proxy :
|
||||
SUP->use_passive_connection = SUP->proxy != NULL ? ftpfs_use_passive_connections_over_proxy :
|
||||
ftpfs_use_passive_connections;
|
||||
|
||||
ftpfs_errno = EIO;
|
||||
@ -1413,7 +1394,7 @@ ftpfs_open_data_connection (struct vfs_class *me, struct vfs_s_super *super, con
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
ftpfs_linear_abort (struct vfs_class *me, vfs_file_handler_t *fh)
|
||||
ftpfs_linear_abort (struct vfs_class *me, vfs_file_handler_t * fh)
|
||||
{
|
||||
struct vfs_s_super *super = FH_SUPER;
|
||||
static unsigned char const ipbuf[3] = { IAC, IP, IAC };
|
||||
@ -1786,7 +1767,7 @@ ftpfs_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
ftpfs_file_store (struct vfs_class *me, vfs_file_handler_t *fh, char *name, char *localname)
|
||||
ftpfs_file_store (struct vfs_class *me, vfs_file_handler_t * fh, char *name, char *localname)
|
||||
{
|
||||
int h, sock, n_read, n_written;
|
||||
off_t n_stored;
|
||||
@ -1877,7 +1858,7 @@ ftpfs_file_store (struct vfs_class *me, vfs_file_handler_t *fh, char *name, char
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
ftpfs_linear_start (struct vfs_class *me, vfs_file_handler_t *fh, off_t offset)
|
||||
ftpfs_linear_start (struct vfs_class *me, vfs_file_handler_t * fh, off_t offset)
|
||||
{
|
||||
char *name;
|
||||
|
||||
@ -1900,7 +1881,7 @@ ftpfs_linear_start (struct vfs_class *me, vfs_file_handler_t *fh, off_t offset)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
ftpfs_linear_read (struct vfs_class *me, vfs_file_handler_t *fh, void *buf, size_t len)
|
||||
ftpfs_linear_read (struct vfs_class *me, vfs_file_handler_t * fh, void *buf, size_t len)
|
||||
{
|
||||
ssize_t n;
|
||||
struct vfs_s_super *super = FH_SUPER;
|
||||
@ -1930,7 +1911,7 @@ ftpfs_linear_read (struct vfs_class *me, vfs_file_handler_t *fh, void *buf, size
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
ftpfs_linear_close (struct vfs_class *me, vfs_file_handler_t *fh)
|
||||
ftpfs_linear_close (struct vfs_class *me, vfs_file_handler_t * fh)
|
||||
{
|
||||
if (FH_SOCK != -1)
|
||||
ftpfs_linear_abort (me, fh);
|
||||
@ -1965,50 +1946,49 @@ ftpfs_ctl (void *fh, int ctlop, void *arg)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
ftpfs_send_command (struct vfs_class *me, const char *filename, const char *cmd, int flags)
|
||||
ftpfs_send_command (const vfs_path_t * vpath, const char *cmd, int flags)
|
||||
{
|
||||
const char *rpath;
|
||||
char *p, *mpath;
|
||||
char *p;
|
||||
struct vfs_s_super *super;
|
||||
int r;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
int flush_directory_cache = (flags & OPT_FLUSH);
|
||||
|
||||
mpath = g_strdup (filename);
|
||||
rpath = vfs_s_get_path_mangle (me, mpath, &super, 0);
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
rpath = vfs_s_get_path (vpath, &super, 0);
|
||||
if (rpath == NULL)
|
||||
{
|
||||
g_free (mpath);
|
||||
return -1;
|
||||
}
|
||||
p = ftpfs_translate_path (me, super, rpath);
|
||||
r = ftpfs_command (me, super, WAIT_REPLY, cmd, p);
|
||||
|
||||
p = ftpfs_translate_path (path_element->class, super, rpath);
|
||||
r = ftpfs_command (path_element->class, super, WAIT_REPLY, cmd, p);
|
||||
g_free (p);
|
||||
vfs_stamp_create (&vfs_ftpfs_ops, super);
|
||||
if (flags & OPT_IGNORE_ERROR)
|
||||
r = COMPLETE;
|
||||
if (r != COMPLETE)
|
||||
{
|
||||
me->verrno = EPERM;
|
||||
g_free (mpath);
|
||||
path_element->class->verrno = EPERM;
|
||||
return -1;
|
||||
}
|
||||
if (flush_directory_cache)
|
||||
vfs_s_invalidate (me, super);
|
||||
g_free (mpath);
|
||||
vfs_s_invalidate (path_element->class, super);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
ftpfs_chmod (struct vfs_class *me, const char *path, int mode)
|
||||
ftpfs_chmod (const vfs_path_t * vpath, int mode)
|
||||
{
|
||||
char buf[BUF_SMALL];
|
||||
int ret;
|
||||
|
||||
g_snprintf (buf, sizeof (buf), "SITE CHMOD %4.4o /%%s", mode & 07777);
|
||||
|
||||
ret = ftpfs_send_command (me, path, buf, OPT_FLUSH);
|
||||
ret = ftpfs_send_command (vpath, buf, OPT_FLUSH);
|
||||
|
||||
return ftpfs_ignore_chattr_errors ? 0 : ret;
|
||||
}
|
||||
@ -2016,16 +1996,19 @@ ftpfs_chmod (struct vfs_class *me, const char *path, int mode)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
ftpfs_chown (struct vfs_class *me, const char *path, uid_t owner, gid_t group)
|
||||
ftpfs_chown (const vfs_path_t * vpath, uid_t owner, gid_t group)
|
||||
{
|
||||
#if 0
|
||||
(void) vpath;
|
||||
(void) owner;
|
||||
(void) group;
|
||||
|
||||
ftpfs_errno = EPERM;
|
||||
return -1;
|
||||
#else
|
||||
/* Everyone knows it is not possible to chown remotely, so why bother them.
|
||||
If someone's root, then copy/move will always try to chown it... */
|
||||
(void) me;
|
||||
(void) path;
|
||||
(void) vpath;
|
||||
(void) owner;
|
||||
(void) group;
|
||||
return 0;
|
||||
@ -2035,9 +2018,9 @@ ftpfs_chown (struct vfs_class *me, const char *path, uid_t owner, gid_t group)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
ftpfs_unlink (struct vfs_class *me, const char *path)
|
||||
ftpfs_unlink (const vfs_path_t * vpath)
|
||||
{
|
||||
return ftpfs_send_command (me, path, "DELE /%s", OPT_FLUSH);
|
||||
return ftpfs_send_command (vpath, "DELE /%s", OPT_FLUSH);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -2048,11 +2031,9 @@ ftpfs_is_same_dir (struct vfs_class *me, struct vfs_s_super *super, const char *
|
||||
{
|
||||
(void) me;
|
||||
|
||||
if (!SUP->cwdir)
|
||||
return 0;
|
||||
if (strcmp (path, SUP->cwdir) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
if (super->path_element->path == NULL)
|
||||
return FALSE;
|
||||
return (strcmp (path, super->path_element->path) == 0);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -2071,13 +2052,11 @@ ftpfs_chdir_internal (struct vfs_class *me, struct vfs_s_super *super, const cha
|
||||
g_free (p);
|
||||
|
||||
if (r != COMPLETE)
|
||||
{
|
||||
ftpfs_errno = EIO;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free (SUP->cwdir);
|
||||
SUP->cwdir = g_strdup (remote_path);
|
||||
g_free (super->path_element->path);
|
||||
super->path_element->path = g_strdup (remote_path);
|
||||
SUP->cwd_deferred = 0;
|
||||
}
|
||||
return r;
|
||||
@ -2086,34 +2065,34 @@ ftpfs_chdir_internal (struct vfs_class *me, struct vfs_s_super *super, const cha
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
ftpfs_rename (struct vfs_class *me, const char *path1, const char *path2)
|
||||
ftpfs_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
|
||||
{
|
||||
ftpfs_send_command (me, path1, "RNFR /%s", OPT_FLUSH);
|
||||
return ftpfs_send_command (me, path2, "RNTO /%s", OPT_FLUSH);
|
||||
ftpfs_send_command (vpath1, "RNFR /%s", OPT_FLUSH);
|
||||
return ftpfs_send_command (vpath2, "RNTO /%s", OPT_FLUSH);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
ftpfs_mkdir (struct vfs_class *me, const char *path, mode_t mode)
|
||||
ftpfs_mkdir (const vfs_path_t * vpath, mode_t mode)
|
||||
{
|
||||
(void) mode; /* FIXME: should be used */
|
||||
|
||||
return ftpfs_send_command (me, path, "MKD /%s", OPT_FLUSH);
|
||||
return ftpfs_send_command (vpath, "MKD /%s", OPT_FLUSH);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
ftpfs_rmdir (struct vfs_class *me, const char *path)
|
||||
ftpfs_rmdir (const vfs_path_t * vpath)
|
||||
{
|
||||
return ftpfs_send_command (me, path, "RMD /%s", OPT_FLUSH);
|
||||
return ftpfs_send_command (vpath, "RMD /%s", OPT_FLUSH);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
ftpfs_fh_open (struct vfs_class *me, vfs_file_handler_t *fh, int flags, mode_t mode)
|
||||
ftpfs_fh_open (struct vfs_class *me, vfs_file_handler_t * fh, int flags, mode_t mode)
|
||||
{
|
||||
ftp_fh_data_t *ftp;
|
||||
|
||||
@ -2187,7 +2166,7 @@ ftpfs_fh_open (struct vfs_class *me, vfs_file_handler_t *fh, int flags, mode_t m
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
ftpfs_fh_close (struct vfs_class *me, vfs_file_handler_t *fh)
|
||||
ftpfs_fh_close (struct vfs_class *me, vfs_file_handler_t * fh)
|
||||
{
|
||||
if (fh->handle != -1 && !fh->ino->localname)
|
||||
{
|
||||
@ -2235,7 +2214,10 @@ ftpfs_fill_names (struct vfs_class *me, fill_names_f func)
|
||||
const struct vfs_s_super *super = (const struct vfs_s_super *) iter->data;
|
||||
char *name;
|
||||
|
||||
name = g_strconcat ("/#ftp:", SUP->user, "@", SUP->host, "/", SUP->cwdir, (char *) NULL);
|
||||
name =
|
||||
g_strconcat (vfs_ftpfs_ops.prefix, VFS_PATH_URL_DELIMITER, super->path_element->user,
|
||||
"@", super->path_element->host, "/", super->path_element->path,
|
||||
(char *) NULL);
|
||||
func (name);
|
||||
g_free (name);
|
||||
}
|
||||
@ -2252,7 +2234,6 @@ ftpfs_netrc_next (void)
|
||||
"login", "password", "passwd", "account", "macdef", NULL
|
||||
};
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
netrcp = skip_separators (netrcp);
|
||||
@ -2286,15 +2267,10 @@ ftpfs_netrc_next (void)
|
||||
if (!*buffer)
|
||||
return NETRC_NONE;
|
||||
|
||||
i = NETRC_DEFAULT;
|
||||
while (keywords[i - 1])
|
||||
{
|
||||
if (!strcmp (keywords[i - 1], buffer))
|
||||
for (i = NETRC_DEFAULT; keywords[i - 1] != NULL; i++)
|
||||
if (strcmp (keywords[i - 1], buffer) == 0)
|
||||
return i;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return NETRC_UNKNOWN;
|
||||
}
|
||||
|
||||
@ -2407,11 +2383,10 @@ ftpfs_netrc_lookup (const char *host, char **login, char **pass)
|
||||
} *rup_cache = NULL, *rupp;
|
||||
|
||||
/* Initialize *login and *pass */
|
||||
if (!login)
|
||||
return 0;
|
||||
g_free (*login);
|
||||
*login = NULL;
|
||||
if (pass)
|
||||
*pass = NULL;
|
||||
g_free (*pass);
|
||||
*pass = NULL;
|
||||
|
||||
/* Look up in the cache first */
|
||||
for (rupp = rup_cache; rupp != NULL; rupp = rupp->next)
|
||||
@ -2521,19 +2496,13 @@ ftpfs_netrc_lookup (const char *host, char **login, char **pass)
|
||||
|
||||
rupp = g_new (struct rupcache, 1);
|
||||
rupp->host = g_strdup (host);
|
||||
rupp->login = rupp->pass = 0;
|
||||
rupp->login = g_strdup (*login);
|
||||
rupp->pass = g_strdup (tmp_pass);
|
||||
|
||||
if (*login != NULL)
|
||||
{
|
||||
rupp->login = g_strdup (*login);
|
||||
}
|
||||
if (tmp_pass != NULL)
|
||||
rupp->pass = g_strdup (tmp_pass);
|
||||
rupp->next = rup_cache;
|
||||
rup_cache = rupp;
|
||||
|
||||
if (pass)
|
||||
*pass = tmp_pass;
|
||||
*pass = tmp_pass;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2585,7 +2554,7 @@ init_ftpfs (void)
|
||||
vfs_s_init_class (&vfs_ftpfs_ops, &ftpfs_subclass);
|
||||
vfs_ftpfs_ops.name = "ftpfs";
|
||||
vfs_ftpfs_ops.flags = VFSF_NOLINKS;
|
||||
vfs_ftpfs_ops.prefix = "ftp:";
|
||||
vfs_ftpfs_ops.prefix = "ftp";
|
||||
vfs_ftpfs_ops.done = &ftpfs_done;
|
||||
vfs_ftpfs_ops.fill_names = ftpfs_fill_names;
|
||||
vfs_ftpfs_ops.chmod = ftpfs_chmod;
|
||||
|
@ -59,14 +59,13 @@ static struct vfs_class vfs_local_ops;
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void *
|
||||
local_open (struct vfs_class *me, const char *file, int flags, mode_t mode)
|
||||
local_open (const vfs_path_t * vpath, int flags, mode_t mode)
|
||||
{
|
||||
int *local_info;
|
||||
int fd;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
(void) me;
|
||||
|
||||
fd = open (file, NO_LINEAR (flags), mode);
|
||||
fd = open (path_element->path, NO_LINEAR (flags), mode);
|
||||
if (fd == -1)
|
||||
return 0;
|
||||
|
||||
@ -79,14 +78,13 @@ local_open (struct vfs_class *me, const char *file, int flags, mode_t mode)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void *
|
||||
local_opendir (struct vfs_class *me, const char *dirname)
|
||||
local_opendir (const vfs_path_t * vpath)
|
||||
{
|
||||
DIR **local_info;
|
||||
DIR *dir;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
(void) me;
|
||||
|
||||
dir = opendir (dirname);
|
||||
dir = opendir (path_element->path);
|
||||
if (!dir)
|
||||
return 0;
|
||||
|
||||
@ -119,85 +117,86 @@ local_closedir (void *data)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
local_stat (struct vfs_class *me, const char *path, struct stat *buf)
|
||||
local_stat (const vfs_path_t * vpath, struct stat *buf)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
return stat (path, buf);
|
||||
return stat (path_element->path, buf);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
local_lstat (struct vfs_class *me, const char *path, struct stat *buf)
|
||||
local_lstat (const vfs_path_t * vpath, struct stat *buf)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
#ifndef HAVE_STATLSTAT
|
||||
return lstat (path, buf);
|
||||
return lstat (path_element->path, buf);
|
||||
#else
|
||||
return statlstat (path, buf);
|
||||
return statlstat (path_element->path, buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
local_chmod (struct vfs_class *me, const char *path, int mode)
|
||||
local_chmod (const vfs_path_t * vpath, int mode)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
return chmod (path, mode);
|
||||
return chmod (path_element->path, mode);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
local_chown (struct vfs_class *me, const char *path, uid_t owner, gid_t group)
|
||||
local_chown (const vfs_path_t * vpath, uid_t owner, gid_t group)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
return chown (path, owner, group);
|
||||
return chown (path_element->path, owner, group);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
local_utime (struct vfs_class *me, const char *path, struct utimbuf *times)
|
||||
local_utime (const vfs_path_t * vpath, struct utimbuf *times)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
return utime (path, times);
|
||||
return utime (path_element->path, times);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
local_readlink (struct vfs_class *me, const char *path, char *buf, size_t size)
|
||||
local_readlink (const vfs_path_t * vpath, char *buf, size_t size)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
return readlink (path, buf, size);
|
||||
return readlink (path_element->path, buf, size);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
local_unlink (struct vfs_class *me, const char *path)
|
||||
local_unlink (const vfs_path_t * vpath)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
return unlink (path);
|
||||
return unlink (path_element->path);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
local_symlink (struct vfs_class *me, const char *n1, const char *n2)
|
||||
local_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element1 = vfs_path_get_by_index (vpath1, -1);
|
||||
vfs_path_element_t *path_element2 = vfs_path_get_by_index (vpath2, -1);
|
||||
|
||||
return symlink (n1, n2);
|
||||
return symlink (path_element1->path, path_element2->path);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -230,80 +229,81 @@ local_write (void *data, const char *buf, size_t nbyte)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
local_rename (struct vfs_class *me, const char *a, const char *b)
|
||||
local_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element1 = vfs_path_get_by_index (vpath1, -1);
|
||||
vfs_path_element_t *path_element2 = vfs_path_get_by_index (vpath2, -1);
|
||||
|
||||
return rename (a, b);
|
||||
return rename (path_element1->path, path_element2->path);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
local_chdir (struct vfs_class *me, const char *path)
|
||||
local_chdir (const vfs_path_t * vpath)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
return chdir (path);
|
||||
return chdir (path_element->path);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
local_mknod (struct vfs_class *me, const char *path, mode_t mode, dev_t dev)
|
||||
local_mknod (const vfs_path_t * vpath, mode_t mode, dev_t dev)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
return mknod (path, mode, dev);
|
||||
return mknod (path_element->path, mode, dev);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
local_link (struct vfs_class *me, const char *p1, const char *p2)
|
||||
local_link (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element1 = vfs_path_get_by_index (vpath1, -1);
|
||||
vfs_path_element_t *path_element2 = vfs_path_get_by_index (vpath2, -1);
|
||||
|
||||
return link (p1, p2);
|
||||
return link (path_element1->path, path_element2->path);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
local_mkdir (struct vfs_class *me, const char *path, mode_t mode)
|
||||
local_mkdir (const vfs_path_t * vpath, mode_t mode)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
return mkdir (path, mode);
|
||||
return mkdir (path_element->path, mode);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
local_rmdir (struct vfs_class *me, const char *path)
|
||||
local_rmdir (const vfs_path_t * vpath)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
return rmdir (path);
|
||||
return rmdir (path_element->path);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static char *
|
||||
local_getlocalcopy (struct vfs_class *me, const char *path)
|
||||
local_getlocalcopy (const vfs_path_t * vpath)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
return g_strdup (path);
|
||||
return g_strdup (path_element->path);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
local_ungetlocalcopy (struct vfs_class *me, const char *path, const char *local, int has_changed)
|
||||
local_ungetlocalcopy (const vfs_path_t * vpath, const char *local, int has_changed)
|
||||
{
|
||||
(void) me;
|
||||
(void) path;
|
||||
(void) vpath;
|
||||
(void) local;
|
||||
(void) has_changed;
|
||||
|
||||
|
@ -50,7 +50,7 @@
|
||||
#include "lib/vfs/vfs.h"
|
||||
#include "lib/vfs/utilvfs.h"
|
||||
#include "src/vfs/local/local.h"
|
||||
#include "lib/vfs/gc.h" /* vfs_stamp_create */
|
||||
#include "lib/vfs/gc.h" /* vfs_stamp_create */
|
||||
|
||||
#include "sfs.h"
|
||||
|
||||
@ -118,19 +118,19 @@ cachedfile_compare (const void *a, const void *b)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
sfs_vfmake (struct vfs_class *me, const char *name, char *cache)
|
||||
sfs_vfmake (const vfs_path_t * vpath, char *cache)
|
||||
{
|
||||
char *inpath, *op;
|
||||
int w;
|
||||
char pad[10240];
|
||||
char *s, *t = pad;
|
||||
int was_percent = 0;
|
||||
char *pname; /* name of parent archive */
|
||||
char *pqname; /* name of parent archive, quoted */
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
pname = g_strdup (name);
|
||||
vfs_split (pname, &inpath, &op);
|
||||
w = (*me->which) (me, op);
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
pname = vfs_path_to_str_elements_count (vpath, -1);
|
||||
w = (*path_element->class->which) (path_element->class, path_element->vfs_prefix);
|
||||
if (w == -1)
|
||||
vfs_die ("This cannot happen... Hopefully.\n");
|
||||
|
||||
@ -173,7 +173,7 @@ sfs_vfmake (struct vfs_class *me, const char *name, char *cache)
|
||||
ptr = pqname;
|
||||
break;
|
||||
case '2':
|
||||
ptr = op + strlen (sfs_prefix[w]);
|
||||
ptr = path_element->path;
|
||||
break;
|
||||
case '3':
|
||||
ptr = cache;
|
||||
@ -208,32 +208,37 @@ sfs_vfmake (struct vfs_class *me, const char *name, char *cache)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static const char *
|
||||
sfs_redirect (struct vfs_class *me, const char *name)
|
||||
sfs_redirect (const vfs_path_t * vpath)
|
||||
{
|
||||
GSList *cur;
|
||||
cachedfile *cf;
|
||||
char *cache;
|
||||
int handle;
|
||||
vfs_path_element_t *path_element;
|
||||
char *path = vfs_path_to_str (vpath);
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
cur = g_slist_find_custom (head, path, cachedfile_compare);
|
||||
g_free (path);
|
||||
|
||||
cur = g_slist_find_custom (head, name, cachedfile_compare);
|
||||
if (cur != NULL)
|
||||
{
|
||||
cf = (cachedfile *) cur->data;
|
||||
vfs_stamp (&vfs_sfs_ops, cf);
|
||||
return cf->cache;
|
||||
}
|
||||
cf = (cachedfile *) cur->data;
|
||||
vfs_stamp (&vfs_sfs_ops, cf);
|
||||
return cf->cache;
|
||||
}
|
||||
|
||||
handle = vfs_mkstemps (&cache, "sfs", name);
|
||||
handle = vfs_mkstemps (&cache, "sfs", path_element->path);
|
||||
|
||||
if (handle == -1)
|
||||
return "/SOMEONE_PLAYING_DIRTY_TMP_TRICKS_ON_US";
|
||||
|
||||
close (handle);
|
||||
|
||||
if (sfs_vfmake (me, name, cache) == 0)
|
||||
if (sfs_vfmake (vpath, cache) == 0)
|
||||
{
|
||||
cf = g_new (cachedfile, 1);
|
||||
cf->name = g_strdup (name);
|
||||
cf->name = vfs_path_to_str (vpath);
|
||||
cf->cache = cache;
|
||||
head = g_slist_prepend (head, cf);
|
||||
|
||||
@ -249,13 +254,13 @@ sfs_redirect (struct vfs_class *me, const char *name)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void *
|
||||
sfs_open (struct vfs_class *me, const char *path, int flags, mode_t mode)
|
||||
sfs_open (const vfs_path_t * vpath /*struct vfs_class *me, const char *path */ , int flags,
|
||||
mode_t mode)
|
||||
{
|
||||
int *sfs_info;
|
||||
int fd;
|
||||
|
||||
path = sfs_redirect (me, path);
|
||||
fd = open (path, NO_LINEAR (flags), mode);
|
||||
fd = open (sfs_redirect (vpath), NO_LINEAR (flags), mode);
|
||||
if (fd == -1)
|
||||
return 0;
|
||||
|
||||
@ -268,71 +273,65 @@ sfs_open (struct vfs_class *me, const char *path, int flags, mode_t mode)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
sfs_stat (struct vfs_class *me, const char *path, struct stat *buf)
|
||||
sfs_stat (const vfs_path_t * vpath, struct stat *buf)
|
||||
{
|
||||
path = sfs_redirect (me, path);
|
||||
return stat (path, buf);
|
||||
return stat (sfs_redirect (vpath), buf);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
sfs_lstat (struct vfs_class *me, const char *path, struct stat *buf)
|
||||
sfs_lstat (const vfs_path_t * vpath, struct stat *buf)
|
||||
{
|
||||
path = sfs_redirect (me, path);
|
||||
#ifndef HAVE_STATLSTAT
|
||||
return lstat (path, buf);
|
||||
return lstat (sfs_redirect (vpath), buf);
|
||||
#else
|
||||
return statlstat (path, buf);
|
||||
return statlstat (sfs_redirect (vpath), buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
sfs_chmod (struct vfs_class *me, const char *path, int mode)
|
||||
sfs_chmod (const vfs_path_t * vpath, int mode)
|
||||
{
|
||||
path = sfs_redirect (me, path);
|
||||
return chmod (path, mode);
|
||||
return chmod (sfs_redirect (vpath), mode);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
sfs_chown (struct vfs_class *me, const char *path, uid_t owner, gid_t group)
|
||||
sfs_chown (const vfs_path_t * vpath, uid_t owner, gid_t group)
|
||||
{
|
||||
path = sfs_redirect (me, path);
|
||||
return chown (path, owner, group);
|
||||
return chown (sfs_redirect (vpath), owner, group);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
sfs_utime (struct vfs_class *me, const char *path, struct utimbuf *times)
|
||||
sfs_utime (const vfs_path_t * vpath, struct utimbuf *times)
|
||||
{
|
||||
path = sfs_redirect (me, path);
|
||||
return utime (path, times);
|
||||
return utime (sfs_redirect (vpath), times);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
sfs_readlink (struct vfs_class *me, const char *path, char *buf, size_t size)
|
||||
sfs_readlink (const vfs_path_t * vpath, char *buf, size_t size)
|
||||
{
|
||||
path = sfs_redirect (me, path);
|
||||
return readlink (path, buf, size);
|
||||
return readlink (sfs_redirect (vpath), buf, size);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static vfsid
|
||||
sfs_getid (struct vfs_class *me, const char *path)
|
||||
sfs_getid (const vfs_path_t * vpath)
|
||||
{
|
||||
GSList *cur;
|
||||
|
||||
(void) me;
|
||||
char *path = vfs_path_to_str (vpath);
|
||||
|
||||
cur = g_slist_find_custom (head, path, cachedfile_compare);
|
||||
g_free (path);
|
||||
|
||||
return (vfsid) (cur != NULL ? cur->data : NULL);
|
||||
}
|
||||
@ -348,7 +347,7 @@ sfs_free (vfsid id)
|
||||
which = (struct cachedfile *) id;
|
||||
cur = g_slist_find (head, which);
|
||||
if (cur == NULL)
|
||||
vfs_die ("Free of thing which is unknown to me\n");
|
||||
vfs_die ("Free of thing which is unknown to me\n");
|
||||
|
||||
which = (struct cachedfile *) cur->data;
|
||||
unlink (which->cache);
|
||||
@ -386,19 +385,17 @@ sfs_nothingisopen (vfsid id)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static char *
|
||||
sfs_getlocalcopy (struct vfs_class *me, const char *path)
|
||||
sfs_getlocalcopy (const vfs_path_t * vpath)
|
||||
{
|
||||
path = sfs_redirect (me, path);
|
||||
return g_strdup (path);
|
||||
return g_strdup (sfs_redirect (vpath));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
sfs_ungetlocalcopy (struct vfs_class *me, const char *path, const char *local, int has_changed)
|
||||
sfs_ungetlocalcopy (const vfs_path_t * vpath, const char *local, int has_changed)
|
||||
{
|
||||
(void) me;
|
||||
(void) path;
|
||||
(void) vpath;
|
||||
(void) local;
|
||||
(void) has_changed;
|
||||
return 0;
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
/*** declarations of public functions ************************************************************/
|
||||
|
||||
void init_sfs(void);
|
||||
void init_sfs (void);
|
||||
|
||||
/*** inline functions ****************************************************************************/
|
||||
|
||||
|
@ -84,11 +84,6 @@ extern FILE *dbf;
|
||||
#define CNV_LANG(s) dos_to_unix(s,False)
|
||||
#define GNAL_VNC(s) unix_to_dos(s,False)
|
||||
|
||||
/* Extract the hostname and username from the path */
|
||||
/* path is in the form: [user@]hostname/share/remote-dir */
|
||||
#define smbfs_get_host_and_username(path, host, user, port, pass) \
|
||||
vfs_split_url (*path, host, user, port, pass, SMB_PORT, 0)
|
||||
|
||||
#define smbfs_lstat smbfs_stat /* no symlinks on smb filesystem? */
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
@ -124,7 +119,7 @@ typedef struct
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
static const char *const IPC = "IPC$";
|
||||
static const char *const URL_HEADER = "/#smb:";
|
||||
static const char *const URL_HEADER = "smb" VFS_PATH_URL_DELIMITER;
|
||||
|
||||
static int my_errno;
|
||||
static uint32 err;
|
||||
@ -969,11 +964,11 @@ smbfs_closedir (void *info)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
smbfs_chmod (struct vfs_class *me, const char *path, int mode)
|
||||
smbfs_chmod (const vfs_path_t * vpath, int mode)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
DEBUG (3, ("smbfs_chmod(path:%s, mode:%d)\n", path, mode));
|
||||
DEBUG (3, ("smbfs_chmod(path:%s, mode:%d)\n", path_element->path, mode));
|
||||
/* my_errno = EOPNOTSUPP;
|
||||
return -1; *//* cannot chmod on smb filesystem */
|
||||
return 0; /* make mc happy */
|
||||
@ -982,11 +977,11 @@ smbfs_chmod (struct vfs_class *me, const char *path, int mode)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
smbfs_chown (struct vfs_class *me, const char *path, uid_t owner, gid_t group)
|
||||
smbfs_chown (const vfs_path_t * vpath, uid_t owner, gid_t group)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
DEBUG (3, ("smbfs_chown(path:%s, owner:%d, group:%d)\n", path, owner, group));
|
||||
DEBUG (3, ("smbfs_chown(path:%s, owner:%d, group:%d)\n", path_element->path, owner, group));
|
||||
my_errno = EOPNOTSUPP; /* ready for your labotomy? */
|
||||
return -1;
|
||||
}
|
||||
@ -994,12 +989,12 @@ smbfs_chown (struct vfs_class *me, const char *path, uid_t owner, gid_t group)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
smbfs_utime (struct vfs_class *me, const char *path, struct utimbuf *times)
|
||||
smbfs_utime (const vfs_path_t * vpath, struct utimbuf *times)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
(void) times;
|
||||
|
||||
DEBUG (3, ("smbfs_utime(path:%s)\n", path));
|
||||
DEBUG (3, ("smbfs_utime(path:%s)\n", path_element->path));
|
||||
my_errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
||||
@ -1007,11 +1002,11 @@ smbfs_utime (struct vfs_class *me, const char *path, struct utimbuf *times)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
smbfs_readlink (struct vfs_class *me, const char *path, char *buf, size_t size)
|
||||
smbfs_readlink (const vfs_path_t * vpath, char *buf, size_t size)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
DEBUG (3, ("smbfs_readlink(path:%s, buf:%s, size:%zu)\n", path, buf, size));
|
||||
DEBUG (3, ("smbfs_readlink(path:%s, buf:%s, size:%zu)\n", path_element->path, buf, size));
|
||||
my_errno = EOPNOTSUPP;
|
||||
return -1; /* no symlinks on smb filesystem? */
|
||||
}
|
||||
@ -1019,11 +1014,12 @@ smbfs_readlink (struct vfs_class *me, const char *path, char *buf, size_t size)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
smbfs_symlink (struct vfs_class *me, const char *n1, const char *n2)
|
||||
smbfs_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element1 = vfs_path_get_by_index (vpath1, -1);
|
||||
vfs_path_element_t *path_element2 = vfs_path_get_by_index (vpath2, -1);
|
||||
|
||||
DEBUG (3, ("smbfs_symlink(n1:%s, n2:%s)\n", n1, n2));
|
||||
DEBUG (3, ("smbfs_symlink(n1:%s, n2:%s)\n", path_element1->path, path_element2->path));
|
||||
my_errno = EOPNOTSUPP;
|
||||
return -1; /* no symlinks on smb filesystem? */
|
||||
}
|
||||
@ -1322,44 +1318,50 @@ smbfs_open_link (char *host, char *path, const char *user, int *port, char *this
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static char *
|
||||
smbfs_get_path (smbfs_connection ** sc, const char *path)
|
||||
smbfs_get_path (smbfs_connection ** sc, const vfs_path_t * vpath)
|
||||
{
|
||||
char *user, *host, *remote_path, *pass;
|
||||
int port = SMB_PORT;
|
||||
char *remote_path = NULL;
|
||||
vfs_path_element_t *url;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
char *path = path_element->path;
|
||||
|
||||
DEBUG (3, ("smbfs_get_path(%s)\n", path));
|
||||
if (strncmp (path, URL_HEADER, HEADER_LEN))
|
||||
if (strncmp (path, URL_HEADER, HEADER_LEN) != 0)
|
||||
return NULL;
|
||||
path += HEADER_LEN;
|
||||
|
||||
if (*path == '/') /* '/' leading server name */
|
||||
path++; /* probably came from server browsing */
|
||||
|
||||
if ((remote_path = smbfs_get_host_and_username (&path, &host, &user, &port, &pass)))
|
||||
if ((*sc = smbfs_open_link (host, remote_path, user, &port, pass)) == NULL)
|
||||
{
|
||||
g_free (remote_path);
|
||||
remote_path = NULL;
|
||||
}
|
||||
g_free (host);
|
||||
g_free (user);
|
||||
if (pass)
|
||||
wipe_password (pass);
|
||||
url = vfs_url_split (path, SMB_PORT, URL_FLAGS_NONE);
|
||||
|
||||
if (!remote_path)
|
||||
if (url != NULL)
|
||||
{
|
||||
*sc = smbfs_open_link (url->host, url->path, url->user, &url->port, url->password);
|
||||
wipe_password (url->password);
|
||||
|
||||
if (*sc != NULL)
|
||||
remote_path = g_strdup (url->path);
|
||||
|
||||
vfs_path_element_free (url);
|
||||
}
|
||||
|
||||
if (remote_path == NULL)
|
||||
return NULL;
|
||||
|
||||
/* NOTE: tildes are deprecated. See ftpfs.c */
|
||||
{
|
||||
int f = !strcmp (remote_path, "/~");
|
||||
if (f || !strncmp (remote_path, "/~/", 3))
|
||||
int f = strcmp (remote_path, "/~") ? 0 : 1;
|
||||
|
||||
if (f != 0 || strncmp (remote_path, "/~/", 3) == 0)
|
||||
{
|
||||
char *s;
|
||||
s = concat_dir_and_file ((*sc)->home, remote_path + 3 - f);
|
||||
g_free (remote_path);
|
||||
return s;
|
||||
remote_path = s;
|
||||
}
|
||||
}
|
||||
|
||||
return remote_path;
|
||||
}
|
||||
|
||||
@ -1380,23 +1382,22 @@ is_error (int result, int errno_num)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void *
|
||||
smbfs_opendir (struct vfs_class *me, const char *dirname)
|
||||
smbfs_opendir (const vfs_path_t * vpath)
|
||||
{
|
||||
opendir_info *smbfs_info;
|
||||
smbfs_connection *sc;
|
||||
char *remote_dir;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
(void) me;
|
||||
DEBUG (3, ("smbfs_opendir(dirname:%s)\n", path_element->path));
|
||||
|
||||
DEBUG (3, ("smbfs_opendir(dirname:%s)\n", dirname));
|
||||
|
||||
if (!(remote_dir = smbfs_get_path (&sc, dirname)))
|
||||
if (!(remote_dir = smbfs_get_path (&sc, vpath)))
|
||||
return NULL;
|
||||
|
||||
/* FIXME: where freed? */
|
||||
smbfs_info = g_new (opendir_info, 1);
|
||||
smbfs_info->server_list = FALSE;
|
||||
smbfs_info->path = g_strdup (dirname); /* keep original */
|
||||
smbfs_info->path = g_strdup (path_element->path); /* keep original */
|
||||
smbfs_info->dirname = remote_dir;
|
||||
smbfs_info->conn = sc;
|
||||
smbfs_info->entries = 0;
|
||||
@ -1458,7 +1459,11 @@ smbfs_fake_share_stat (const char *server_url, const char *path, struct stat *bu
|
||||
/* Make sure there is such share at server */
|
||||
smbfs_connection *sc;
|
||||
char *p;
|
||||
p = smbfs_get_path (&sc, path);
|
||||
vfs_path_t *vpath = vfs_path_from_str (path);
|
||||
|
||||
p = smbfs_get_path (&sc, vpath);
|
||||
vfs_path_free (vpath);
|
||||
|
||||
g_free (p);
|
||||
if (p)
|
||||
{
|
||||
@ -1655,15 +1660,14 @@ smbfs_get_stat_info (smbfs_connection * sc, const char *path, struct stat *buf)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
smbfs_chdir (struct vfs_class *me, const char *path)
|
||||
smbfs_chdir (const vfs_path_t * vpath)
|
||||
{
|
||||
char *remote_dir;
|
||||
smbfs_connection *sc;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
(void) me;
|
||||
|
||||
DEBUG (3, ("smbfs_chdir(path:%s)\n", path));
|
||||
if (!(remote_dir = smbfs_get_path (&sc, path)))
|
||||
DEBUG (3, ("smbfs_chdir(path:%s)\n", path_element->path));
|
||||
if (!(remote_dir = smbfs_get_path (&sc, vpath)))
|
||||
return -1;
|
||||
g_free (remote_dir);
|
||||
|
||||
@ -1673,19 +1677,20 @@ smbfs_chdir (struct vfs_class *me, const char *path)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
smbfs_loaddir_by_name (struct vfs_class *me, const char *path)
|
||||
smbfs_loaddir_by_name (const vfs_path_t * vpath)
|
||||
{
|
||||
void *info;
|
||||
char *mypath, *p;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
mypath = g_strdup (path);
|
||||
mypath = g_strdup (path_element->path);
|
||||
p = strrchr (mypath, '/');
|
||||
|
||||
if (p > mypath)
|
||||
*p = 0;
|
||||
DEBUG (6, ("smbfs_loaddir_by_name(%s)\n", mypath));
|
||||
smbfs_chdir (me, mypath);
|
||||
info = smbfs_opendir (me, mypath);
|
||||
smbfs_chdir (vpath);
|
||||
info = smbfs_opendir (vpath);
|
||||
g_free (mypath);
|
||||
if (!info)
|
||||
return -1;
|
||||
@ -1697,24 +1702,25 @@ smbfs_loaddir_by_name (struct vfs_class *me, const char *path)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
smbfs_stat (struct vfs_class *me, const char *path, struct stat *buf)
|
||||
smbfs_stat (const vfs_path_t * vpath, struct stat *buf)
|
||||
{
|
||||
smbfs_connection *sc;
|
||||
pstring server_url;
|
||||
char *service, *pp, *at;
|
||||
const char *p;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
DEBUG (3, ("smbfs_stat(path:%s)\n", path));
|
||||
DEBUG (3, ("smbfs_stat(path:%s)\n", path_element->path));
|
||||
|
||||
if (!current_info)
|
||||
{
|
||||
DEBUG (1, ("current_info = NULL: "));
|
||||
if (smbfs_loaddir_by_name (me, path) < 0)
|
||||
if (smbfs_loaddir_by_name (vpath) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check if stating server */
|
||||
p = path;
|
||||
p = path_element->path;
|
||||
if (strncmp (p, URL_HEADER, HEADER_LEN))
|
||||
{
|
||||
DEBUG (1, ("'%s' doesnt start with '%s' (length %d)\n", p, URL_HEADER, HEADER_LEN));
|
||||
@ -1747,19 +1753,19 @@ smbfs_stat (struct vfs_class *me, const char *path, struct stat *buf)
|
||||
{
|
||||
if (!current_info->server_list)
|
||||
{
|
||||
if (smbfs_loaddir_by_name (me, path) < 0)
|
||||
if (smbfs_loaddir_by_name (vpath) < 0)
|
||||
return -1;
|
||||
}
|
||||
return smbfs_fake_server_stat (server_url, path, buf);
|
||||
return smbfs_fake_server_stat (server_url, path_element->path, buf);
|
||||
}
|
||||
|
||||
if (!strchr (++pp, '/'))
|
||||
{
|
||||
return smbfs_fake_share_stat (server_url, path, buf);
|
||||
return smbfs_fake_share_stat (server_url, path_element->path, buf);
|
||||
}
|
||||
|
||||
/* stating inside share at this point */
|
||||
if (!(service = smbfs_get_path (&sc, path))) /* connects if necessary */
|
||||
if (!(service = smbfs_get_path (&sc, vpath))) /* connects if necessary */
|
||||
return -1;
|
||||
{
|
||||
int hostlen = strlen (current_bucket->host);
|
||||
@ -1794,7 +1800,7 @@ smbfs_stat (struct vfs_class *me, const char *path, struct stat *buf)
|
||||
if (strncmp (p, pp, strlen (p)) != 0)
|
||||
{
|
||||
DEBUG (6, ("desired '%s' is not loaded, we have '%s'\n", p, pp));
|
||||
if (smbfs_loaddir_by_name (me, path) < 0)
|
||||
if (smbfs_loaddir_by_name (vpath) < 0)
|
||||
{
|
||||
g_free (service);
|
||||
return -1;
|
||||
@ -1803,7 +1809,7 @@ smbfs_stat (struct vfs_class *me, const char *path, struct stat *buf)
|
||||
}
|
||||
g_free (service);
|
||||
/* stat dirs & files under shares now */
|
||||
return smbfs_get_stat_info (sc, path, buf);
|
||||
return smbfs_get_stat_info (sc, path_element->path, buf);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -1845,11 +1851,13 @@ smbfs_lseek (void *data, off_t offset, int whence)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
smbfs_mknod (struct vfs_class *me, const char *path, mode_t mode, dev_t dev)
|
||||
smbfs_mknod (const vfs_path_t * vpath, mode_t mode, dev_t dev)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
DEBUG (3, ("smbfs_mknod(path:%s, mode:%d, dev:%u)\n", path, mode, (unsigned int) dev));
|
||||
DEBUG (3,
|
||||
("smbfs_mknod(path:%s, mode:%d, dev:%u)\n", path_element->path, mode,
|
||||
(unsigned int) dev));
|
||||
my_errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
||||
@ -1857,19 +1865,18 @@ smbfs_mknod (struct vfs_class *me, const char *path, mode_t mode, dev_t dev)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
smbfs_mkdir (struct vfs_class *me, const char *path, mode_t mode)
|
||||
smbfs_mkdir (const vfs_path_t * vpath, mode_t mode)
|
||||
{
|
||||
smbfs_connection *sc;
|
||||
char *remote_file;
|
||||
char *cpath;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
(void) me;
|
||||
|
||||
DEBUG (3, ("smbfs_mkdir(path:%s, mode:%d)\n", path, (int) mode));
|
||||
if ((remote_file = smbfs_get_path (&sc, path)) == 0)
|
||||
DEBUG (3, ("smbfs_mkdir(path:%s, mode:%d)\n", path_element->path, (int) mode));
|
||||
if ((remote_file = smbfs_get_path (&sc, vpath)) == 0)
|
||||
return -1;
|
||||
g_free (remote_file);
|
||||
cpath = smbfs_convert_path (path, FALSE);
|
||||
cpath = smbfs_convert_path (path_element->path, FALSE);
|
||||
|
||||
if (!cli_mkdir (sc->cli, cpath))
|
||||
{
|
||||
@ -1886,19 +1893,18 @@ smbfs_mkdir (struct vfs_class *me, const char *path, mode_t mode)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
smbfs_rmdir (struct vfs_class *me, const char *path)
|
||||
smbfs_rmdir (const vfs_path_t * vpath)
|
||||
{
|
||||
smbfs_connection *sc;
|
||||
char *remote_file;
|
||||
char *cpath;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
(void) me;
|
||||
|
||||
DEBUG (3, ("smbfs_rmdir(path:%s)\n", path));
|
||||
if ((remote_file = smbfs_get_path (&sc, path)) == 0)
|
||||
DEBUG (3, ("smbfs_rmdir(path:%s)\n", path_element->path));
|
||||
if ((remote_file = smbfs_get_path (&sc, vpath)) == 0)
|
||||
return -1;
|
||||
g_free (remote_file);
|
||||
cpath = smbfs_convert_path (path, FALSE);
|
||||
cpath = smbfs_convert_path (path_element->path, FALSE);
|
||||
|
||||
if (!cli_rmdir (sc->cli, cpath))
|
||||
{
|
||||
@ -1916,11 +1922,12 @@ smbfs_rmdir (struct vfs_class *me, const char *path)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
smbfs_link (struct vfs_class *me, const char *p1, const char *p2)
|
||||
smbfs_link (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element1 = vfs_path_get_by_index (vpath1, -1);
|
||||
vfs_path_element_t *path_element2 = vfs_path_get_by_index (vpath2, -1);
|
||||
|
||||
DEBUG (3, ("smbfs_link(p1:%s, p2:%s)\n", p1, p2));
|
||||
DEBUG (3, ("smbfs_link(p1:%s, p2:%s)\n", path_element1->path, path_element2->path));
|
||||
my_errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
||||
@ -1942,10 +1949,9 @@ smbfs_free (vfsid id)
|
||||
static void
|
||||
smbfs_forget (const char *path)
|
||||
{
|
||||
char *host, *user, *p;
|
||||
int port;
|
||||
vfs_path_element_t *p;
|
||||
|
||||
if (strncmp (path, URL_HEADER, HEADER_LEN))
|
||||
if (strncmp (path, URL_HEADER, HEADER_LEN) != 0)
|
||||
return;
|
||||
|
||||
DEBUG (3, ("smbfs_forget(path:%s)\n", path));
|
||||
@ -1954,45 +1960,44 @@ smbfs_forget (const char *path)
|
||||
if (path[0] == '/' && path[1] == '/')
|
||||
path += 2;
|
||||
|
||||
if ((p = smbfs_get_host_and_username (&path, &host, &user, &port, NULL)))
|
||||
p = vfs_url_split (path, SMB_PORT, URL_FLAGS_NONE);
|
||||
if (p != NULL)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
g_free (p);
|
||||
|
||||
for (i = 0; i < SMBFS_MAX_CONNECTIONS; i++)
|
||||
{
|
||||
if (smbfs_connections[i].cli
|
||||
&& (strcmp (host, smbfs_connections[i].host) == 0)
|
||||
&& (strcmp (user, smbfs_connections[i].user) == 0)
|
||||
&& (port == smbfs_connections[i].port))
|
||||
&& (strcmp (p->host, smbfs_connections[i].host) == 0)
|
||||
&& (strcmp (p->user, smbfs_connections[i].user) == 0)
|
||||
&& (p->port == smbfs_connections[i].port))
|
||||
{
|
||||
|
||||
/* close socket: the child owns it now */
|
||||
cli_shutdown (smbfs_connections[i].cli);
|
||||
|
||||
/* reopen the connection */
|
||||
smbfs_connections[i].cli = smbfs_do_connect (host, smbfs_connections[i].service);
|
||||
smbfs_connections[i].cli = smbfs_do_connect (p->host, smbfs_connections[i].service);
|
||||
}
|
||||
}
|
||||
|
||||
vfs_path_element_free (p);
|
||||
}
|
||||
g_free (host);
|
||||
g_free (user);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
smbfs_setctl (struct vfs_class *me, const char *path, int ctlop, void *arg)
|
||||
smbfs_setctl (const vfs_path_t * vpath, int ctlop, void *arg)
|
||||
{
|
||||
(void) me;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
(void) arg;
|
||||
|
||||
DEBUG (3, ("smbfs_setctl(path:%s, ctlop:%d)\n", path, ctlop));
|
||||
DEBUG (3, ("smbfs_setctl(path:%s, ctlop:%d)\n", path_element->path, ctlop));
|
||||
switch (ctlop)
|
||||
{
|
||||
case VFS_SETCTL_FORGET:
|
||||
smbfs_forget (path);
|
||||
smbfs_forget (path_element->path);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
@ -2057,18 +2062,17 @@ smbfs_open_readwrite (smbfs_handle * remote_handle, char *rname, int flags, mode
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void *
|
||||
smbfs_open (struct vfs_class *me, const char *file, int flags, mode_t mode)
|
||||
smbfs_open (const vfs_path_t * vpath, int flags, mode_t mode)
|
||||
{
|
||||
char *remote_file;
|
||||
void *ret;
|
||||
smbfs_connection *sc;
|
||||
smbfs_handle *remote_handle;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
(void) me;
|
||||
DEBUG (3, ("smbfs_open(file:%s, flags:%d, mode:%o)\n", path_element->path, flags, mode));
|
||||
|
||||
DEBUG (3, ("smbfs_open(file:%s, flags:%d, mode:%o)\n", file, flags, mode));
|
||||
|
||||
if (!(remote_file = smbfs_get_path (&sc, file)))
|
||||
if (!(remote_file = smbfs_get_path (&sc, vpath)))
|
||||
return 0;
|
||||
|
||||
remote_file = free_after (smbfs_convert_path (remote_file, FALSE), remote_file);
|
||||
@ -2089,14 +2093,12 @@ smbfs_open (struct vfs_class *me, const char *file, int flags, mode_t mode)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
smbfs_unlink (struct vfs_class *me, const char *path)
|
||||
smbfs_unlink (const vfs_path_t * vpath)
|
||||
{
|
||||
smbfs_connection *sc;
|
||||
char *remote_file;
|
||||
|
||||
(void) me;
|
||||
|
||||
if ((remote_file = smbfs_get_path (&sc, path)) == 0)
|
||||
if ((remote_file = smbfs_get_path (&sc, vpath)) == 0)
|
||||
return -1;
|
||||
|
||||
remote_file = free_after (smbfs_convert_path (remote_file, FALSE), remote_file);
|
||||
@ -2115,18 +2117,16 @@ smbfs_unlink (struct vfs_class *me, const char *path)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
smbfs_rename (struct vfs_class *me, const char *a, const char *b)
|
||||
smbfs_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
|
||||
{
|
||||
smbfs_connection *sc;
|
||||
char *ra, *rb;
|
||||
int retval;
|
||||
|
||||
(void) me;
|
||||
|
||||
if ((ra = smbfs_get_path (&sc, a)) == 0)
|
||||
if ((ra = smbfs_get_path (&sc, vpath1)) == 0)
|
||||
return -1;
|
||||
|
||||
if ((rb = smbfs_get_path (&sc, b)) == 0)
|
||||
if ((rb = smbfs_get_path (&sc, vpath2)) == 0)
|
||||
{
|
||||
g_free (ra);
|
||||
return -1;
|
||||
@ -2200,7 +2200,7 @@ init_smbfs (void)
|
||||
tcp_init ();
|
||||
|
||||
vfs_smbfs_ops.name = "smbfs";
|
||||
vfs_smbfs_ops.prefix = "smb:";
|
||||
vfs_smbfs_ops.prefix = "smb";
|
||||
vfs_smbfs_ops.flags = VFSF_NOLINKS;
|
||||
vfs_smbfs_ops.init = smbfs_init;
|
||||
vfs_smbfs_ops.fill_names = smbfs_fill_names;
|
||||
|
@ -275,29 +275,31 @@ tar_free_archive (struct vfs_class *me, struct vfs_s_super *archive)
|
||||
|
||||
/* Returns fd of the open tar file */
|
||||
static int
|
||||
tar_open_archive_int (struct vfs_class *me, const char *name, struct vfs_s_super *archive)
|
||||
tar_open_archive_int (struct vfs_class *me, const vfs_path_t * vpath, struct vfs_s_super *archive)
|
||||
{
|
||||
int result, type;
|
||||
tar_super_data_t *arch;
|
||||
mode_t mode;
|
||||
struct vfs_s_inode *root;
|
||||
char *archive_name = vfs_path_to_str (vpath);
|
||||
|
||||
result = mc_open (name, O_RDONLY);
|
||||
result = mc_open (archive_name, O_RDONLY);
|
||||
if (result == -1)
|
||||
{
|
||||
message (D_ERROR, MSG_ERROR, _("Cannot open tar archive\n%s"), name);
|
||||
message (D_ERROR, MSG_ERROR, _("Cannot open tar archive\n%s"), archive_name);
|
||||
g_free (archive_name);
|
||||
ERRNOR (ENOENT, -1);
|
||||
}
|
||||
|
||||
archive->name = g_strdup (name);
|
||||
archive->name = archive_name;
|
||||
archive->data = g_new (tar_super_data_t, 1);
|
||||
arch = (tar_super_data_t *) archive->data;
|
||||
mc_stat (name, &arch->st);
|
||||
mc_stat (archive_name, &arch->st);
|
||||
arch->fd = -1;
|
||||
arch->type = TAR_UNKNOWN;
|
||||
|
||||
/* Find out the method to handle this tar file */
|
||||
type = get_compression_type (result, name);
|
||||
type = get_compression_type (result, archive_name);
|
||||
mc_lseek (result, 0, SEEK_SET);
|
||||
if (type != COMPRESSION_NONE)
|
||||
{
|
||||
@ -395,12 +397,12 @@ tar_fill_stat (struct vfs_s_super *archive, struct stat *st, union record *heade
|
||||
case TAR_GNU:
|
||||
st->st_uid =
|
||||
*header->header.uname ? vfs_finduid (header->header.uname) : tar_from_oct (8,
|
||||
header->
|
||||
header.uid);
|
||||
header->header.
|
||||
uid);
|
||||
st->st_gid =
|
||||
*header->header.gname ? vfs_findgid (header->header.gname) : tar_from_oct (8,
|
||||
header->
|
||||
header.gid);
|
||||
header->header.
|
||||
gid);
|
||||
switch (header->header.linkflag)
|
||||
{
|
||||
case LF_BLK:
|
||||
@ -727,18 +729,17 @@ tar_read_header (struct vfs_class *me, struct vfs_s_super *archive, int tard, si
|
||||
* Returns 0 on success, -1 on error.
|
||||
*/
|
||||
static int
|
||||
tar_open_archive (struct vfs_class *me, struct vfs_s_super *archive, const char *name, char *op)
|
||||
tar_open_archive (struct vfs_s_super *archive, const vfs_path_t * vpath,
|
||||
const vfs_path_element_t * vpath_element)
|
||||
{
|
||||
/* Initial status at start of archive */
|
||||
ReadStatus status = STATUS_EOFMARK;
|
||||
ReadStatus prev_status;
|
||||
int tard;
|
||||
|
||||
(void) op;
|
||||
|
||||
current_tar_position = 0;
|
||||
/* Open for reading */
|
||||
tard = tar_open_archive_int (me, name, archive);
|
||||
tard = tar_open_archive_int (vpath_element->class, vpath, archive);
|
||||
if (tard == -1)
|
||||
return -1;
|
||||
|
||||
@ -747,7 +748,7 @@ tar_open_archive (struct vfs_class *me, struct vfs_s_super *archive, const char
|
||||
size_t h_size;
|
||||
|
||||
prev_status = status;
|
||||
status = tar_read_header (me, archive, tard, &h_size);
|
||||
status = tar_read_header (vpath_element->class, archive, tard, &h_size);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
@ -768,10 +769,15 @@ tar_open_archive (struct vfs_class *me, struct vfs_s_super *archive, const char
|
||||
|
||||
/* Error on first record */
|
||||
case STATUS_EOFMARK:
|
||||
message (D_ERROR, MSG_ERROR, _("%s\ndoesn't look like a tar archive."), name);
|
||||
/* FALL THRU */
|
||||
{
|
||||
char *archive_name = vfs_path_to_str (vpath);
|
||||
message (D_ERROR, MSG_ERROR, _("%s\ndoesn't look like a tar archive."),
|
||||
archive_name);
|
||||
g_free (archive_name);
|
||||
/* FALL THRU */
|
||||
|
||||
/* Error after header rec */
|
||||
/* Error after header rec */
|
||||
}
|
||||
case STATUS_SUCCESS:
|
||||
/* Error after error */
|
||||
|
||||
@ -798,31 +804,35 @@ tar_open_archive (struct vfs_class *me, struct vfs_s_super *archive, const char
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void *
|
||||
tar_super_check (struct vfs_class *me, const char *archive_name, char *op)
|
||||
tar_super_check (const vfs_path_t * vpath)
|
||||
{
|
||||
static struct stat stat_buf;
|
||||
char *archive_name = vfs_path_to_str (vpath);
|
||||
int stat_result;
|
||||
|
||||
(void) me;
|
||||
(void) op;
|
||||
stat_result = mc_stat (archive_name, &stat_buf);
|
||||
g_free (archive_name);
|
||||
|
||||
if (mc_stat (archive_name, &stat_buf))
|
||||
return NULL;
|
||||
return &stat_buf;
|
||||
return (stat_result != 0) ? NULL : &stat_buf;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
tar_super_same (struct vfs_class *me, struct vfs_s_super *parc,
|
||||
const char *archive_name, char *op, void *cookie)
|
||||
tar_super_same (const vfs_path_element_t * vpath_element, struct vfs_s_super *parc,
|
||||
const vfs_path_t * vpath, void *cookie)
|
||||
{
|
||||
struct stat *archive_stat = cookie; /* stat of main archive */
|
||||
char *archive_name = vfs_path_to_str (vpath);
|
||||
|
||||
(void) me;
|
||||
(void) op;
|
||||
(void) vpath_element;
|
||||
|
||||
if (strcmp (parc->name, archive_name))
|
||||
if (strcmp (parc->name, archive_name) != 0)
|
||||
{
|
||||
g_free (archive_name);
|
||||
return 0;
|
||||
}
|
||||
g_free (archive_name);
|
||||
|
||||
/* Has the cached archive been changed on the disk? */
|
||||
if (((tar_super_data_t *) parc->data)->st.st_mtime < archive_stat->st_mtime)
|
||||
@ -863,7 +873,7 @@ tar_read (void *fh, char *buffer, size_t count)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
tar_fh_open (struct vfs_class *me, vfs_file_handler_t *fh, int flags, mode_t mode)
|
||||
tar_fh_open (struct vfs_class *me, vfs_file_handler_t * fh, int flags, mode_t mode)
|
||||
{
|
||||
(void) fh;
|
||||
(void) mode;
|
||||
|
@ -146,18 +146,22 @@ undelfs_shutdown (void)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
undelfs_get_path (const char *dirname, char **fsname, char **file)
|
||||
undelfs_get_path (const vfs_path_t * vpath, char **fsname, char **file)
|
||||
{
|
||||
const char *p;
|
||||
const char *p, *dirname;
|
||||
vfs_path_element_t *path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
|
||||
/* To look like filesystem, we have virtual directories
|
||||
/#undel:XXX, which have no subdirectories. XXX is replaced with
|
||||
hda5, sdb8 etc, which is assumed to live under /dev.
|
||||
-- pavel@ucw.cz */
|
||||
|
||||
dirname = path_element->path;
|
||||
|
||||
*fsname = NULL;
|
||||
|
||||
if (strncmp (dirname, "/#undel:", 8))
|
||||
if (strncmp (dirname, "/#undel", 7))
|
||||
return;
|
||||
|
||||
dirname += 8;
|
||||
@ -330,11 +334,13 @@ undelfs_loaddel (void)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void *
|
||||
undelfs_opendir (struct vfs_class *me, const char *dirname)
|
||||
undelfs_opendir (const vfs_path_t * vpath)
|
||||
{
|
||||
char *file, *f;
|
||||
vfs_path_element_t *path_element;
|
||||
|
||||
undelfs_get_path (dirname, &file, &f);
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
undelfs_get_path (vpath, &file, &f);
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
@ -374,10 +380,10 @@ undelfs_opendir (struct vfs_class *me, const char *dirname)
|
||||
/* Now load the deleted information */
|
||||
if (!undelfs_loaddel ())
|
||||
goto quit_opendir;
|
||||
vfs_print_message (_("%s: done."), me->name);
|
||||
vfs_print_message (_("%s: done."), path_element->class->name);
|
||||
return fs;
|
||||
quit_opendir:
|
||||
vfs_print_message (_("%s: failure"), me->name);
|
||||
vfs_print_message (_("%s: failure"), path_element->class->name);
|
||||
ext2fs_close (fs);
|
||||
fs = NULL;
|
||||
return 0;
|
||||
@ -423,17 +429,16 @@ undelfs_closedir (void *vfs_info)
|
||||
/* We do not support lseek */
|
||||
|
||||
static void *
|
||||
undelfs_open (struct vfs_class *me, const char *fname, int flags, mode_t mode)
|
||||
undelfs_open (const vfs_path_t * vpath, int flags, mode_t mode)
|
||||
{
|
||||
char *file, *f;
|
||||
ext2_ino_t inode, i;
|
||||
undelfs_file *p = NULL;
|
||||
(void) me;
|
||||
(void) flags;
|
||||
(void) mode;
|
||||
|
||||
/* Only allow reads on this file system */
|
||||
undelfs_get_path (fname, &file, &f);
|
||||
undelfs_get_path (vpath, &file, &f);
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
@ -631,13 +636,12 @@ undelfs_stat_int (int inode_index, struct stat *buf)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
undelfs_lstat (struct vfs_class *me, const char *path, struct stat *buf)
|
||||
undelfs_lstat (const vfs_path_t * vpath, struct stat *buf)
|
||||
{
|
||||
int inode_index;
|
||||
char *file, *f;
|
||||
(void) me;
|
||||
|
||||
undelfs_get_path (path, &file, &f);
|
||||
undelfs_get_path (vpath, &file, &f);
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
@ -684,13 +688,12 @@ undelfs_fstat (void *vfs_info, struct stat *buf)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
undelfs_chdir (struct vfs_class *me, const char *path)
|
||||
undelfs_chdir (const vfs_path_t * vpath)
|
||||
{
|
||||
char *file, *f;
|
||||
int fd;
|
||||
(void) me;
|
||||
|
||||
undelfs_get_path (path, &file, &f);
|
||||
undelfs_get_path (vpath, &file, &f);
|
||||
if (!file)
|
||||
return -1;
|
||||
|
||||
@ -727,12 +730,11 @@ undelfs_lseek (void *vfs_info, off_t offset, int whence)
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static vfsid
|
||||
undelfs_getid (struct vfs_class *me, const char *path)
|
||||
undelfs_getid (const vfs_path_t * vpath)
|
||||
{
|
||||
char *fname, *fsname;
|
||||
(void) me;
|
||||
|
||||
undelfs_get_path (path, &fsname, &fname);
|
||||
undelfs_get_path (vpath, &fsname, &fname);
|
||||
|
||||
if (!fsname)
|
||||
return NULL;
|
||||
@ -804,7 +806,7 @@ void
|
||||
init_undelfs (void)
|
||||
{
|
||||
vfs_undelfs_ops.name = "undelfs";
|
||||
vfs_undelfs_ops.prefix = "undel:";
|
||||
vfs_undelfs_ops.prefix = "undel";
|
||||
vfs_undelfs_ops.init = undelfs_init;
|
||||
vfs_undelfs_ops.open = undelfs_open;
|
||||
vfs_undelfs_ops.close = undelfs_close;
|
||||
|
@ -236,10 +236,13 @@ mcview_done (mcview_t * view)
|
||||
if (mcview_remember_file_position && view->filename != NULL)
|
||||
{
|
||||
char *canon_fname;
|
||||
canon_fname = vfs_canon (view->filename);
|
||||
vfs_path_t *vpath;
|
||||
vpath = vfs_path_from_str (view->filename);
|
||||
canon_fname = vfs_path_to_str (vpath);
|
||||
save_file_position (canon_fname, -1, 0, view->dpy_start, view->saved_bookmarks);
|
||||
view->saved_bookmarks = NULL;
|
||||
g_free (canon_fname);
|
||||
vfs_path_free (vpath);
|
||||
}
|
||||
|
||||
/* Write back the global viewer mode */
|
||||
@ -290,7 +293,9 @@ mcview_set_codeset (mcview_t * view)
|
||||
const char *cp_id = NULL;
|
||||
|
||||
view->utf8 = TRUE;
|
||||
cp_id = get_codepage_id (mc_global.source_codepage >= 0 ? mc_global.source_codepage : mc_global.display_codepage);
|
||||
cp_id =
|
||||
get_codepage_id (mc_global.source_codepage >=
|
||||
0 ? mc_global.source_codepage : mc_global.display_codepage);
|
||||
if (cp_id != NULL)
|
||||
{
|
||||
GIConv conv;
|
||||
@ -432,7 +437,7 @@ mcview_lock_file (mcview_t * view)
|
||||
char *fullpath;
|
||||
gboolean ret;
|
||||
|
||||
fullpath = g_build_filename (view->workdir, view->filename, (char *) NULL);
|
||||
fullpath = mc_build_filename (view->workdir, view->filename, (char *) NULL);
|
||||
ret = lock_file (fullpath);
|
||||
g_free (fullpath);
|
||||
|
||||
@ -447,7 +452,7 @@ mcview_unlock_file (mcview_t * view)
|
||||
char *fullpath;
|
||||
gboolean ret;
|
||||
|
||||
fullpath = g_build_filename (view->workdir, view->filename, (char *) NULL);
|
||||
fullpath = mc_build_filename (view->workdir, view->filename, (char *) NULL);
|
||||
ret = unlock_file (fullpath);
|
||||
g_free (fullpath);
|
||||
|
||||
|
@ -282,7 +282,7 @@ mcview_load (mcview_t * view, const char *command, const char *file, int start_l
|
||||
if ((view->workdir == NULL) && (file != NULL))
|
||||
{
|
||||
if (!g_path_is_absolute (file))
|
||||
view->workdir = g_strdup (vfs_get_current_dir ());
|
||||
view->workdir = vfs_get_current_dir ();
|
||||
else
|
||||
{
|
||||
/* try extract path form filename */
|
||||
@ -294,7 +294,7 @@ mcview_load (mcview_t * view, const char *command, const char *file, int start_l
|
||||
else
|
||||
{
|
||||
g_free (dirname);
|
||||
view->workdir = g_strdup (vfs_get_current_dir ());
|
||||
view->workdir = vfs_get_current_dir ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -387,12 +387,15 @@ mcview_load (mcview_t * view, const char *command, const char *file, int start_l
|
||||
char *canon_fname;
|
||||
long line, col;
|
||||
off_t new_offset;
|
||||
vfs_path_t *vpath;
|
||||
|
||||
canon_fname = vfs_canon (view->filename);
|
||||
vpath = vfs_path_from_str (view->filename);
|
||||
canon_fname = vfs_path_to_str (vpath);
|
||||
load_file_position (canon_fname, &line, &col, &new_offset, &view->saved_bookmarks);
|
||||
new_offset = min (new_offset, mcview_get_filesize (view));
|
||||
view->dpy_start = mcview_bol (view, new_offset, 0);
|
||||
g_free (canon_fname);
|
||||
vfs_path_free (vpath);
|
||||
}
|
||||
else if (start_line > 0)
|
||||
mcview_moveto (view, start_line - 1, 0);
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user