diff options
Diffstat (limited to 'libxdg-vfs-client')
31 files changed, 3667 insertions, 0 deletions
diff --git a/libxdg-vfs-client/.cvsignore b/libxdg-vfs-client/.cvsignore new file mode 100644 index 0000000..6d3654f --- /dev/null +++ b/libxdg-vfs-client/.cvsignore @@ -0,0 +1,27 @@ +*.la +*.lo +*.o +ABOUT-NLS +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/libxdg-vfs-client/AUTHORS b/libxdg-vfs-client/AUTHORS new file mode 100644 index 0000000..d76f6e9 --- /dev/null +++ b/libxdg-vfs-client/AUTHORS @@ -0,0 +1 @@ +Norbert Frese (nf2@scheinwelt.at) 2006 diff --git a/libxdg-vfs-client/COPYING b/libxdg-vfs-client/COPYING new file mode 100644 index 0000000..1edf08c --- /dev/null +++ b/libxdg-vfs-client/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/libxdg-vfs-client/ChangeLog b/libxdg-vfs-client/ChangeLog new file mode 100644 index 0000000..ede0d5c --- /dev/null +++ b/libxdg-vfs-client/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/libxdg-vfs-client/INSTALL b/libxdg-vfs-client/INSTALL new file mode 100644 index 0000000..23e5f25 --- /dev/null +++ b/libxdg-vfs-client/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/libxdg-vfs-client/Makefile.am b/libxdg-vfs-client/Makefile.am new file mode 100644 index 0000000..a459377 --- /dev/null +++ b/libxdg-vfs-client/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src tests diff --git a/libxdg-vfs-client/Makefile.cvs b/libxdg-vfs-client/Makefile.cvs new file mode 100644 index 0000000..1e17bc9 --- /dev/null +++ b/libxdg-vfs-client/Makefile.cvs @@ -0,0 +1,6 @@ +all: + @libtoolize + @aclocal + @autoheader + @automake --add-missing + @autoconf diff --git a/libxdg-vfs-client/NEWS b/libxdg-vfs-client/NEWS new file mode 100644 index 0000000..4af1832 --- /dev/null +++ b/libxdg-vfs-client/NEWS @@ -0,0 +1 @@ +None
\ No newline at end of file diff --git a/libxdg-vfs-client/README b/libxdg-vfs-client/README new file mode 100644 index 0000000..09fe2be --- /dev/null +++ b/libxdg-vfs-client/README @@ -0,0 +1,8 @@ +libxdg-vfs-client +================= + +C-client library for xdg-vfs + + +(for examples see the 'tests'-directory) + diff --git a/libxdg-vfs-client/configure.ac b/libxdg-vfs-client/configure.ac new file mode 100644 index 0000000..ac6d1e1 --- /dev/null +++ b/libxdg-vfs-client/configure.ac @@ -0,0 +1,28 @@ +dnl Process this file with autoconf to produce a configure script. + +dnl AC_INIT(src/main.c) +AC_INIT(src/xdg_vfs_client.c) +dnl AM_CONFIG_HEADER(config.h) + +PACKAGE=libxdg-vfs-client +VERSION=0.1.8 + +AM_INIT_AUTOMAKE($PACKAGE,$VERSION) + +AC_PROG_CC +AC_STDC_HEADERS +AC_PROG_INSTALL + +AC_ENABLE_SHARED(yes) +AC_PROG_LIBTOOL + +dnl PKG_CHECK_MODULES(DEPS, glib-2.0 >= 2.0) + +AC_SUBST(DEPS_CFLAGS) +AC_SUBST(DEPS_LIBS) + +AC_OUTPUT([ +Makefile +src/Makefile +tests/Makefile +]) diff --git a/libxdg-vfs-client/doc/imgs/libxdg-vfs-demo-filebrowser-gnome.png b/libxdg-vfs-client/doc/imgs/libxdg-vfs-demo-filebrowser-gnome.png Binary files differnew file mode 100644 index 0000000..fc95061 --- /dev/null +++ b/libxdg-vfs-client/doc/imgs/libxdg-vfs-demo-filebrowser-gnome.png diff --git a/libxdg-vfs-client/doc/imgs/libxdg-vfs-demo-filebrowser-kde.png b/libxdg-vfs-client/doc/imgs/libxdg-vfs-demo-filebrowser-kde.png Binary files differnew file mode 100644 index 0000000..580a99a --- /dev/null +++ b/libxdg-vfs-client/doc/imgs/libxdg-vfs-demo-filebrowser-kde.png diff --git a/libxdg-vfs-client/doc/imgs/libxdg-vfs-demo-filebrowser-root.png b/libxdg-vfs-client/doc/imgs/libxdg-vfs-demo-filebrowser-root.png Binary files differnew file mode 100644 index 0000000..0f4da0e --- /dev/null +++ b/libxdg-vfs-client/doc/imgs/libxdg-vfs-demo-filebrowser-root.png diff --git a/libxdg-vfs-client/doc/libxdg-vfs.html b/libxdg-vfs-client/doc/libxdg-vfs.html new file mode 100644 index 0000000..b0ba724 --- /dev/null +++ b/libxdg-vfs-client/doc/libxdg-vfs.html @@ -0,0 +1,208 @@ +<html> + <head> + <title>libxdg-vfs</title> + </head> + <body> + <h1>libxdg-vfs</h1> + <p><em>libxdg-vfs</em> provides a generic API to the Virtual-File-System libraries KIO and Gnome-VFS. + It supports the commands + <ul> + <li><em>backend</em> (obtain backend information)</li> + <li><em>get</em> (read file)</li> + <li><em>put</em> (write file)</li> + <li><em>cp</em> (copy file)</li> + <li><em>mv</em> (move file)</li> + <li><em>rm</em> (erase file)</li> + <li><em>mkdir</em> (create folder)</li> + <li><em>rmdir</em> (delete folder)</li> + <li><em>info</em> (get file-info)</li> + <li><em>setattrs</em> (set file attributes)</li> + <li><em>ls</em> (list directory)</li> + <li><em>openfildlg</em> (show open-file-dialog)</li> + <li><em>savefildlg</em> (show save-file-dialog)</li> + </ul> + </p> + <p>It is designed to work in synchronous as well as asynchronous context.</p> + <h2>Backends</h2> + <p>The backend executables (xdg_vfs_kde or xdg_vfs_gnome) are forked as child process and + the communication goes through the stdin/stdout pipes of the child-process (the <em>shell</em>-mode of the backend executables is used). The backends are in the separate packages xdg-vfs-kde.tar.gz and xdg-vfs-gnome.tar.gz.</p> + <h2>Sessions</h2> + <p>To open a session call the function:</p> +<code> +XdgVfsResult xdg_vfs_sess_start(XdgVfsSession ** session, char * preferredDesktop); +</code> + <p>The library will launch the child-process and return a session pointer. Use "this" (or NULL) - to + autodetect the current desktop - or "kde" / "gnome" for the <em>preferredDesktop</em> argument. + </p> + <h2>Running Commands</h2> + <p>A session can run a sequence of VFS commands. Because the backends are single-threaded and synchronous + you can only run one command after the other in a session (for parallel commands open a second session). + Here are some examples: + </p> + <h3>Copying a file</h3> + <p>Let's see how a copying a file is done:</p> +<code> +XdgVfsResult r = xdg_vfs_sess_cmd_copyFile(session, "protocol://user@server/srcfile", "protocol://user@server/targetfile"); +</code> + <p>After calling this function you have to read the response items until you get a return value different from + XDGVFS_RESULT_CONTINUES. Internally the 'readItem' function has only a single 'read(incoming_fd)' call per + iteration. This is to prevent blocking in an async application + (you have to watch for read-events on the fd returned by xdg_vfs_sess_getIncomingFiledescriptor()) + </p> +<pre> +XdgVfsResult r; +XdgVfsItemType type; +XdgVfsItem * item; + +while ((r = xdg_vfs_sess_readItem(session, &type, &item, NULL, NULL)) == XDGVFS_RESULT_CONTINUES) +{ + switch (type) + { + case XDGVFS_ITEMTYPE_COPY_HEAD: + { + XdgVfsCopyHead * head = (XdgVfsCopyHead*) item; + fprintf(stderr, "copying uri_src='%s' to uri_target='%s'\n", + head->uri_src, head->uri_target); + break; + } + case XDGVFS_ITEMTYPE_PROGRESS: + { + XdgVfsProgress * progress = (XdgVfsProgress *) item; + fprintf(stderr, "progress: copied=%d size=%d\n", progress->copied, progress->size); + break; + } + case XDGVFS_ITEMTYPE_NONE: + { + break; /* no complete item -> continue */ + } + default: + { + fprintf(stderr, "unexpected item - type=%d\n", type); + break; + } + } + xdg_vfs_item_unref(item); +} +if (r) { /* command failed */ } +</pre> + <h3>Reading a file</h3> + <p>When reading a file you will receive information items and data chunks.</p> +<pre> +XdgVfsResult r; +r = xdg_vfs_sess_cmd_getFile(session, "protocol://user@server/file"); +if (r) { /* command init error */ } + +char * buf=NULL; +int len=0; +XdgVfsItemType type; +XdgVfsItem * item; + +while ((r = xdg_vfs_sess_readItem(session, &type, &item, &buf, &len)) == XDGVFS_RESULT_CONTINUES) +{ + switch (type) + { + case XDGVFS_ITEMTYPE_GET_HEAD: + { + XdgVfsSimpleHead * head = (XdgVfsSimpleHead*) item; + fprintf(stderr, "reading file uri='%s'\n", head->uri); + break; + } + case XDGVFS_DATAIN: + { + fprintf(stderr, "file-data chunklen=%d\n", len); + fwrite (buf, 1, len, stdout); /* your file data */ + break; + } + case XDGVFS_ITEMTYPE_DATAIN_DONE: + { + XdgVfsDataInDoneItem * dii = (XdgVfsDataInDoneItem *) item; + fprintf(stderr, "read done - bytecount='%d'\n", dii->bytecount); + break; + } + case XDGVFS_ITEMTYPE_NONE: + { + break; + } + default: + { + fprintf(stderr, "unexpected item - type=%d\n", type); + break; + } + } + xdg_vfs_item_unref(item); +} +if (r) { /* command failed */ } +</pre> + <h3>Opening a file-dialog</h3> +<pre> +XdgVfsResult r; +r = xdg_vfs_sess_cmd_openFileDialog(session, "protocol://user@server/directory", 0); +if (r) { /* command init error */ } + +while ((r = xdg_vfs_sess_readItem(session, &type, &item, NULL, NULL)) == XDGVFS_RESULT_CONTINUES) +{ + switch(type) + { + case XDGVFS_ITEMTYPE_OPENFILEDLG_RESPONSE: + { + XdgVfsOpenFileDlgResponse * dlgResp = (XdgVfsOpenFileDlgResponse*) item; + fprintf(stderr, "selected_uri='%s'\n", dlgResp->selected_uri); + break; + } + case XDGVFS_ITEMTYPE_NONE: + { + break; + } + default: + { + fprintf(stderr, "unexpected item - type=%d\n", type); + break; + } + } + xdg_vfs_item_unref(item); +} +if (r) { /* command failed */ } +</pre> +<h3>Other Commands</h3> +<p>For the other commands see the samples in the 'tests' directory of the tarball. +Also have a look at <em>xdg_vfs_client.h</em> and <em>xdg_vfs_common.h</em> (list of result codes). +<h2>Async Applications</h2> +<p>Check the filedescriptor of the sessions incoming pipe in your event loop before calling</p> +<code> +XdgVfsResult xdg_vfs_sess_readItem(XdgVfsSession * sess, XdgVfsItemType * typeOut, + XdgVfsItem ** itemOut, char ** buffer, int * len); +</code> +<p>and the outgoing pipes filedescriptor before calling</p> +<code> +XdgVfsResult xdg_vfs_sess_sendData(XdgVfsSession * sess); +</code> +<p>(only required when writing a file).</p> +<h2>VFS browser demo</h2> +<p>Libxdg-vfs-demo-filebrowser is a simple file-system-browser (written in Gtk+) which uses libxdg-vfs. +I'm trying to find out whether libxdg-vfs could be used as backend for file-choosers (like GtkFileChooser) - especially in cases +where you need to customize file-dialogs and the simple Open/Save file-dialogs provided by libxdg-vfs won't +suffice.</p> +<p><em>Root URI of the VFS-backend:</em></p> +<p><code>XdgVfsBackendInfo</code> has a field called <code>system_uri</code> +which points to the virtual root folder (often listed in side-panes of file-dialogs) of the VFS backend. +Like <em>system:/</em> on KDE or <em>computer://</em> on Gnome. +</p> +<p><em>Icons and Icon-themes:</em></p> +<p><code>XdgVfsBackendInfo</code> has a field called <code>file_icon_theme</code> (which is 'crystalsvg' on KDE and 'gnome' on Gnome). +The <code>XdgVfsFileInfo</code> structure (returned when listing directories) has an <code>iconname</code> field. +With this information we can look up the right file-icons, without even knowing which backend is running. +</p> +<p>Screenshot: VFS browser using KIO and Gnome-VFS backend (pointing to root folder of the VFS):</p> +<p><img src="imgs/libxdg-vfs-demo-filebrowser-root.png"></p> +<p>Screenshot: VFS browser using the Gnome-VFS backend:</p> +<p><img src="imgs/libxdg-vfs-demo-filebrowser-gnome.png"></p> +<p>Screenshot: VFS browser using the KIO backend:</p> +<p><img src="imgs/libxdg-vfs-demo-filebrowser-kde.png"></p> + +<h2>Sources/Docs</h2> +<p>Downloads: <a href="http://www.scheinwelt.at/~norbertf/dadapt/files/xdg_utils/">http://www.scheinwelt.at/~norbertf/dadapt/files/xdg_utils/</a></p> +<p>Backend manual: <a href="http://www.scheinwelt.at/~norbertf/dadapt/files/xdg_utils/doc/xdg-vfs.html">http://www.scheinwelt.at/~norbertf/dadapt/files/xdg_utils/doc/xdg-vfs.html</a></p> +<p>Portland VFS task: <a href="http://portland.freedesktop.org/wiki/TaskVFS">http://portland.freedesktop.org/wiki/TaskVFS</a></p> +<p>___ n.f. 2006 ___</p> + </body> +</html> diff --git a/libxdg-vfs-client/src/.cvsignore b/libxdg-vfs-client/src/.cvsignore new file mode 100644 index 0000000..26a73db --- /dev/null +++ b/libxdg-vfs-client/src/.cvsignore @@ -0,0 +1,8 @@ +*.la +*.lo +*.o +.deps +.libs +Makefile +Makefile.in + diff --git a/libxdg-vfs-client/src/Makefile.am b/libxdg-vfs-client/src/Makefile.am new file mode 100644 index 0000000..b6494a9 --- /dev/null +++ b/libxdg-vfs-client/src/Makefile.am @@ -0,0 +1,12 @@ + +AM_CPPFLAGS = $(DEPS_CFLAGS) + +lib_LTLIBRARIES = libxdg_vfs_client.la + +libxdg_vfs_client_la_SOURCES = xdg_vfs_client.c xdg_vfs_forkexec.c xdg_vfs_errstrs.c +libxdg_vfs_client_la_LIBADD = $(DEPS_LIBS) +libxdg_vfs_client_la_LDFLAGS = $(all_libraries) + +libxdg_vfs_clientincludedir = $(includedir) +libxdg_vfs_clientinclude_HEADERS = xdg_vfs_client.h xdg_vfs_common.h +noinst_HEADERS = xdg_vfs_forkexec.h diff --git a/libxdg-vfs-client/src/xdg_vfs_client.c b/libxdg-vfs-client/src/xdg_vfs_client.c new file mode 100644 index 0000000..14730a8 --- /dev/null +++ b/libxdg-vfs-client/src/xdg_vfs_client.c @@ -0,0 +1,1252 @@ +/* +# xdg_vfs_client.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 <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "xdg_vfs_client.h" +#include "xdg_vfs_common.h" + +/* ==== utils ==== */ + +static XdgVfsFileType _translate_filetype(char * filetype) { + if (strcmp (filetype, "UNKNOWN")==0) + return XDGVFS_FILE_TYPE_UNKNOWN; + if (strcmp (filetype, "REGULAR")==0) + return XDGVFS_FILE_TYPE_REGULAR; + if (strcmp (filetype, "DIRECTORY")==0) + return XDGVFS_FILE_TYPE_DIRECTORY; + if (strcmp (filetype, "FIFO")==0) + return XDGVFS_FILE_TYPE_FIFO; + if (strcmp (filetype, "SOCKET")==0) + return XDGVFS_FILE_TYPE_SOCKET; + if (strcmp (filetype, "CHARDEV")==0) + return XDGVFS_FILE_TYPE_CHARDEV; + if (strcmp (filetype, "BLOCKDEV")==0) + return XDGVFS_FILE_TYPE_BLOCKDEV; + if (strcmp (filetype, "SYMLINK")==0) + return XDGVFS_FILE_TYPE_SYMLINK; + if (strcmp (filetype, "VFSMOUNTPOINT")==0) + return XDGVFS_FILE_TYPE_VFSMOUNTPOINT; + return XDGVFS_FILE_TYPE_UNREC; +}; + + +static int parse_pair(char * theLine, char ** keyName, char ** valueStr, long long int * valueLLInt) { + char * pValue = NULL; + char * tailptr; + + + *keyName = theLine; + *valueStr = NULL; + *valueLLInt = -1; + if (!theLine) return -1; //error + + if (*theLine) { + int c=0; + while (theLine[c] != '\0') { + if (theLine[c] == '=') { + theLine[c] = '\0'; + pValue = theLine +c +1; + } + + c++; + } + } + if (!pValue) return -2; + *valueStr = pValue; + errno = 0; + *valueLLInt = strtoll (pValue, &tailptr, 10); + if (errno) { + *valueLLInt =0; + return 2; + } + return 1; +} + +static int _parse_failure(char * failureStr, char ** errstr) { + char * pValue = failureStr + strlen(XDGVFS_TAG_FAILED); + char * tailptr; + errno = 0; + int errcode = strtol (pValue, &tailptr, 10); + + if (errno) { + *errstr = NULL; + return -1; + } + // fprintf(stderr, "errorcode = %d\n", errcode); + *errstr=tailptr; + return errcode; +} + +static void _init_job(XdgVfsSession * sess) { + + sess->currentItemType = 0; + sess->currentItem = NULL; + sess->lastJobErrorCode = 0; + sess->lastJobErrorText = NULL; + + sess->outBuf_used = 0; + +} + +static XdgVfsResult _finish_simple_job(XdgVfsSession * sess) +{ + XdgVfsResult r; + XdgVfsItemType type=0; + XdgVfsItem * item=NULL; + + while ((r=xdg_vfs_sess_readItem(sess, &type, + &item, NULL, NULL)) == XDGVFS_RESULT_CONTINUES) + { + // if (XDG_VFS_DEBUG_IPC) fprintf(stderr, "_finish simple job\n"); + switch (type) + { + case XDGVFS_ITEMTYPE_NONE: + { + break; + } + default: + { + fprintf(stderr, "simple job - unexpected item - type=%d\n", type); + break; + } + } + xdg_vfs_item_unref(item); + } + return r; +} + +/* =============== sessions =============== */ + +static char * _detect_desktop() { + char * e; + e = getenv ("GNOME_DESKTOP_SESSION_ID"); + if (e && strcmp(e, "") != 0) return "gnome"; + e = getenv ("KDE_FULL_SESSION"); + if (e && strcmp(e, "true") == 0) return "kde"; + return NULL; +} + + +XdgVfsResult xdg_vfs_sess_start(XdgVfsSession ** sessOut, char * preferredDesktop) { + int r; + char * desktop; + char * exePrefix = "xdg_vfs_"; + char * childArgv[] = { "xdg_vfs_client", "shell", NULL }; + + if (preferredDesktop && strcmp(preferredDesktop, "this") != 0) + desktop = preferredDesktop; + else + desktop = _detect_desktop(); + + if (!desktop) + return XDGVFS_RESULT_CANNOT_LAUNCH_BACKEND; + + XdgVfsSession * newSess = malloc(sizeof(XdgVfsSession)); + + char executableName[strlen(exePrefix) + strlen(preferredDesktop) + 1]; + executableName[0] = '\0'; + + strcat(executableName, exePrefix); + strcat(executableName, desktop); + + //puts(executableName); + + r = xdg_vfs_forkexec(executableName, childArgv, &newSess->pid, &newSess->fd_out, &newSess->fd_in); + + if (r) { + free(newSess); + *sessOut = NULL; + return XDGVFS_RESULT_IOERR; + } + newSess->inBuf = malloc(XDGVFS_CLIENT_BUFFERSIZE+1); + newSess->rawBufIn = malloc(XDGVFS_CLIENT_BUFFERSIZE+1); + newSess->inBuf_size = XDGVFS_CLIENT_BUFFERSIZE; + newSess->inBuf_used = 0; + _init_job(newSess); + newSess->stateIn = XDGVFS_STATE_EXPECTING_PROMPT; + newSess->recurse_count = 0; + + while (1) { + r = xdg_vfs_sess_readItem(newSess, NULL, + NULL, NULL, NULL); + /* fprintf(stderr, "readItem r=%d state=%d\n", r, newSess->stateIn); */ + + if (newSess->stateIn == XDGVFS_STATE_READY) break; + if (r!=XDGVFS_RESULT_CONTINUES) { + xdg_vfs_sess_close(newSess); + return XDGVFS_RESULT_CANNOT_LAUNCH_BACKEND; + } + } + + *sessOut = newSess; + + return XDGVFS_RESULT_OK; +} + +int xdg_vfs_sess_getIncomingFiledescriptor(XdgVfsSession * sess) +{ + return sess->fd_in; +} + +int xdg_vfs_sess_getOutgoingFiledescriptor(XdgVfsSession * sess) +{ + return sess->fd_out; +} + +int xdg_vfs_sess_isBusy(XdgVfsSession * sess) +{ + return sess->stateIn != XDGVFS_STATE_READY; +} + + +XdgVfsResult xdg_vfs_sess_close(XdgVfsSession * sess) { + if (!sess) { + fprintf(stderr, "NULL pointer passed to xdg_vfs_sess_close!\n"); + return XDGVFS_ERRORCODE_GENERIC; + } + close(sess->fd_out); + close(sess->fd_in); + free(sess->inBuf); + free(sess); + return XDGVFS_RESULT_OK; +} + +/* ================ file/dir change monitoring ============ */ + +void xdg_vfs_sess_set_monitor_callback( + XdgVfsSession * sess, + XdgVfsMonitorCallback cb, + void * userdata + ) +{ + sess->monitor_cb = cb; + sess->monitor_cb_userdata=userdata; +} + +/* ================ items ================= */ + +XdgVfsItem * xdg_vfs_item_ref(XdgVfsItem * item) { + item->refcount++; + return item; +} + +void xdg_vfs_item_unref(XdgVfsItem * item) { + if (item && --item->refcount <= 0) { + switch (item->type) + { + case XDGVFS_ITEMTYPE_FILEINFO: + { + XdgVfsFileInfo * _item = (XdgVfsFileInfo *) item; + if (_item->uri) free(_item->uri); + if (_item->basename) free(_item->basename); + if (_item->mimetype) free(_item->mimetype); + if (_item->user) free(_item->user); + if (_item->group) free(_item->group); + if (_item->mountpoint_id) free(_item->mountpoint_id); + break; + } + case XDGVFS_ITEMTYPE_GET_HEAD: + case XDGVFS_ITEMTYPE_PUT_HEAD: + case XDGVFS_ITEMTYPE_SETATTRS_HEAD: + case XDGVFS_ITEMTYPE_MKDIR_HEAD: + case XDGVFS_ITEMTYPE_RMDIR_HEAD: + case XDGVFS_ITEMTYPE_RM_HEAD: + case XDGVFS_ITEMTYPE_LS_HEAD: + { + // fprintf(stderr,"why1\n"); + XdgVfsSimpleHead * _item = (XdgVfsSimpleHead*) item; + if (_item->uri) free (_item->uri); + break; + } + case XDGVFS_ITEMTYPE_OPENFILEDLG_RESPONSE: + { + XdgVfsOpenFileDlgResponse * _item = (XdgVfsOpenFileDlgResponse*) item; + if (_item->selected_localpath) free(_item->selected_localpath); + if (_item->selected_uri) free(_item->selected_uri); + break; + } + case XDGVFS_ITEMTYPE_SAVEFILEDLG_RESPONSE: + { + // fprintf(stderr,"why\n"); + XdgVfsSaveFileDlgResponse * _item = (XdgVfsSaveFileDlgResponse*) item; + if (_item->selected_localpath) free(_item->selected_localpath); + if (_item->selected_uri) free(_item->selected_uri); + break; + } + case XDGVFS_ITEMTYPE_COPY_HEAD: + { + XdgVfsCopyHead * _item = (XdgVfsCopyHead*) item; + if (_item->uri_src) free(_item->uri_src); + if (_item->uri_target) free(_item->uri_target); + break; + } + case XDGVFS_ITEMTYPE_MOVE_HEAD: + { + XdgVfsMoveHead * _item = (XdgVfsMoveHead*) item; + if (_item->uri_src) free(_item->uri_src); + if (_item->uri_target) free(_item->uri_target); + break; + } + case XDGVFS_ITEMTYPE_BACKENDINFO: + { + XdgVfsBackendInfo * _item = (XdgVfsBackendInfo*) item; + if (_item->backend_id) free(_item->backend_id); + if (_item->system_uri) free(_item->system_uri); + if (_item->file_icon_theme) free(_item->file_icon_theme); + break; + } + + } + free(item); + + } + +} + + +/* ================ command utils =============== */ + +static XdgVfsResult _write_command(XdgVfsSession * sess, char * command, const char * argv[]) { + if (!sess) + { + fprintf(stderr, "NULL pointer passed to _write_command!\n"); + return XDGVFS_ERRORCODE_GENERIC; + } + if (sess->stateIn != XDGVFS_STATE_READY) return XDGVFS_RESULT_BAD_STATE; + FILE* out = fdopen(dup(sess->fd_out), "w"); + fputs(command, out); + int c=0; + while(argv[c] != NULL) { + const char * arg = argv[c]; + fputc((int)' ', out); + fputc((int)'"', out); + fputs(arg, out); /* todo: escape double quotes! */ + fputc((int)'"', out); + c++; + } + fputc(10, out); + fflush(out); + fclose(out); + //printf("written command!\n"); + sess->stateIn = XDGVFS_STATE_READING_TEXT; + _init_job(sess); + return XDGVFS_RESULT_OK; +} + +XdgVfsResult xdg_vfs_sess_cmd_cancel(XdgVfsSession * sess) { + /* not implemented yet */ + return XDGVFS_RESULT_OK; +} + +/* ========================= Commands ========================== */ + +XdgVfsResult xdg_vfs_sess_cmd_backendInfo(XdgVfsSession * sess) +{ + const char * argv[] = { NULL }; + return _write_command(sess, "backend", argv); +} + + +XdgVfsResult xdg_vfs_sess_cmd_getFile(XdgVfsSession * sess, const char * filename) +{ + const char * argv[] = { filename, "-e", NULL }; + return _write_command(sess, "get", argv); +} + +XdgVfsResult xdg_vfs_sess_cmd_putFile(XdgVfsSession * sess, const char * filename, + XdgVfsFlags flags) +{ + const char * argv[] = { filename, "-e", NULL, NULL }; + if (flags & XDGVFS_FLAGS_OVERWRITE) + { + argv[2] = "--overwrite"; + } + return _write_command(sess, "put", argv); +} + +XdgVfsResult xdg_vfs_sess_cmd_getFileInfo(XdgVfsSession * sess, const char * filename) +{ + const char * argv[] = { filename, NULL }; + return _write_command(sess, "info", argv); +} + +XdgVfsResult xdg_vfs_sess_cmd_setAttrs(XdgVfsSession * sess, + const char * filename, int permissions, int setPermFlag, char * user, char * group) +{ + XdgVfsResult r; + int an = 1; + const char * argv[] = { filename, NULL, NULL, NULL, NULL }; + + if ((!user) && (!group) && (!setPermFlag)) return XDGVFS_RESULT_PARAMETER_ERR; + + if (user) + { + char * str = calloc(256,1); + strncat(str, "--user=", 255); + strncat(str, user, 255); + argv[an++] = str; + } + if (group) + { + char * str = calloc(256,1); + strncat(str, "--group=", 255); + strncat(str, user, 255); + argv[an++] = str; + } + if (setPermFlag) + { + char * str = calloc(256,1); + snprintf (str, 255, "--permissions=%d\n", permissions); + argv[an++] = str; + } + r = _write_command(sess, "info", argv); + + if (argv[1]) free((void*)argv[1]); + if (argv[2]) free((void*)argv[2]); + if (argv[3]) free((void*)argv[3]); + return r; +} + +XdgVfsResult xdg_vfs_sess_cmd_copyFile(XdgVfsSession * sess, const char * filename_src, const char * filename_target) +{ + const char * argv[] = { filename_src, filename_target, "--progress", NULL }; + return _write_command(sess, "cp", argv); +} + +XdgVfsResult xdg_vfs_sess_cmd_moveFile(XdgVfsSession * sess, const char * filename_src, const char * filename_target) +{ + const char * argv[] = { filename_src, filename_target, "--progress", NULL }; + return _write_command(sess, "mv", argv); +} + + +XdgVfsResult xdg_vfs_sess_cmd_listDirectory(XdgVfsSession * sess, const char * filename) +{ + const char * argv[] = { filename, "--dive-de-links", NULL }; + return _write_command(sess, "ls", argv); +} + +XdgVfsResult xdg_vfs_sess_cmd_makeDirectory(XdgVfsSession * sess, const char * filename) +{ + const char * argv[] = { filename, NULL }; + return _write_command(sess, "mkdir", argv); +} + +XdgVfsResult xdg_vfs_sess_cmd_removeDirectory(XdgVfsSession * sess, const char * filename) +{ + const char * argv[] = { filename, NULL }; + return _write_command(sess, "rmdir", argv); +} + +XdgVfsResult xdg_vfs_sess_cmd_removeFile(XdgVfsSession * sess, const char * filename) +{ + const char * argv[] = { filename, NULL }; + return _write_command(sess, "rm", argv); +} + +XdgVfsResult xdg_vfs_sess_cmd_mount(XdgVfsSession * sess, const char * mountpoint_id) +{ + const char * argv[] = { mountpoint_id, NULL }; + return _write_command(sess, "mount", argv); +} + +XdgVfsResult xdg_vfs_sess_cmd_monitorDir(XdgVfsSession * sess, const char * uri) +{ + const char * argv[] = { uri, NULL }; + XdgVfsResult r = _write_command(sess, "mondir", argv); + if (r) return r; + return _finish_simple_job(sess); +} + +XdgVfsResult xdg_vfs_sess_cmd_monitorFile(XdgVfsSession * sess, const char * uri) +{ + const char * argv[] = { uri, NULL }; + XdgVfsResult r = _write_command(sess, "monfile", argv); + if (r) return r; + return _finish_simple_job(sess); + +} + +XdgVfsResult xdg_vfs_sess_cmd_removeMonitor(XdgVfsSession * sess, const char * uri) +{ + const char * argv[] = { uri, NULL }; + XdgVfsResult r = _write_command(sess, "rmmon", argv); + if (r) return r; + return _finish_simple_job(sess); +} + + +XdgVfsResult xdg_vfs_sess_cmd_openFileDialog(XdgVfsSession * sess, const char * filename, XdgVfsFlags flags) +{ + const char * argv[] = { filename, NULL, NULL, NULL }; + + if (flags & XDGVFS_FLAGS_INSTANT_GET) { + argv[1] = "--instant-get"; + } + if (flags & XDGVFS_FLAGS_QRY_FILEINFO) { + argv[2] = "-i"; + } + return _write_command(sess, "openfiledlg", argv); + +} + +XdgVfsResult xdg_vfs_sess_cmd_saveFileDialog(XdgVfsSession * sess, const char * filename, XdgVfsFlags flags) +{ + const char * argv[] = { filename, NULL, NULL }; + + if (flags & XDGVFS_FLAGS_INSTANT_PUT) { + argv[1] = "--instant-put"; + } + return _write_command(sess, "savefiledlg", argv); +} + +/* ========================= Reading and writing ========================== */ + +static XdgVfsResult _read_chunk(XdgVfsSession * sess) +{ + int i, n; + char * buf = sess->inBuf; + int used = sess->inBuf_used; + int size = sess->inBuf_size; + + n = read (sess->fd_in, buf+used, size-used,0); + if (n==0) + { + return XDGVFS_RESULT_IOERR; // EOF -> child process has died + } + if (n<0) + { + printf ("reading head returns: %d\n", n); + perror ("error reading"); + return XDGVFS_RESULT_IOERR; // EOF -> child process has died + } + if (XDG_VFS_DEBUG_IPC) + { + fwrite (buf+used, 1, n, stderr); + fflush(stderr); + } + + sess->inBuf_used = used+n; + return XDGVFS_RESULT_OK; +} + +static char * _get_str_blocking(XdgVfsSession * sess, int size) { + char * buf = sess->inBuf; + int used = sess->inBuf_used; + char * str; + while (sess->inBuf_used < size) + { + XdgVfsResult r = _read_chunk(sess); + if (r) + { + fprintf(stdout, "_get_str_blocking problem: %d\n", r); + return NULL; + } + } + str = malloc(size+1); + memcpy(str, buf, size); + str[size]='\0'; + memcpy(buf, buf+size, used-size); + sess->inBuf_used = used-size; + return str; +} + +static char * _get_next_line(XdgVfsSession * sess) { + char * theLine = NULL; + char * buf = sess->inBuf; + int i; + int used = sess->inBuf_used; + //buf[used+1] = '\0'; + //fprintf(stderr, "_get_next_line used=%d buf=%s\n", used, buf); + for (i = 0; i < used; i++) { + if (buf[i] == '\n') { + buf[i] = '\0'; + theLine=strdup(buf); + memcpy(buf, buf+i+1, used-i); /* shift data left */ + sess->inBuf_used = used-i-1; + break; + } + } + return theLine; +} + + + +static XdgVfsResult _xdg_vfs_sess_parseLine(XdgVfsSession * sess, XdgVfsItemType * type, XdgVfsItem ** item) +{ + char * theLine; + + *type = XDGVFS_ITEMTYPE_NONE; + *item = NULL; + + + theLine = _get_next_line(sess); + if (!theLine) + { + XdgVfsResult r = _read_chunk(sess); + if (r) return r; + theLine = _get_next_line(sess); + } + + + if (XDG_VFS_DEBUG_IPC) fprintf(stdout, "t=%d line: >>%s<<\n", (sess->currentItemType), theLine); + + if (theLine && theLine[0] != '\0') + { + if (theLine[0] == '[' || theLine[0] == '(' || theLine[0] == ':') + { + /* We got a new Object - thus we have to return the old one */ + XdgVfsItem * newItem = NULL; + + if (strcmp(theLine, XDGVFS_TAG_BACKEND)==0) + { + XdgVfsBackendInfo * _newItem = calloc(1, sizeof(XdgVfsBackendInfo)); + newItem = (XdgVfsItem*) _newItem; + newItem->type = XDGVFS_ITEMTYPE_BACKENDINFO; + } + else if (strcmp(theLine, XDGVFS_TAG_GET)==0) + { + XdgVfsSimpleHead * _newItem = calloc(1, sizeof(XdgVfsSimpleHead)); + newItem = (XdgVfsItem*) _newItem; + newItem->type = XDGVFS_ITEMTYPE_GET_HEAD; + } + else if (strcmp(theLine, XDGVFS_TAG_PUT)==0) + { + XdgVfsSimpleHead * _newItem = calloc(1, sizeof(XdgVfsSimpleHead)); + newItem = (XdgVfsItem*) _newItem; + newItem->type = XDGVFS_ITEMTYPE_PUT_HEAD; + } + else if (strcmp(theLine, XDGVFS_TAG_ESCAPEDDATA_OUT)==0) + { + XdgVfsDataInDoneItem * _newItem = calloc(1, sizeof(XdgVfsDataInDoneItem)); + _newItem->bytecount = 0; + newItem = (XdgVfsItem*) _newItem; + newItem->type = XDGVFS_ITEMTYPE_DATAIN_DONE; + sess->stateIn = XDGVFS_STATE_READING_DATA; + } + else if (strcmp(theLine,XDGVFS_TAG_PUT)==0) + { + XdgVfsSimpleHead * _newItem = calloc(1, sizeof(XdgVfsSimpleHead)); + newItem = (XdgVfsItem*) _newItem; + newItem->type = XDGVFS_ITEMTYPE_GET_HEAD; + } + else if (strcmp(theLine, XDGVFS_TAG_ESCAPEDDATA_IN)==0) + { + XdgVfsDataOutDoneItem * _newItem = calloc(1, sizeof(XdgVfsDataOutDoneItem)); + newItem = (XdgVfsItem*) _newItem; + _newItem->bytecount = 0; + newItem->type = XDGVFS_ITEMTYPE_DATAOUT_DONE; + sess->stateIn = XDGVFS_STATE_WRITING_DATA; + } + else if (strcmp(theLine,XDGVFS_TAG_CP)==0) + { + XdgVfsCopyHead * _newItem = calloc(1, sizeof(XdgVfsCopyHead)); + newItem = (XdgVfsItem*) _newItem; + newItem->type = XDGVFS_ITEMTYPE_COPY_HEAD; + } + else if (strcmp(theLine,XDGVFS_TAG_MV)==0) + { + XdgVfsMoveHead * _newItem = calloc(1, sizeof(XdgVfsMoveHead)); + newItem = (XdgVfsItem*) _newItem; + newItem->type = XDGVFS_ITEMTYPE_MOVE_HEAD; + } + else if (strcmp(theLine,XDGVFS_TAG_PROGRESS)==0) + { + XdgVfsProgress * _newItem = calloc(1, sizeof(XdgVfsProgress)); + newItem = (XdgVfsItem*) _newItem; + newItem->type = XDGVFS_ITEMTYPE_PROGRESS; + } + else if (strcmp(theLine,XDGVFS_TAG_FILEINFO)==0 + || strcmp(theLine,XDGVFS_TAG_DIRENTRY)==0) + { + XdgVfsFileInfo * _newItem = calloc(1, sizeof(XdgVfsFileInfo)); + newItem = (XdgVfsItem*) _newItem; + newItem->type = XDGVFS_ITEMTYPE_FILEINFO; + } + else if (strcmp(theLine,XDGVFS_TAG_SETATTRS)==0) + { + XdgVfsSimpleHead * _newItem = calloc(1, sizeof(XdgVfsSimpleHead)); + newItem = (XdgVfsItem*) _newItem; + newItem->type = XDGVFS_ITEMTYPE_SETATTRS_HEAD; + } + else if (strcmp(theLine,XDGVFS_TAG_LS)==0) + { + XdgVfsSimpleHead * _newItem = calloc(1, sizeof(XdgVfsSimpleHead)); + newItem = (XdgVfsItem*) _newItem; + newItem->type = XDGVFS_ITEMTYPE_LS_HEAD; + } + else if (strcmp(theLine,XDGVFS_TAG_MKDIR)==0) + { + XdgVfsSimpleHead * _newItem = calloc(1, sizeof(XdgVfsSimpleHead)); + newItem = (XdgVfsItem*) _newItem; + newItem->type = XDGVFS_ITEMTYPE_MKDIR_HEAD; + } + else if (strcmp(theLine,XDGVFS_TAG_RMDIR)==0) + { + XdgVfsSimpleHead * _newItem = calloc(1, sizeof(XdgVfsSimpleHead)); + newItem = (XdgVfsItem*) _newItem; + newItem->type = XDGVFS_ITEMTYPE_RMDIR_HEAD; + } + else if (strcmp(theLine,XDGVFS_TAG_RM)==0) + { + XdgVfsSimpleHead * _newItem = calloc(1, sizeof(XdgVfsSimpleHead)); + newItem = (XdgVfsItem*) _newItem; + newItem->type = XDGVFS_ITEMTYPE_RMDIR_HEAD; + } + else if (strcmp(theLine,XDGVFS_TAG_MOUNT)==0) + { + //XdgVfsSimpleHead * _newItem = calloc(1, sizeof(XdgVfsSimpleHead)); + newItem = NULL; + //newItem->type = XDGVFS_ITEMTYPE_NONE; + } + else if (strcmp(theLine,XDGVFS_TAG_OPENFILEDLG)==0) + { + XdgVfsOpenFileDlgResponse * _newItem = calloc(1, sizeof(XdgVfsOpenFileDlgResponse)); + newItem = (XdgVfsItem*) _newItem; + newItem->type = XDGVFS_ITEMTYPE_OPENFILEDLG_RESPONSE; + } + else if (strcmp(theLine,XDGVFS_TAG_SAVEFILEDLG)==0) + { + XdgVfsSaveFileDlgResponse * _newItem = calloc(1, sizeof(XdgVfsSaveFileDlgResponse)); + newItem = (XdgVfsItem*) _newItem; + newItem->type = XDGVFS_ITEMTYPE_SAVEFILEDLG_RESPONSE; + } + /* finished? */ + else if (strcmp(theLine,XDGVFS_TAG_DONE)==0) + { + //fprintf(stderr,"done\n"); + sess->stateIn = XDGVFS_STATE_EXPECTING_PROMPT; + sess->lastJobErrorCode = XDGVFS_ERRORCODE_OK; + } + else if (strncmp(theLine,XDGVFS_TAG_FAILED, strlen(XDGVFS_TAG_FAILED)) ==0) + { + char * errstr; + sess->lastJobErrorCode = _parse_failure(theLine, &errstr); + sess->stateIn = XDGVFS_STATE_EXPECTING_PROMPT; + //fprintf(stderr,"failed code=%d\n", sess->lastJobErrorCode); + sess->currentItemType = XDGVFS_ITEMTYPE_NONE; + sess->currentItem = NULL; // fixme unref! + } else { + fprintf(stderr,"unexpected tag: %s\n", theLine); + sess->stateIn = XDGVFS_STATE_ERROR_LEAVING; + return XDGVFS_RESULT_IOERR; + } + + *type = sess->currentItemType; + *item = sess->currentItem; + if (newItem) { + newItem->refcount = 1; + sess->currentItemType = newItem->type; + sess->currentItem = newItem; + } else { + sess->currentItemType = XDGVFS_ITEMTYPE_NONE; + sess->currentItem = NULL; + } + + } + else if(theLine[0] == XDGVFS_TAG_MONITOREVENT [0]) + { + int l = strlen(theLine); + if (l>2 && sess->monitor_cb) + { + char * changed_uri = strdup(theLine+2); + sess->monitor_cb(sess, changed_uri, sess->monitor_cb_userdata); + free(changed_uri); + } + else + fprintf(stderr, "monitorevent: line too short\n"); + } + else + { + XdgVfsItem * rItem = sess->currentItem; + char * keyname; + char * valueStr; + long long int valueLLInt; + parse_pair(theLine, &keyname, &valueStr, &valueLLInt); + switch(sess->currentItemType) + { + case(XDGVFS_ITEMTYPE_GET_HEAD): + case(XDGVFS_ITEMTYPE_PUT_HEAD): + case(XDGVFS_ITEMTYPE_MKDIR_HEAD): + case(XDGVFS_ITEMTYPE_RMDIR_HEAD): + case(XDGVFS_ITEMTYPE_RM_HEAD): + case(XDGVFS_ITEMTYPE_LS_HEAD): + case(XDGVFS_ITEMTYPE_SETATTRS_HEAD): + { + XdgVfsSimpleHead * _rItem = (XdgVfsSimpleHead*)rItem; + if (strcmp(keyname, "uri")==0) + _rItem->uri = strdup(valueStr); + break; + } + case(XDGVFS_ITEMTYPE_BACKENDINFO): + { + + XdgVfsBackendInfo * _rItem = (XdgVfsBackendInfo*)rItem; + if (strcmp(keyname, "backend_id")==0) + _rItem->backend_id = strdup(valueStr); + if (strcmp(keyname, "system_uri")==0) + _rItem->system_uri = strdup(valueStr); + if (strcmp(keyname, "file_icon_theme")==0) + _rItem->file_icon_theme = strdup(valueStr); + break; + } + case(XDGVFS_ITEMTYPE_FILEINFO): + { + + XdgVfsFileInfo * _rItem = (XdgVfsFileInfo*)rItem; + if (strcmp(keyname, "basename")==0) + _rItem->basename = strdup(valueStr); + if (strcmp(keyname, "mimetype")==0) + _rItem->mimetype = strdup(valueStr); + if (strcmp(keyname, "iconname")==0) + _rItem->iconname = strdup(valueStr); + if (strcmp(keyname, "uri")==0) + _rItem->uri = strdup(valueStr); + if (strcmp(keyname, "user")==0) + _rItem->user = strdup(valueStr); + if (strcmp(keyname, "group")==0) + _rItem->group = strdup(valueStr); + if (strcmp(keyname, "linkdest")==0) + _rItem->linkdest = strdup(valueStr); + if (strcmp(keyname, "filetype")==0) + _rItem->filetype = _translate_filetype(valueStr); + if (strcmp(keyname, "mountpoint_id")==0) + _rItem->mountpoint_id = strdup(valueStr); + + if (strcmp(keyname, "permissions")==0) + _rItem->permissions = valueLLInt; + if (strcmp(keyname, "size")==0) + _rItem->size = valueLLInt; + if (strcmp(keyname, "atime")==0) + _rItem->atime = valueLLInt; + if (strcmp(keyname, "mtime")==0) + _rItem->mtime = valueLLInt; + if (strcmp(keyname, "ctime")==0) + _rItem->ctime = valueLLInt; + if (strcmp(keyname, "is_mounted")==0) + _rItem->is_mounted = valueLLInt; + break; + } + case(XDGVFS_ITEMTYPE_PROGRESS): + { + XdgVfsProgress * _rItem = (XdgVfsProgress*)rItem; + if (strcmp(keyname, "total_bytes")==0) + _rItem->size = valueLLInt; + if (strcmp(keyname, "bytes_copied")==0) + _rItem->copied = valueLLInt; + break; + } + case(XDGVFS_ITEMTYPE_OPENFILEDLG_RESPONSE): + { + XdgVfsOpenFileDlgResponse * _rItem = (XdgVfsOpenFileDlgResponse*) rItem; + if (strcmp(keyname, "selected_localpath")==0) + _rItem->selected_localpath = strdup(valueStr);; + if (strcmp(keyname, "selected_uri")==0) + _rItem->selected_uri = strdup(valueStr);; + break; + } + case(XDGVFS_ITEMTYPE_SAVEFILEDLG_RESPONSE): + { + XdgVfsSaveFileDlgResponse * _rItem = (XdgVfsSaveFileDlgResponse*) rItem; + if (strcmp(keyname, "selected_localpath")==0) + _rItem->selected_localpath = strdup(valueStr);; + if (strcmp(keyname, "selected_uri")==0) + _rItem->selected_uri = strdup(valueStr);; + break; + } + case(XDGVFS_ITEMTYPE_COPY_HEAD): + { + XdgVfsCopyHead * _rItem = (XdgVfsCopyHead*) rItem; + if (strcmp(keyname, "uri_src")==0) + _rItem->uri_src = strdup(valueStr);; + if (strcmp(keyname, "uri_target")==0) + _rItem->uri_target = strdup(valueStr);; + break; + } + case(XDGVFS_ITEMTYPE_MOVE_HEAD): + { + XdgVfsMoveHead * _rItem = (XdgVfsMoveHead*) rItem; + if (strcmp(keyname, "uri_src")==0) + _rItem->uri_src = strdup(valueStr);; + if (strcmp(keyname, "uri_target")==0) + _rItem->uri_target = strdup(valueStr);; + break; + } + case(XDGVFS_ITEMTYPE_DATAIN_DONE): + break; + } + //if (valueStr) free(valueStr); + } + } + return XDGVFS_RESULT_CONTINUES; +} + +static void _debug_print_out_buffer(XdgVfsSession * sess) { + int i; + //sess->inBuf[sess->inBuf_used+1] = '\0'; + // + fprintf(stderr, "buf: used=%d '", sess->inBuf_used); + for (i=0;i<sess->inBuf_used;i++) + { + int c = sess->inBuf[i]; + if (c < 32 || c > 126) + fputc('.', stderr); + else + fputc(c, stderr); + } + fprintf(stderr, "'\n"); +} + +static XdgVfsResult _report_size(XdgVfsSession * sess, int len) +{ + if (sess->currentItemType == XDGVFS_ITEMTYPE_DATAIN_DONE) + { + XdgVfsDataInDoneItem * item = (XdgVfsDataInDoneItem *) sess->currentItem; + item->bytecount+=len; + return XDGVFS_RESULT_OK; + + } + else + { + fprintf(stderr,"fatal: data-in-item not found!!!\n"); + sess->stateIn = XDGVFS_STATE_ERROR_LEAVING; + return XDGVFS_RESULT_FATAL_ERR; + } +} + +static XdgVfsResult _read_data(XdgVfsSession * sess, XdgVfsItemType * typeOut, char ** buffer, int * len) +{ + *buffer = NULL; + *len = 0; + if (sess->inBuf_used<2) + { + //fprintf(stderr, "readchunk\n"); + XdgVfsResult r = _read_chunk(sess); + if (r) return r; + } + + char * buf = sess->inBuf; + int used = sess->inBuf_used; + //fprintf(stderr, "\nlen = %d\n", used); + int i=0; + char * outptr = sess->rawBufIn; + while (i<used) + { + char c = buf[i]; + if (c == '~') + { + i++; + if (i<used) + { + if (buf[i] == '~') + { + i++; + *outptr++ = '~'; + continue; + } + else + if (buf[i] == '\n') + { + memcpy(buf, buf+i+1, used-i); + *buffer = sess->rawBufIn; + *len = outptr - sess->rawBufIn; + sess->inBuf_used = used-i-1; + + _report_size(sess, *len); + /* fprintf(stderr, "read all data - end found len=%d\n", *len); */ + /* _debug_print_out_buffer(sess); */ + + sess->stateIn = XDGVFS_STATE_READING_TEXT; + /* finished - switch back to text-mode */ + *typeOut = XDGVFS_DATAIN; + return XDGVFS_RESULT_CONTINUES; + } + else + { + *buffer = NULL; + *len = 0; + fprintf(stderr, "unescaping error at pos=%d buffer len=%d:\n", i, used); + _debug_print_out_buffer(sess); + fprintf(stderr, "unescaped buffer:\n"); + fwrite (sess->rawBufIn, 1, outptr - sess->rawBufIn, stdout); + sess->inBuf_used = 0; + sess->stateIn = XDGVFS_STATE_ERROR_LEAVING; + + return XDGVFS_RESULT_UNESCAPING_DATA_ERR; + } + } + else + { + buf[0]='~'; /* cannot process this - leave escape char in buffer */ + sess->inBuf_used = 1; + *buffer = sess->rawBufIn; + *len = outptr - sess->rawBufIn; + _report_size(sess, *len); + *typeOut = XDGVFS_DATAIN; + return XDGVFS_RESULT_CONTINUES; + } + } + else + { + i++; + *outptr++ = c; + } + } + + *buffer = sess->rawBufIn; + *len = outptr - sess->rawBufIn; + _report_size(sess, *len); + sess->inBuf_used = 0; + *typeOut = XDGVFS_DATAIN; + return XDGVFS_RESULT_CONTINUES; +} + + +static XdgVfsResult _xdg_vfs_sess_readItem(XdgVfsSession * sess, XdgVfsItemType * typeOut, + XdgVfsItem ** itemOut, char ** buffer, int * len) +{ + + if (typeOut) *typeOut = 0; + if (itemOut) *itemOut = NULL; + if (buffer) *buffer = NULL; + if (len) * len=0; + + if (XDG_VFS_DEBUG_IPC) fprintf(stderr, "state=%d\n", sess->stateIn); + // _debug_print_out_buffer(sess); + + + switch(sess->stateIn) + { + case(XDGVFS_STATE_EXPECTING_PROMPT): + + if (sess->inBuf_used >= 2) + { + char * prompt = _get_str_blocking(sess, 2); + if (prompt && strcmp(prompt, "> ")==0) + { + sess->stateIn = XDGVFS_STATE_READY; + free(prompt); + return sess->lastJobErrorCode; + } + else + { + if(prompt) free (prompt); + return XDGVFS_ERRORCODE_CORRUPTED_DATA; + } + } +/* else if (sess->inBuf_used > 2) + { + return XDGVFS_ERRORCODE_CORRUPTED_DATA; + } */ + else + { + XdgVfsResult r = _read_chunk(sess); + if (r) return r; + return XDGVFS_RESULT_CONTINUES; + } + break; + case(XDGVFS_STATE_READY): + { + XdgVfsResult r = _xdg_vfs_sess_parseLine(sess, typeOut, itemOut); + if (typeOut && *typeOut != XDGVFS_ITEMTYPE_NONE) + { + fprintf(stderr, + "WARNING: calling this function in 'ready-state' shouldn't " + "return anything except triggering file monitoring events!" + " itemType=%d\n", typeOut); + + if (typeOut) *typeOut=XDGVFS_ITEMTYPE_NONE; + if (itemOut) + { + xdg_vfs_item_unref(*itemOut); + *itemOut=NULL; + } + return XDGVFS_RESULT_BAD_STATE; + } + if (r!=XDGVFS_RESULT_CONTINUES) + { + fprintf(stderr, + "WARNING: calling this function in 'ready-state' shouldn't" + " return errors!\n"); + return r; + } + return XDGVFS_RESULT_OK; + } + case(XDGVFS_STATE_READING_TEXT): + return _xdg_vfs_sess_parseLine(sess, typeOut, itemOut); + case(XDGVFS_STATE_READING_DATA): + return _read_data(sess, typeOut, buffer, len); + case(XDGVFS_STATE_WRITING_DATA): + *typeOut = XDGVFS_DATAOUT; + return XDGVFS_RESULT_CONTINUES; + case(XDGVFS_STATE_ERROR_LEAVING): + return XDGVFS_RESULT_IOERR; + + default: + return XDGVFS_RESULT_BAD_STATE; + } + return XDGVFS_ERRORCODE_OK; +} + +XdgVfsResult xdg_vfs_sess_readItem(XdgVfsSession * sess, XdgVfsItemType * typeOut, + XdgVfsItem ** itemOut, char ** buffer, int * len) +{ + XdgVfsResult r; + if (sess->recurse_count > 0) { + fprintf(stderr, "Warning: cannot recurse readItem function!\n"); + return XDGVFS_RESULT_BAD_STATE; + } + sess->recurse_count = sess->recurse_count+1; + r= _xdg_vfs_sess_readItem(sess, typeOut, itemOut, buffer, len); + sess->recurse_count = sess->recurse_count-1; + return r; +} + +static int _chk_incoming(XdgVfsSession * sess) +{ + /* check for canceled */ + int filedes = sess->fd_in; + 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 = 0; + 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 incoming data\n"); + return 0; + } + else + { + return 1; + } +} + + +XdgVfsResult xdg_vfs_sess_sendData(XdgVfsSession * sess) { + + if (_chk_incoming(sess)) + { + sess->stateIn = XDGVFS_STATE_READING_TEXT; + return XDGVFS_RESULT_IOERR; + } + + + if (sess->outBuf_used - sess->outBuf_sent == 0) return XDGVFS_RESULT_GIVE_ME_DATA; + + ssize_t len = write (sess->fd_out, + sess->outBuf + sess->outBuf_sent, + sess->outBuf_used - sess->outBuf_sent); + // fprintf(stderr, "sent %d bytes\n", len); + //sleep(1); + if (len == -1) { + if (errno == EAGAIN) return XDGVFS_RESULT_CALL_SENDDATA_AGAIN; + perror ("sending data to xdg-vfs process - IOERR"); + return XDGVFS_RESULT_IOERR; + } + sess->outBuf_sent += len; + + + if (sess->outBuf_used - sess->outBuf_sent == 0) { + if (sess->outBuf_EOF) { + sess->stateIn = XDGVFS_STATE_READING_TEXT; + return XDGVFS_RESULT_OK; + } + return XDGVFS_RESULT_GIVE_ME_DATA; + } + + return XDGVFS_RESULT_CALL_SENDDATA_AGAIN; + +} + +XdgVfsResult xdg_vfs_sess_putDataChunk(XdgVfsSession * sess, char * data, int len) { + + sess->outBuf_sent = 0; + if (len == 0 ) { /* EOF */ + if (data) { + fprintf(stderr, "WARNING: set data to NULL on EOF!!\n"); + } + + sess->outBuf[0] = '~'; + sess->outBuf[1] = '\n'; + sess->outBuf_used = 2; + sess->outBuf_EOF = 1; + return XDGVFS_RESULT_CALL_SENDDATA_AGAIN; + } + + if (sess->currentItemType == XDGVFS_ITEMTYPE_DATAOUT_DONE) { + XdgVfsDataOutDoneItem * dii = (XdgVfsDataOutDoneItem *) sess->currentItem; + dii->bytecount += len; + } + else + { + fprintf(stderr, "Where is my object?\n"); + return XDGVFS_RESULT_BAD_STATE; + } + + if (!sess->outBuf) sess->outBuf = malloc(len*2); /* can be max twice the data size */ + if (sess->outBuf_size < len * 2) + { + sess->outBuf = realloc (sess->outBuf, len * 2); + sess->outBuf_size = len * 2; + } + int i = 0; + char * wptr = sess->outBuf; + for (i = 0; i<len; i++) + { + char c = data[i]; + if (c == '~') /* escape it */ + { + *wptr++ = '~'; + *wptr++ = '~'; + } + else + *wptr++ = c; + } + sess->outBuf_used = wptr - sess->outBuf; + + return XDGVFS_RESULT_CALL_SENDDATA_AGAIN; + +} + + + + diff --git a/libxdg-vfs-client/src/xdg_vfs_client.h b/libxdg-vfs-client/src/xdg_vfs_client.h new file mode 100644 index 0000000..6ba6f19 --- /dev/null +++ b/libxdg-vfs-client/src/xdg_vfs_client.h @@ -0,0 +1,491 @@ +/* +# xdg_vfs_client.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 XDGVFS_CLIENT_H_ +#define XDGVFS_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <xdg_vfs_common.h> + +#define XDG_VFS_DEBUG_IPC 1 + +#define XDGVFS_CLIENT_BUFFERSIZE 8192 + +typedef size_t XdgVfsFileSize; + + +/* ====== incoming Items ======== */ + + +/** +* itemtypes +*/ +typedef enum { + XDGVFS_ITEMTYPE_FILEINFO = 1, + XDGVFS_ITEMTYPE_SETATTRS_HEAD = 2, + XDGVFS_ITEMTYPE_DIR_HEAD = 3, + XDGVFS_ITEMTYPE_DIR_ENTRY = 4, + XDGVFS_ITEMTYPE_PROGRESS = 5, + XDGVFS_ITEMTYPE_GET_HEAD = 6, + XDGVFS_ITEMTYPE_PUT_HEAD = 7, + XDGVFS_ITEMTYPE_COPY_HEAD = 8, + XDGVFS_ITEMTYPE_MOVE_HEAD = 9, + XDGVFS_ITEMTYPE_MKDIR_HEAD = 10, + XDGVFS_ITEMTYPE_RMDIR_HEAD = 11, + XDGVFS_ITEMTYPE_RM_HEAD = 12, + XDGVFS_ITEMTYPE_LS_HEAD = 13, + XDGVFS_ITEMTYPE_OPENFILEDLG_RESPONSE = 14, + XDGVFS_ITEMTYPE_SAVEFILEDLG_RESPONSE = 15, + XDGVFS_ITEMTYPE_DATAIN_DONE = 16, + XDGVFS_ITEMTYPE_DATAOUT_DONE = 17, + XDGVFS_DATAIN = 18, + XDGVFS_DATAOUT = 19, + XDGVFS_ITEMTYPE_BACKENDINFO = 20, + + XDGVFS_ITEMTYPE_NONE = 0 +} XdgVfsItemType; + + +typedef struct { + XdgVfsItemType type; + int refcount; +} XdgVfsItem; + +typedef struct { + XdgVfsItem itm; + char * backend_id; + char * system_uri; + char * file_icon_theme; +} XdgVfsBackendInfo; + + +typedef struct { + XdgVfsItem itm; + XdgVfsFileSize bytecount; +} XdgVfsDataInDoneItem; + +typedef struct { + XdgVfsItem itm; + XdgVfsFileSize bytecount; +} XdgVfsDataOutDoneItem; + +typedef struct { + XdgVfsItem itm; + char * uri; +} XdgVfsSimpleHead; + +/** +* fileinfo filetypes +*/ +typedef enum { + XDGVFS_FILE_TYPE_UNKNOWN = 1, + XDGVFS_FILE_TYPE_REGULAR = 2, + XDGVFS_FILE_TYPE_DIRECTORY = 3, + XDGVFS_FILE_TYPE_FIFO = 4, + XDGVFS_FILE_TYPE_SOCKET = 5, + XDGVFS_FILE_TYPE_CHARDEV = 6, + XDGVFS_FILE_TYPE_BLOCKDEV = 7, + XDGVFS_FILE_TYPE_SYMLINK = 8, + XDGVFS_FILE_TYPE_VFSMOUNTPOINT = 9, + XDGVFS_FILE_TYPE_UNREC = 0 +} XdgVfsFileType; + +/** +* fileinfo item +*/ +typedef struct { + XdgVfsItem itm; + char * uri; + char * basename; + char * mimetype; + size_t size; + int permissions; + char * user; + char * group; + int atime; + int ctime; + int mtime; + char * linkdest; + XdgVfsFileType filetype; + char * iconname; + char * mountpoint_id; + int is_mounted; +} XdgVfsFileInfo; + +typedef struct { + XdgVfsItem itm; + char * selected_localpath; + char * selected_uri; +} XdgVfsOpenFileDlgResponse; + +typedef struct { + XdgVfsItem itm; + char * selected_localpath; + char * selected_uri; +} XdgVfsSaveFileDlgResponse; + +typedef struct { + XdgVfsItem itm; + char * uri_src; + char * uri_target; +} XdgVfsCopyHead; + +typedef struct { + XdgVfsItem itm; + char * uri_src; + char * uri_target; +} XdgVfsMoveHead; + +typedef struct { + XdgVfsItem itm; + int percent; + XdgVfsFileSize size; + XdgVfsFileSize copied; +} XdgVfsProgress; + + +/* ====== flags and return values ======== */ + +/* +* Command flags +*/ +typedef enum { + XDGVFS_FLAGS_NONE = 0, + XDGVFS_FLAGS_OVERWRITE = 2, + XDGVFS_FLAGS_INSTANT_GET = 4, + XDGVFS_FLAGS_INSTANT_PUT = 8, + XDGVFS_FLAGS_QRY_FILEINFO = 16 +} XdgVfsFlags; + +/** +* xdg-vfs return values: +* values less than 0 are client errors. +* values greater than 0 are XDGVFS_ERRORCODE_* errors! +*/ +#define XDGVFS_RESULT_CANNOT_LAUNCH_BACKEND -10 +#define XDGVFS_RESULT_CALL_SENDDATA_AGAIN -9 +#define XDGVFS_RESULT_GIVE_ME_DATA -8 +#define XDGVFS_RESULT_PARAMETER_ERR -7 +#define XDGVFS_RESULT_FATAL_ERR -6 +#define XDGVFS_RESULT_UNESCAPING_DATA_ERR -5 +#define XDGVFS_RESULT_BAD_STATE -4 +#define XDGVFS_RESULT_IOERR -3 +#define XDGVFS_RESULT_NOT_POSSIBLE -2 +#define XDGVFS_RESULT_CONTINUES -1 +#define XDGVFS_RESULT_DONE 0 +#define XDGVFS_RESULT_OK 0 + +#define XDGVFS_RESULT_CANNOT_LAUNCH_BACKEND_STR "Client: Cannot launch backend" +#define XDGVFS_RESULT_CALL_SENDDATA_AGAIN_STR "Client: call sendData again" +#define XDGVFS_RESULT_GIVE_ME_DATA_STR "Client: give me data" +#define XDGVFS_RESULT_PARAMETER_ERR_STR "Client: parameter error" +#define XDGVFS_RESULT_FATAL_ERR_STR "Client: fatal error" +#define XDGVFS_RESULT_UNESCAPING_DATA_ERR_STR "Client: unescaping data error" +#define XDGVFS_RESULT_BAD_STATE_STR "Client: bad state" +#define XDGVFS_RESULT_IOERR_STR "Client: IOERR" +#define XDGVFS_RESULT_NOT_POSSIBLE_STR "Client: operation not possible" +#define XDGVFS_RESULT_CONTINUES_STR "Client: result continues" +#define XDGVFS_RESULT_OK_STR "Client: OK/DONE" + +typedef int XdgVfsResult; + +/** +* session state +*/ +typedef enum { + XDGVFS_STATE_ERROR_LEAVING = -1, + XDGVFS_STATE_READING_DATA = 1, + XDGVFS_STATE_WRITING_DATA = 2, + XDGVFS_STATE_EXPECTING_PROMPT = 3, + XDGVFS_STATE_READY = 4, + XDGVFS_STATE_READING_TEXT = 5 +} XdgVfsState; + +typedef struct _XdgVfsSession XdgVfsSession; + +typedef void (*XdgVfsMonitorCallback)(XdgVfsSession * sess, char * uri, void * user_data); + +/* +* Session Object +* never access the members of this stuct directly (it might change)! +*/ +struct _XdgVfsSession { + /* all members are private! */ + + /* pipes to the sub-process */ + int fd_in; + int fd_out; + + int pid; + + /* incoming data buffers */ + char * inBuf; + int inBuf_used; + int inBuf_size; + XdgVfsState stateIn; + + char * rawBufIn; + + /* outgoing data buffers */ + char * outBuf; + int outBuf_sent; + int outBuf_used; + int outBuf_size; + int outBuf_EOF; + XdgVfsState stateOut; + + /* incoming items */ + XdgVfsItemType currentItemType; + XdgVfsItem * currentItem; + + int lastJobErrorCode; + char * lastJobErrorText; + + /* file/dir change monitoring */ + XdgVfsMonitorCallback monitor_cb; + void * monitor_cb_userdata; + + /* recursion protection */ + int recurse_count; + +}; + + +/** +* +* Start Session and setup child process +* (with a session you can run a 'session of' xdg-vfs commands (one after the other) +* pass NULL or "this" for the current desktop or "kde"/"gnome" for preferredDesktop. +*/ +XdgVfsResult xdg_vfs_sess_start(XdgVfsSession ** sessOut, char * preferredDesktop); + +/** +* Close session and kill child process +* +*/ +XdgVfsResult xdg_vfs_sess_close(XdgVfsSession * sess); + +/** +* Cancel the current Command +* +*/ +XdgVfsResult xdg_vfs_sess_cmd_cancel(XdgVfsSession * sess); + +/** +* Watch this fd to avoid blocking in xdgvfs_sess_readItem() +* +*/ +int xdg_vfs_sess_getIncomingFiledescriptor(XdgVfsSession * sess); + +/** +* Watch this fd to avoid blocking in xdg_vfs_sess_sendData(); +* +*/ +int xdg_vfs_sess_getOutgoingFiledescriptor(XdgVfsSession * sess); + +/** +* Check if the session is ready for commands +* +*/ +int xdg_vfs_sess_isBusy(XdgVfsSession * sess); + +/* ============== file/dirwatch monitor ===================== */ + +void xdg_vfs_sess_set_monitor_callback( + XdgVfsSession * sess, + XdgVfsMonitorCallback cb, + void * userdata + ); + +/* ====================== VFS Commands =======================*/ + +/* +* After running a command the session will leave the READY state and +* you have to read items from the session. +*/ +/** +* Command: get Backend Info +* +*/ + +XdgVfsResult xdg_vfs_sess_cmd_backendInfo(XdgVfsSession * sess); +/** +* Command: get File +* +*/ +XdgVfsResult xdg_vfs_sess_cmd_getFile(XdgVfsSession * sess, const char * filename); + +/** +* Command: put File +* +*/ +XdgVfsResult xdg_vfs_sess_cmd_putFile(XdgVfsSession * sess, const char * filename, + XdgVfsFlags flags); + +/** +* Command: getFileInfo +* +*/ +XdgVfsResult xdg_vfs_sess_cmd_getFileInfo(XdgVfsSession * sess, const char * filename); + +/** +* Command: SetAttrs +* +*/ +XdgVfsResult xdg_vfs_sess_cmd_setAttrs(XdgVfsSession * sess, + const char * filename, int permissions, int setPermFlag, char * user, char * group); + +/** +* Command: CopyFile +* +*/ +XdgVfsResult xdg_vfs_sess_cmd_copyFile(XdgVfsSession * sess, const char * filename_src, const char * filename_target); + +/** +* Command: Move File +* +*/ +XdgVfsResult xdg_vfs_sess_cmd_moveFile(XdgVfsSession * sess, const char * filename_src, const char * filename_target); + +/** +* Command: Make Directory +* +*/ +XdgVfsResult xdg_vfs_sess_cmd_makeDirectory(XdgVfsSession * sess, const char * filename); + +/** +* Command: Remove Directory +* +*/ +XdgVfsResult xdg_vfs_sess_cmd_removeDirectory(XdgVfsSession * sess, const char * filename); + +/** +* Command: Delete File +* +*/ +XdgVfsResult xdg_vfs_sess_cmd_removeFile(XdgVfsSession * sess, const char * filename); + +/** +* Command: List Directory +* +*/ +XdgVfsResult xdg_vfs_sess_cmd_listDirectory(XdgVfsSession * sess, const char * filename); + +/** +* Command: Mount +* +*/ +XdgVfsResult xdg_vfs_sess_cmd_mount(XdgVfsSession * sess, const char * mountpoint_id); + +/** +* Command: monitor directory +* This is a simple command, you don't have to read items to finish. +*/ +XdgVfsResult xdg_vfs_sess_cmd_monitorDir(XdgVfsSession * sess, const char * uri); + +/** +* Command: monitor file +* This is a simple command, you don't have to read items to finish. +*/ +XdgVfsResult xdg_vfs_sess_cmd_monitorFile(XdgVfsSession * sess, const char * uri); + +/** +* Command: remove monitor +* This is a simple command, you don't have to read items to finish. +*/ +XdgVfsResult xdg_vfs_sess_cmd_removeMonitor(XdgVfsSession * sess, const char * uri); + +/** +* Command: Show Open-File-Dialog +* +*/ +XdgVfsResult xdg_vfs_sess_cmd_openFileDialog(XdgVfsSession * sess, const char * filename, XdgVfsFlags flags); + +/** +* Command: Show Save-File-Dialog +* +*/ +XdgVfsResult xdg_vfs_sess_cmd_saveFileDialog(XdgVfsSession * sess, const char * filename, XdgVfsFlags flags); + +/* ============= READ / WRITE FUNCTIONS ============= */ + +/** +* Read an Item or a Chunk of File-Data. Continue reading items until +* the return value is != XDGVFS_RESULT_CONTINUES +* +*/ +XdgVfsResult xdg_vfs_sess_readItem(XdgVfsSession * sess, XdgVfsItemType * typeOut, + XdgVfsItem ** itemOut, char ** buffer, int * len); + + +/** +* Put a Chunk of File-Data into the outgoing buffer. +* set len = 0 on EOF +* will return XDGVFS_RESULT_GIVE_ME_DATA (if there is no error) +*/ +XdgVfsResult xdg_vfs_sess_putDataChunk(XdgVfsSession * sess, char * data, int len); + +/** +* Send data from the outgoing buffer - repeat this on +* XDGVFS_RESULT_CALL_SENDDATA_AGAIN until you get +* XDGVFS_RESULT_GIVE_ME_DATA or XDGVFS_RESULT_OK (finished); +* +* if you want to do that nonblocking check the outgoing fd first +*/ +XdgVfsResult xdg_vfs_sess_sendData(XdgVfsSession * sess); + + + +/* ================= XdgVfsItem ======================*/ + +/** +* increase reference Count +* +*/ +XdgVfsItem * xdg_vfs_item_ref(XdgVfsItem * item); + +/** +* decrease reference Count +* +*/ +void xdg_vfs_item_unref(XdgVfsItem * item); + +/* =================== tools ========================= */ + +char * xdg_vfs_resultToString(XdgVfsResult code); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/libxdg-vfs-client/src/xdg_vfs_common.h b/libxdg-vfs-client/src/xdg_vfs_common.h new file mode 100644 index 0000000..3963983 --- /dev/null +++ b/libxdg-vfs-client/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/libxdg-vfs-client/src/xdg_vfs_errstrs.c b/libxdg-vfs-client/src/xdg_vfs_errstrs.c new file mode 100644 index 0000000..a68326f --- /dev/null +++ b/libxdg-vfs-client/src/xdg_vfs_errstrs.c @@ -0,0 +1,137 @@ +/* +# xdg_vfs_errstrs.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 "xdg_vfs_client.h" +#include "xdg_vfs_common.h" + +typedef struct +{ + int code; + char * str; +} XdgVfsErrorToStringMapping; + +XdgVfsErrorToStringMapping _xdg_vfs_error2string_mapping_arr[] = +{ + + { XDGVFS_ERRORCODE_OK , "OK" }, + { XDGVFS_ERRORCODE_CANCELED , "Canceled" }, + { XDGVFS_ERRORCODE_BAD_PARAMETER , "Bad Parameter" }, + { XDGVFS_ERRORCODE_NOT_SUPPORTED , "Not supported" }, + { XDGVFS_ERRORCODE_GENERIC , "Generic error" }, + { XDGVFS_ERRORCODE_INIT_ERROR , "init error" }, + { XDGVFS_ERRORCODE_DATA_ERROR , "Data error" }, + { XDGVFS_ERRORCODE_IO_ERROR , "IO error" }, + { XDGVFS_ERRORCODE_NOT_PERMITTED , "Not permitted" }, + { XDGVFS_ERRORCODE_MALFORMED_URL , "Malformed URL" }, + { XDGVFS_ERRORCODE_PROTOCOL_ERROR , "Protocol error" }, + { XDGVFS_ERRORCODE_USR_OR_GRP_NOT_FOUND , "User or Group not found" }, + { XDGVFS_ERRORCODE_INTERNAL , "Internal error" }, + { XDGVFS_ERRORCODE_CANNOT_OPEN_FOR_WRITING , "Cannot open for writing"}, + { XDGVFS_ERRORCODE_CANNOT_OPEN_FOR_READING , "Cannot open for reading"}, + { XDGVFS_ERRORCODE_IS_DIRECTORY , "is directory"}, + { XDGVFS_ERRORCODE_IS_FILE , "is file"}, + { XDGVFS_ERRORCODE_NOT_FOUND , "not found"}, + { XDGVFS_ERRORCODE_ALREADY_EXISTS , "already exists"}, + { XDGVFS_ERRORCODE_HOST_NOT_FOUND , "host not found"}, + { XDGVFS_ERRORCODE_ACCESS_DENIED , "access denied"}, + { XDGVFS_ERRORCODE_CANNOT_ENTER_DIRECTORY , "cannot enter directory"}, + { XDGVFS_ERRORCODE_PROTOCOL_IS_NOT_A_FILESYSTEM , "protocol is not a filesystem"}, + { XDGVFS_ERRORCODE_LOOP , "loop"}, + { XDGVFS_ERRORCODE_COULD_NOT_CREATE_SOCKET , "cannot create socket"}, + { XDGVFS_ERRORCODE_COULD_NOT_CONNECT , "could not connect"}, + { XDGVFS_ERRORCODE_ERR_CONNECTION_BROKEN , "conection broken"}, + { XDGVFS_ERRORCODE_COULD_NOT_MOUNT , "could not mount"}, + { XDGVFS_ERRORCODE_COULD_NOT_UNMOUNT , "could not unmount"}, + { XDGVFS_ERRORCODE_SOCKET_ERROR , "socket error"}, + { XDGVFS_ERRORCODE_LOGIN_FAILED , "login failed"}, + { XDGVFS_ERRORCODE_OPERATION_FAILED , "operation failed"}, + { XDGVFS_ERRORCODE_CANNOT_RESUME , "cannot resume"}, + { XDGVFS_ERRORCODE_OUT_OF_MEMORY , "out of memory"}, + { XDGVFS_ERRORCODE_UNKNOWN_PROXY_HOST , "unknown proxy host"}, + { XDGVFS_ERRORCODE_ABORTED , "aborted"}, + { XDGVFS_ERRORCODE_TIMEOUT , "timeout"}, + { XDGVFS_ERRORCODE_SERVICE_NOT_AVAILABLE , "service not available"}, + { XDGVFS_ERRORCODE_CANNOT_DELETE_ORIGINAL , "cannot delete original"}, + { XDGVFS_ERRORCODE_CANNOT_DELETE_PARTIAL , "cannot delete partial"}, + { XDGVFS_ERRORCODE_CANNOT_RENAME_ORIGINAL , "cannot rename original"}, + { XDGVFS_ERRORCODE_CANNOT_RENAME_PARTIAL , "cannot rename partial"}, + { XDGVFS_ERRORCODE_NEED_PASSWD , "need passwd"}, + { XDGVFS_ERRORCODE_NO_CONTENT , "no content"}, + { XDGVFS_ERRORCODE_NO_SPACE , "no space"}, + { XDGVFS_ERRORCODE_IDENTICAL_FILES , "identical files"}, + { XDGVFS_ERRORCODE_CORRUPTED_DATA , "corrupted data"}, + { XDGVFS_ERRORCODE_WRONG_FORMAT , "wrong format"}, + { XDGVFS_ERRORCODE_ERROR_BAD_FILE , "bad file"}, + { XDGVFS_ERRORCODE_TOO_BIG , "too big"}, + { XDGVFS_ERRORCODE_NOT_OPEN , "not open"}, + { XDGVFS_ERRORCODE_INVALID_OPEN_MODE , "invalid open mode"}, + { XDGVFS_ERRORCODE_TOO_MANY_OPEN_FILES , "too many open files"}, + { XDGVFS_ERRORCODE_EOF , "End of file (EOF)"}, + { XDGVFS_ERRORCODE_IN_PROGRESS , "In Progress" }, + { XDGVFS_ERRORCODE_INTERRUPTED , "interrupted" }, + { XDGVFS_ERRORCODE_HOST_HAS_NO_ADDRESS , "Host has no address" }, + { XDGVFS_ERRORCODE_DIRECTORY_NOT_EMPTY , "Directory not empty" }, + { XDGVFS_ERRORCODE_TOO_MANY_LINKS , "Too many links" }, + { XDGVFS_ERRORCODE_READ_ONLY_FILE_SYSTEM , "Read only filesystem" }, + { XDGVFS_ERRORCODE_NOT_SAME_FILE_SYSTEM , "not the same filesystem" }, + { XDGVFS_ERRORCODE_NAME_TOO_LONG , "name too long" }, + { XDGVFS_ERRORCODE_SERVICE_OBSOLETE , "service obsolete" }, + { XDGVFS_ERRORCODE_NO_DEFAULT , "no default" }, + { XDGVFS_ERRORCODE_NAMESERVER , "nameserver error" }, + { XDGVFS_ERRORCODE_LOCKED , "locked" }, + { XDGVFS_ERRORCODE_DEPRECATED_FUNCTION , "deprecated function" }, + { XDGVFS_ERRORCODE_DIRECTORY_BUSY , "directory busy" }, + { XDGVFS_ERRORCODE_NOT_A_DIRECTORY , "not a directory" } +}; + +char * xdg_vfs_resultToString(XdgVfsResult code) +{ + int i; + for (i=0;i<sizeof(_xdg_vfs_error2string_mapping_arr)/sizeof(XdgVfsErrorToStringMapping);i++) + { + if (_xdg_vfs_error2string_mapping_arr[i].code == code) + return _xdg_vfs_error2string_mapping_arr[i].str; + } + + switch(code) + { + case(XDGVFS_RESULT_CANNOT_LAUNCH_BACKEND): return XDGVFS_RESULT_CANNOT_LAUNCH_BACKEND_STR; + case(XDGVFS_RESULT_CALL_SENDDATA_AGAIN): return XDGVFS_RESULT_CALL_SENDDATA_AGAIN_STR; + case(XDGVFS_RESULT_GIVE_ME_DATA): return XDGVFS_RESULT_GIVE_ME_DATA_STR; + case(XDGVFS_RESULT_PARAMETER_ERR): return XDGVFS_RESULT_PARAMETER_ERR_STR; + case(XDGVFS_RESULT_FATAL_ERR): return XDGVFS_RESULT_FATAL_ERR_STR; + case(XDGVFS_RESULT_UNESCAPING_DATA_ERR): return XDGVFS_RESULT_UNESCAPING_DATA_ERR_STR; + case(XDGVFS_RESULT_BAD_STATE): return XDGVFS_RESULT_BAD_STATE_STR; + case(XDGVFS_RESULT_IOERR): return XDGVFS_RESULT_IOERR_STR; + case(XDGVFS_RESULT_NOT_POSSIBLE): return XDGVFS_RESULT_NOT_POSSIBLE_STR; + case(XDGVFS_RESULT_CONTINUES): return XDGVFS_RESULT_CONTINUES_STR; + case(XDGVFS_RESULT_OK): return XDGVFS_RESULT_OK_STR; + } + return "Client: cannot translate error code to string!"; +} + + diff --git a/libxdg-vfs-client/src/xdg_vfs_forkexec.c b/libxdg-vfs-client/src/xdg_vfs_forkexec.c new file mode 100644 index 0000000..83b4747 --- /dev/null +++ b/libxdg-vfs-client/src/xdg_vfs_forkexec.c @@ -0,0 +1,100 @@ +/* +# xdg_vfs_forkexec.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 <unistd.h> +#include <stdio.h> +#include "xdg_vfs_forkexec.h" + + +int xdg_vfs_forkexec(char * filename, char ** argv, pid_t * child_pid, int * childs_stdin, int * childs_stdout) +{ + + pid_t pid; + int child_stdin_pipe[2]; + int child_stdout_pipe[2]; + + + /* create pipes */ + if (pipe (child_stdin_pipe)) + { + fprintf (stderr, "Pipe child_stdin_pipe failed.\n"); + return 1; + } + + if (pipe (child_stdout_pipe)) + { + fprintf (stderr, "Pipe child_stdout_pipe failed.\n"); + return 1; + } + + + /* create the child process */ + pid = fork (); + if (pid == (pid_t) 0) + { + int r; + /* this is the child process. close other ends of the pipes. */ + close (child_stdin_pipe[1]); + close (child_stdout_pipe[0]); + + dup2 (child_stdin_pipe[0], STDIN_FILENO); + dup2 (child_stdout_pipe[1], STDOUT_FILENO); + + r = execvp(filename, argv); + if (r) { + close (child_stdin_pipe[0]); + close (child_stdout_pipe[1]); + fprintf(stderr, "after fork execvp(%s, argv) ", filename); + perror("failed"); + exit(1); + } + exit(0); + } + else if (pid < (pid_t) 0) + { + /* the fork failed */ + fprintf (stderr, "Fork failed.\n"); + return 1; + } + else + { + /* this is the parent process. close other ends first. */ + close (child_stdin_pipe[0]); + close (child_stdout_pipe[1]); + //write_to_pipe (mypipe[1]); + + *childs_stdin = child_stdin_pipe[1]; + *childs_stdout = child_stdout_pipe[0]; + + *child_pid = pid; + + return 0; + } +} + + + diff --git a/libxdg-vfs-client/src/xdg_vfs_forkexec.h b/libxdg-vfs-client/src/xdg_vfs_forkexec.h new file mode 100644 index 0000000..de2a8a6 --- /dev/null +++ b/libxdg-vfs-client/src/xdg_vfs_forkexec.h @@ -0,0 +1,40 @@ +/* +# xdg_vfs_forkexec.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_FORKEXEC_H +#define XDG_VFS_FORKEXEC_H + +#ifdef __cplusplus +extern "C" { +#endif + +int xdg_vfs_forkexec(char * filename, char ** argv, pid_t * child_pid, int * childs_stdin, int * childs_stdout); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/libxdg-vfs-client/tests/.cvsignore b/libxdg-vfs-client/tests/.cvsignore new file mode 100644 index 0000000..26a73db --- /dev/null +++ b/libxdg-vfs-client/tests/.cvsignore @@ -0,0 +1,8 @@ +*.la +*.lo +*.o +.deps +.libs +Makefile +Makefile.in + diff --git a/libxdg-vfs-client/tests/Makefile.am b/libxdg-vfs-client/tests/Makefile.am new file mode 100644 index 0000000..a55fa2b --- /dev/null +++ b/libxdg-vfs-client/tests/Makefile.am @@ -0,0 +1,28 @@ +bin_PROGRAMS = test1 sample1_multi sample2_getfile sample3_putfile \ + sample4_copy sample5_mount sample6_monitor + +test1_SOURCES = test1.c +test1_LDADD = ../src/libxdg_vfs_client.la $(DEPS_LIBS) + +sample1_multi_SOURCES = sample1_multi.c +sample1_multi_LDADD = ../src/libxdg_vfs_client.la $(DEPS_LIBS) + +sample2_getfile_SOURCES = sample2_getfile.c +sample2_getfile_LDADD = ../src/libxdg_vfs_client.la $(DEPS_LIBS) + +sample3_putfile_SOURCES = sample3_putfile.c +sample3_putfile_LDADD = ../src/libxdg_vfs_client.la $(DEPS_LIBS) + +sample4_copy_SOURCES = sample4_copy.c +sample4_copy_LDADD = ../src/libxdg_vfs_client.la $(DEPS_LIBS) + +sample5_mount_SOURCES = sample5_mount.c +sample5_mount_LDADD = ../src/libxdg_vfs_client.la $(DEPS_LIBS) + +sample6_monitor_SOURCES = sample6_monitor.c +sample6_monitor_LDADD = ../src/libxdg_vfs_client.la $(DEPS_LIBS) + +INCLUDES = $(all_includes) -I$(top_srcdir)/src + +AM_CPPFLAGS = $(DEPS_CFLAGS) + diff --git a/libxdg-vfs-client/tests/sample1_multi.c b/libxdg-vfs-client/tests/sample1_multi.c new file mode 100644 index 0000000..5feec20 --- /dev/null +++ b/libxdg-vfs-client/tests/sample1_multi.c @@ -0,0 +1,316 @@ +/* +# sample1_multi.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 "xdg_vfs_client.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +int main(int argc, char *argv[]) +{ + XdgVfsResult r; + XdgVfsSession * session; + + if (argc!=2) { + fprintf(stderr,"usage: %s {gnome|kde|this}\n", argv[0]); + exit(1); + } + + r = xdg_vfs_sess_start(&session, argv[1]); + + if (r) { + fprintf(stderr, " session start problem=%d\n", r); + return 1; + } + + fprintf(stderr, "======= test 0 : backend info =======\n", r); + + r = xdg_vfs_sess_cmd_backendInfo(session); + + if (r) { + fprintf(stderr, "test 0 cmd problem=%d\n", r); + return 1; + } + + XdgVfsItemType type; + XdgVfsItem * item; + + while ((r=xdg_vfs_sess_readItem(session, &type, + &item, NULL, NULL)) == XDGVFS_RESULT_CONTINUES) + { + switch(type) + { + case XDGVFS_ITEMTYPE_BACKENDINFO: + { + XdgVfsBackendInfo * backendInfo = (XdgVfsBackendInfo*) item; + fprintf(stderr, "backend_id='%s' system_uri='%s' file_icon_theme='%s'\n", + backendInfo->backend_id, + backendInfo->system_uri, + backendInfo->file_icon_theme); + } + case XDGVFS_ITEMTYPE_NONE: + { + break; + } + default: + { + fprintf(stderr, "unexpected item - type=%d\n", type); + break; + } + } + xdg_vfs_item_unref(item); + } + fprintf(stderr, "test 0 result=%d\n", r); + + fprintf(stderr, "======= test 1 : info / =======\n", r); + + r = xdg_vfs_sess_cmd_getFileInfo(session, "/"); + + if (r) { + fprintf(stderr, "test 1 cmd problem=%d\n", r); + return 1; + } + + while ((r=xdg_vfs_sess_readItem(session, &type, + &item, NULL, NULL)) == XDGVFS_RESULT_CONTINUES) + { + //fprintf(stderr, "got item type %d\n", typeOut); + switch(type) + { + case XDGVFS_ITEMTYPE_FILEINFO: + { + XdgVfsFileInfo * info = (XdgVfsFileInfo*) item; + fprintf(stderr, "got fileinfo uri='%s'\n", info->uri); + } + case XDGVFS_ITEMTYPE_NONE: + { + break; + } + default: + { + fprintf(stderr, "unexpected item - type=%d\n", type); + break; + } + } + xdg_vfs_item_unref(item); + } + fprintf(stderr, "test 1 result=%d\n", r); + + fprintf(stderr, "======= test 2 : info /notexist =======\n", r); + + r = xdg_vfs_sess_cmd_getFileInfo(session, "/notexist"); + if (r) { + fprintf(stderr, "test 2 cmd problem=%d\n", r); + return 1; + } + + while ((r=xdg_vfs_sess_readItem(session, &type, + &item, NULL, NULL)) == XDGVFS_RESULT_CONTINUES) + { + switch(type) + { + case XDGVFS_ITEMTYPE_FILEINFO: + { + XdgVfsFileInfo * info = (XdgVfsFileInfo*) item; + fprintf(stderr, "got fileinfo uri='%s'\n", info->uri); + break; + } + case XDGVFS_ITEMTYPE_NONE: + { + break; + } + default: + { + fprintf(stderr, "unexpected item - type=%d\n", type); + break; + } + } + xdg_vfs_item_unref(item); + } + fprintf(stderr, "test 2 result=%d\n", r); + + fprintf(stderr, "======= test 3 : ls /usr/local/bin =======\n", r); + + r = xdg_vfs_sess_cmd_listDirectory(session, "/usr/local/bin"); + + if (r) { + fprintf(stderr, "test 3 cmd problem=%d\n", r); + return 1; + } + + while ((r=xdg_vfs_sess_readItem(session, &type, + &item, NULL, NULL)) == XDGVFS_RESULT_CONTINUES) + { + switch(type) + { + case XDGVFS_ITEMTYPE_LS_HEAD: + { + XdgVfsSimpleHead * head = (XdgVfsSimpleHead*) item; + fprintf(stdout, "got ls header uri='%s'\n", head->uri); + break; + } + + case XDGVFS_ITEMTYPE_FILEINFO: + { + XdgVfsFileInfo * info = (XdgVfsFileInfo*) item; + fprintf(stdout, "got fileinfo uri='%s'\n", info->uri); + break; + } + case XDGVFS_ITEMTYPE_NONE: + { + break; + } + default: + { + fprintf(stderr, "unexpected item - type=%d\n", type); + break; + } + } + xdg_vfs_item_unref(item); + } + fprintf(stderr, "test 3 result=%d\n", r); + + fprintf(stderr, "======= test 4 : openfiledlg =======\n", r); + + r = xdg_vfs_sess_cmd_openFileDialog(session, NULL, 0); + if (r) { + fprintf(stderr, "test 4 cmd rval=%d\n", r); + return 1; + } + + while ((r=xdg_vfs_sess_readItem(session, &type, + &item, NULL, NULL)) == XDGVFS_RESULT_CONTINUES) + { + switch(type) + { + case XDGVFS_ITEMTYPE_OPENFILEDLG_RESPONSE: + { + XdgVfsOpenFileDlgResponse * dlgResp = (XdgVfsOpenFileDlgResponse*) item; + fprintf(stderr, "selected_uri='%s'\n", dlgResp->selected_uri); + break; + } + case XDGVFS_ITEMTYPE_NONE: + { + break; + } + default: + { + fprintf(stderr, "unexpected item - type=%d\n", type); + break; + } + } + xdg_vfs_item_unref(item); + } + + fprintf(stderr, "test 4 result=%d\n", r); + + fprintf(stderr, "======= test 5 : savefiledlg =======\n", r); + + r = xdg_vfs_sess_cmd_saveFileDialog(session, "/tmp", 0); + if (r) { + fprintf(stderr, "test 5 cmd rval=%d\n", r); + return 1; + } + + while ((r=xdg_vfs_sess_readItem(session, &type, + &item, NULL, NULL)) == XDGVFS_RESULT_CONTINUES) + { + switch(type) + { + case XDGVFS_ITEMTYPE_SAVEFILEDLG_RESPONSE: + { + XdgVfsSaveFileDlgResponse * dlgResp = (XdgVfsSaveFileDlgResponse*) item; + fprintf(stderr, "selected_uri='%s'\n", dlgResp->selected_uri); + break; + } + case XDGVFS_ITEMTYPE_NONE: + { + break; + } + default: + { + fprintf(stderr, "unexpected item - type=%d\n", type); + break; + } + } + xdg_vfs_item_unref(item); + } + fprintf(stderr, "test 5 result=%d\n", r); + + fprintf(stderr, "======= test 6 : get /etc/passwd =======\n", r); + + r = xdg_vfs_sess_cmd_getFile(session, "/etc/passwd"); + if (r) { + fprintf(stderr, "test 6 cmd rval=%d\n", r); + return 1; + } + + char * buf; + int len; + + while ((r=xdg_vfs_sess_readItem(session, &type, + &item, &buf, &len)) == XDGVFS_RESULT_CONTINUES) + { + switch (type) + { + case XDGVFS_ITEMTYPE_GET_HEAD: + { + XdgVfsSimpleHead * sh = (XdgVfsSimpleHead*) item; + fprintf(stderr, "'get' header uri='%s'\n", sh->uri); + break; + } + case XDGVFS_DATAIN: + { + fprintf(stderr, "'data' chunklen=%d\n", len); + fwrite (buf, 1, len, stderr); + break; + } + case XDGVFS_ITEMTYPE_DATAIN_DONE: + { + XdgVfsDataInDoneItem * dii = (XdgVfsDataInDoneItem *) item; + fprintf(stderr, "data done bytecount='%d'\n", dii->bytecount); + break; + } + case XDGVFS_ITEMTYPE_NONE: + { + break; + } + default: + { + fprintf(stderr, "unexpected item - type=%d\n", type); + break; + } + } + xdg_vfs_item_unref(item); + } + fprintf(stderr, "test 6 result=%d\n", r); + return 1; + + xdg_vfs_sess_close(session); + sleep (1); +} diff --git a/libxdg-vfs-client/tests/sample2_getfile.c b/libxdg-vfs-client/tests/sample2_getfile.c new file mode 100644 index 0000000..92a81f3 --- /dev/null +++ b/libxdg-vfs-client/tests/sample2_getfile.c @@ -0,0 +1,106 @@ +/* +# sample2_getfile.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 "xdg_vfs_client.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +int main(int argc, char *argv[]) +{ + XdgVfsResult r; + XdgVfsSession * session; + + if (argc!=3) { + fprintf(stderr,"usage: %s {gnome|kde|this} FILENAME\n", argv[0]); + exit(1); + } + + r = xdg_vfs_sess_start(&session, argv[1]); + + if (r) { + fprintf(stderr, "start session error=%d\n", r); + return 1; + } + + fprintf(stderr, "======= test : getFile -> stdout =======\n", r); + + r = xdg_vfs_sess_cmd_getFile(session, argv[2]); + + if (r) { + fprintf(stderr, "test cmd problem=%d\n", r); + return 1; + } + + char * buf=NULL; + int len=0; + XdgVfsItemType type; + XdgVfsItem * item; + + while ((r = xdg_vfs_sess_readItem(session, &type, &item, &buf, &len)) == XDGVFS_RESULT_CONTINUES) + { + switch (type) + { + case XDGVFS_ITEMTYPE_GET_HEAD: + { + XdgVfsSimpleHead * head = (XdgVfsSimpleHead*) item; + fprintf(stderr, "reading file uri='%s'\n", head->uri); + break; + } + case XDGVFS_DATAIN: + { + fprintf(stderr, "file-data chunklen=%d\n", len); + fwrite (buf, 1, len, stdout); /* your file data */ + break; + } + case XDGVFS_ITEMTYPE_DATAIN_DONE: + { + XdgVfsDataInDoneItem * dii = (XdgVfsDataInDoneItem *) item; + fprintf(stderr, "read done - bytecount='%d'\n", dii->bytecount); + break; + } + case XDGVFS_ITEMTYPE_NONE: + { + break; + } + default: + { + fprintf(stderr, "unexpected item - type=%d\n", type); + break; + } + } + xdg_vfs_item_unref(item); + } + if (r) { + fprintf(stderr, "test 4 result=%d\n", r); + return 1; + } + + xdg_vfs_sess_close(session); + sleep (1); +} diff --git a/libxdg-vfs-client/tests/sample3_putfile.c b/libxdg-vfs-client/tests/sample3_putfile.c new file mode 100644 index 0000000..fa73517 --- /dev/null +++ b/libxdg-vfs-client/tests/sample3_putfile.c @@ -0,0 +1,117 @@ +/* +# sample3_putfile.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 "xdg_vfs_client.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +int main(int argc, char *argv[]) +{ + XdgVfsResult r; + XdgVfsSession * session; + + if (argc!=3) { + fprintf(stderr,"usage: %s {gnome|kde|this} FILENAME\n", argv[0]); + exit(1); + } + + r = xdg_vfs_sess_start(&session, argv[1]); + + if (r) { + fprintf(stderr, "sess start error=%d\n", r); + return 1; + } + + + fprintf(stderr, "======= test : putFile =======\n", r); + + r = xdg_vfs_sess_cmd_putFile(session, argv[2], 0); + + if (r) { + fprintf(stderr, "test cmd problem=%d\n", r); + return 1; + } + + XdgVfsItemType type=0; + XdgVfsItem * item=NULL; + int n = 5; + + while ((r=xdg_vfs_sess_readItem(session, &type, + &item, NULL, NULL)) == XDGVFS_RESULT_CONTINUES) + { + // fprintf(stderr, "got item type=%d\n", typeOut); + switch (type) + { + case XDGVFS_ITEMTYPE_PUT_HEAD: + { + XdgVfsSimpleHead * sh = (XdgVfsSimpleHead*) item; + fprintf(stderr, "'put' head uri='%s'\n", sh->uri); + break; + } + case XDGVFS_DATAOUT: + { + XdgVfsResult wr; + + /* send file */ + + if (n--) wr = xdg_vfs_sess_putDataChunk(session, "Hello World", 10); + else wr = xdg_vfs_sess_putDataChunk(session, NULL, 0); /* EOF */ + + fprintf(stderr, "writing chunk rval=%d\n", wr); + + while (wr == XDGVFS_RESULT_CALL_SENDDATA_AGAIN) { + wr = xdg_vfs_sess_sendData(session); + fprintf(stderr, "sending chunk rval=%d\n", wr); + } + + break; + } + case XDGVFS_ITEMTYPE_DATAOUT_DONE: + { + XdgVfsDataOutDoneItem * dii = (XdgVfsDataOutDoneItem *) item; + fprintf(stderr, "data out done bytecount=%d\n", dii->bytecount); + break; + } + case XDGVFS_ITEMTYPE_NONE: + { + break; + } + default: + { + fprintf(stderr, "unexpected item - type=%d\n", type); + break; + } + } + xdg_vfs_item_unref(item); + } + fprintf(stderr, "test result=%d\n", r); + + xdg_vfs_sess_close(session); + +} diff --git a/libxdg-vfs-client/tests/sample4_copy.c b/libxdg-vfs-client/tests/sample4_copy.c new file mode 100644 index 0000000..d6656ef --- /dev/null +++ b/libxdg-vfs-client/tests/sample4_copy.c @@ -0,0 +1,102 @@ +/* +# sample4_copy.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 "xdg_vfs_client.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +int main(int argc, char *argv[]) +{ + XdgVfsResult r; + XdgVfsSession * session; + + if (argc!=4) { + fprintf(stderr,"usage: %s {gnome|kde|this} FILENAME FILENAME\n", argv[0]); + exit(1); + } + + r = xdg_vfs_sess_start(&session, argv[1]); + + if (r) { + fprintf(stderr, "sess start error=%d\n", r); + return 1; + } + + + fprintf(stderr, "======= test : copy file =======\n", r); + + + + r = xdg_vfs_sess_cmd_copyFile(session, argv[2], argv[3]); + + if (r) { + fprintf(stderr, "test cmd problem=%d\n", r); + return 1; + } + + XdgVfsItemType type=0; + XdgVfsItem * item=NULL; + int n = 5; + + while ((r=xdg_vfs_sess_readItem(session, &type, + &item, NULL, NULL)) == XDGVFS_RESULT_CONTINUES) + { + // fprintf(stderr, "got item type=%d\n", typeOut); + switch (type) + { + case XDGVFS_ITEMTYPE_COPY_HEAD: + { + XdgVfsCopyHead * head = (XdgVfsCopyHead*) item; + fprintf(stderr, "copying uri_src='%s' to uri_target='%s'\n", + head->uri_src, head->uri_target); + break; + } + case XDGVFS_ITEMTYPE_PROGRESS: + { + XdgVfsProgress * progress = (XdgVfsProgress *) item; + fprintf(stderr, "progress: copied=%d size=%d\n", progress->copied, progress->size); + break; + } + case XDGVFS_ITEMTYPE_NONE: + { + break; + } + default: + { + fprintf(stderr, "unexpected item - type=%d\n", type); + break; + } + } + xdg_vfs_item_unref(item); + } + fprintf(stderr, "test result=%d\n", r); + + xdg_vfs_sess_close(session); + +} diff --git a/libxdg-vfs-client/tests/sample5_mount.c b/libxdg-vfs-client/tests/sample5_mount.c new file mode 100644 index 0000000..a285d6c --- /dev/null +++ b/libxdg-vfs-client/tests/sample5_mount.c @@ -0,0 +1,95 @@ +/* +# sample5_mount.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 "xdg_vfs_client.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +int main(int argc, char *argv[]) +{ + XdgVfsResult r; + XdgVfsSession * session; + + if (argc!=3) { + fprintf(stderr,"usage: %s {gnome|kde|this} MOUNTPOINT_ID\n", argv[0]); + exit(1); + } + + r = xdg_vfs_sess_start(&session, argv[1]); + + if (r) { + fprintf(stderr, "sess start error=%d\n", r); + return 1; + } + + + fprintf(stderr, "======= test : mount =======\n", r); + + + + r = xdg_vfs_sess_cmd_mount(session, argv[2]); + + if (r) { + fprintf(stderr, "test cmd problem=%d\n", r); + return 1; + } + + XdgVfsItemType type=0; + XdgVfsItem * item=NULL; + int n = 5; + + while ((r=xdg_vfs_sess_readItem(session, &type, + &item, NULL, NULL)) == XDGVFS_RESULT_CONTINUES) + { + switch (type) + { + case XDGVFS_ITEMTYPE_NONE: + { + break; + } + case XDGVFS_ITEMTYPE_FILEINFO: + { + /* lists the volumes just mounted */ + XdgVfsFileInfo * info = (XdgVfsFileInfo*) item; + fprintf(stderr, "mounted as uri=%s\n", info->uri); + break; + } + default: + { + fprintf(stderr, "unexpected item - type=%d\n", type); + break; + } + } + xdg_vfs_item_unref(item); + } + fprintf(stderr, "test result=%d\n", r); + + xdg_vfs_sess_close(session); + +} diff --git a/libxdg-vfs-client/tests/sample6_monitor.c b/libxdg-vfs-client/tests/sample6_monitor.c new file mode 100644 index 0000000..875281f --- /dev/null +++ b/libxdg-vfs-client/tests/sample6_monitor.c @@ -0,0 +1,105 @@ +/* +# sample5_mount.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 "xdg_vfs_client.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +void myXdgVfsMonitorCallback(XdgVfsSession * sess, char * uri, void * user_data) +{ + printf("changed: %s\n", uri); +} + +int main(int argc, char *argv[]) +{ + XdgVfsResult r; + XdgVfsSession * session; + + if (argc!=3) { + fprintf(stderr,"usage: %s {gnome|kde|this} MONITOR_DIR_URI\n", argv[0]); + exit(1); + } + + r = xdg_vfs_sess_start(&session, argv[1]); + + if (r) { + fprintf(stderr, "sess start error=%d\n", r); + return 1; + } + + xdg_vfs_sess_set_monitor_callback(session, myXdgVfsMonitorCallback, NULL); + + fprintf(stderr, "======= test : monitor =======\n", r); + + + + r = xdg_vfs_sess_cmd_monitorDir(session, argv[2]); + + if (r) { + fprintf(stderr, "monitor cmd problem=%d\n", r); + return 1; + } + + fprintf(stderr, "Now waiting for monitor events!\n"); + + if(xdg_vfs_sess_isBusy(session)) + { + fprintf(stderr, "We can't wait for monitor events when the session is busy!\n"); + return 1; + } + + /* because the session is in ready state, we will not receive XDGVFS_RESULT_CONTINUES */ + + XdgVfsItemType type=0; + XdgVfsItem * item=NULL; + + while ((r=xdg_vfs_sess_readItem(session, &type, + &item, NULL, NULL)) == XDGVFS_RESULT_OK) + { + switch (type) + { + case XDGVFS_ITEMTYPE_NONE: + { + break; + } + default: + { + fprintf(stderr, "unexpected item - type=%d\n", type); + break; + } + } + xdg_vfs_item_unref(item); + } + + fprintf(stderr, "cmd monitor result=%d\n", r); + + + xdg_vfs_sess_close(session); + +} diff --git a/libxdg-vfs-client/tests/test1.c b/libxdg-vfs-client/tests/test1.c new file mode 100644 index 0000000..03a51d8 --- /dev/null +++ b/libxdg-vfs-client/tests/test1.c @@ -0,0 +1,63 @@ +/* +* +* Copyright (C) 2005 Norbert Frese +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +* + */ + +#include "xdg_vfs_client.h" +#include "xdg_vfs_forkexec.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +int main(int argc, char *argv[]) +{ + printf("hello world\n"); + + int child_pid; + int childs_stdin; + int childs_stdout; + int r; + + // /home/norbert/work/c/xdg-vfs-gnome/src/ + r = xdg_vfs_forkexec("xdg_vfs_gnome", argv, &child_pid, &childs_stdin, &childs_stdout); + printf("r=%d\n", r); + printf("pid=%d\n", child_pid); + + FILE * fout = fdopen (childs_stdin, "w"); + + fprintf(fout, "info /\nquit\n"); + fflush(fout); + + puts("====="); + + FILE * fin = fdopen (childs_stdout, "r"); + if (!fin) perror("fopen"); + int c; + + while ((c =fgetc(fin)) != EOF) { + putchar (':'); putchar(c); + } + + perror("reading"); + + int status; + r= waitpid(child_pid, &status, 0); + if (r==-1) perror("waitpid:"); + printf("r=%d\n", r); +} |