diff options
Diffstat (limited to 'xdg-vfs-gnome')
-rw-r--r-- | xdg-vfs-gnome/.cvsignore | 26 | ||||
-rw-r--r-- | xdg-vfs-gnome/AUTHORS | 1 | ||||
-rw-r--r-- | xdg-vfs-gnome/COPYING | 18 | ||||
-rw-r--r-- | xdg-vfs-gnome/ChangeLog | 7 | ||||
-rw-r--r-- | xdg-vfs-gnome/INSTALL | 236 | ||||
-rw-r--r-- | xdg-vfs-gnome/Makefile.am | 1 | ||||
-rw-r--r-- | xdg-vfs-gnome/Makefile.cvs | 6 | ||||
-rw-r--r-- | xdg-vfs-gnome/NEWS | 1 | ||||
-rw-r--r-- | xdg-vfs-gnome/README | 132 | ||||
-rw-r--r-- | xdg-vfs-gnome/configure.ac | 27 | ||||
-rw-r--r-- | xdg-vfs-gnome/desc/xdg-vfs.xml | 475 | ||||
-rw-r--r-- | xdg-vfs-gnome/src/.cvsignore | 8 | ||||
-rw-r--r-- | xdg-vfs-gnome/src/Makefile.am | 13 | ||||
-rw-r--r-- | xdg-vfs-gnome/src/xdg_vfs.c | 531 | ||||
-rw-r--r-- | xdg-vfs-gnome/src/xdg_vfs.h | 135 | ||||
-rw-r--r-- | xdg-vfs-gnome/src/xdg_vfs_common.h | 146 | ||||
-rw-r--r-- | xdg-vfs-gnome/src/xdg_vfs_gnome.c | 1099 | ||||
-rw-r--r-- | xdg-vfs-gnome/src/xdg_vfs_gnome.h | 39 | ||||
-rw-r--r-- | xdg-vfs-gnome/src/xdg_vfs_gnome_monitor.c | 238 | ||||
-rw-r--r-- | xdg-vfs-gnome/src/xdg_vfs_gnome_volumes.c | 521 |
20 files changed, 3660 insertions, 0 deletions
diff --git a/xdg-vfs-gnome/.cvsignore b/xdg-vfs-gnome/.cvsignore new file mode 100644 index 0000000..280e90a --- /dev/null +++ b/xdg-vfs-gnome/.cvsignore @@ -0,0 +1,26 @@ +*.la +*.lo +*.o +Makefile +Makefile.in +aclocal.m4 +autom4te.cache +config.cache +config.h +config.h.in +config.log +config.status +configure +libtool +config.guess +config.sub +depcomp +install-sh +ltmain.sh +missing +stamp-h1 +.libs +.deps +.cdtproject +.project + diff --git a/xdg-vfs-gnome/AUTHORS b/xdg-vfs-gnome/AUTHORS new file mode 100644 index 0000000..25d341d --- /dev/null +++ b/xdg-vfs-gnome/AUTHORS @@ -0,0 +1 @@ +Norbert Frese (nf2@scheinwelt.at) 2006
\ No newline at end of file diff --git a/xdg-vfs-gnome/COPYING b/xdg-vfs-gnome/COPYING new file mode 100644 index 0000000..1edf08c --- /dev/null +++ b/xdg-vfs-gnome/COPYING @@ -0,0 +1,18 @@ +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. diff --git a/xdg-vfs-gnome/ChangeLog b/xdg-vfs-gnome/ChangeLog new file mode 100644 index 0000000..ede0d5c --- /dev/null +++ b/xdg-vfs-gnome/ChangeLog @@ -0,0 +1,7 @@ +2005-11-21 gettextize <bug-gnu-gettext@gnu.org> + + * Makefile.am (SUBDIRS): Add po. + (ACLOCAL_AMFLAGS): New variable. + (EXTRA_DIST): New variable. + * configure.ac (AC_OUTPUT): Add po/Makefile.in. + diff --git a/xdg-vfs-gnome/INSTALL b/xdg-vfs-gnome/INSTALL new file mode 100644 index 0000000..23e5f25 --- /dev/null +++ b/xdg-vfs-gnome/INSTALL @@ -0,0 +1,236 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free +Software Foundation, Inc. + +This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + +These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for +details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + +You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + +By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + +Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + +There may be some features `configure' cannot figure out automatically, +but needs to determine by the type of machine the package will run on. +Usually, assuming the package is built to be run on the _same_ +architectures, `configure' can figure that out, but if it prints a +message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + +If you want to set default values for `configure' scripts to share, you +can create a site shell script called `config.site' that gives default +values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + +Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). Here is a another example: + + /bin/bash ./configure CONFIG_SHELL=/bin/bash + +Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent +configuration-related scripts to be executed by `/bin/bash'. + +`configure' Invocation +====================== + +`configure' recognizes the following options to control how it operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/xdg-vfs-gnome/Makefile.am b/xdg-vfs-gnome/Makefile.am new file mode 100644 index 0000000..af437a6 --- /dev/null +++ b/xdg-vfs-gnome/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/xdg-vfs-gnome/Makefile.cvs b/xdg-vfs-gnome/Makefile.cvs new file mode 100644 index 0000000..1e17bc9 --- /dev/null +++ b/xdg-vfs-gnome/Makefile.cvs @@ -0,0 +1,6 @@ +all: + @libtoolize + @aclocal + @autoheader + @automake --add-missing + @autoconf diff --git a/xdg-vfs-gnome/NEWS b/xdg-vfs-gnome/NEWS new file mode 100644 index 0000000..4af1832 --- /dev/null +++ b/xdg-vfs-gnome/NEWS @@ -0,0 +1 @@ +None
\ No newline at end of file diff --git a/xdg-vfs-gnome/README b/xdg-vfs-gnome/README new file mode 100644 index 0000000..177431f --- /dev/null +++ b/xdg-vfs-gnome/README @@ -0,0 +1,132 @@ +XDG_VFS_GNOME +============= + +xdg_vfs_gnome is a command line client for gnome-vfs. It can read and write +files, list directories, open file-dialogs,... File-data is not stored in +temporary files, but instead is pushed/pulled via stdin and stdout. + +xdg_vfs_gnome is linked to the gnomeui libraries and therefore will pop up password dialogs etc. (which the gnome-vfs command line utilities can't) + +The aim of 'xdg_vfs_gnome' is to give third party desktop applications access +to Gnome-VFS without linking to the Gnome-libraries directly. It could be hidden behind a generic 'xdg_vfs' script, which switches between KIO, +Gnome-VFS,... command line clients. + + +Samples: +======== + +-) reading a file + +$ xdg_vfs_gnome get file:///etc/lilo.conf + +$ xdg_vfs_gnome get http://www.freedesktop.org + +will stream a remote file to stdout which could be read into the hosts +applications memory via the C-function popen(..,'r'); + +$ xdg_vfs_gnome openfiledlg --instant-get + +will open a file-dialog to browse to a remote or local file and instantly +stream the file-data of the selected file to stdout. + +$ xdg_vfs_gnome openfiledlg --instant-get --qry-fileinfo --slow-mime --tagged + +By adding those switches xdg_vfs_gnome will also 'stat' the remote file and +try to detect it's mime-type, size,... + +-) writing a file + +$ cat /etc/passwd | xdg_vfs_gnome put ftp://user@host/mydir/file.txt + +or use something like popen(..,'w') to stream file-data to create a remote file. + +-) listing a directory + +$ xdg_vfs_gnome ls sftp://user@host/dir/ + + +There are two operation modes: +============================== + +*) single command + +*) shell mode (like the command-line ftp client). In shell mode the + host application can talk to 'xdg_vfs_gnome' by connecting to the + stdin and stdout pipes to execute a sequence of vfs commands. + (for instance QProcess or functions like g_spawn_async_with_pipes() allow + connecting to stdin and stdout of a child process) + +The advantage of shell mode is that passwords are kept in memory +(the user doesn't have log in again and again) and avoiding startup-delay +when executing multiple commands (for instance if the client application +is a file-manager) + +Tagged-mode: +============ + +the -t, --tagged option tells xdg_gnome_vfs to add 'labels' when a command +returns multiple 'parts'. For instance + +> xdg_vfs_gnome openfiledlg --instant-get --qry-fileinfo --tagged + +will return an [OpenFileDlg], a [FileInfo] and a [Data] section. + +Escaping file data: +=================== + +When operating in shell- or tagged- mode you will need an escape character +to signal the end of binary data. This is done via the -e and --escape-data +switch. By default '~' is the escape character. '~~' has to be treated as +single '~' and '~\n' as EOF. The escape-character can be changed by +the -e35 or --escape-data=35 option. (when you want to use '#' ASCII 35 as escape +character) + +Usage screen: +============= + +Usage: xdg_vfs [command] [options] [filename] + + Commands: + get [filename] : remote file->stdout + info [file or dir] : stat a remote file->stdout + put [filename] : stdin->create remote file + ls [dir] : list directory + openfiledlg [dir] : show open file dialog and return selected file + savefiledlg [dir] [fname] : show save file dialog and return selected file + shell : interactive mode + + Options: + -t, --tagged : tagged mode (file-data should be escaped) + -i, --qry-fileinfo : qry file-info when retrieving a file + --show-metadata : show metadata when retrieving a file + requires tagged mode! + -m, --slow-mime : more accurate mime-type detection (slow) + -e, --escape-data : escape file data (for end of data detection) + -eXXX, --escape-data=XXX : set and use a user defined escape character + XXX = ascii code! + --end-seperator= : add a custom seperator inbetween blocks + --overwrite : allow overwriting files (put) + --instant-get : openfiledilog instant get file->stdout + --instant-put : savefiledilog instant put file from stdin + + +Todo: +===== + +*) Implement more VFS-Commands (set file-info, mkdir/rmdir, copy, move,...) + +*) Progress reporting via stdout + +*) multi file-open-dialog + +*) Improve exit codes + +*) Write xdg_vfs_kde + +*) -w switch. Is there a way to pass the window-id to Gnome for accurate placement of dialogs? + +*) Write a sample client application (a simple file-manager for instance) + +... + + diff --git a/xdg-vfs-gnome/configure.ac b/xdg-vfs-gnome/configure.ac new file mode 100644 index 0000000..8dc0073 --- /dev/null +++ b/xdg-vfs-gnome/configure.ac @@ -0,0 +1,27 @@ +dnl Process this file with autoconf to produce a configure script. + +dnl AC_INIT(src/main.c) +AC_INIT(src/xdg_vfs_gnome.c) +dnl AM_CONFIG_HEADER(config.h) + +PACKAGE=xdg-vfs-gnome +VERSION=0.1.14 + +AM_INIT_AUTOMAKE($PACKAGE,$VERSION) + +AC_PROG_CC +AC_STDC_HEADERS +AC_PROG_INSTALL + +AC_ENABLE_SHARED(yes) +AC_PROG_LIBTOOL + +PKG_CHECK_MODULES(DEPS, gtk+-2.0 >= 2.2 gnome-vfs-2.0 >= 2.0 libgnomeui-2.0 >= 2.0) + +AC_SUBST(DEPS_CFLAGS) +AC_SUBST(DEPS_LIBS) + +AC_OUTPUT([ +Makefile +src/Makefile +]) diff --git a/xdg-vfs-gnome/desc/xdg-vfs.xml b/xdg-vfs-gnome/desc/xdg-vfs.xml new file mode 100644 index 0000000..cc0e828 --- /dev/null +++ b/xdg-vfs-gnome/desc/xdg-vfs.xml @@ -0,0 +1,475 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/xsl" + href="http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl"?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ +]> +<refentry id="xdg-mime"> + <refentryinfo> + <title>xdg-vfs Manual</title> + <copyright> + <year>2006</year> + </copyright> + <author> + <firstname>Norbert</firstname> + <surname>Frese</surname> + </author> + <address><email>nf2@scheinwelt.at</email></address> + <releaseinfo>This is release 0.1 of the xdg-mime Manual.</releaseinfo> + </refentryinfo> + + <refmeta> + <refentrytitle>xdg-vfs</refentrytitle> + <manvolnum>1</manvolnum> + </refmeta> + + <refnamediv> + <refname>xdg-vfs</refname> + <refpurpose>command line tool for accessing the desktops vfs system</refpurpose> + </refnamediv> + + <refsynopsisdiv> + <cmdsynopsis> + <command>xdg-vfs</command> + <arg choice="plain"><option>get</option></arg> + <arg><option>--tagged</option> + <arg><option>--qry-fileinfo</option> + <arg><option>--slow-mime</option></arg> + </arg> + </arg> + <arg><option>--escape-data</option></arg> + <arg choice="plain"><replaceable>URI</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>xdg-vfs</command> + <arg choice="plain"><option>put</option></arg> + <arg><option>--tagged</option></arg> + <arg><option>--escape-data</option></arg> + <arg><option>--overwrite</option></arg> + <arg choice="plain"><replaceable>URI</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>xdg-vfs</command> + <arg choice="plain"><option>info</option></arg> + <arg><option>--tagged</option></arg> + <arg><option>--slow-mime</option></arg> + <arg choice="plain"><replaceable>URI</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>xdg-vfs</command> + <arg choice="plain"><option>ls</option></arg> + <arg><option>--tagged</option></arg> + <arg><option>--slow-mime</option></arg> + <arg choice="plain"><replaceable>URI</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>xdg-vfs</command> + <arg choice="plain"><option>openfiledlg</option></arg> + <arg><option>--tagged</option> + <arg><option>--qry-fileinfo</option> + <arg><option>--slow-mime</option></arg> + </arg> + </arg> + <arg><option>--instant-get</option></arg> + <arg><option>--escape-data</option></arg> + <arg><replaceable>START_URI</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>xdg-vfs</command> + <arg choice="plain"><option>savefiledlg</option></arg> + <arg><option>--tagged</option></arg> + <arg><option>--instant-put</option></arg> + <arg><option>--escape-data</option></arg> + <arg><replaceable>START_DIR_URI</replaceable></arg> + <arg><replaceable>DEFAULT_FILENAME</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>xdg-vfs</command> + <arg choice="plain"><option>shell</option></arg> + </cmdsynopsis> +</refsynopsisdiv> + + <refsect1 id="description"> + <title>Description</title> + <para> + The xdg-vfs program can be used to access the desktops vfs system. + </para> + </refsect1> + <refsect1 id="commands"> + <title>Commands</title> + <variablelist> + <varlistentry> + <term><option>get</option></term> + <listitem> + <simpara> + Download a file <replaceable>URI</replaceable> and stream contents to stdout. + </simpara> + <simpara> + In tagged mode it will return <computeroutput>[GET]</computeroutput> as section header, + the filename as key/value pair + <computeroutput>uri=file:///dir/filename</computeroutput> + and the subsection header <computeroutput>(>>>ESCAPED_DATA>>>)</computeroutput> or + <computeroutput>(>>>RAW_DATA>>>)</computeroutput> followed by the file-data. + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><option>put</option></term> + <listitem> + <simpara> + Write a file <replaceable>URI</replaceable> and stream contents from stdin. + </simpara> + <simpara> + In tagged mode it will return <computeroutput>[PUT]</computeroutput> as section header, + the filename as key/value pair + <computeroutput>uri=file:///dir/filename</computeroutput> + and the subsection header <computeroutput>(<<<ESCAPED_DATA<<<)</computeroutput> or + <computeroutput>(<<<RAW_DATA<<<)</computeroutput>, waiting for the file-data on stdin. + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><option>info</option></term> + <listitem> + <simpara> + Determine file-info of <replaceable>URI</replaceable> and determine its mime-type. + </simpara> + <simpara> + In tagged mode it will return <computeroutput>[FILEINFO]</computeroutput> as section header. + </simpara> + <para> + The attributes of the file are described by the following key=value pairs. In case the file is a + Symlink, the attributes of the target file will be shown. Therefore the filetype will never be + 'SYMLINK'. + <variablelist> + <varlistentry> + <term><computeroutput>uri=</computeroutput></term> + <listitem> + <simpara> + Absolute URI of the file + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><computeroutput>basename=</computeroutput></term> + <listitem> + <simpara> + Filename without path + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><computeroutput>size=</computeroutput></term> + <listitem> + <simpara> + Byte-size of the file + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><computeroutput>permissions=</computeroutput></term> + <listitem> + <simpara> + Permissions (octal) + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><computeroutput>filetype=</computeroutput></term> + <listitem> + <simpara> + <computeroutput>UNKNOWN, REGULAR, DIRECTORY, FIFO, SOCKET, + CHARDEV, BLOCKDEV</computeroutput> or <computeroutput>SYMLINK</computeroutput> + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><computeroutput>ctime=, atime=, mtime=</computeroutput></term> + <listitem> + <simpara> + Timestamps + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><computeroutput>userid=, groupid=</computeroutput></term> + <listitem> + <simpara> + User and Group-ID (Gnome-VFS) + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><computeroutput>user=, group=</computeroutput></term> + <listitem> + <simpara> + User- and Groupname (KIO) + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><computeroutput>mimetype=</computeroutput></term> + <listitem> + <simpara> + Mimetype + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><computeroutput>linkdest=</computeroutput></term> + <listitem> + <simpara> + Target if the file is a symbolic link + </simpara> + </listitem> + </varlistentry> +</variablelist> + + + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><option>ls</option></term> + <listitem> + <simpara> + List directory <replaceable>URI</replaceable>. + </simpara> + <simpara> + In tagged mode it will print <computeroutput>[LS]</computeroutput> as section header, and the + Entries (same format as for 'info' command) lead by the subheader + <computeroutput>(DIRENTRY)</computeroutput>. + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><option>openfiledlg</option></term> + <listitem> + <simpara> + Show an open-file-dialog and set the inital dir/filename to <replaceable>START_URI</replaceable>. Can be combined + with the <command>get</command> command by using the --instant-get switch. + </simpara> + <simpara> + In tagged mode it will print <computeroutput>[OPENFILEDLG]</computeroutput> as section header. The + returned key-value pairs are: <computeroutput>selected_localpath=</computeroutput> + and <computeroutput>selected_uri=</computeroutput>. The first one will only show up for local files. + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><option>savefiledlg</option></term> + <listitem> + <simpara> + Show an save-file-dialog and set the inital dir/filename to <replaceable>START_DIR_URI</replaceable>, + and the default-filename <replaceable>DEFAULT_FILENAME</replaceable>. +Can be combined + with the <command>put</command> command by using the --instant-put switch. + </simpara> + <simpara> + In tagged mode it will print <computeroutput>[SAVEFILEDLG]</computeroutput> as section header. The + returned key-value pairs are: <computeroutput>selected_localpath=</computeroutput> + and <computeroutput>selected_uri=</computeroutput>. The first one will only show up for local files. + </simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><option>shell</option></term> + <listitem> + <simpara> + Enter interactive shell mode (like the command-line ftp client). + Will always turn --tagged mode on. --escaped mode is strongly recommended + when transfering files via stdin/stdout. In shell mode the + host application can talk to <command>xdg-vfs</command> by connecting to the + stdin and stdout pipes to execute a sequence of vfs commands. + (for instance QProcess or functions like g_spawn_async_with_pipes() allow + connecting to stdin and stdout of a child process) + </simpara> + </listitem> + </varlistentry> + </variablelist> + + </refsect1> + + + <refsect1 id="options"> + <title>Options</title> + <variablelist> + <varlistentry> + <term><option>--tagged, -t</option></term> + <listitem> + <simpara> + Switch to machine parsable <emphasis>tagged-mode</emphasis>. + Main sections will have square brackets: <replaceable>[GET]</replaceable>. + Subsections will have round brackets: <replaceable>(DIRENTRY)</replaceable> + </simpara> + </listitem> + </varlistentry> + + + <varlistentry> + <term><option>--escape-data, -e</option></term> + <listitem> + <simpara> + Use an <replaceable>escape-character</replaceable> when writing/reading file-data to signal EOF. + Strongly recommended in <emphasis>tagged-mode</emphasis>. + By default '~' is the escape character. '~~' has to be treated as + single '~' and '~\n' as EOF. The escape-character can be changed by + the <command>-e35</command> or <command>--escape-data=35</command> option. + (when you want to use '#' ASCII 35 as escape + character) + </simpara> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--qry-fileinfo, -i</option></term> + <listitem> + <simpara> + Run fileinfo <command>info</command> command before retieving a file (in commands <command>get</command> + or <command>openfiledlg --instant-get</command>. + Will only work in <command>--tagged</command> mode. + </simpara> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--overwrite</option></term> + <listitem> + <simpara> + Allow overwriting an existing file in command <command>put</command>. + </simpara> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--instant-get</option></term> + <listitem> + <simpara> + Instantly <command>get</command> data of selected file in a <command>openfiledlg</command>. + </simpara> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--instant-put</option></term> + <listitem> + <simpara> + Instantly <command>put</command> data of selected file in a <command>savefiledlg</command>. + The user will be asked if he wants to overwrite the file - therefor the --overwrite flag is assumed 'on' + here. + </simpara> + </listitem> + </varlistentry> + + + <varlistentry> + <term><option>--help</option></term> + <listitem> + <simpara> + Show this help. + </simpara> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--version</option></term> + <listitem> + <simpara> + Show the xdg-vfs version information. + </simpara> + </listitem> + </varlistentry> + + </variablelist> + </refsect1> + <refsect1 id="examples"> + <title>Examples</title> + <para> +<programlisting> +xdg-vfs get file:///etc/lilo.conf + +xdg-vfs get http://www.freedesktop.org +</programlisting> + Will stream a remote file to stdout which could be read into the hosts +applications memory via the C-function popen(..,'r'); + </para> + <para> +<programlisting> +xdg-vfs openfiledlg --instant-get +</programlisting> + Will open a file-dialog to browse to a remote or local file and instantly + stream the file-data of the selected file to stdout. + + </para> + <para> +<programlisting> +xdg-vfs openfiledlg --instant-get --qry-fileinfo --slow-mime --tagged --escape-data +</programlisting> + By adding those switches xdg_vfs_gnome will also 'stat' the remote file and + try to detect it's mime-type, size,... Escaping file-data is always recommended in --tagged mode. + </para> + <para> +<programlisting> +cat /etc/passwd | xdg-vfs put ftp://user@host/mydir/file.txt +</programlisting> + or use something like popen(..,'w') to stream file-data to create a remote file. + </para> + <para> +<programlisting> +xdg-vfs ls sftp://user@host/dir/ --tagged +</programlisting> + List a remote directory. Tagged mode is recommended for listing directories. + + </para> + <para> + This shows the output of a command in 'tagged' mode (when the user selects /etc/passwd): + +<programlisting> +$ src/xdg_vfs_gnome openfiledlg --instant-get -i --tagged -e +[OPENFILEDLG] +selected_localpath=/etc/passwd +selected_uri=file:///etc/passwd +[FILEINFO] +basename=passwd +size=1389 +userid=0 +groupid=0 +permissions=644 +mtime=1149433809 +atime=1149596399 +ctime=1149433809 +filetype=REGULAR +mimetype=text/plain +uri=file:///etc/passwd +[GET] +uri=file:///etc/passwd +(>>>ESCAPED_DATA>>>) +root:x:0:0:root:/root:/bin/bash +bin:x:1:1:bin:/bin:/bin/sh +~ +$ +</programlisting> + </para> + </refsect1> + <refsect1 id="rvals"> + <title>Return Codes</title> + <para> + Return values of the xdg-vfs backends: +<programlisting> +OK 0 +CANCELED 10 +USAGEERR 11 +NOTSUPPORTED 12 +GENERIC 13 +INITERR 14 +DATAERR 15 +IOERR 16 +NOTPERMITTED 17 +INVALIDURI 18 +</programlisting> + + + </para> + </refsect1> + +</refentry> diff --git a/xdg-vfs-gnome/src/.cvsignore b/xdg-vfs-gnome/src/.cvsignore new file mode 100644 index 0000000..26a73db --- /dev/null +++ b/xdg-vfs-gnome/src/.cvsignore @@ -0,0 +1,8 @@ +*.la +*.lo +*.o +.deps +.libs +Makefile +Makefile.in + diff --git a/xdg-vfs-gnome/src/Makefile.am b/xdg-vfs-gnome/src/Makefile.am new file mode 100644 index 0000000..712950c --- /dev/null +++ b/xdg-vfs-gnome/src/Makefile.am @@ -0,0 +1,13 @@ +bin_PROGRAMS = xdg_vfs_gnome + +xdg_vfs_gnome_SOURCES = xdg_vfs_gnome.c \ + xdg_vfs.c \ + xdg_vfs_gnome_volumes.c \ + xdg_vfs_gnome_monitor.c + +xdg_vfs_gnome_LDADD = $(DEPS_LIBS) + +AM_CFLAGS = $(DEPS_CFLAGS) + +noinst_HEADERS = xdg_vfs.h xdg_vfs_common.h xdg_vfs_gnome.h + diff --git a/xdg-vfs-gnome/src/xdg_vfs.c b/xdg-vfs-gnome/src/xdg_vfs.c new file mode 100644 index 0000000..f0956da --- /dev/null +++ b/xdg-vfs-gnome/src/xdg_vfs.c @@ -0,0 +1,531 @@ +/* +# xdg_vfs.c +# +# Copyright 2006, Norbert Frese +# +# LICENSE: +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +#---------------------------------------------*/ + +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> + +#include <sys/types.h> +#include <sys/time.h> + +#include "xdg_vfs_common.h" +#include "xdg_vfs.h" + +char * end_seperator; +int data_esc_char= DEFAULT_DATA_ESC_CHAR; +int xdgvfs_file_permissions = XDGVFS_DEFAULT_FILE_PERMISSIONS; +int xdgvfs_dir_permissions = XDGVFS_DEFAULT_DIR_PERMISSIONS; +int debug_mode = 1; + +int xdg_vfs_getDataEscChar() +{ + return data_esc_char; +} + +char * xdg_vfs_getCustomEndSeparator() +{ + return end_seperator; +} + +/** +* print a key/value pair +* (value is a string) +*/ +void xdg_vfs_ppair_str(FILE * f, const char * key, const char * value, int opts) +{ + fprintf(f,key); + fprintf(f,"="); + if (value) fprintf(f,"%s\n", value); + else fprintf(f, "\n"); +} + +/** +* look if there is a cancel character on stdin +*/ +int xdg_vfs_chk_stdin(int wait_secs) +{ + /* check for canceled */ + int filedes = fileno (stdin); + int r; + fd_set set; + struct timeval timeout; + + + /* Initialize the file descriptor set. */ + FD_ZERO (&set); + FD_SET (filedes, &set); + + /* Initialize the timeout data structure. */ + timeout.tv_sec = wait_secs; + timeout.tv_usec = 0; + + /* select returns 0 if timeout, 1 if input available, -1 if error. */ + r= select (FD_SETSIZE, &set, NULL, NULL, &timeout); + if (r==0) return 0; + if (r==-1) + { + fprintf(stderr, "WARNING: Error when checking stdin for cancel character\n"); + return -1; /* error! */ + } + return 1; +} + +int xdg_vfs_chk_canceled(int opts) { + + if (!(opts & XDGVFS_OPT_CANCELABLE)) return 0; + + int r = xdg_vfs_chk_stdin(0)==1; + + if (r==1) + { + int c = getc(stdin); + if (c==DEFAULT_CANCEL_CHAR) return 1; + fprintf(stderr, "WARNING: Bad cancel character!\n"); + return 1; + } + return r; +} + +int empty_stdin() { /* not used */ + + /* fclean(stdin); */ + while (xdg_vfs_chk_stdin(0)==1) { + char buf[10]; + read(stdin, buf, 10); + } +} + + +/** +* print usage +*/ +int pusage(int opts) +{ + if (!(opts & XDGVFS_OPT_INTERACTIVE_MODE)) + fprintf(stderr, "Usage: xdg_vfs [command] [options] [filenames]\n"); + else + fprintf(stderr, "Usage: [command] [options] [filename]\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " Commands: \n"); + + fprintf(stderr, " backend : print backend infos\n"); + fprintf(stderr, " get [uri] : remote file->stdout\n"); + fprintf(stderr, " put [uri] : stdin->create remote file\n"); + fprintf(stderr, " info [uri] : stat a remote file\n"); + fprintf(stderr, " setattrs [uri] : set file attributes\n"); + fprintf(stderr, " cp [uri] [uri] : copy file\n"); + fprintf(stderr, " mv [uri] [uri] : move/rename file\n"); + fprintf(stderr, " rm [uri] : remove file\n"); + fprintf(stderr, " mkdir [uri] : make directory\n"); + fprintf(stderr, " rmdir [uri] : remove directory\n"); + fprintf(stderr, " ls [uri] : list directory\n"); + fprintf(stderr, " mount [id] : mount\n"); + fprintf(stderr, " openfiledlg [uri] : show file-save dialog\n"); + fprintf(stderr, " savefiledlg [uri] [fname] : show file-open dialog\n"); + if (!(opts & XDGVFS_OPT_INTERACTIVE_MODE)) + fprintf(stderr, " shell : interactive mode\n"); + else + fprintf(stderr, " quit : exit interactive mode\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " Options: \n"); + fprintf(stderr, " -t, --tagged : tagged mode (file-data should be escaped)\n"); + fprintf(stderr, " -i, --qry-fileinfo : qry file-info when retrieving a file\n"); + /* fprintf(stderr, " --show-metadata : show metadata when retrieving a file\n"); */ + fprintf(stderr, " requires tagged mode!\n"); + fprintf(stderr, " --dive-de-links : dive into desktop-entry links (if folders)\n"); + fprintf(stderr, " -m, --slow-mime : more accurate mime-type detection (slow)\n"); + fprintf(stderr, " -e, --escape-data : escape file data (for end of data detection)\n"); + fprintf(stderr, " -eXXX, --escape-data=XXX : set and use a user defined escape character\n"); + fprintf(stderr, " XXX = ascii code!\n"); + fprintf(stderr, " --cancelable : allow sending cancel character to stdin\n"); + fprintf(stderr, " --user= : setattrs: set user\n"); + fprintf(stderr, " --group= : setattrs: set group\n"); + fprintf(stderr, " --permissions= : set permissions when creating a file or dir\n"); + fprintf(stderr, " : or in setattrs\n"); + /* fprintf(stderr, " --end-seperator= : add a custom seperator inbetween blocks\n"); */ + fprintf(stderr, " --overwrite : allow overwriting files (put)\n"); + fprintf(stderr, " --instant-get : openfiledilog instant get file->stdout\n"); + fprintf(stderr, " --instant-put : savefiledilog instant put file from stdin\n"); + fprintf(stderr, " --title= : set dialog title\n"); + fprintf(stderr, " --progress : show progress when copying or moving a file\n"); + fprintf(stderr, "\n"); + return XDGVFS_ERRORCODE_BAD_PARAMETER ; +} + +/** +* count ordinary args +*/ +int countargs(int argc, char ** argv) +{ + int i; + int ctr=0; + for (i=0;i<argc;i++) + { + if (argv[i][0] != '-') + { + ctr++; + } + } + return ctr; +} + + +/** +* get n'th arg ignoring options +*/ +char * getarg(int argc, char ** argv, int nr) +{ + int i; + int ctr=0; + for (i=0;i<argc;i++) + { + if (argv[i][0] != '-') + { + if (ctr++==nr) return argv[i]; + } + } + return NULL; +} + +/** +* get certain option value +*/ +char * getoptarg(int argc, char ** argv, const char * optname) +{ + int i; + int ctr=0; + for (i=0;i<argc;i++) + { + if (strncmp (argv[i], optname, strlen(optname))==0) return argv[i]+strlen(optname); + } + return NULL; +} + +/** +* execute commands +*/ +int docommand(int argc, char ** argv, int globopts) +{ + char * command; char * s; char * title; + int cargs = countargs(argc, argv); + int opts = globopts; + int r; + + command = getarg(argc,argv, 1); + + if (!command) return pusage(opts); + + + if (getoptarg(argc,argv, "-t") || getoptarg(argc,argv, "--tagged")) + opts |= XDGVFS_OPT_TAGGED; + if (getoptarg(argc,argv, "-e") || getoptarg(argc,argv, "--escape-data")) + { + opts |= XDGVFS_OPT_DATAESCAPED; + s = getoptarg(argc,argv, "-e"); + if (s && strlen(s)>0) data_esc_char = atoi(s); + s = getoptarg(argc,argv, "--escape-data="); + if (s && strlen(s)>0) data_esc_char = atoi(s); + } + + if (getoptarg(argc,argv, "--permissions=")) + { + s = getoptarg(argc,argv, "--permissions="); + if (s && strlen(s)>0) + { + int perms= atoi(s); + xdgvfs_file_permissions = perms; + xdgvfs_dir_permissions = perms; + } + } + + if (getoptarg(argc,argv, "-m") || getoptarg(argc,argv, "--slow-mime")) + opts |= XDGVFS_OPT_SLOW_MIME_TYPE; + if (getoptarg(argc,argv, "--overwrite")) + opts |= XDGVFS_OPT_OVERWRITE; + + if (getoptarg(argc,argv, "--cancelable")) + opts |= XDGVFS_OPT_CANCELABLE; + + if (getoptarg(argc,argv, "--instant-get")) + opts |= XDGVFS_OPT_INSTANT_GET; + + if (getoptarg(argc,argv, "--instant-put")) + opts |= XDGVFS_OPT_INSTANT_PUT; + + if (getoptarg(argc,argv, "--dive-de-links")) + opts |= XDGVFS_OPT_DIVE_DE_LINKS; + + + if (getoptarg(argc,argv, "-i") || getoptarg(argc,argv, "--qry-fileinfo")) + opts |= XDGVFS_OPT_GET_FILEINFO; + + if (getoptarg(argc,argv, "--show-metadata")) + opts |= XDGVFS_OPT_SHOW_METADATA; + if (getoptarg(argc,argv, "-p") || getoptarg(argc,argv, "--progress")) + opts |= XDGVFS_OPT_PROGRESS; + + title=getoptarg(argc,argv, "--title="); + + + /* printf("debu=%d %d\n", opts, countargs(argc, argv)); */ + + /* get command? */ + if (cargs == 2 && strcmp(command, "backend")==0) + { + return xdg_vfs_backend(opts); + } + else if (cargs == 3 && strcmp(command, "get")==0) + { + return xdg_vfs_get(getarg(argc,argv, 2), opts); + /* info command? */ + } + else if (cargs == 3 && strcmp(command, "info")==0) + { + return xdg_vfs_getFileInfo(getarg(argc,argv, 2), opts); + } + else if (cargs == 3 && strcmp(command, "setattrs")==0) + { + XdgVfsSetFileInfoData fiData = { 0,0,0,0 }; + fiData.user = getoptarg(argc,argv, "--user="); + fiData.group = getoptarg(argc,argv, "--group="); + if (getoptarg(argc,argv, "--permissions=")) + { + s = getoptarg(argc,argv, "--permissions="); + if (s && strlen(s)>0) + { + fiData.perms=atoi(s); + fiData.setPermsFlag = 1; + } + } + return xdg_vfs_setFileInfo(getarg(argc,argv, 2), &fiData, opts); + /* ls caommand? */ + } + else if (cargs == 3 && strcmp(command, "ls")==0) + { + return xdg_vfs_dir(getarg(argc,argv, 2), opts); + /* mount command? */ + } + else if (cargs == 3 && strcmp(command, "mount")==0) + { + return xdg_vfs_mount(getarg(argc,argv, 2), opts); + /* mkdir command? */ + } + else if (cargs == 3 && strcmp(command, "mkdir")==0) + { + return xdg_vfs_mkdir(getarg(argc,argv, 2), xdgvfs_dir_permissions, opts); + } + else if (cargs == 3 && strcmp(command, "rmdir")==0) + { + return xdg_vfs_rmdir(getarg(argc,argv, 2), opts); + } + else if (cargs == 3 && strcmp(command, "put")==0) + { + return xdg_vfs_put(getarg(argc,argv, 2), xdgvfs_file_permissions, opts); + } + else if (cargs == 3 && strcmp(command, "rm")==0) + { + return xdg_vfs_rm(getarg(argc,argv, 2), opts); + } + else if (cargs == 3 && strcmp(command, "monfile")==0) + { + return xdg_vfs_monitor(getarg(argc,argv, 2), 0, opts); + } + else if (cargs == 3 && strcmp(command, "mondir")==0) + { + return xdg_vfs_monitor(getarg(argc,argv, 2), 1, opts); + } + else if (cargs == 3 && strcmp(command, "rmmon")==0) + { + return xdg_vfs_monitor_cancel(getarg(argc,argv, 2), opts); + } + else if (cargs >= 2 && strcmp(command, "openfiledlg")==0) + { + return xdg_vfs_openfiledlg(getarg(argc,argv, 2), NULL, title, opts); + } + else if (cargs >= 2 && strcmp(command, "savefiledlg")==0) + { + return xdg_vfs_savefiledlg(getarg(argc,argv, 2),getarg(argc,argv, 3), + title, xdgvfs_file_permissions, opts); + } + else if (cargs == 4 && strcmp(command, "cp")==0) + { + return xdg_vfs_cp(getarg(argc,argv, 2),getarg(argc,argv, 3), xdgvfs_file_permissions, 0, opts); + } + else if (cargs == 4 && strcmp(command, "mv")==0) + { + return xdg_vfs_cp(getarg(argc,argv, 2),getarg(argc,argv, 3), xdgvfs_file_permissions, 1, opts); + } + else + { + return pusage(opts); + } + return 1; +} + +/** +* main() function +*/ +int xdg_vfs_main(int argc, char ** argv) +{ + if (argc < 2) + { + return pusage(0); + } + + xdg_vfs_init_desklib(argc, argv); + + /* SHELL mode */ + if (countargs(argc,argv)==2 && strcmp(getarg(argc,argv, 1), "shell")==0) + { + while(1) + { + char * lineptr = NULL; + ssize_t len; + size_t n = 0; + + char ** av = calloc(SHELL_MAXARGS, sizeof(char*)); + av[0] = "shell"; + int ac = 1; + + int rcode; + + fprintf(stdout, "> "); + fflush(stdout); + xdg_vfs_monitor_list_events(0); + while (!xdg_vfs_iterate_mainloop_until_incoming_data(fileno(stdin))) + { + xdg_vfs_monitor_list_events(0); + } + len=getline (&lineptr, &n, stdin); + + if (len<0) { + if (len=EOF) { + fprintf(stderr, "xdg-vfs shell mode: stdin closed -> exit\n"); + exit(XDGVFS_ERRORCODE_IO_ERROR); + } + perror("xdg-vfs shell mode: stdin problem -> exit"); + exit(XDGVFS_ERRORCODE_IO_ERROR); + } + + /* printf("lineptr=%s len=%d\n", lineptr, len); */ + /* while(ac < SHELL_MAXARGS && (av[ac]=strtok(ac==1 ? lineptr : NULL, " \n")) ) + ac++; */ + + { + char * lout = calloc(strlen(lineptr)+1,1); + int c=0; + int co=0; + av[ac++] = lout; /* first arg */ + int parsing_error=0; + while(lineptr[c]!='\0') /* read shell line into arg array */ + { + if (lineptr[c] == '"') /* quoted strings */ + { + c++; + while(lineptr[c]!='\0') + { + if (lineptr[c] == '\\') + { + + c++; + if (lineptr[c]=='\\' || lineptr[c]=='"') + { + lout[co++] = lineptr[c++]; + continue; + } else + { + fprintf(stderr, "ERROR: Only '\\' or '\"' are allowed to be escaped with '\\' inside double quotes in shell mode!!!\n"); + parsing_error=1; + } + + } else + { + if (lineptr[c] == '"') + { + c++; + break; + } + lout[co++] = lineptr[c++]; + } + } + + } + + if (lineptr[c] == ' ') + { + lout[co] = '\0'; + av[ac++] = lout+co+1; + co++; + if (ac >= SHELL_MAXARGS) return XDGVFS_ERRORCODE_BAD_PARAMETER; + } else if (lineptr[c] == '\n') + { + /* skip newline */ + } + else + { + lout[co++] = lineptr[c]; + } + c++; + } + + /* if (debug_mode) fprintf(stderr,"av= %s|%s|%s|%s|%s|%s n=%d\n", av[0], av[1], av[2], av[3], av[4],av[5],ac); */ + + if (av[1] && strcmp(av[1], "quit")==0) + { + fprintf(stderr, "BYE!\n"); + return 0; + } + + if (!parsing_error) + { + rcode = docommand(ac,av, XDGVFS_OPT_INTERACTIVE_MODE | XDGVFS_OPT_TAGGED); + if (rcode==0) fprintf(stdout, "%s\n", XDGVFS_TAG_DONE); + else fprintf(stdout, "%s %d\n", XDGVFS_TAG_FAILED, rcode); + } + else + { + fprintf(stdout, "%s %d\n", XDGVFS_TAG_FAILED, XDGVFS_ERRORCODE_BAD_PARAMETER); + } + + free(lineptr); + free(av); + free(lout); + xdg_vfs_iterate_mainloop(); + } + } + /* single command mode */ + } + else + { + return docommand(argc,argv, 0); + } + +} + + + diff --git a/xdg-vfs-gnome/src/xdg_vfs.h b/xdg-vfs-gnome/src/xdg_vfs.h new file mode 100644 index 0000000..26a87b9 --- /dev/null +++ b/xdg-vfs-gnome/src/xdg_vfs.h @@ -0,0 +1,135 @@ +/* +# xdg_vfs.h +# +# Copyright 2006, Norbert Frese +# +# LICENSE: +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +#---------------------------------------------*/ + +#ifndef XDG_VFS_H +#define XDG_VFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/stat.h> + +#define DATA_BUF_SIZE 4096 +#define SHELL_MAXARGS 30 + +#define XDGVFS_DEFAULT_FILE_PERMISSIONS S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH +#define XDGVFS_DEFAULT_DIR_PERMISSIONS S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IXOTH + + + + +/* cli option flags */ + +#define XDGVFS_OPT_TAGGED 1 +#define XDGVFS_OPT_DATAESCAPED 2 +#define XDGVFS_OPT_SLOW_MIME_TYPE 4 +#define XDGVFS_OPT_GET_FILEINFO 8 +#define XDGVFS_OPT_INSTANT_GET 16 +#define XDGVFS_OPT_INSTANT_PUT 32 +#define XDGVFS_OPT_OVERWRITE 64 +#define XDGVFS_OPT_SHOW_METADATA 128 +#define XDGVFS_OPT_INTERACTIVE_MODE 256 +#define XDGVFS_OPT_PROGRESS 512 +#define XDGVFS_OPT_CANCELABLE 1024 +#define XDGVFS_OPT_DIVE_DE_LINKS 2048 + + + +#define XDGVFS_TEXT_SAVEFILEDLG_TITLE "Save File" +#define XDGVFS_TEXT_OPENFILEDLG_TITLE "Open File" + +typedef struct { + const char * user; + const char * group; + unsigned int perms; + int setPermsFlag; +} XdgVfsSetFileInfoData; + +/* implementation independent functions */ + +int xdg_vfs_main(int argc, char ** argv); + +int xdg_vfs_getDataEscChar(); + +char * xdg_vfs_getCustomEndSeparator(); + +void xdg_vfs_ppair_str(FILE * f, const char * key, const char * value, int opts); + +int xdg_vfs_chk_canceled(int opts); + +/* implementation functions */ + +int xdg_vfs_init_desklib(int argc, char** argv); + +int xdg_vfs_iterate_mainloop(); + +int xdg_vfs_iterate_mainloop_until_incoming_data(int fd); + +/* command implementations */ + +int xdg_vfs_backend(int opts); + +int xdg_vfs_dir(const char * text_uri, int opts); + +int xdg_vfs_mount(const char * mountpoint_id, int opts); + +int xdg_vfs_getFileInfo(const char * text_uri, int opts); + +int xdg_vfs_setFileInfo(const char * text_uri, XdgVfsSetFileInfoData * fiData, int opts); + +int xdg_vfs_get(const char * text_uri, int opts); + +int xdg_vfs_put(const char * text_uri, int perms, int opts); + +int xdg_vfs_cp(const char * text_uri_src, const char * text_uri_target, unsigned int perms, int move_flag, int opts); + +int xdg_vfs_mkdir(const char * text_uri, unsigned int perms, int opts); + +int xdg_vfs_rmdir(const char * text_uri, int opts); + +int xdg_vfs_rm(const char * text_uri, int opts); + +int xdg_vfs_openfiledlg(const char * default_dir, const char * default_filename, const char * title, int opts); + +int xdg_vfs_savefiledlg(const char * default_dir, const char * default_filename, + const char * title, unsigned int perms, int opts); + +int xdg_vfs_monitor(char * uri, int is_directory, int opts); + +int xdg_vfs_monitor_cancel(char * uri, int opts); + +int xdg_vfs_monitor_list_events(int opts); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/xdg-vfs-gnome/src/xdg_vfs_common.h b/xdg-vfs-gnome/src/xdg_vfs_common.h new file mode 100644 index 0000000..3963983 --- /dev/null +++ b/xdg-vfs-gnome/src/xdg_vfs_common.h @@ -0,0 +1,146 @@ +/* +# xdg_vfs_common.h +# +# Copyright 2006, Norbert Frese +# +# LICENSE: +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +#---------------------------------------------*/ + +#ifndef XDG_VFS_COMMON_H +#define XDG_VFS_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define DEFAULT_DATA_ESC_CHAR 126 +#define DEFAULT_CANCEL_CHAR (int)'!' + +/* error codes */ + +#define XDGVFS_ERRORCODE_OK 0 +#define XDGVFS_ERRORCODE_CANCELED 10 +#define XDGVFS_ERRORCODE_BAD_PARAMETER 11 +#define XDGVFS_ERRORCODE_NOT_SUPPORTED 12 +#define XDGVFS_ERRORCODE_GENERIC 13 +#define XDGVFS_ERRORCODE_INIT_ERROR 14 +#define XDGVFS_ERRORCODE_DATA_ERROR 15 +#define XDGVFS_ERRORCODE_IO_ERROR 16 +#define XDGVFS_ERRORCODE_NOT_PERMITTED 17 +#define XDGVFS_ERRORCODE_MALFORMED_URL 18 +#define XDGVFS_ERRORCODE_PROTOCOL_ERROR 19 +#define XDGVFS_ERRORCODE_USR_OR_GRP_NOT_FOUND 20 +#define XDGVFS_ERRORCODE_INTERNAL 21 +#define XDGVFS_ERRORCODE_CANNOT_OPEN_FOR_WRITING 22 +#define XDGVFS_ERRORCODE_CANNOT_OPEN_FOR_READING 23 +#define XDGVFS_ERRORCODE_IS_DIRECTORY 24 +#define XDGVFS_ERRORCODE_IS_FILE 25 +#define XDGVFS_ERRORCODE_NOT_FOUND 26 +#define XDGVFS_ERRORCODE_ALREADY_EXISTS 27 +#define XDGVFS_ERRORCODE_HOST_NOT_FOUND 28 +#define XDGVFS_ERRORCODE_ACCESS_DENIED 29 +#define XDGVFS_ERRORCODE_CANNOT_ENTER_DIRECTORY 30 +#define XDGVFS_ERRORCODE_PROTOCOL_IS_NOT_A_FILESYSTEM 31 +#define XDGVFS_ERRORCODE_LOOP 32 +#define XDGVFS_ERRORCODE_COULD_NOT_CREATE_SOCKET 33 +#define XDGVFS_ERRORCODE_COULD_NOT_CONNECT 34 +#define XDGVFS_ERRORCODE_ERR_CONNECTION_BROKEN 35 +#define XDGVFS_ERRORCODE_COULD_NOT_MOUNT 36 +#define XDGVFS_ERRORCODE_COULD_NOT_UNMOUNT 37 +#define XDGVFS_ERRORCODE_SOCKET_ERROR 38 +#define XDGVFS_ERRORCODE_LOGIN_FAILED 39 +#define XDGVFS_ERRORCODE_OPERATION_FAILED 40 +#define XDGVFS_ERRORCODE_CANNOT_RESUME 41 +#define XDGVFS_ERRORCODE_OUT_OF_MEMORY 42 +#define XDGVFS_ERRORCODE_UNKNOWN_PROXY_HOST 43 +#define XDGVFS_ERRORCODE_ABORTED 44 +#define XDGVFS_ERRORCODE_TIMEOUT 45 +#define XDGVFS_ERRORCODE_SERVICE_NOT_AVAILABLE 46 +#define XDGVFS_ERRORCODE_CANNOT_DELETE_ORIGINAL 47 +#define XDGVFS_ERRORCODE_CANNOT_DELETE_PARTIAL 48 +#define XDGVFS_ERRORCODE_CANNOT_RENAME_ORIGINAL 49 +#define XDGVFS_ERRORCODE_CANNOT_RENAME_PARTIAL 50 +#define XDGVFS_ERRORCODE_NEED_PASSWD 51 +#define XDGVFS_ERRORCODE_NO_CONTENT 52 +#define XDGVFS_ERRORCODE_NO_SPACE 53 +#define XDGVFS_ERRORCODE_IDENTICAL_FILES 54 +#define XDGVFS_ERRORCODE_CORRUPTED_DATA 55 +#define XDGVFS_ERRORCODE_WRONG_FORMAT 56 +#define XDGVFS_ERRORCODE_ERROR_BAD_FILE 66 +#define XDGVFS_ERRORCODE_TOO_BIG 67 +#define XDGVFS_ERRORCODE_NOT_OPEN 68 +#define XDGVFS_ERRORCODE_INVALID_OPEN_MODE 69 +#define XDGVFS_ERRORCODE_TOO_MANY_OPEN_FILES 70 +#define XDGVFS_ERRORCODE_EOF 71 +#define XDGVFS_ERRORCODE_IN_PROGRESS 72 +#define XDGVFS_ERRORCODE_INTERRUPTED 73 +#define XDGVFS_ERRORCODE_HOST_HAS_NO_ADDRESS 74 +#define XDGVFS_ERRORCODE_DIRECTORY_NOT_EMPTY 75 +#define XDGVFS_ERRORCODE_TOO_MANY_LINKS 76 +#define XDGVFS_ERRORCODE_READ_ONLY_FILE_SYSTEM 77 +#define XDGVFS_ERRORCODE_NOT_SAME_FILE_SYSTEM 78 +#define XDGVFS_ERRORCODE_NAME_TOO_LONG 79 +#define XDGVFS_ERRORCODE_SERVICE_OBSOLETE 80 +#define XDGVFS_ERRORCODE_NO_DEFAULT 81 +#define XDGVFS_ERRORCODE_NAMESERVER 82 +#define XDGVFS_ERRORCODE_LOCKED 83 +#define XDGVFS_ERRORCODE_DEPRECATED_FUNCTION 84 +#define XDGVFS_ERRORCODE_DIRECTORY_BUSY 85 +#define XDGVFS_ERRORCODE_NOT_A_DIRECTORY 86 + + +/* tags (private!) */ + +#define XDGVFS_TAG_DATA_OUT "(>>>RAW_DATA>>>)" +#define XDGVFS_TAG_ESCAPEDDATA_OUT "(>>>ESCAPED_DATA>>>)" +#define XDGVFS_TAG_DATA_IN "(<<<RAW_DATA<<<)" +#define XDGVFS_TAG_ESCAPEDDATA_IN "(<<<ESCAPED_DATA<<<)" + +#define XDGVFS_TAG_BACKEND "[BACKEND]" +#define XDGVFS_TAG_GET "[GET]" +#define XDGVFS_TAG_PUT "[PUT]" +#define XDGVFS_TAG_CP "[CP]" +#define XDGVFS_TAG_MV "[MV]" +#define XDGVFS_TAG_LS "[LS]" +#define XDGVFS_TAG_FILEINFO "[FILEINFO]" +#define XDGVFS_TAG_SETATTRS "[SETATTRS]" +#define XDGVFS_TAG_SAVEFILEDLG "[SAVEFILEDLG]" +#define XDGVFS_TAG_OPENFILEDLG "[OPENFILEDLG]" +#define XDGVFS_TAG_MKDIR "[MKDIR]" +#define XDGVFS_TAG_RMDIR "[RMDIR]" +#define XDGVFS_TAG_RM "[RM]" +#define XDGVFS_TAG_MOUNT "[MOUNT]" +#define XDGVFS_TAG_MONITOREVENT "*" + + +#define XDGVFS_TAG_METADATA "(METADATA)" +#define XDGVFS_TAG_DIRENTRY "(DIRENTRY)" +#define XDGVFS_TAG_PROGRESS "(PROGRESS)" + +#define XDGVFS_TAG_DONE ":-)" +#define XDGVFS_TAG_FAILED ":-(" + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/xdg-vfs-gnome/src/xdg_vfs_gnome.c b/xdg-vfs-gnome/src/xdg_vfs_gnome.c new file mode 100644 index 0000000..de13dba --- /dev/null +++ b/xdg-vfs-gnome/src/xdg_vfs_gnome.c @@ -0,0 +1,1099 @@ +/* +# xdg_vfs_gnome.c +# +# Copyright 2006, Norbert Frese +# +# LICENSE: +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +#---------------------------------------------*/ + +/** + * READ: + * http://cvs.gnome.org/viewcvs/libgnomeui/file-chooser/ + * http://cvs.gnome.org/viewcvs/libgnomeui/libgnomeui/gnome-icon-lookup.c + * http://standards.freedesktop.org/desktop-entry-spec/ + * http://developer.gimp.org/api/2.0/glib/glib-Key-value-file-parser.html + * http://developer.gnome.org/doc/API/2.0/gnome-vfs-2.0/ + * + */ + + +#include <string.h> + +#include <gtk/gtk.h> +#include <libgnomevfs/gnome-vfs.h> +#include <libgnomeui/libgnomeui.h> +#include <time.h> + +#include <pwd.h> +#include <grp.h> + +#include "xdg_vfs_common.h" +#include "xdg_vfs.h" +#include "xdg_vfs_gnome.h" + +#define DESKTOP_GROUP "Desktop Entry" + + +/* +* translate error codes +*/ +typedef struct +{ + GnomeVFSResult result; + int xdgVfsErr; +} MapGnomeVFSResult; + +MapGnomeVFSResult mapGVFSErrArr[] = +{ + { GNOME_VFS_OK , XDGVFS_ERRORCODE_OK } , + { GNOME_VFS_ERROR_NOT_FOUND , XDGVFS_ERRORCODE_NOT_FOUND } , + { GNOME_VFS_ERROR_GENERIC , XDGVFS_ERRORCODE_GENERIC } , + { GNOME_VFS_ERROR_INTERNAL , XDGVFS_ERRORCODE_INTERNAL } , + { GNOME_VFS_ERROR_BAD_PARAMETERS , XDGVFS_ERRORCODE_BAD_PARAMETER } , + { GNOME_VFS_ERROR_NOT_SUPPORTED , XDGVFS_ERRORCODE_NOT_SUPPORTED } , + { GNOME_VFS_ERROR_IO , XDGVFS_ERRORCODE_IO_ERROR } , + { GNOME_VFS_ERROR_CORRUPTED_DATA , XDGVFS_ERRORCODE_CORRUPTED_DATA } , + { GNOME_VFS_ERROR_WRONG_FORMAT , XDGVFS_ERRORCODE_WRONG_FORMAT } , + { GNOME_VFS_ERROR_BAD_FILE , XDGVFS_ERRORCODE_ERROR_BAD_FILE } , + { GNOME_VFS_ERROR_TOO_BIG , XDGVFS_ERRORCODE_TOO_BIG } , + { GNOME_VFS_ERROR_NO_SPACE , XDGVFS_ERRORCODE_NO_SPACE } , + { GNOME_VFS_ERROR_READ_ONLY , XDGVFS_ERRORCODE_CANNOT_OPEN_FOR_WRITING } , + { GNOME_VFS_ERROR_INVALID_URI , XDGVFS_ERRORCODE_MALFORMED_URL } , + { GNOME_VFS_ERROR_NOT_OPEN , XDGVFS_ERRORCODE_NOT_OPEN } , + { GNOME_VFS_ERROR_INVALID_OPEN_MODE , XDGVFS_ERRORCODE_INVALID_OPEN_MODE } , + { GNOME_VFS_ERROR_ACCESS_DENIED , XDGVFS_ERRORCODE_ACCESS_DENIED } , + { GNOME_VFS_ERROR_TOO_MANY_OPEN_FILES , XDGVFS_ERRORCODE_TOO_MANY_OPEN_FILES } , + { GNOME_VFS_ERROR_EOF , XDGVFS_ERRORCODE_EOF } , + { GNOME_VFS_ERROR_NOT_A_DIRECTORY , XDGVFS_ERRORCODE_NOT_A_DIRECTORY } , + { GNOME_VFS_ERROR_IN_PROGRESS , XDGVFS_ERRORCODE_IN_PROGRESS } , + { GNOME_VFS_ERROR_INTERRUPTED , XDGVFS_ERRORCODE_INTERRUPTED } , + { GNOME_VFS_ERROR_FILE_EXISTS , XDGVFS_ERRORCODE_ALREADY_EXISTS } , + { GNOME_VFS_ERROR_LOOP , XDGVFS_ERRORCODE_LOOP } , + { GNOME_VFS_ERROR_NOT_PERMITTED , XDGVFS_ERRORCODE_NOT_PERMITTED } , + { GNOME_VFS_ERROR_IS_DIRECTORY , XDGVFS_ERRORCODE_IS_DIRECTORY } , + { GNOME_VFS_ERROR_NO_MEMORY , XDGVFS_ERRORCODE_OUT_OF_MEMORY } , + { GNOME_VFS_ERROR_HOST_NOT_FOUND , XDGVFS_ERRORCODE_HOST_NOT_FOUND } , + { GNOME_VFS_ERROR_INVALID_HOST_NAME , XDGVFS_ERRORCODE_HOST_NOT_FOUND } , + { GNOME_VFS_ERROR_HOST_HAS_NO_ADDRESS , XDGVFS_ERRORCODE_HOST_HAS_NO_ADDRESS } , + { GNOME_VFS_ERROR_LOGIN_FAILED , XDGVFS_ERRORCODE_LOGIN_FAILED } , + { GNOME_VFS_ERROR_CANCELLED , XDGVFS_ERRORCODE_CANCELED } , + { GNOME_VFS_ERROR_DIRECTORY_BUSY , XDGVFS_ERRORCODE_DIRECTORY_BUSY } , + { GNOME_VFS_ERROR_DIRECTORY_NOT_EMPTY , XDGVFS_ERRORCODE_DIRECTORY_NOT_EMPTY } , + { GNOME_VFS_ERROR_TOO_MANY_LINKS , XDGVFS_ERRORCODE_TOO_MANY_LINKS } , + { GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM , XDGVFS_ERRORCODE_READ_ONLY_FILE_SYSTEM } , + { GNOME_VFS_ERROR_NOT_SAME_FILE_SYSTEM , XDGVFS_ERRORCODE_NOT_SAME_FILE_SYSTEM } , + { GNOME_VFS_ERROR_NAME_TOO_LONG , XDGVFS_ERRORCODE_NAME_TOO_LONG } , + { GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE , XDGVFS_ERRORCODE_SERVICE_NOT_AVAILABLE } , + { GNOME_VFS_ERROR_SERVICE_OBSOLETE , XDGVFS_ERRORCODE_SERVICE_OBSOLETE } , + { GNOME_VFS_ERROR_PROTOCOL_ERROR , XDGVFS_ERRORCODE_PROTOCOL_ERROR } , + { GNOME_VFS_ERROR_NO_MASTER_BROWSER , XDGVFS_ERRORCODE_INTERNAL } , + { GNOME_VFS_ERROR_NO_DEFAULT , XDGVFS_ERRORCODE_NO_DEFAULT } , + { GNOME_VFS_ERROR_NO_HANDLER , XDGVFS_ERRORCODE_PROTOCOL_ERROR } , + { GNOME_VFS_ERROR_PARSE , XDGVFS_ERRORCODE_CORRUPTED_DATA } , + { GNOME_VFS_ERROR_LAUNCH , XDGVFS_ERRORCODE_INIT_ERROR } , + { GNOME_VFS_ERROR_TIMEOUT , XDGVFS_ERRORCODE_TIMEOUT } , + { GNOME_VFS_ERROR_NAMESERVER , XDGVFS_ERRORCODE_NAMESERVER } , + { GNOME_VFS_ERROR_LOCKED , XDGVFS_ERRORCODE_LOCKED } , + { GNOME_VFS_ERROR_DEPRECATED_FUNCTION , XDGVFS_ERRORCODE_DEPRECATED_FUNCTION } +}; + +int translate_GnomeVFSResult(GnomeVFSResult result) +{ + int i; + for (i=0;i<sizeof(mapGVFSErrArr)/sizeof(MapGnomeVFSResult);i++) + { + /* printf(" %d %d\n", mapErrArr[i].kioErr, mapErrArr[i].xdgVfsErr); */ + if (mapGVFSErrArr[i].result == result) return mapGVFSErrArr[i].xdgVfsErr; + } + return XDGVFS_ERRORCODE_GENERIC; + +} + +/** +* initialize gnome +*/ +int xdg_vfs_init_desklib(int argc, char** argv) +{ + GnomeProgram *my_app; + GOptionContext *option_context; + + my_app = gnome_program_init(PACKAGE, VERSION, LIBGNOMEUI_MODULE, + argc, argv, GNOME_PARAM_NONE); + + gnome_authentication_manager_init(); + + if (!gnome_vfs_init ()) + { + fprintf(stderr, "Count not init Gnome-VFS!\n"); + return XDGVFS_ERRORCODE_INIT_ERROR; + } + + return 0; +} + +/** +* finish pending GUI-events +*/ +int xdg_vfs_iterate_mainloop() +{ + while (g_main_context_pending (NULL)) + g_main_context_iteration(NULL, FALSE); +} + +/** +* print gnome-vfs error +*/ +int print_and_translate_result(GnomeVFSResult result) +{ + const gchar * s; + s = gnome_vfs_result_to_string (result); + + fprintf(stderr, "ERROR: GnomeVFSResult=%s\n",s); + //free(s); + return translate_GnomeVFSResult(result); +} + +#define READ_ENTIRE_FILE_INITAL_BUFSIZE 100 +/** + * read entire file for desktop files + */ +GnomeVFSResult _gnome_vfs_readEntireFile(const char * text_uri, size_t * size, char ** fileData, int opts) +{ + char * buffer = malloc(READ_ENTIRE_FILE_INITAL_BUFSIZE); + size_t bufSize = READ_ENTIRE_FILE_INITAL_BUFSIZE; + GnomeVFSFileSize bytes_read; + int pos=0; + char * full_uri = gnome_vfs_make_uri_from_input(text_uri); + GnomeVFSHandle *handle; + GnomeVFSResult r; + + *fileData = NULL; + + r=gnome_vfs_open(&handle, full_uri, GNOME_VFS_OPEN_READ); + if (r!=GNOME_VFS_OK) + { + return r; + } + + while (1) + { + if (bufSize-pos <= 1) { + bufSize += READ_ENTIRE_FILE_INITAL_BUFSIZE; + buffer = realloc(buffer, bufSize); + } + + r=gnome_vfs_read(handle, buffer+pos, bufSize - pos, &bytes_read); + //fprintf(stderr, "gnome-vfs-read fname=%s, pos=%d bufSize=%d bytes_read=%d\n", full_uri, pos, bufSize, bytes_read); + + if (r!=GNOME_VFS_OK) + { + if (r==GNOME_VFS_ERROR_EOF) { + break; + } + free(buffer); + gnome_vfs_close (handle); + return r; + } + pos += bytes_read; + + } +/* if (pos != size) { + free(buffer); + fprintf(stderr, "Reading entire file problem pos=%d != size=%d\n", pos, size); + gnome_vfs_close (handle); + return GNOME_VFS_ERROR_IO; + } */ + *fileData = buffer; + *size = pos; + return GNOME_VFS_OK; +} + + +GnomeVFSResult _follow_desktop_link(const char * filename, int opts) { + GnomeVFSResult r; + GKeyFile *desktop_file; + char * desktop_file_data; + size_t desktop_file_data_size; + GError * gerror = NULL; + + desktop_file = g_key_file_new (); + + r = _gnome_vfs_readEntireFile(filename, &desktop_file_data_size, &desktop_file_data, opts); + if (r != GNOME_VFS_OK) return r; + + int parseR = g_key_file_load_from_data(desktop_file, + desktop_file_data, + desktop_file_data_size, + G_KEY_FILE_NONE, + &gerror); + g_free(desktop_file_data); + if (!parseR) { + if (gerror != NULL) + { + fprintf (stderr, "Unable to parse desktop file: %s\n", gerror->message); + g_error_free (gerror); + g_key_file_free (desktop_file); + } + } + + gchar *name; + gchar *type; + gchar *URL; + gchar *icon; + + type = g_key_file_get_value (desktop_file, DESKTOP_GROUP, "Type", NULL); + + if (!strncmp (type, "Link", 4) && !strncmp (type, "FSDevice", 8)) + { + g_free(type); + g_key_file_free (desktop_file); + return ! GNOME_VFS_OK; + } + + name = g_key_file_get_value (desktop_file, DESKTOP_GROUP, "Name", NULL); + + + + URL = g_key_file_get_value (desktop_file, DESKTOP_GROUP, "URL", NULL); + + icon = g_key_file_get_value (desktop_file, DESKTOP_GROUP, "Icon", NULL); + + if (name) fprintf (stdout, "basename=%s\n", name); + if (type) fprintf (stdout, "# de type=%s\n", type); + if (URL) fprintf (stdout, "uri=%s\n", URL); + if (icon) fprintf (stdout, "iconname=%s\n", icon); + + fprintf(stdout, "filetype=DIRECTORY\n"); + + /* + ret = + g_free (type); + */ + + g_free(name); + g_free(type); + g_free(URL); + g_free(icon); + + g_key_file_free (desktop_file); + + return GNOME_VFS_OK; + +} + +/** +* print fileinfo in key-value pair style +*/ +void xdg_gnome_vfs_printFileInfo(FILE * f, const char * full_uri, GnomeVFSFileInfo * info, int opts) +{ + + GnomeVFSFileInfoFields valid = info->valid_fields; + int did_de_dive = 0; + + + if (opts & XDGVFS_OPT_DIVE_DE_LINKS) + { + + if ((info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE) != 0 + && strcmp (gnome_vfs_file_info_get_mime_type (info), "application/x-desktop") == 0) + { + + if (_follow_desktop_link(full_uri, opts) == GNOME_VFS_OK) + { + // fprintf(stderr, "dive!\n"); + return; + } + + } + } + + fprintf(f, "basename=%s\n", info->name); + + if (valid & GNOME_VFS_FILE_INFO_FIELDS_SIZE) + { + fprintf(f, "size=%u\n", info->size); + } + if (1) + { + struct passwd * passwdEntry; + struct group * groupEntry; + + passwdEntry = getpwuid ((uid_t)info->uid); + if (passwdEntry) + { + xdg_vfs_ppair_str(f, "user", passwdEntry->pw_name, opts); + } + + groupEntry = getgrgid ((gid_t)info->gid); + if (groupEntry) + { + xdg_vfs_ppair_str(f, "group", groupEntry->gr_name, opts); + } + + /* fprintf(f, "userid=%d\n", info->uid); + fprintf(f, "groupid=%d\n", info->gid); */ + } + + if (valid & GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS) + { + fprintf(f, "permissions=%d\n", info->permissions); + } + + if (valid & GNOME_VFS_FILE_INFO_FIELDS_MTIME) + { + fprintf(f, "mtime=%d\n", info->mtime); + } + + if (valid & GNOME_VFS_FILE_INFO_FIELDS_ATIME) + { + fprintf(f, "atime=%d\n", info->atime); + } + + if (valid & GNOME_VFS_FILE_INFO_FIELDS_CTIME) + { + fprintf(f, "ctime=%d\n", info->ctime); + } + + if (valid & GNOME_VFS_FILE_INFO_FIELDS_TYPE) + { + char * tstr="UNKNOWN"; + + switch(info->type) + { + case(GNOME_VFS_FILE_TYPE_UNKNOWN): tstr = "UNKNOWN"; break; + case(GNOME_VFS_FILE_TYPE_REGULAR): tstr = "REGULAR"; break; + case(GNOME_VFS_FILE_TYPE_DIRECTORY): tstr = "DIRECTORY"; break; + case(GNOME_VFS_FILE_TYPE_FIFO): tstr = "FIFO"; break; + case(GNOME_VFS_FILE_TYPE_SOCKET): tstr = "SOCKET"; break; + case(GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE): tstr = "CHARDEV"; break; + case(GNOME_VFS_FILE_TYPE_BLOCK_DEVICE): tstr = "BLOCKDEV"; break; + case(GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK): tstr = "SYMLINK"; break; + /* default: tstr = "UNKNOWN"; break; */ + } + fprintf(f, "filetype=%s\n", tstr); + + } + + if (valid & GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME) + { + fprintf(f, "linkdest=%s\n", info->symlink_name); + } + + if (valid & GNOME_VFS_FILE_INFO_FIELDS_SIZE) + { + fprintf(f, "mimetype=%s\n", info->mime_type); + } + + GnomeIconLookupResultFlags iconLookupResultFlags; + char * iconname = gnome_icon_lookup (gtk_icon_theme_get_default (), + NULL, + NULL /* const char *file_uri */, + NULL, + info, + info->mime_type, + GNOME_ICON_LOOKUP_FLAGS_NONE, + &iconLookupResultFlags); + if (iconname) fprintf(f, "iconname=%s\n", iconname); + g_free(iconname); + + xdg_vfs_ppair_str(stdout, "uri", full_uri, opts); + + if (xdg_vfs_getCustomEndSeparator()) + fprintf(stdout, "\n%s\n", xdg_vfs_getCustomEndSeparator()); +} + + +/** +* Command: fileinfo +*/ +int xdg_vfs_getFileInfo(const char * text_uri, int opts) +{ + GnomeVFSResult r; + GnomeVFSFileInfo * info = gnome_vfs_file_info_new (); + char * full_uri = gnome_vfs_make_uri_from_input(text_uri); + + if (opts & XDGVFS_OPT_TAGGED) puts(XDGVFS_TAG_FILEINFO); + + GnomeVFSFileInfoOptions infoOpts = GNOME_VFS_FILE_INFO_FOLLOW_LINKS | GNOME_VFS_FILE_INFO_GET_MIME_TYPE; + + if (opts & XDGVFS_OPT_SLOW_MIME_TYPE) infoOpts |= GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE; + + r=gnome_vfs_get_file_info(full_uri, + info, + infoOpts); + xdg_vfs_iterate_mainloop(); + + if (r!=GNOME_VFS_OK) + { + g_free(full_uri); + gnome_vfs_file_info_unref (info); + return print_and_translate_result(r); + } + + xdg_gnome_vfs_printFileInfo(stdout, full_uri, info, opts); + + + gnome_vfs_file_info_unref (info); + g_free(full_uri); + return 0; +} + +/** +* Command: setattrs +*/ +int xdg_vfs_setFileInfo(const char * text_uri, XdgVfsSetFileInfoData * fiData, int opts) +{ + GnomeVFSResult r; + char * full_uri = gnome_vfs_make_uri_from_input(text_uri); + struct passwd * passwdEntry; + struct group * groupEntry; + GnomeVFSFileInfo * info = gnome_vfs_file_info_new (); + info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_NONE; + GnomeVFSSetFileInfoMask setFileInfoMask = GNOME_VFS_SET_FILE_INFO_NONE; + + if (opts & XDGVFS_OPT_TAGGED) puts(XDGVFS_TAG_SETATTRS); + + if (fiData->user) + { + passwdEntry = getpwnam(fiData->user); + if (passwdEntry) + { + setFileInfoMask |= GNOME_VFS_SET_FILE_INFO_OWNER; + + info->uid = passwdEntry->pw_uid; + } + else + { + fprintf(stderr, "ERROR: User '%s' not found in passwd\n", fiData->user); + gnome_vfs_file_info_unref (info); g_free(full_uri); + return XDGVFS_ERRORCODE_USR_OR_GRP_NOT_FOUND; + } + } + + if (fiData->group) + { + groupEntry = getgrnam(fiData->group); + if (groupEntry) + { + setFileInfoMask |= GNOME_VFS_SET_FILE_INFO_OWNER; + info->gid = groupEntry->gr_gid; + } + else + { + fprintf(stderr, "ERROR: Group '%s' not found in group database\n", fiData->group); + gnome_vfs_file_info_unref (info); g_free(full_uri); + return XDGVFS_ERRORCODE_USR_OR_GRP_NOT_FOUND; + } + } + + if (fiData->setPermsFlag) + { + setFileInfoMask |= GNOME_VFS_SET_FILE_INFO_PERMISSIONS; + info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS; + info->permissions = fiData->perms; + } + + r = gnome_vfs_set_file_info(full_uri, info, setFileInfoMask); + + xdg_vfs_iterate_mainloop(); + + if (r!=GNOME_VFS_OK) + { + g_free(full_uri); + gnome_vfs_file_info_unref (info); + return print_and_translate_result(r); + } + + xdg_vfs_ppair_str(stdout, "uri", full_uri, opts); + + gnome_vfs_file_info_unref (info); + g_free(full_uri); + return XDGVFS_ERRORCODE_OK; +} + +/** +* Command: list directory +*/ +int xdg_vfs_dir(const char * text_uri, int opts) +{ + GnomeVFSResult r; + GnomeVFSDirectoryHandle *handle; + char * full_uri = gnome_vfs_make_uri_from_input(text_uri); + GnomeVFSFileInfo * info = gnome_vfs_file_info_new (); + + if (opts & XDGVFS_OPT_TAGGED) { + puts(XDGVFS_TAG_LS); + xdg_vfs_ppair_str(stdout, "uri", full_uri, opts); + } + + if (strcmp(full_uri, "tvolumes:")==0) + { + test_volume_list(); + return XDGVFS_ERRORCODE_OK; + } + + if (strcmp(full_uri, "tdrives:")==0) + { + test_drive_list(); + return XDGVFS_ERRORCODE_OK; + } + + if (strcmp(full_uri, "vfsroot://")==0) + { + _xdg_vfs_gnome_ls_vfsroot(opts & XDGVFS_OPT_TAGGED); + return XDGVFS_ERRORCODE_OK; + } + + + GnomeVFSFileInfoOptions infoOpts = GNOME_VFS_FILE_INFO_FOLLOW_LINKS | GNOME_VFS_FILE_INFO_GET_MIME_TYPE; + + if (opts & XDGVFS_OPT_SLOW_MIME_TYPE) infoOpts |= GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE; + + r=gnome_vfs_directory_open (&handle, + full_uri, + infoOpts); + + xdg_vfs_iterate_mainloop(); + + if (r!=GNOME_VFS_OK) + { + if (r==GNOME_VFS_ERROR_CANCELLED) + { + fprintf(stderr, "ERROR: Operation canceled\n"); + return XDGVFS_ERRORCODE_CANCELED; + } + return print_and_translate_result(r); + } + + while(1) + { + // char *entryUri; + r=gnome_vfs_directory_read_next(handle, info); + if (r!=GNOME_VFS_OK) + { + if (r==GNOME_VFS_ERROR_EOF) break; /* ok EOF */ + return print_and_translate_result(r); + } + if (opts & XDGVFS_OPT_TAGGED) puts(XDGVFS_TAG_DIRENTRY); + + + GnomeVFSURI* dirUri = gnome_vfs_uri_new(full_uri); + GnomeVFSURI* fileUri = gnome_vfs_uri_append_path(dirUri, + info->name); + + char * nuri = gnome_vfs_uri_to_string(fileUri, + GNOME_VFS_URI_HIDE_NONE); +/* + if (!g_str_has_suffix (full_uri, "/")) + entryUri = g_strconcat(full_uri, "/", info->name, NULL); + else + entryUri = g_strconcat(full_uri, info->name, NULL); + + char * entryUriEscaped = gnome_vfs_make_uri_from_input(entryUri); +*/ + + xdg_gnome_vfs_printFileInfo(stdout, nuri, info, opts); + + + // xdg_vfs_ppair_str(stdout, "uri", entryUriEscaped, opts); + //g_free(entryUriEscaped); + //g_free(entryUri); + gnome_vfs_uri_unref (dirUri); + gnome_vfs_uri_unref (fileUri); + g_free(nuri); + + gnome_vfs_file_info_clear (info); + if (!(opts & XDGVFS_OPT_TAGGED)) putchar(10); + } + + gnome_vfs_directory_close(handle); + gnome_vfs_file_info_unref (info); + return XDGVFS_ERRORCODE_OK; + +} + +/** +* Command: read file +*/ +int xdg_vfs_get(const char * text_uri, int opts) +{ + char buffer[DATA_BUF_SIZE]; + GnomeVFSFileSize bytes_read; + int i, rr; + int escChar = xdg_vfs_getDataEscChar(); + char * full_uri = gnome_vfs_make_uri_from_input(text_uri); + GnomeVFSHandle *handle; + GnomeVFSResult r; + + if (opts & XDGVFS_OPT_GET_FILEINFO) + { + if (!(opts & XDGVFS_OPT_TAGGED)) + { + fprintf(stderr, "ERROR: qry fileinfo in 'get' command requires tagged mode!\n"); + return XDGVFS_ERRORCODE_BAD_PARAMETER; + } + rr=xdg_vfs_getFileInfo(text_uri, opts); + if (rr != 0) return rr; + } + + if (opts & XDGVFS_OPT_TAGGED) + { + puts(XDGVFS_TAG_GET); + xdg_vfs_ppair_str(stdout, "uri", full_uri, opts); + } + r=gnome_vfs_open(&handle, full_uri, GNOME_VFS_OPEN_READ); + if (r!=GNOME_VFS_OK) + { + if (r==GNOME_VFS_ERROR_CANCELLED) + { + fprintf(stderr, "ERROR: Operation canceled\n"); + return XDGVFS_ERRORCODE_CANCELED; + } + return print_and_translate_result(r); + } + + xdg_vfs_iterate_mainloop(); + + if (opts & XDGVFS_OPT_TAGGED) + { + puts(opts & XDGVFS_OPT_DATAESCAPED ? XDGVFS_TAG_ESCAPEDDATA_OUT : XDGVFS_TAG_DATA_OUT); + } + + while (1) + { + r=gnome_vfs_read(handle, buffer, DATA_BUF_SIZE, &bytes_read); + if (r!=GNOME_VFS_OK) + { + if (r==GNOME_VFS_ERROR_EOF) break; /* ok EOF */ + return print_and_translate_result(r); + } + for(i=0;i<bytes_read;i++) + { + int c = (int)buffer[i]; + /* escape char */ + if (c == escChar && opts & XDGVFS_OPT_DATAESCAPED) putchar(escChar); + putchar (c); + } + + } + if (opts & XDGVFS_OPT_DATAESCAPED) + { + putchar(escChar); // Escape char + putchar(10); + //fprintf(stdout, "\n[/Data]\n"); + } else if (opts & XDGVFS_OPT_TAGGED) putchar(10); + + if (xdg_vfs_getCustomEndSeparator()) + fprintf(stdout, "%s\n", xdg_vfs_getCustomEndSeparator()); + gnome_vfs_close(handle); + return XDGVFS_ERRORCODE_OK; +} + +/** +* Command: mkdir +*/ +int xdg_vfs_mkdir(const char * text_uri, unsigned int perms, int opts) +{ + GnomeVFSResult r; + char * full_uri = gnome_vfs_make_uri_from_input(text_uri); + if (opts & XDGVFS_OPT_TAGGED) + { + puts(XDGVFS_TAG_MKDIR); + xdg_vfs_ppair_str(stdout, "uri", full_uri, opts); + } + r = gnome_vfs_make_directory(full_uri, perms); + if (r!=GNOME_VFS_OK) + { + return print_and_translate_result(r); + } + return XDGVFS_ERRORCODE_OK; +} + +/** +* Command: rmdir +*/ +int xdg_vfs_rmdir(const char * text_uri, int opts) +{ + GnomeVFSResult r; + char * full_uri = gnome_vfs_make_uri_from_input(text_uri); + if (opts & XDGVFS_OPT_TAGGED) + { + puts(XDGVFS_TAG_RMDIR); + xdg_vfs_ppair_str(stdout, "uri", full_uri, opts); + } + r= gnome_vfs_remove_directory(full_uri); + if (r!=GNOME_VFS_OK) + { + return print_and_translate_result(r); + } + return XDGVFS_ERRORCODE_OK; +} + +/** +* Command: rm +*/ +int xdg_vfs_rm(const char * text_uri, int opts) +{ + GnomeVFSResult r; + char * full_uri = gnome_vfs_make_uri_from_input(text_uri); + if (opts & XDGVFS_OPT_TAGGED) + { + puts(XDGVFS_TAG_RM); + xdg_vfs_ppair_str(stdout, "uri", full_uri, opts); + } + r= gnome_vfs_unlink (full_uri); + if (r!=GNOME_VFS_OK) + { + return print_and_translate_result(r); + } + return XDGVFS_ERRORCODE_OK; +} + +/** +* Copy/Move progress callback +*/ +time_t progress_lasttime=0; + +gint gnomeVFSXferProgressCallback (GnomeVFSXferProgressInfo *info, + gpointer data) +{ + int opts = 0; + + if (data) opts = *((int *)data); + if (opts & XDGVFS_OPT_PROGRESS && info) + { + time_t now = time(NULL); + if ((progress_lasttime < now)) + { + progress_lasttime=now; + puts(XDGVFS_TAG_PROGRESS); + printf("total_bytes=%d\n", info->file_size); + printf("bytes_copied=%d\n", info->bytes_copied); + } + } + info->vfs_status = GNOME_VFS_OK; + if (xdg_vfs_chk_canceled(opts)) + { + return FALSE; + } + return TRUE; +} + +/** +* Command: cp/mv +*/ +int xdg_vfs_cp(const char * text_uri_src, const char * text_uri_target, unsigned int perms, int move_flag, int opts) +{ + GnomeVFSResult r; + GnomeVFSXferOptions xfer_opts = (move_flag ? GNOME_VFS_XFER_REMOVESOURCE : GNOME_VFS_XFER_DEFAULT); + GnomeVFSXferErrorMode error_mode = GNOME_VFS_XFER_ERROR_MODE_ABORT; + GnomeVFSXferOverwriteMode overwrite_mode = + (opts & XDGVFS_OPT_OVERWRITE) + ? GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE + : GNOME_VFS_XFER_OVERWRITE_MODE_ABORT; + const char * full_uri_src = gnome_vfs_make_uri_from_input(text_uri_src); + const char * full_uri_target = gnome_vfs_make_uri_from_input(text_uri_target); + GnomeVFSURI* gfull_uri_src = gnome_vfs_uri_new(full_uri_src); + GnomeVFSURI* gfull_uri_target = gnome_vfs_uri_new(full_uri_target); + + if (opts & XDGVFS_OPT_TAGGED) + { + puts(move_flag ? XDGVFS_TAG_MV : XDGVFS_TAG_CP); + xdg_vfs_ppair_str(stdout, "uri_src", full_uri_src, opts); + xdg_vfs_ppair_str(stdout, "uri_target", full_uri_target, opts); + } + + r = gnome_vfs_xfer_uri (gfull_uri_src, + gfull_uri_target, + xfer_opts, + error_mode, + overwrite_mode, + gnomeVFSXferProgressCallback, + &opts); + gnome_vfs_uri_unref (gfull_uri_src); + gnome_vfs_uri_unref (gfull_uri_target); + + if (r!=GNOME_VFS_OK) + { + return print_and_translate_result(r); + } + return XDGVFS_ERRORCODE_OK; +} + +/** +* Command: write file +*/ +int xdg_vfs_put(const char * text_uri, int perms, int opts) +{ + char buffer[DATA_BUF_SIZE]; + GnomeVFSFileSize bytes_written; + int i, rr, c; + int escChar = xdg_vfs_getDataEscChar(); + char * full_uri = gnome_vfs_make_uri_from_input(text_uri); + GnomeVFSHandle *handle; + GnomeVFSResult r; + + if (opts & XDGVFS_OPT_TAGGED) + { + puts(XDGVFS_TAG_PUT); + xdg_vfs_ppair_str(stdout, "uri", full_uri, opts); + // puts(opts & XDGVFS_OPT_DATAESCAPED ? XDGVFS_TAG_ESCAPEDDATA_IN : XDGVFS_TAG_DATA_IN); + } + + r=gnome_vfs_create(&handle, full_uri, + GNOME_VFS_OPEN_WRITE, + !(opts & XDGVFS_OPT_OVERWRITE), + perms); + + xdg_vfs_iterate_mainloop(); + + //r=gnome_vfs_open(&handle, text_uri, GNOME_VFS_OPEN_WRITE); + if (r!=GNOME_VFS_OK) + { + g_free(full_uri); + if (r==GNOME_VFS_ERROR_CANCELLED) + { + fprintf(stderr, "ERROR: Operation canceled\n"); + return XDGVFS_ERRORCODE_CANCELED; + } + return print_and_translate_result(r); + } + + if (opts & XDGVFS_OPT_TAGGED) // wait for data! + { + puts(opts & XDGVFS_OPT_DATAESCAPED ? XDGVFS_TAG_ESCAPEDDATA_IN : XDGVFS_TAG_DATA_IN); + fflush(stdout); + } + + + while (1) + { + int eofflag=0; + int len = 0; + for (i=0;i<DATA_BUF_SIZE;i++) + { /* read chunk */ + c = getc(stdin); + if (c==EOF) + { + eofflag =1; + break; + } + if (c == escChar && opts & XDGVFS_OPT_DATAESCAPED) + { + int c2 = getc(stdin); + if (c2==EOF) + { + eofflag =1; + break; + } + + if (c2!=escChar) + { + if (c2!='\n') + { + g_free(full_uri); + fprintf(stderr, "ERROR: Data escaping error\n"); + return XDGVFS_ERRORCODE_DATA_ERROR; + } + eofflag = 1; + break; + } + } + + + buffer[i] = (unsigned char)c; + len++; + } + + /* check for errors */ + if (ferror (stdin)) + { + //fprintf(stderr, "ERROR: Stdin error\n"); + g_free(full_uri); + perror("ERROR: Stdin error\n"); + return XDGVFS_ERRORCODE_DATA_ERROR; + } + + char * p = buffer; + while (len>0) + { /* write chunk */ + r=gnome_vfs_write(handle, p, len, &bytes_written); + if (r!=GNOME_VFS_OK) + { + // error delete file + g_free(full_uri); + return print_and_translate_result(r); + } + p += bytes_written; + len -= bytes_written; + } + if(eofflag) break; + } + gnome_vfs_close(handle); + g_free(full_uri); + return XDGVFS_ERRORCODE_OK; +} + +/** +* Command: open file dialog +*/ +int xdg_vfs_openfiledlg(const char * default_dir, const char * default_filename, const char * title, int opts) +{ + GtkWidget *dialog; + + gtk_init (0, NULL); + + + dialog = gtk_file_chooser_dialog_new (title ? title : XDGVFS_TEXT_OPENFILEDLG_TITLE, + NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + /* + + dialog = gtk_file_chooser_dialog_new ("Save File", + NULL, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + */ + + gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER (dialog), FALSE); + + if (default_dir) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), default_dir); + //if (default_filename) gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), default_filename); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + char *filename, *uri; + + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + + uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)); + + if (!(opts & XDGVFS_OPT_INSTANT_GET) || opts & XDGVFS_OPT_TAGGED) + { + if (opts & XDGVFS_OPT_TAGGED) puts(XDGVFS_TAG_OPENFILEDLG); + if (filename) fprintf(stdout, "selected_localpath=%s\n", filename); + if (uri) fprintf(stdout, "selected_uri=%s\n", uri); + + if (xdg_vfs_getCustomEndSeparator()) + fprintf(stdout, "\n%s\n", xdg_vfs_getCustomEndSeparator()); + } + + gtk_widget_destroy (dialog); + if (opts & XDGVFS_OPT_INSTANT_GET) return xdg_vfs_get(uri, opts); + return XDGVFS_ERRORCODE_OK; + + } + else + { + gtk_widget_destroy (dialog); + fprintf(stderr, "ERROR: Dialog canceled\n"); + return XDGVFS_ERRORCODE_CANCELED; + } +} + +/** +* Command: save file dlg +*/ +int xdg_vfs_savefiledlg(const char * default_dir, const char * default_filename, + const char * title, unsigned int perms, int opts) +{ + GtkWidget *dialog; + + gtk_init (0, NULL); + + dialog = gtk_file_chooser_dialog_new (title ? title : XDGVFS_TEXT_SAVEFILEDLG_TITLE, + NULL, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER (dialog), FALSE); + gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE); + + if (default_dir) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), default_dir); + if (default_filename) gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), default_filename); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + char *filename, *uri; + + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + + uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)); + + if (!(opts & XDGVFS_OPT_INSTANT_PUT) || opts & XDGVFS_OPT_TAGGED) + { + if (opts & XDGVFS_OPT_TAGGED) puts(XDGVFS_TAG_SAVEFILEDLG); + if (filename) fprintf(stdout, "selected_localpath=%s\n", filename); + if (uri) fprintf(stdout, "selected_uri=%s\n", uri); + + if (xdg_vfs_getCustomEndSeparator()) + fprintf(stdout, "\n%s\n", xdg_vfs_getCustomEndSeparator()); + } + + gtk_widget_destroy (dialog); + if (opts & XDGVFS_OPT_INSTANT_PUT) return xdg_vfs_put(uri, perms, opts | XDGVFS_OPT_OVERWRITE); + return XDGVFS_ERRORCODE_OK; + } + else + { + gtk_widget_destroy (dialog); + fprintf(stderr, "ERROR: Dialog canceled\n"); + return XDGVFS_ERRORCODE_CANCELED; + } +} + +int xdg_vfs_backend(int opts) +{ + if (opts & XDGVFS_OPT_TAGGED) + { + puts(XDGVFS_TAG_BACKEND); + } + xdg_vfs_ppair_str(stdout, "backend_id", "gnome", opts); + xdg_vfs_ppair_str(stdout, "system_uri", "vfsroot://", opts); + xdg_vfs_ppair_str(stdout, "file_icon_theme", "gnome", opts); + return XDGVFS_ERRORCODE_OK; +} + + +int xdg_vfs_mount(const char * mountpoint_id, int opts) +{ + return _xdg_vfs_gnome_mount(mountpoint_id, opts & XDGVFS_OPT_TAGGED); + + +} + +/** +* main() +*/ +int main(int argc, char ** argv) +{ + return xdg_vfs_main(argc, argv); +} diff --git a/xdg-vfs-gnome/src/xdg_vfs_gnome.h b/xdg-vfs-gnome/src/xdg_vfs_gnome.h new file mode 100644 index 0000000..d8d1f95 --- /dev/null +++ b/xdg-vfs-gnome/src/xdg_vfs_gnome.h @@ -0,0 +1,39 @@ +/* +# xdg_vfs_gnome.h +# +# Copyright 2006, Norbert Frese +# +# LICENSE: +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +#---------------------------------------------*/ + +#ifndef XDG_VFS_GNOME_H +#define XDG_VFS_GNOME_H + +/* private decls */ + +int _xdg_vfs_gnome_mount(char * mountpoint_id, int tagged); + +int _xdg_vfs_gnome_ls_vfsroot(int tagged); + +int print_and_translate_result(GnomeVFSResult result); + +#endif diff --git a/xdg-vfs-gnome/src/xdg_vfs_gnome_monitor.c b/xdg-vfs-gnome/src/xdg_vfs_gnome_monitor.c new file mode 100644 index 0000000..0729a94 --- /dev/null +++ b/xdg-vfs-gnome/src/xdg_vfs_gnome_monitor.c @@ -0,0 +1,238 @@ +/* +# xdg_vfs_gnome_monitor.c +# +# Copyright 2006, Norbert Frese +# +# LICENSE: +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +#---------------------------------------------*/ + +#include <string.h> + +#include <gtk/gtk.h> +#include <libgnomevfs/gnome-vfs.h> +#include <libgnomeui/libgnomeui.h> +#include <time.h> + +#include "xdg_vfs_common.h" +#include "xdg_vfs.h" +#include "xdg_vfs_gnome.h" + +typedef struct +{ + char * monitor_uri; + GnomeVFSMonitorHandle * handle; + int has_events; +} XdgVfsGnomeMonitor; + +int global_event_count=0; + +GList * monitor_list = NULL; + +void myGnomeVFSMonitorCallback(GnomeVFSMonitorHandle *handle, + const gchar *monitor_uri, + const gchar *info_uri, + GnomeVFSMonitorEventType event_type, + gpointer user_data) +{ + GList *current_monitor; + int found = 0; + /*fprintf(stderr, "monitor event monitor_uri=%s info_uri=%s event_type=%d\n", + monitor_uri, + info_uri, + event_type);*/ + + for (current_monitor = monitor_list; current_monitor != NULL; current_monitor = current_monitor->next) + { + + XdgVfsGnomeMonitor *monitor = (XdgVfsGnomeMonitor*)current_monitor->data; + if (monitor->handle == handle) + { + monitor->has_events++; + global_event_count++; + found = 1; + } + } + if (found==0) fprintf(stderr, + "Warning: got event for unregistered handle monitor_uri=%s\n", monitor_uri); +} + +XdgVfsGnomeMonitor * new_xdg_vfs_gnome_monitor() +{ + XdgVfsGnomeMonitor * monitor = calloc(1,sizeof(XdgVfsGnomeMonitor)); + return monitor; +} + + +int xdg_vfs_monitor(char * uri, int is_directory, int opts) +{ + GnomeVFSResult r; + GnomeVFSMonitorHandle *handle; + char * full_uri = gnome_vfs_make_uri_from_input(uri); + + GList *current_monitor; + for (current_monitor = monitor_list; current_monitor != NULL; current_monitor = current_monitor->next) + { + XdgVfsGnomeMonitor *monitor = (XdgVfsGnomeMonitor*)current_monitor->data; + if( strcmp(uri, monitor->monitor_uri) ==0) + return XDGVFS_ERRORCODE_ALREADY_EXISTS; // monitor exists + } + + /* dirty hack: watch computer:// for drive changes */ + char * watch_uri = strcmp(uri, "vfsroot://")==0 ? "computer://" : full_uri; + + r = gnome_vfs_monitor_add(&handle, + watch_uri, + is_directory ? GNOME_VFS_MONITOR_DIRECTORY : GNOME_VFS_MONITOR_FILE, + myGnomeVFSMonitorCallback, + NULL /* user_data */); + + if (r==GNOME_VFS_OK) + { + XdgVfsGnomeMonitor * monitor = new_xdg_vfs_gnome_monitor(); + monitor->handle = handle; + monitor->monitor_uri = strdup(full_uri); + monitor_list = g_list_append(monitor_list, monitor); + } + + g_free(full_uri); + if (r!=GNOME_VFS_OK) return print_and_translate_result(r); + return XDGVFS_ERRORCODE_OK; +} + + +int xdg_vfs_monitor_cancel(char * uri, int opts) +{ + char * full_uri = gnome_vfs_make_uri_from_input(uri); + GList *current_monitor; + int found = 0; + for (current_monitor = monitor_list; current_monitor != NULL; current_monitor = current_monitor->next) + { + XdgVfsGnomeMonitor *monitor = (XdgVfsGnomeMonitor*)current_monitor->data; + if( strcmp(full_uri, monitor->monitor_uri) == 0) + { + GnomeVFSResult r = gnome_vfs_monitor_cancel (monitor->handle); + if (r!=GNOME_VFS_OK) + print_and_translate_result(r); + g_free(monitor->monitor_uri); + monitor_list = g_list_remove(monitor_list, monitor); + found = 1; + break; + } + } + + if (!found) + { + fprintf(stderr, "monitor with uri=%s not found!\n", full_uri); + g_free(full_uri); + return XDGVFS_ERRORCODE_NOT_FOUND; + } + g_free(full_uri); + return XDGVFS_ERRORCODE_OK; +} + +int xdg_vfs_monitor_list_events(int opts) +{ + GList *current_monitor; + int save_count = global_event_count; + int found = 0; + for (current_monitor = monitor_list; current_monitor != NULL; current_monitor = current_monitor->next) + { + XdgVfsGnomeMonitor *monitor = (XdgVfsGnomeMonitor*)current_monitor->data; + if (monitor->has_events) + { + fprintf(stdout, "%s %s\n", XDGVFS_TAG_MONITOREVENT, monitor->monitor_uri); + monitor->has_events = 0; + } + } + fflush(stdout); + global_event_count = 0; + return save_count; +} + +/* ======================== loop and wait for fd =============== */ + +typedef struct { + GSource gs; + GPollFD * gpoll; + gboolean done; +} WaitGSource; + + +gboolean wait_gs_prepare(GSource *source, gint *timeout_) +{ + WaitGSource * wsource = (WaitGSource*)source; + //fprintf(stderr, "hi1\n"); + wsource->gpoll->events = G_IO_IN | G_IO_HUP | G_IO_ERR; + *timeout_ = -1; + return FALSE; +} + +gboolean wait_gs_check(GSource *source) +{ + WaitGSource * wsource = (WaitGSource*)source; + //fprintf(stderr, "hi2 %d\n", wsource->gpoll->fd); + if (wsource->gpoll->revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) + { + //fprintf(stderr, "hi3\n"); + return TRUE; + } + return FALSE; +} + +gboolean wait_gs_dispatch(GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + WaitGSource * wsource = (WaitGSource*)source; + wsource->done = TRUE; + return TRUE; +} + +GSourceFuncs wait_gs_funcs = { + .prepare = wait_gs_prepare, + .check = wait_gs_check, + .dispatch = wait_gs_dispatch +}; + +int xdg_vfs_iterate_mainloop_until_incoming_data(int fd) +{ + GPollFD gpoll={0}; + gpoll.fd = fd; + + GSource* source = g_source_new(&wait_gs_funcs, sizeof(WaitGSource)); + WaitGSource * wsource = (WaitGSource*)source; + wsource->gpoll = &gpoll; + wsource->done = FALSE; + g_source_add_poll(source, &gpoll); + g_source_set_can_recurse(source,TRUE); + + g_source_attach(source,NULL); + + //while (!(wsource->done)){ + //fprintf(stderr, "loop\n"); + g_main_context_iteration(NULL,TRUE); + //} + int done = wsource->done; + g_source_destroy (source); + return done; +} + diff --git a/xdg-vfs-gnome/src/xdg_vfs_gnome_volumes.c b/xdg-vfs-gnome/src/xdg_vfs_gnome_volumes.c new file mode 100644 index 0000000..fc2fc93 --- /dev/null +++ b/xdg-vfs-gnome/src/xdg_vfs_gnome_volumes.c @@ -0,0 +1,521 @@ +/* +# xdg_vfs_gnome_volumes.c +# +# Copyright 2006, Norbert Frese +# +# LICENSE: +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +#---------------------------------------------*/ + +#include <glib.h> +#include <libgnomevfs/gnome-vfs.h> + +#include "xdg_vfs_common.h" +#include "xdg_vfs.h" + +#define DEBUG_VOLUMES 1 + +/* =============== print entries =============== */ + + +void _print_filesystem() +{ + fprintf(stdout, + "basename=Filesystem\n" + "uri=file:///\n" + "filetype=DIRECTORY\n" + "iconname=gnome-dev-harddisk\n" + ); +} + +void _print_network() +{ + fprintf(stdout, + "basename=Network\n" + "uri=network://\n" + "filetype=DIRECTORY\n" + "iconname=gnome-fs-network\n" + ); +} + +void _print_home() +{ + char * home_uri = gnome_vfs_get_uri_from_local_path (g_get_home_dir ()); + fprintf(stdout, + "basename=Home\n" + "uri=%s\n" + "filetype=DIRECTORY\n" + "iconname=gnome-fs-home\n" + , home_uri + ); +} + + +int _print_volume(GnomeVFSVolume *volume) +{ + char* activation_uri = gnome_vfs_volume_get_activation_uri + (volume); + char* display_name = gnome_vfs_volume_get_display_name + (volume); + GnomeVFSDeviceType device_type = gnome_vfs_volume_get_device_type + (volume); + + char* filesystem_type = gnome_vfs_volume_get_filesystem_type + (volume); + GnomeVFSVolumeType volume_type = gnome_vfs_volume_get_volume_type + (volume); + + char* icon = gnome_vfs_volume_get_icon(volume); + + char* device_path = gnome_vfs_volume_get_device_path + (volume); + + gboolean is_mounted = gnome_vfs_volume_is_mounted(volume); + + gboolean user_visible = gnome_vfs_volume_is_user_visible + (volume); + + gboolean read_only = gnome_vfs_volume_is_read_only (volume); + + if (DEBUG_VOLUMES) + { + fprintf(stdout, "# (VOLUME)\n"); + fprintf(stdout, "# activation_uri=%s\n", activation_uri); + fprintf(stdout, "# display_name=%s\n", display_name); + fprintf(stdout, "# icon=%s\n", icon); + fprintf(stdout, "# volume_type=%d\n", volume_type); + fprintf(stdout, "# device_type=%d\n", device_type); + fprintf(stdout, "# filesystem_type=%s\n", filesystem_type); + fprintf(stdout, "# device_path=%s\n", device_path); + fprintf(stdout, "# is_mounted=%d\n", is_mounted); + fprintf(stdout, "# user_visible=%d\n", user_visible); + fprintf(stdout, "# read_only=%d\n", read_only); + } + + if (is_mounted) + { + fprintf(stdout, "uri=%s\n", activation_uri); + fprintf(stdout, "is_mounted=1\n"); + /* fprintf(stdout, "filetype=DIRECTORY\n"); */ + } + else + fprintf(stdout, "is_mounted=0\n"); + { + GnomeVFSDrive * drive = gnome_vfs_volume_get_drive(volume); + if (drive) + fprintf(stdout, "mountpoint_id=%d\n", gnome_vfs_drive_get_id (drive)); + gnome_vfs_drive_unref(drive); + + fprintf(stdout, "filetype=VFSMOUNTPOINT\n"); + } + fprintf(stdout, "basename=%s\n", display_name); + fprintf(stdout, "iconname=%s\n", icon); + + fprintf(stdout, "\n"); + + g_free(activation_uri); + g_free(display_name); + g_free(filesystem_type); + g_free(icon); + g_free(device_path); + +} + +int _print_drive(GnomeVFSDrive *drive) +{ + + char * icon= gnome_vfs_drive_get_icon(drive); + int drive_id=gnome_vfs_drive_get_id (drive); + gboolean is_mounted= gnome_vfs_drive_is_mounted(drive); + gboolean is_user_visible=gnome_vfs_drive_is_user_visible (drive); + char * device_path=gnome_vfs_drive_get_device_path (drive); + char * activation_uri=gnome_vfs_drive_get_activation_uri(drive); + char * display_name=gnome_vfs_drive_get_display_name(drive); + + if (DEBUG_VOLUMES) + { + fprintf(stdout, "# (DRIVE)\n"); + fprintf(stdout, "# drive_icon=%s\n", icon); + fprintf(stdout, "# drive_id=%d\n", drive_id); + fprintf(stdout, "# is_mounted=%d\n", is_mounted); + fprintf(stdout, "# is_user_visible=%d\n", is_user_visible); + fprintf(stdout, "# device_path=%s\n", device_path); + fprintf(stdout, "# activation_uri=%s\n", activation_uri); + fprintf(stdout, "# display_name=%s\n", display_name); + } + fprintf(stdout, "iconname=%s\n", icon); + fprintf(stdout, "basename=%s\n", display_name); + if (is_mounted) + fprintf(stdout, "uri=%s\n", activation_uri); + fprintf(stdout, "mountpoint_id=%d\n", drive_id); + fprintf(stdout, "is_mounted=%d\n", is_mounted); + + fprintf(stdout, "filetype=VFSMOUNTPOINT\n"); + + fprintf(stdout, "\n"); + + g_free(icon); + g_free(device_path); + g_free(activation_uri); + g_free(display_name); + +} + + +/* =================== implementation ================ */ + + +GList * _xdg_vfs_gnome_vfsroot_list() { + + GList* entries=NULL; + + GnomeVFSVolumeMonitor * volume_monitor = gnome_vfs_get_volume_monitor(); + + GList* drive_list = gnome_vfs_volume_monitor_get_connected_drives + (volume_monitor); + + + + GList *current_drive; + + for (current_drive = drive_list; current_drive != NULL; current_drive = current_drive->next) + { + + GnomeVFSDrive *drive = GNOME_VFS_DRIVE(current_drive->data); + + //_print_drive(drive); + //printf("drive\n"); + + char* drive_activation_uri = gnome_vfs_drive_get_activation_uri(drive); + + /* don't list root filesystem, because it's included by hand */ + if (drive_activation_uri && strcmp(drive_activation_uri, "file:///")==0) + { + g_free(drive_activation_uri); + gnome_vfs_drive_unref(drive); + continue; + } + + + + GList* vol_list = gnome_vfs_drive_get_mounted_volumes(drive); + + GList *current_vol; + int visible_volumes_count = 0; // count the visible volumes on this drive + + for (current_vol = vol_list; current_vol != NULL; current_vol = current_vol->next) + { + GnomeVFSVolume *volume; + volume = GNOME_VFS_VOLUME (current_vol->data); + + char * device_path = gnome_vfs_volume_get_device_path(volume); + char* activation_uri = gnome_vfs_volume_get_activation_uri(volume); + + /* + if (device_path && + (strcmp(device_path, "/dev/root")==0 + || strcmp(device_path, "rootfs")==0 + ))*/ + /* don't list root filesystem, because it's included by hand */ + if (activation_uri && strcmp(activation_uri, "file:///")==0) + { + g_free(device_path); + g_free(activation_uri); + gnome_vfs_volume_unref(volume); + continue; + } + g_free(device_path); + g_free(activation_uri); + + if (TRUE || gnome_vfs_volume_is_user_visible(volume)) + { + // printf("volume\n"); + entries = g_list_append(entries, volume); + visible_volumes_count++;/* fprintf(stdout, "\n"); */ + } + else + { + gnome_vfs_volume_unref (volume); + } + + } + + /* if there is no volumes, append the drive object */ + if (visible_volumes_count<1 /* && gnome_vfs_drive_is_user_visible (drive)*/) + { + entries = g_list_append(entries, drive); + } + else + { + gnome_vfs_drive_unref(drive); + + } + g_list_free(vol_list); + + } + + /* read the remote shares */ + + //fprintf(stderr, "\nand now the network shares #####\n"); + + { + GList *vol_list; + GList *current_vol; + + GnomeVFSVolumeMonitor * volume_monitor = gnome_vfs_get_volume_monitor(); + + vol_list = gnome_vfs_volume_monitor_get_mounted_volumes(volume_monitor); + + for (current_vol = vol_list; current_vol != NULL; current_vol = current_vol->next) + { + GnomeVFSVolume *volume = GNOME_VFS_VOLUME (current_vol->data); + + if (gnome_vfs_volume_get_volume_type(volume) == GNOME_VFS_VOLUME_TYPE_CONNECTED_SERVER) + { + entries = g_list_append(entries, volume); + } + else + { + gnome_vfs_volume_unref (volume); + } + } + g_list_free(vol_list); + } + + return entries; + +} + +int _xdg_vfs_gnome_ls_vfsroot(int tagged) +{ + + GList* entries=_xdg_vfs_gnome_vfsroot_list(); + + GList* current_entry; + + if (tagged) puts(XDGVFS_TAG_DIRENTRY); + _print_home(); + puts(""); + if (tagged) puts(XDGVFS_TAG_DIRENTRY); + _print_filesystem(); + puts(""); + if (tagged) puts(XDGVFS_TAG_DIRENTRY); + _print_network(); + puts(""); + + for (current_entry = entries; current_entry!=NULL; current_entry = current_entry->next) + { + + if (tagged) puts(XDGVFS_TAG_DIRENTRY); + if (GNOME_IS_VFS_VOLUME(current_entry->data)) + { + GnomeVFSVolume *volume = GNOME_VFS_VOLUME (current_entry->data); + _print_volume(volume); + gnome_vfs_volume_unref (volume); + } + else if (GNOME_IS_VFS_DRIVE(current_entry->data)) + { + GnomeVFSDrive *drive = GNOME_VFS_DRIVE(current_entry->data); + _print_drive(drive); + gnome_vfs_drive_unref(drive); + } + else + fprintf(stdout, "# unexpected list item!\n"); + } + g_list_free(entries); + return 1; +} + + +/* ==================== mounting =================== */ + +int mount_stoploop; +int mount_tagged; + +void volume_monitor_mount_handler(GnomeVFSVolumeMonitor *vfsvolumemonitor, + GnomeVFSVolume *arg1, gpointer user_data) +{ + + int drive_id = *((int*)user_data); + + GnomeVFSDrive * drive = gnome_vfs_volume_get_drive(arg1); + if (gnome_vfs_drive_get_id(drive) == drive_id) + { + /* ha! we got the right drive */ + mount_stoploop|=2; + + GList* vol_list = gnome_vfs_drive_get_mounted_volumes(drive); + + GList *current_vol; + int visible_volumes_count = 0; // count the visible volumes on this drive + + if (mount_tagged) puts(XDGVFS_TAG_MOUNT); + for (current_vol = vol_list; current_vol != NULL; current_vol = current_vol->next) + { + GnomeVFSVolume * volume = GNOME_VFS_VOLUME (current_vol->data); + if (mount_tagged) puts(XDGVFS_TAG_DIRENTRY); + _print_volume(volume); + } + + + + } +} + +void myGnomeVFSVolumeOpCallback(gboolean succeeded, + char *error, + char *detailed_error, + gpointer data) +{ + int * r = (int*)data; + + if (succeeded) + { + fprintf(stderr, "VolumeOpCallback: mount succeeded\n"); + mount_stoploop|=1; /* wait for volume monitor callback before stopping loop */ + *r = XDGVFS_ERRORCODE_OK; + } + else + { + fprintf(stderr, "VolumeOpCallback: mount failed: %s %s\n", error, detailed_error); + *r = XDGVFS_ERRORCODE_COULD_NOT_MOUNT; + mount_stoploop=3; /* stop loop instantly*/ + } + +} + + +int _xdg_vfs_gnome_mount(char * mountpoint_id, int tagged) +{ + int mount_drive_id = atoi(mountpoint_id); + mount_tagged = tagged; + + GnomeVFSVolumeMonitor * volume_monitor = gnome_vfs_get_volume_monitor(); + + GList* drive_list = gnome_vfs_volume_monitor_get_connected_drives + (volume_monitor); + + GList *current_drive; + + for (current_drive = drive_list; current_drive != NULL; current_drive = current_drive->next) + { + + GnomeVFSDrive *drive = GNOME_VFS_DRIVE(current_drive->data); + + + + if (gnome_vfs_drive_get_id (drive) == mount_drive_id) + { + int r; + fprintf(stderr, "mounting drive with drive_id=%d!\n", mount_drive_id); + + gulong handler_id = g_signal_connect(volume_monitor, "volume-mounted", + G_CALLBACK(volume_monitor_mount_handler), &mount_drive_id); + + gnome_vfs_drive_mount (drive, myGnomeVFSVolumeOpCallback, &r); + + /* wait for both callbacks to occur */ + mount_stoploop=0; + while (!(mount_stoploop==3)) + { + // fprintf(stderr, "looping\n"); + g_main_context_iteration(NULL, TRUE); + } + + g_signal_handler_disconnect (volume_monitor, handler_id); + g_list_free(drive_list); + return r; + } + + } + g_list_free(drive_list); + fprintf(stderr, "mount-problem drive with drive_id=%d not found!\n", mount_drive_id); + return XDGVFS_ERRORCODE_GENERIC; + +} + +/* =============== tests =============== */ + +int test_drive_list() { + + GnomeVFSVolumeMonitor * volume_monitor = gnome_vfs_get_volume_monitor(); + + GList* drive_list = gnome_vfs_volume_monitor_get_connected_drives + (volume_monitor); + + printf("%p\n", drive_list); + + GList *current_drive; + + for (current_drive = drive_list; current_drive != NULL; current_drive = current_drive->next) + { + + GnomeVFSDrive *drive = GNOME_VFS_DRIVE(current_drive->data); + + _print_drive(drive); + + GList* vol_list = gnome_vfs_drive_get_mounted_volumes(drive); + + GList *current_vol; + + for (current_vol = vol_list; current_vol != NULL; current_vol = current_vol->next) + { + GnomeVFSVolume *volume; + volume = GNOME_VFS_VOLUME (current_vol->data); + + _print_volume(volume); + + } + + } + + +} + +int test_volume_list() { + + GList *vol_list; + GList *current_vol; + + GnomeVFSVolumeMonitor * volume_monitor = gnome_vfs_get_volume_monitor(); + + vol_list = gnome_vfs_volume_monitor_get_mounted_volumes(volume_monitor); + + for (current_vol = vol_list; current_vol != NULL; current_vol = current_vol->next) + { + GnomeVFSVolume *volume; + volume = GNOME_VFS_VOLUME (current_vol->data); + + _print_volume(volume); + /* g_free(activation_uri); + g_free(display_name); + g_free(filesystem_type); + g_free(device_path); + g_free(is_mounted); */ + } + +} + + + + + + |