#include <glib/gmessages.h>
#include "captivefs-misc.h"
#include "captivefs-attr.h"
+#include "captivefs-vfs.h"
#include <fcntl.h>
#include <captive/client-vfs.h>
#include <captive/client-file.h>
+#include <captive/client.h>
#include <lufs/fs.h>
+/* Config: */
+#define CLIENT_LUFS_USE_COUNT "client-lufs-use_count"
+
+
+/* map: (const gchar *utf8) -> (CaptiveFileObject *) */
+static GHashTable *FileHandle_hash;
+G_LOCK_DEFINE_STATIC(FileHandle_hash);
+
+static void FileHandle_hash_init(void)
+{
+ G_LOCK(FileHandle_hash);
+ if (!FileHandle_hash) {
+ FileHandle_hash=g_hash_table_new_full(g_str_hash,g_str_equal,
+ (GDestroyNotify)g_free, /* key_destroy_func */
+ (GDestroyNotify)NULL); /* value_destroy_func; handled by FileHandle_hash_captive_file_object_weak_notify() */
+ }
+ G_UNLOCK(FileHandle_hash);
+}
+
+/* Do not: GObject->ref_count
+ * as 'ref_count' may be increased for deleted files by ParentConnector
+ * until the volume gets unmounted. Therefore any deleted file would not
+ * be removed from our 'FileHandle_hash' and no object would be reinstantiable
+ * under the original deleted name.
+ */
+static gint FileHandle_get_use_count(CaptiveFileObject *captive_file_object)
+{
+ g_return_val_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object),0);
+
+ return GPOINTER_TO_INT(g_object_get_data(G_OBJECT(captive_file_object),CLIENT_LUFS_USE_COUNT));
+}
+
+static void FileHandle_set_use_count(CaptiveFileObject *captive_file_object,gint use_count)
+{
+ g_return_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object));
+
+ g_object_set_data(G_OBJECT(captive_file_object),CLIENT_LUFS_USE_COUNT,GINT_TO_POINTER(use_count));
+}
+
+/* FileHandle_hash_init(); must be executed! */
+/* G_LOCK(FileHandle_hash); must be held! */
+static void FileHandle_enter
+ (struct captivefs_vfs *captivefs_vfs,CaptiveFileObject *captive_file_object,const gchar *name_normalized)
+{
+gint use_count;
+
+ g_return_if_fail(captivefs_vfs_validate(captivefs_vfs));
+ g_return_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object));
+ g_return_if_fail(name_normalized);
+
+ use_count=FileHandle_get_use_count(captive_file_object);
+ if (captivefs_vfs->options.debug_messages)
+ g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"FileHandle_enter: name_normalized=%s, use_count++=%d",
+ name_normalized,(int)use_count);
+ g_assert(use_count>=0);
+ use_count++;
+ FileHandle_set_use_count(captive_file_object,use_count);
+ if (use_count>1) {
+ g_assert(captive_file_object==g_hash_table_lookup(FileHandle_hash,name_normalized));
+ return;
+ }
+ g_assert(NULL==g_hash_table_lookup(FileHandle_hash,name_normalized));
+ g_object_ref(captive_file_object);
+ g_hash_table_insert(FileHandle_hash,g_strdup(name_normalized),captive_file_object);
+}
+
+/* FileHandle_hash_init(); must be executed! */
+/* G_LOCK(FileHandle_hash); must be held! */
+/* G_LOCK(libcaptive); must NOT be held! */
+static void FileHandle_leave_locked
+ (struct captivefs_vfs *captivefs_vfs,CaptiveFileObject *captive_file_object,const gchar *name)
+{
+gboolean errbool;
+gint use_count;
+gchar *name_normalized;
+
+ g_return_if_fail(captivefs_vfs_validate(captivefs_vfs));
+ g_return_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object));
+ g_return_if_fail(name);
+
+ name_normalized=captive_path_normalize(name);
+ use_count=FileHandle_get_use_count(captive_file_object);
+ if (captivefs_vfs->options.debug_messages)
+ g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"FileHandle_leave_locked: name_normalized=%s, use_count--=%d",
+ name_normalized,(int)use_count);
+ g_assert(use_count>=1);
+ use_count--;
+ FileHandle_set_use_count(captive_file_object,use_count);
+ g_assert(captive_file_object==g_hash_table_lookup(FileHandle_hash,name_normalized));
+ if (use_count>=1) {
+ g_free(name_normalized);
+ return;
+ }
+ errbool=g_hash_table_remove(FileHandle_hash,name_normalized);
+ g_assert(errbool==TRUE);
+ G_LOCK(libcaptive);
+ g_object_unref(captive_file_object);
+ G_UNLOCK(libcaptive);
+ g_assert(NULL==g_hash_table_lookup(FileHandle_hash,name_normalized));
+ g_free(name_normalized);
+}
+
+/* FileHandle_hash_init(); must be executed! */
+/* G_LOCK(FileHandle_hash); must NOT be held! */
+/* G_LOCK(libcaptive); must NOT be held! */
+static void FileHandle_leave(struct captivefs_vfs *captivefs_vfs,CaptiveFileObject *captive_file_object,const gchar *name)
+{
+ g_return_if_fail(captivefs_vfs_validate(captivefs_vfs));
+ g_return_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object));
+ g_return_if_fail(name);
+
+ G_LOCK(FileHandle_hash);
+ FileHandle_leave_locked(captivefs_vfs,captive_file_object,name);
+ G_UNLOCK(FileHandle_hash);
+}
+
+/* 'name' is required to exist. */
+static CaptiveFileObject *FileHandle_lookup_enter(struct captivefs_vfs *captivefs_vfs,const char *name)
+{
+CaptiveFileObject *captive_file_object;
+gchar *name_normalized;
+
+ g_return_val_if_fail(captivefs_vfs_validate(captivefs_vfs),NULL);
+ g_return_val_if_fail(name!=NULL,NULL);
+
+ name_normalized=captive_path_normalize(name);
+ FileHandle_hash_init();
+ G_LOCK(FileHandle_hash);
+ captive_file_object=g_hash_table_lookup(FileHandle_hash,name_normalized);
+ if (!captive_file_object) {
+ G_UNLOCK(FileHandle_hash);
+ g_warning("FileHandle_lookup_enter: FileHandle not found of: %s",name_normalized);
+ g_free(name_normalized);
+ return NULL;
+ }
+ g_assert(CAPTIVE_FILE_IS_OBJECT(captive_file_object));
+ FileHandle_enter(captivefs_vfs,captive_file_object,name_normalized);
+ G_UNLOCK(FileHandle_hash);
+ g_free(name_normalized);
+
+ return captive_file_object;
+}
+
+/* 'name' will be opened if needed. */
+static CaptiveFileObject *FileHandle_lookup_open_enter(struct captivefs_vfs *captivefs_vfs,const char *name,gboolean create)
+{
+CaptiveFileObject *captive_file_object;
+GnomeVFSResult errvfsresult;
+gchar *name_normalized;
+
+ g_return_val_if_fail(captivefs_vfs_validate(captivefs_vfs),NULL);
+ g_return_val_if_fail(name!=NULL,NULL);
+
+ name_normalized=captive_path_normalize(name);
+ FileHandle_hash_init();
+ G_LOCK(FileHandle_hash);
+ captive_file_object=g_hash_table_lookup(FileHandle_hash,name_normalized);
+ if (!create && captive_file_object) {
+ g_assert(CAPTIVE_FILE_IS_OBJECT(captive_file_object));
+ FileHandle_enter(captivefs_vfs,captive_file_object,name_normalized);
+ G_UNLOCK(FileHandle_hash);
+ g_free(name_normalized);
+ return captive_file_object;
+ }
+ if ( create && captive_file_object) {
+ g_assert(CAPTIVE_FILE_IS_OBJECT(captive_file_object));
+ FileHandle_enter(captivefs_vfs,captive_file_object,name_normalized);
+ G_UNLOCK(FileHandle_hash);
+ g_free(name_normalized);
+ return NULL;
+ }
+
+ /* FIXME: Respect 'gnome_vfs_open_mode'.
+ * We would have to do some reopens of files already contained in 'FileHandle_hash'.
+ * As W32 filesystem will allow us to open file 'GNOME_VFS_OPEN_WRITE'
+ * even on read-only media we use the full open permissions always.
+ */
+ if (!create) {
+ G_LOCK(libcaptive);
+ errvfsresult=captive_file_new_open(&captive_file_object,captivefs_vfs->captive_vfs_object,name_normalized,
+ GNOME_VFS_OPEN_READ|GNOME_VFS_OPEN_WRITE|GNOME_VFS_OPEN_RANDOM);
+ G_UNLOCK(libcaptive);
+ /* HIDDEN SYSTEM files (FIXME: or just HIDDEN or just SYSTEM?)
+ * refuse to be GNOME_VFS_OPEN_WRITE-opened.
+ */
+ if (errvfsresult==GNOME_VFS_ERROR_ACCESS_DENIED) {
+ G_LOCK(libcaptive);
+ errvfsresult=captive_file_new_open(&captive_file_object,captivefs_vfs->captive_vfs_object,name_normalized,
+ GNOME_VFS_OPEN_READ|GNOME_VFS_OPEN_RANDOM);
+ G_UNLOCK(libcaptive);
+ }
+ }
+ else {
+ G_LOCK(libcaptive);
+ errvfsresult=captive_file_new_create(&captive_file_object,captivefs_vfs->captive_vfs_object,name_normalized,
+ GNOME_VFS_OPEN_READ|GNOME_VFS_OPEN_WRITE|GNOME_VFS_OPEN_RANDOM, /* mode */
+ FALSE, /* exclusive */
+ 0600); /* perm */
+ G_UNLOCK(libcaptive);
+ }
+ if (errvfsresult!=GNOME_VFS_OK) {
+ G_UNLOCK(FileHandle_hash);
+ g_free(name_normalized);
+ return NULL;
+ }
+ FileHandle_enter(captivefs_vfs,captive_file_object,name_normalized);
+ G_UNLOCK(FileHandle_hash);
+ g_object_unref(captive_file_object); /* for captive_file_new_open() / captive_file_new_create() */
+ g_free(name_normalized);
+
+ return captive_file_object;
+}
+
/* Read a file/dir's attributes
* Fill all relevant data into the fattr structure.
* The uid/gid fields are just ownership hints hints:
* last accessed directory in readdir, or, as this code does, changing
* to the current directory there.
*/
-int captivefs_stat(CaptiveVfsObject *captive_vfs_object,const char *name,struct lufs_fattr *fattr)
+int captivefs_stat(struct captivefs_vfs *captivefs_vfs,const char *name,struct lufs_fattr *fattr)
{
GnomeVFSResult errvfsresult;
CaptiveFileObject *captive_file_object;
GnomeVFSFileInfo file_info;
- g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
+ g_return_val_if_fail(captivefs_vfs_validate(captivefs_vfs),-1);
g_return_val_if_fail(name!=NULL,-1);
g_return_val_if_fail(fattr!=NULL,-1);
- if (VFS_DEBUG_MESSAGES(captive_vfs_object))
+ if (captivefs_vfs->options.debug_messages)
g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_stat: name=%s",name);
- G_LOCK(libcaptive);
- errvfsresult=captive_file_new_open(&captive_file_object,captive_vfs_object,name,GNOME_VFS_OPEN_READ);
- G_UNLOCK(libcaptive);
- if (errvfsresult!=GNOME_VFS_OK)
- goto fail;
+ name=CAPTIVEFS_FILENAME_TO_UTF8_ALLOCA(name);
+
+ captive_file_object=FileHandle_lookup_open_enter(captivefs_vfs,name,FALSE);
+ if (!captive_file_object)
+ return -1;
G_LOCK(libcaptive);
errvfsresult=captive_file_file_info_get(captive_file_object,&file_info);
G_UNLOCK(libcaptive);
- if (errvfsresult!=GNOME_VFS_OK)
- goto fail_unref;
- G_LOCK(libcaptive);
- g_object_unref(captive_file_object);
- G_UNLOCK(libcaptive);
+ FileHandle_leave(captivefs_vfs,captive_file_object,name);
- if (!captivefs_GnomeVFSFileInfo_to_lufs_fattr(fattr,&file_info))
+ if (errvfsresult!=GNOME_VFS_OK)
return -1;
- return 0;
+ if (!captivefs_GnomeVFSFileInfo_to_lufs_fattr(captivefs_vfs,fattr,&file_info))
+ return -1;
-fail_unref:
- G_LOCK(libcaptive);
- g_object_unref(captive_file_object);
- G_UNLOCK(libcaptive);
-fail:
- return -1;
+ return 0;
}
/* Create a file
*/
-int captivefs_create(CaptiveVfsObject *captive_vfs_object,const char *file,int mode)
+int captivefs_create(struct captivefs_vfs *captivefs_vfs,const char *file,int mode)
{
-GnomeVFSResult errvfsresult;
CaptiveFileObject *captive_file_object;
- g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
+ g_return_val_if_fail(captivefs_vfs_validate(captivefs_vfs),-1);
g_return_val_if_fail(file!=NULL,-1);
- if (VFS_DEBUG_MESSAGES(captive_vfs_object))
+ if (captivefs_vfs->options.debug_messages)
g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_create: file=%s,mode=0x%X",file,mode);
- G_LOCK(libcaptive);
- errvfsresult=captive_file_new_create(&captive_file_object,captive_vfs_object,file,GNOME_VFS_OPEN_WRITE,
- FALSE, /* exclusive */
- mode); /* perm */
- G_UNLOCK(libcaptive);
- if (errvfsresult!=GNOME_VFS_OK)
+ file=CAPTIVEFS_FILENAME_TO_UTF8_ALLOCA(file);
+
+ captive_file_object=FileHandle_lookup_open_enter(captivefs_vfs,file,TRUE);
+ if (!captive_file_object)
return -1;
- G_LOCK(libcaptive);
- g_object_unref(captive_file_object);
- G_UNLOCK(libcaptive);
+ FileHandle_leave(captivefs_vfs,captive_file_object,file);
return 0;
}
/* Delete a file
*/
-int captivefs_unlink(CaptiveVfsObject *captive_vfs_object,const char *file)
+int captivefs_unlink(struct captivefs_vfs *captivefs_vfs,const char *file)
{
GnomeVFSResult errvfsresult;
CaptiveFileObject *captive_file_object;
- g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
+ g_return_val_if_fail(captivefs_vfs_validate(captivefs_vfs),-1);
g_return_val_if_fail(file!=NULL,-1);
- if (VFS_DEBUG_MESSAGES(captive_vfs_object))
+ if (captivefs_vfs->options.debug_messages)
g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_unlink: file=%s",file);
- G_LOCK(libcaptive);
- errvfsresult=captive_file_new_open(&captive_file_object,captive_vfs_object,file,GNOME_VFS_OPEN_WRITE);
- G_UNLOCK(libcaptive);
- if (errvfsresult!=GNOME_VFS_OK)
- goto fail;
+ file=CAPTIVEFS_FILENAME_TO_UTF8_ALLOCA(file);
+
+ captive_file_object=FileHandle_lookup_open_enter(captivefs_vfs,file,FALSE);
+ if (!captive_file_object)
+ return -1;
G_LOCK(libcaptive);
errvfsresult=captive_file_remove(captive_file_object);
G_UNLOCK(libcaptive);
- if (errvfsresult!=GNOME_VFS_OK)
- goto fail_unref;
- G_LOCK(libcaptive);
- g_object_unref(captive_file_object);
- G_UNLOCK(libcaptive);
+ FileHandle_leave(captivefs_vfs,captive_file_object,file);
- return 0;
+ if (errvfsresult!=GNOME_VFS_OK)
+ return -1;
-fail_unref:
- G_LOCK(libcaptive);
- g_object_unref(captive_file_object);
- G_UNLOCK(libcaptive);
-fail:
- return -1;
+ return 0;
}
/* Rename a file/dir
*/
-int captivefs_rename(CaptiveVfsObject *captive_vfs_object,const char *old_name,const char *new_name)
+int captivefs_rename(struct captivefs_vfs *captivefs_vfs,const char *old_name,const char *new_name)
{
GnomeVFSResult errvfsresult;
CaptiveFileObject *captive_file_object;
+gint use_count;
- g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
+ g_return_val_if_fail(captivefs_vfs_validate(captivefs_vfs),-1);
g_return_val_if_fail(old_name!=NULL,-1);
g_return_val_if_fail(new_name!=NULL,-1);
- if (VFS_DEBUG_MESSAGES(captive_vfs_object))
+ if (captivefs_vfs->options.debug_messages)
g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_rename: old_name=%s,new_name=%s",old_name,new_name);
- G_LOCK(libcaptive);
- errvfsresult=captive_file_new_open(&captive_file_object,captive_vfs_object,old_name,GNOME_VFS_OPEN_WRITE);
- G_UNLOCK(libcaptive);
- if (errvfsresult!=GNOME_VFS_OK)
- goto fail;
-
- G_LOCK(libcaptive);
- errvfsresult=captive_file_move(captive_file_object,new_name,
- FALSE); /* force_replace */
- G_UNLOCK(libcaptive);
- if (errvfsresult!=GNOME_VFS_OK)
- goto fail_unref;
+ old_name=CAPTIVEFS_FILENAME_TO_UTF8_ALLOCA(old_name);
+ new_name=CAPTIVEFS_FILENAME_TO_UTF8_ALLOCA(new_name);
- G_LOCK(libcaptive);
- g_object_unref(captive_file_object);
- G_UNLOCK(libcaptive);
+ captive_file_object=FileHandle_lookup_open_enter(captivefs_vfs,old_name,FALSE);
+ if (!captive_file_object)
+ return -1;
- return 0;
+ G_LOCK(FileHandle_hash);
+ use_count=FileHandle_get_use_count(captive_file_object);
+ g_assert(use_count>=1);
+ if (use_count!=1) {
+ if (captivefs_vfs->options.debug_messages)
+ g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_rename: old_name=%s,new_name=%s: BUSY use_count=%d",
+ old_name,new_name,(int)use_count);
+ G_UNLOCK(FileHandle_hash);
+ FileHandle_leave(captivefs_vfs,captive_file_object,old_name);
+ return -1;
+ }
-fail_unref:
G_LOCK(libcaptive);
- g_object_unref(captive_file_object);
+ errvfsresult=captive_file_move(captive_file_object,new_name,
+ FALSE); /* force_replace */
G_UNLOCK(libcaptive);
-fail:
- return -1;
-}
-
-
-/* map: (const gchar *) -> (CaptiveFileObject *) */
-static GHashTable *FileHandle_hash;
-
-static void FileHandle_hash_value_destroy_func(CaptiveFileObject *captive_file_object)
-{
- g_return_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object));
-
- g_object_unref(captive_file_object);
-}
-
-static void FileHandle_hash_init(void)
-{
- if (FileHandle_hash)
- return;
- FileHandle_hash=g_hash_table_new_full(g_str_hash,g_str_equal,
- (GDestroyNotify)g_free, /* key_destroy_func */
- (GDestroyNotify)FileHandle_hash_value_destroy_func); /* value_destroy_func */
-}
-
-static CaptiveFileObject *FileHandle_lookup(const char *name)
-{
-CaptiveFileObject *captive_file_object;
- g_return_val_if_fail(name!=NULL,NULL);
+ FileHandle_leave_locked(captivefs_vfs,captive_file_object,old_name);
+ G_UNLOCK(FileHandle_hash);
- FileHandle_hash_init();
- if (!(captive_file_object=g_hash_table_lookup(FileHandle_hash,name))) {
- g_warning("FileHandle_lookup: FileHandle not found of: %s",name);
- return NULL;
- }
-
- g_assert(CAPTIVE_FILE_IS_OBJECT(captive_file_object));
+ if (errvfsresult!=GNOME_VFS_OK)
+ return -1;
- return captive_file_object;
+ return 0;
}
* a "flags" variable, this only has a "mode" variable. To convert to the
* POSIX version, ->flags=mode^O_ACCMODE and ->mode=mode&O_ACCMODE.
*/
-int captivefs_open(CaptiveVfsObject *captive_vfs_object,const char *file,unsigned mode)
+int captivefs_open(struct captivefs_vfs *captivefs_vfs,const char *file,unsigned mode)
{
CaptiveFileObject *captive_file_object;
GnomeVFSOpenMode gnome_vfs_open_mode;
-GnomeVFSResult errvfsresult;
- g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
+ /* We may be called from the parent. */
+ g_return_val_if_fail(captivefs_vfs!=NULL,FALSE);
g_return_val_if_fail(file!=NULL,-1);
- if (VFS_DEBUG_MESSAGES(captive_vfs_object))
+ if (captivefs_vfs->options.debug_messages)
g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_open: file=%s,mode=0x%X",file,mode);
- FileHandle_hash_init();
- if ((captive_file_object=g_hash_table_lookup(FileHandle_hash,file))) {
- g_assert(CAPTIVE_FILE_IS_OBJECT(captive_file_object));
- g_warning("captivefs_open: FileHandle already exists of: %s",file);
+ file=CAPTIVEFS_FILENAME_TO_UTF8_ALLOCA(file);
+
+ if (!captivefs_vfs_validate(captivefs_vfs))
return -1;
- }
- if (mode & (O_RDONLY|O_WRONLY|O_RDWR)) {
+ if (mode & ~(O_RDONLY|O_WRONLY|O_RDWR)) {
g_warning("captivefs_open: Unrecognized 'mode' 0x%X",mode);
return -1;
}
return -1;
}
- G_LOCK(libcaptive);
- errvfsresult=captive_file_new_open(&captive_file_object,captive_vfs_object,file,
- gnome_vfs_open_mode|GNOME_VFS_OPEN_RANDOM);
- G_UNLOCK(libcaptive);
- if (errvfsresult!=GNOME_VFS_OK)
+ captive_file_object=FileHandle_lookup_open_enter(captivefs_vfs,file,FALSE);
+ if (!captive_file_object)
return -1;
- g_hash_table_insert(FileHandle_hash,g_strdup(file),captive_file_object);
-
+ /* Leave 'captive_file_object' entered. */
return 0;
}
-int captivefs_release(CaptiveVfsObject *captive_vfs_object,const char *file)
+int captivefs_release(struct captivefs_vfs *captivefs_vfs,const char *file)
{
- g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
+CaptiveFileObject *captive_file_object;
+
+ g_return_val_if_fail(captivefs_vfs_validate(captivefs_vfs),-1);
g_return_val_if_fail(file!=NULL,-1);
- if (VFS_DEBUG_MESSAGES(captive_vfs_object))
+ if (captivefs_vfs->options.debug_messages)
g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_release: file=%s",file);
- FileHandle_hash_init();
- if (!g_hash_table_remove(FileHandle_hash,file)) {
- g_warning("captivefs_release: FileHandle not found of: %s",file);
+ file=CAPTIVEFS_FILENAME_TO_UTF8_ALLOCA(file);
+
+ if (!(captive_file_object=FileHandle_lookup_enter(captivefs_vfs,file)))
return -1;
- }
+
+ FileHandle_leave(captivefs_vfs,captive_file_object,file); /* for FileHandle_lookup_enter() */
+ FileHandle_leave(captivefs_vfs,captive_file_object,file);
return 0;
}
/* Read from a file. Changed to use the (2) routines not for efficiency,
* but to make it work with 64-bit offsets :-(.
*/
-int captivefs_read(CaptiveVfsObject *captive_vfs_object,const char *file,long long offset,unsigned long count,void *buf)
+int captivefs_read(struct captivefs_vfs *captivefs_vfs,const char *file,long long offset,unsigned long count,void *buf)
{
CaptiveFileObject *captive_file_object;
GnomeVFSFileSize bytes_read;
GnomeVFSResult errvfsresult;
- g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
+ g_return_val_if_fail(captivefs_vfs_validate(captivefs_vfs),-1);
g_return_val_if_fail(file!=NULL,-1);
g_return_val_if_fail(buf!=NULL || count==0,-1);
- if (VFS_DEBUG_MESSAGES(captive_vfs_object))
+ if (captivefs_vfs->options.debug_messages)
g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_read: file=%s,offset=%" G_GINT64_FORMAT ",count=0x%lX",
file,(gint64)offset,count);
- if (!(captive_file_object=FileHandle_lookup(file)))
+ file=CAPTIVEFS_FILENAME_TO_UTF8_ALLOCA(file);
+
+ if (!(captive_file_object=FileHandle_lookup_enter(captivefs_vfs,file)))
return -1;
+ /* Do not unlock 'libcaptive' between seek() and read()! */
G_LOCK(libcaptive);
errvfsresult=captive_file_seek(captive_file_object,GNOME_VFS_SEEK_START,offset);
- G_UNLOCK(libcaptive);
- if (errvfsresult!=GNOME_VFS_OK)
+ if (errvfsresult!=GNOME_VFS_OK) {
+ G_UNLOCK(libcaptive);
+ FileHandle_leave(captivefs_vfs,captive_file_object,file);
return -1;
+ }
- G_LOCK(libcaptive);
errvfsresult=captive_file_read(captive_file_object,buf,count,&bytes_read);
G_UNLOCK(libcaptive);
+ FileHandle_leave(captivefs_vfs,captive_file_object,file);
if (errvfsresult!=GNOME_VFS_OK)
return -1;
/* Write to a file
*/
-int captivefs_write(CaptiveVfsObject *captive_vfs_object,const char *file,long long offset,unsigned long count,const void *buf)
+int captivefs_write(struct captivefs_vfs *captivefs_vfs,const char *file,long long offset,unsigned long count,const void *buf)
{
CaptiveFileObject *captive_file_object;
GnomeVFSFileSize bytes_written;
GnomeVFSResult errvfsresult;
- g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
+ g_return_val_if_fail(captivefs_vfs_validate(captivefs_vfs),-1);
g_return_val_if_fail(file!=NULL,-1);
g_return_val_if_fail(buf!=NULL || count==0,-1);
- if (VFS_DEBUG_MESSAGES(captive_vfs_object))
+ if (captivefs_vfs->options.debug_messages)
g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_write: file=%s,offset=%" G_GINT64_FORMAT ",count=0x%lX",
file,(gint64)offset,count);
- if (!(captive_file_object=FileHandle_lookup(file)))
+ file=CAPTIVEFS_FILENAME_TO_UTF8_ALLOCA(file);
+
+ if (!(captive_file_object=FileHandle_lookup_enter(captivefs_vfs,file)))
return -1;
+ /* Do not unlock 'libcaptive' between seek() and write()! */
G_LOCK(libcaptive);
errvfsresult=captive_file_seek(captive_file_object,GNOME_VFS_SEEK_START,offset);
- G_UNLOCK(libcaptive);
- if (errvfsresult!=GNOME_VFS_OK)
+ if (errvfsresult!=GNOME_VFS_OK) {
+ G_UNLOCK(libcaptive);
+ FileHandle_leave(captivefs_vfs,captive_file_object,file);
return -1;
+ }
- G_LOCK(libcaptive);
errvfsresult=captive_file_write(captive_file_object,buf,count,&bytes_written);
G_UNLOCK(libcaptive);
+ FileHandle_leave(captivefs_vfs,captive_file_object,file);
if (errvfsresult!=GNOME_VFS_OK)
return -1;
/* Change a file/dir's attributes
*/
-int captivefs_setattr(CaptiveVfsObject *captive_vfs_object,const char *file,const struct lufs_fattr *fattr)
+int captivefs_setattr(struct captivefs_vfs *captivefs_vfs,const char *file,const struct lufs_fattr *fattr)
{
GnomeVFSFileInfo file_info;
GnomeVFSResult errvfsresult;
CaptiveFileObject *captive_file_object;
- g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
+ g_return_val_if_fail(captivefs_vfs_validate(captivefs_vfs),-1);
g_return_val_if_fail(file!=NULL,-1);
g_return_val_if_fail(fattr!=NULL,-1);
- if (VFS_DEBUG_MESSAGES(captive_vfs_object))
+ if (captivefs_vfs->options.debug_messages)
g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_setattr: file=%s",file);
+ file=CAPTIVEFS_FILENAME_TO_UTF8_ALLOCA(file);
+
if (!captivefs_lufs_fattr_to_GnomeVFSFileInfo(&file_info,fattr))
return -1;
- G_LOCK(libcaptive);
- errvfsresult=captive_file_new_open(&captive_file_object,captive_vfs_object,file,GNOME_VFS_OPEN_WRITE);
- G_UNLOCK(libcaptive);
- if (errvfsresult!=GNOME_VFS_OK)
- goto fail;
+ captive_file_object=FileHandle_lookup_open_enter(captivefs_vfs,file,FALSE);
+ if (!captive_file_object)
+ return -1;
G_LOCK(libcaptive);
- errvfsresult=captive_file_file_info_set(captive_file_object,&file_info,file_info.valid_fields);
+ errvfsresult=captive_file_file_info_set(captive_file_object,&file_info,
+ 0
+ | 0 /* 'GNOME_VFS_SET_FILE_INFO_NAME' is never set */
+ | (!(file_info.valid_fields&GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS) ? 0 : GNOME_VFS_SET_FILE_INFO_PERMISSIONS)
+ | 0 /* 'GNOME_VFS_SET_FILE_INFO_OWNER' is never set */
+ | (!(file_info.valid_fields&(0
+ | GNOME_VFS_FILE_INFO_FIELDS_ATIME
+ | GNOME_VFS_FILE_INFO_FIELDS_MTIME
+ | GNOME_VFS_FILE_INFO_FIELDS_CTIME))
+ ? 0 : GNOME_VFS_SET_FILE_INFO_TIME));
G_UNLOCK(libcaptive);
- if (errvfsresult!=GNOME_VFS_OK)
- goto fail_unref;
-
G_LOCK(libcaptive);
- g_object_unref(captive_file_object);
+ if (errvfsresult==GNOME_VFS_OK)
+ errvfsresult=captive_file_truncate(captive_file_object,fattr->f_size);
G_UNLOCK(libcaptive);
+ FileHandle_leave(captivefs_vfs,captive_file_object,file);
+ if (errvfsresult!=GNOME_VFS_OK)
+ return -1;
return 0;
-
-fail_unref:
- G_LOCK(libcaptive);
- g_object_unref(captive_file_object);
- G_UNLOCK(libcaptive);
-fail:
- return -1;
}