Software: Apache/2.2.16 (Debian). PHP/5.3.3-7+squeeze19 uname -a: Linux mail.tri-specialutilitydistrict.com 2.6.32-5-amd64 #1 SMP Tue May 13 16:34:35 UTC uid=33(www-data) gid=33(www-data) groups=33(www-data) Safe-mode: OFF (not secure) /usr/share/doc/libgnomevfs2-common/html/ drwxr-xr-x |
Viewing file: Select action/file-type:
IntroductionThis section will introduce the basic concepts that are needed for writing GNOME Virtual File System modules. GNOME VFS URIs (Uniform Resource Identifiers)The GNOME Virtual file system uses URIs similiar to the standard WWW URIs. The basic difference between a VFS URI and WWW URI is that, while with WWW URIs you can only use a single protocol for accessing a certain file, with GNOME VFS URIs you can combine different access methods in sequence. For example, suppose you want to access file
The GNOME Virtual File System lets you express this by combining the three access methods (i.e. tar, GZIP and FTP) into a single URI. Access methods are combined in the URI by using the `#' character, followed by the name for the access method and the subpath for that specific access method. The subpath can be omitted for those storage methods that do not need a path to retrieve the file. (For example, a GZIP file always contains a single uncompressed file, so no path is needed to locate the uncompressed file within the GZIP file. But on the other hand, the TAR method requires a path to locate a specific file or directory.) For example, in the case we outlined above, the URI would look something like: ftp://username:password@host.net/path/to/file.tar.gz#gzip:#tar:/path/to/hello.c Each method/subpath couple is called a URI element. When URI elements are combined like this, each URI element uses the previous one to access a base resource into which it will look up a file, using the subpath information. For this reason, we will say that each element is the parent element for the following one. The first URI element, the one which has no parent, is called the toplevel element. It does not use the `#' character; instead, it uses the standard syntax of WWW URIs: method://user:password@host/path/to/file This way, normal WWW URIs can be used with the GNOME Virtual File System. Toplevel elements are also special because they let users specify user names, passwords and host names, while non-toplevel elements don't. The GnomeVFSURI typeWithin the GNOME Virtual File System library, URI elements are represented by a special type, GnomeVFSURI, which is meant to represent user-provided URIs in a machine-optimized way. Every GnomeVFSURI contains the following information:
GNOME Virtual File System access method implementationIn the GNOME Virtual File System, the implementations for all the access methods are loaded at runtime, as shared library modules. The modules are loaded during parsing of the string URI. If the parser encounters an access method for which no implementation is currently loaded, it retrieves the corresponding library file, dynamically links it into the executable, and initializes it. After initialization, the module returns a special GnomeVFSMethod object that contains pointers to the various implementation functions for that specific method. By storing a pointer to this object into the GnomeVFSURI type, the VFS library is then able to use these functions for file access. How file access is performedWhen the VFS library needs to perform some file operation, it performs the following steps:
Combining the access methods is always done within the method implementation. If the method implementation needs to do some file operation on the the parent URI element, it can do so by simply invoking the corresponding VFS function, by using the parent pointer in the GnomeVFSURI object. For example, suppose you have to read a simple URI like the following: file:/home/ettore/file.gz#gzip: In this case, the GZIP method will be invoked with a
pointer to the GnomeVFSURI describing the
`gzip' part. The GZIP method will be able to read
Implementing an access method in practiceImplementing a new access method is really not difficult at all. This section explains how this is done. Using shared librariesEvery module must be compiled as a shared library (i.e. a
The current way for accessing the right module for the
right method is very simple, and is based on file names. In
practice, a module implementing an access method named
This might change in the future. The initialization/shutdown functionsEvery shared library module must provide two functions: GnomeVFSMethod *vfs_module_init (const char *method_name, const char *args); void vfs_module_shutdown (GnomeVFSMethod *method); These are the only functions that the VFS library will access directly. All the other symbols (i.e. functions and variables) in the module should be made static.
The GnomeVFSMethod objectThis object contains pointers to the module implementation functions. A method can choose itself which functions to implement. However, it must at least provide a GnomeVFSMethodOpenFunc and GnomeVFSMethodIsLocalFunc implementation. struct GnomeVFSMethod { gsize method_table_size; /* Used for versioning */ GnomeVFSMethodOpenFunc open; GnomeVFSMethodCreateFunc create; GnomeVFSMethodCloseFunc close; GnomeVFSMethodReadFunc read; GnomeVFSMethodWriteFunc write; GnomeVFSMethodSeekFunc seek; GnomeVFSMethodTellFunc tell; GnomeVFSMethodTruncateHandleFunc truncate_handle; GnomeVFSMethodOpenDirectoryFunc open_directory; GnomeVFSMethodCloseDirectoryFunc close_directory; GnomeVFSMethodReadDirectoryFunc read_directory; GnomeVFSMethodGetFileInfoFunc get_file_info; GnomeVFSMethodGetFileInfoFromHandleFunc get_file_info_from_handle; GnomeVFSMethodIsLocalFunc is_local; GnomeVFSMethodMakeDirectoryFunc make_directory; GnomeVFSMethodRemoveDirectoryFunc remove_directory; GnomeVFSMethodMoveFunc move; GnomeVFSMethodUnlinkFunc unlink; GnomeVFSMethodCheckSameFSFunc check_same_fs; GnomeVFSMethodSetFileInfo set_file_info; GnomeVFSMethodTruncateFunc truncate; GnomeVFSMethodFindDirectoryFunc find_directory; GnomeVFSMethodCreateSymbolicLinkFunc create_symbolic_link; GnomeVFSMethodMonitorAddFunc monitor_add; GnomeVFSMethodMonitorCancelFunc monitor_cancel; GnomeVFSMethodFileControlFunc file_control; GnomeVFSMethodForgetCacheFunc forget_cache; GnomeVFSMethodGetVolumeFreeSpaceFunc get_volume_free_space; }; typedef GnomeVFSResult (* GnomeVFSMethodOpenFunc) (GnomeVFSMethod *method, GnomeVFSMethodHandle **method_handle_return, GnomeVFSURI *uri, GnomeVFSOpenMode mode, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodCreateFunc) (GnomeVFSMethod *method, GnomeVFSMethodHandle **method_handle_return, GnomeVFSURI *uri, GnomeVFSOpenMode mode, gboolean exclusive, guint perm, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodCloseFunc) (GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodReadFunc) (GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle, gpointer buffer, GnomeVFSFileSize num_bytes, GnomeVFSFileSize *bytes_read_return, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodWriteFunc) (GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle, gconstpointer buffer, GnomeVFSFileSize num_bytes, GnomeVFSFileSize *bytes_written_return, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodSeekFunc) (GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle, GnomeVFSSeekPosition whence, GnomeVFSFileOffset offset, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodTellFunc) (GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle, GnomeVFSFileSize *offset_return); typedef GnomeVFSResult (* GnomeVFSMethodOpenDirectoryFunc) (GnomeVFSMethod *method, GnomeVFSMethodHandle **method_handle, GnomeVFSURI *uri, GnomeVFSFileInfoOptions options, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodCloseDirectoryFunc) (GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodReadDirectoryFunc) (GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle, GnomeVFSFileInfo *file_info, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodGetFileInfoFunc) (GnomeVFSMethod *method, GnomeVFSURI *uri, GnomeVFSFileInfo *file_info, GnomeVFSFileInfoOptions options, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodGetFileInfoFromHandleFunc) (GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle, GnomeVFSFileInfo *file_info, GnomeVFSFileInfoOptions options, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodTruncateFunc) (GnomeVFSMethod *method, GnomeVFSURI *uri, GnomeVFSFileSize length, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodTruncateHandleFunc) (GnomeVFSMethod *method, GnomeVFSMethodHandle *handle, GnomeVFSFileSize length, GnomeVFSContext *context); typedef gboolean (* GnomeVFSMethodIsLocalFunc) (GnomeVFSMethod *method, const GnomeVFSURI *uri); typedef GnomeVFSResult (* GnomeVFSMethodMakeDirectoryFunc) (GnomeVFSMethod *method, GnomeVFSURI *uri, guint perm, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodFindDirectoryFunc) (GnomeVFSMethod *method, GnomeVFSURI *find_near_uri, GnomeVFSFindDirectoryKind kind, GnomeVFSURI **result_uri, gboolean create_if_needed, gboolean find_if_needed, guint perm, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodRemoveDirectoryFunc) (GnomeVFSMethod *method, GnomeVFSURI *uri, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodMoveFunc) (GnomeVFSMethod *method, GnomeVFSURI *old_uri, GnomeVFSURI *new_uri, gboolean force_replace, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodUnlinkFunc) (GnomeVFSMethod *method, GnomeVFSURI *uri, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodCheckSameFSFunc) (GnomeVFSMethod *method, GnomeVFSURI *a, GnomeVFSURI *b, gboolean *same_fs_return, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodSetFileInfo) (GnomeVFSMethod *method, GnomeVFSURI *a, const GnomeVFSFileInfo *info, GnomeVFSSetFileInfoMask mask, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodCreateSymbolicLinkFunc) (GnomeVFSMethod *method, GnomeVFSURI *uri, const gchar *target_reference, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodMonitorAddFunc) (GnomeVFSMethod *method, GnomeVFSMethodHandle **method_handle_return, GnomeVFSURI *uri, GnomeVFSMonitorType monitor_type); typedef GnomeVFSResult (* GnomeVFSMethodMonitorCancelFunc) (GnomeVFSMethod *method, GnomeVFSMethodHandle *handle); typedef GnomeVFSResult (* GnomeVFSMethodFileControlFunc) (GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle, const char *operation, gpointer operation_data, GnomeVFSContext *context); typedef GnomeVFSResult (* GnomeVFSMethodForgetCacheFunc) (GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle, GnomeVFSFileOffset offset, GnomeVFSFileSize size); typedef GnomeVFSResult (* GnomeVFSMethodGetVolumeFreeSpaceFunc) (GnomeVFSMethod *method, const GnomeVFSURI *uri, GnomeVFSFileSize *free_space); Handling cancellationAs VFS operations might take very long to complete, especially in the case of transient errors (such as a network server that has gone down), the GNOME Virtual File System Library provides a standard way to handle the cancellation of VFS operations. The GnomeVFSCancellation objectThe object that encapsulates this functionality is GnomeVFSCancellation. Most implementation functions get a pointer to such an object, and are expected to use this object to recognize when an operation should be interrupted. The most simple way to check for a cancellation request is
to poll the object with
gboolean gnome_vfs_cancellation_check (GnomeVFSCancellation *cancellation); This function will return a nonzero value if the current operation should be cancelled. Notice that cancellation is an asynchronous operation that might happen outside your function, in parallel with the code that you are writing. For example, in the case of threads, the request will be set in the master thread; in the case of slave CORBA-driven processes, the request will be activated by a Unix signal. So you can expect a cancellation request to happen (and consequently be signalled in GnomeVFSCancellation) at any time. For this reason, you should be calling this function periodically, whenever you are going to perform several iterations of the same task, or execute a single expensive task. When the function returns a nonzero value, the correct way to react is:
Note, there are some other situations in which you want to be able to interrupt an I/O operation when a cancellation request is performed. In such cases, polling is not a viable option. For this reason, GnomeVFSCancellation provides an alternative way of sending notifications, using a file descriptor. To use this feature, you should use the following function: gint gnome_vfs_cancellation_get_fd (GnomeVFSCancellation *cancellation); When this function is called, it will return an open file
descriptor, which is the read-side of a pipe. The pipe will be
given a character from the write side as soon as a cancellation
request is sent. You can check for a cancellation by using the
For example, if you are reading from a file descriptor and
you want to check for a pending cancellation at the same time,
you can set up Dealing with EINTRIn order to maximize the chance of cancelling an operation immediately, the GNOME Virtual File System can sends a signal to the asynchronous thread or process. This does not happen on all the systems and setups, though. The result of this is that, if a process is in the middle of a Unix system call while receiving this signal, the system call might be interrupted and return a EINTR error. For this reason, when you receive EINTR
you should check if a cancellation request is pending, using
Basic guidelines for writing a moduleWriting GNOME VFS modules is easy, but there are a few things that you must keep in mind when hacking them:
How to make the code thread safeAlthough it might sound scary at first, making the code for the modules thread safe is not complicated at all. First of all, make sure the amount of global variables is kept to the bare minimum. If possible, you should avoid them at all cost. For those cases where globals are inevitable (such as
caches, connection pools or things like that), you have to make
sure every variable is properly associated with a mutex, and
that the mutex is locked before every access to this variable
and released afterwards. You can also use
Generally speaking, if you are going to dynamically allocate structures that are shared by more than one operation/file, you should provide all of them with their nice mutex locks. Finally, make sure mutexes are used only if they are available. One way to do so is to use macros like the following: #ifdef G_THREADS_ENABLED #define MUTEX_NEW() g_mutex_new () #define MUTEX_FREE(a) g_mutex_free (a) #define MUTEX_LOCK(a) if ((a) != NULL) g_mutex_lock (a) #define MUTEX_UNLOCK(a) if ((a) != NULL) g_mutex_unlock (a) #else #define MUTEX_NEW() NULL #define MUTEX_FREE(a) #define MUTEX_LOCK(a) #define MUTEX_UNLOCK(a) #endif
(Probably it would be a good idea to have something in the private GNOME VFS API that does this stuff for all the modules.) |
:: Command execute :: | |
--[ c99shell v. 2.0 [PHP 7 Update] [25.02.2019] maintained by KaizenLouie | C99Shell Github | Generation time: 0.0083 ]-- |