1
1
* 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:
  ...
Этот коммит содержится в:
Slava Zanko 2011-06-23 14:46:11 +03:00
родитель fcfa76be3d ef676d3244
Коммит f2ebbd2eb4
77 изменённых файлов: 6764 добавлений и 2672 удалений

Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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, &param_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, &current_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, &current_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, &current_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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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;
}
/* --------------------------------------------------------------------------------------------- */

Просмотреть файл

@ -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

Просмотреть файл

@ -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);
}
/* --------------------------------------------------------------------------------------------- */

Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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);

Просмотреть файл

@ -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);