gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r5153 - gnunet-fuse


From: gnunet
Subject: [GNUnet-SVN] r5153 - gnunet-fuse
Date: Wed, 27 Jun 2007 23:10:02 -0600 (MDT)

Author: amatus
Date: 2007-06-27 23:10:01 -0600 (Wed, 27 Jun 2007)
New Revision: 5153

Added:
   gnunet-fuse/mknod.c
   gnunet-fuse/write.c
Modified:
   gnunet-fuse/Makefile.am
   gnunet-fuse/dirent.c
   gnunet-fuse/getattr.c
   gnunet-fuse/gnfs.h
   gnunet-fuse/main.c
   gnunet-fuse/open.c
   gnunet-fuse/read.c
   gnunet-fuse/special_file.c
Log:
First steps towards write support. You can now create files and write to them, 
but they are not published.

Modified: gnunet-fuse/Makefile.am
===================================================================
--- gnunet-fuse/Makefile.am     2007-06-28 03:34:55 UTC (rev 5152)
+++ gnunet-fuse/Makefile.am     2007-06-28 05:10:01 UTC (rev 5153)
@@ -4,10 +4,12 @@
        dirent.c \
        getattr.c \
        main.c \
+       mknod.c \
        open.c \
        read.c \
        readdir.c \
        special_file.c \
+       write.c \
        gnfs.h \
        gettext.h
 

Modified: gnunet-fuse/dirent.c
===================================================================
--- gnunet-fuse/dirent.c        2007-06-28 03:34:55 UTC (rev 5152)
+++ gnunet-fuse/dirent.c        2007-06-28 05:10:01 UTC (rev 5153)
@@ -21,6 +21,7 @@
 #include <unistd.h>
 #include <glib.h>
 #include <string.h>
+#include <errno.h>
 #include "gnfs.h"
 
 GHashTable *path_hash;
@@ -119,7 +120,7 @@
                de->de_dirty = 1;
                if(type == DE_FILE)
                {
-                       char filename[] = "/tmp/gnfsXXXXXX";
+                       char filename[] = GN_MKSTEMP_FILE;
 
                        de->de_fd = mkstemp(filename);
                        de->de_filename = STRDUP(filename);
@@ -264,9 +265,7 @@
        ECRS_FileInfo *fis;
 };
 
-int dirent_upload_locked(struct dirent *de);
-
-void upload_foreach(gpointer key, gpointer value, gpointer data)
+static void upload_foreach(gpointer key, gpointer value, gpointer data)
 {
        struct dirent *de = value;
        struct upload_data *d = data;
@@ -284,18 +283,17 @@
                }
                else
                {
-                       dirent_upload_locked(de);
+                       gn_dirent_upload_locked(de);
                }
        }
+       d->fis[d->count].uri = ECRS_dupUri(de->de_fi.uri);
+       d->fis[d->count].meta = ECRS_dupMetaData(de->de_fi.meta);
        d->count++;
-       d->fis = REALLOC(d->fis, d->count * sizeof(*d->fis));
-       d->fis[d->count - 1].uri = ECRS_dupUri(de->de_fi.uri);
-       d->fis[d->count - 1].meta = ECRS_dupMetaData(de->de_fi.meta);
 out:
        SEMAPHORE_UP(de->de_file_sema);
 }
 
-void upcb(guint64 totalBytes, guint64 completedBytes, cron_t eta,
+static void upcb(guint64 totalBytes, guint64 completedBytes, cron_t eta,
        void *closure)
 {
        (void)totalBytes;
@@ -304,65 +302,126 @@
        (void)closure;
 }
 
-int tt(void *closure)
+static int tt(void *closure)
 {
        (void)closure;
 
        return fuse_interrupted() ? SYSERR : OK;
 }
 
-int dirent_upload_locked(struct dirent *de)
+/*
+ * Make a dirty dirent clean - it should be a good tradeoff to only upload
+ * changes to directories here and upload changes to files on release
+ */
+int gn_dirent_upload_locked(struct dirent *de)
 {
-       int i, fd;
+       int i, ret, fd;
        struct upload_data d;
-       char *buf, filename[] = "/tmp/gnfsXXXXXX";
+       char *buf, filename[] = GN_MKSTEMP_FILE;
        guint64 len;
        struct ECRS_URI *uri;
 
+       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+               "%s: called for '%s'\n", __FUNCTION__, de->de_path);
+
+       /* We may be already clean */
        if(!de->de_dirty)
                return 0;
+       
+       /* Collect FileInfo from hash table and make a GNUnet directory*/
        d.count = 0;
-       d.fis = NULL;
+       d.fis = MALLOC(g_hash_table_size(de->de_dir) * sizeof(*d.fis));
        g_hash_table_foreach(de->de_dir, upload_foreach, &d);
-       if(ECRS_createDirectory(ectx, &buf, &len, d.count, d.fis,
-               de->de_fi.meta) == SYSERR)
-               goto out;
+       ret = ECRS_createDirectory(ectx, &buf, &len, d.count, d.fis,
+               de->de_fi.meta);
+       for(i = 0; i < d.count; i++)
+       {
+               ECRS_freeUri(d.fis[i].uri);
+               ECRS_freeMetaData(d.fis[i].meta);
+       }
+       if(ret == SYSERR)
+       {
+               GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR,
+                       "%s: ECRS_createDirectory failed\n",
+                       __FUNCTION__);
+               return -1;
+       }
+       FREE(d.fis);
+
+       /* Write the GNUnet directory out to a file and upload it */
        fd = mkstemp(filename);
        if(fd == -1)
-               goto out;
+       {
+               GE_LOG_STRERROR_FILE(ectx, GE_BULK | GE_DEVELOPER
+                       | GE_ERROR, "mkstemp", filename);
+               return -1;
+       }
        write(fd, buf, len);
+       ret = ECRS_uploadFile(ectx, cfg, filename, NO, anonymity, priority,
+               -1, upcb, NULL, tt, NULL, &uri);
        close(fd);
-       if(ECRS_uploadFile(ectx, cfg, filename, NO, anonymity, priority,
-               -1, upcb, NULL, tt, NULL, &uri) == SYSERR)
-               goto out_unlink_file;
+       unlink(filename);
+       if(ret == SYSERR)
+       {
+               GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR,
+                       "%s: ECRS_uploadFile failed\n", __FUNCTION__);
+               return -1;
+       }
+
+       /* Update the dirent info with our new URI and mark it clean */
        if(de->de_fi.uri != NULL)
                ECRS_freeUri(de->de_fi.uri);
        de->de_fi.uri = uri;
        g_hash_table_destroy(de->de_dir);
        de->de_dirty = 0;
-out_unlink_file:
-       unlink(filename);
-out:
-       for(i = 0; i < d.count; i++)
-       {
-               ECRS_freeUri(d.fis[i].uri);
-               ECRS_freeMetaData(d.fis[i].meta);
-       }
-       FREE(d.fis);
        return 0;
 }
 
+static void dpcb(unsigned long long totalBytes,
+        unsigned long long completedBytes, cron_t eta,
+        unsigned long long lastBlockOffset, const char *lastBlock,
+        unsigned int lastBlockSize, void *cls) 
+{       
+       (void)totalBytes;
+       (void)completedBytes;
+       (void)eta;
+       (void)lastBlockOffset;
+       (void)lastBlock;
+       (void)lastBlockSize;
+       (void)cls;
+}
+
 /*
- * Make a dirty dirent clean - it should be a good tradeoff to only upload
- * changes to directories here and upload changes to files on release
+ * Download a file for writing, de_file_sema must be held.
  */
-int gn_dirent_upload(struct dirent *de)
+int gn_dirent_download_locked(struct dirent *de)
 {
-       int ret;
+       char filename[] = GN_MKSTEMP_FILE;
 
-       if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
+       /* We may already be dirty */
+       if(!de->de_dirty)
+               return 0;
+
+       /* Do the download */
+       de->de_fd = mkstemp(filename);
+       if(de->de_fd == -1)
+       {
+               GE_LOG_STRERROR_FILE(ectx, GE_BULK | GE_DEVELOPER
+                       | GE_ERROR, "mkstemp", filename);
                return -1;
-       ret = dirent_upload_locked(de);
-       SEMAPHORE_UP(de->de_file_sema);
-       return ret;
+       }
+       de->de_filename = STRDUP(filename);
+
+       if(ECRS_downloadFile(ectx, cfg, de->de_fi.uri, filename, anonymity,
+               dpcb, NULL, tt, NULL) == SYSERR)
+       {
+               close(de->de_fd);
+               FREE(de->de_filename);
+               return -1;
+       }
+
+       /* Mark ourselves dirty, we don't have to mark our parent directory
+        * dirty until we sync this file back into GNUnet, see above. */
+       de->de_dirty = 1;
+       return 0;
 }

Modified: gnunet-fuse/getattr.c
===================================================================
--- gnunet-fuse/getattr.c       2007-06-28 03:34:55 UTC (rev 5152)
+++ gnunet-fuse/getattr.c       2007-06-28 05:10:01 UTC (rev 5153)
@@ -19,7 +19,6 @@
  */
 
 #include <sys/stat.h>
-#include <stdio.h>
 #include <string.h>
 #include <errno.h>
 #include <fuse.h>
@@ -30,8 +29,8 @@
        struct dirent *de;
        guint64 size = 0;
 
-       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "getattr for '%s'\n",
-               path);
+       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: for '%s'\n",
+               __FUNCTION__, path);
 
        /* Check to see if this is a special file */
        if(gn_exists_special_file(path))
@@ -47,7 +46,7 @@
        de = gn_dirent_find(path);
        if(de == NULL)
        {
-               GE_LOG(ectx, GE_BULK | GE_USER | GE_ERROR,
+               GE_LOG(ectx, GE_BULK | GE_USER | GE_DEBUG,
                        "%s: could not find path '%s'\n", __FUNCTION__, path);
                return -ENOENT;
        }
@@ -57,7 +56,7 @@
        stbuf->st_mode |= de->de_type == DE_DIR ? S_IFDIR : S_IFREG;
        stbuf->st_nlink = 1;
        if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
-               return -ENOENT;
+               return -EIO;
        if(de->de_dirty)
        {
                if(de->de_type == DE_FILE && disk_file_size(ectx,
@@ -68,7 +67,7 @@
                                __FUNCTION__, de->de_filename);
                        SEMAPHORE_UP(de->de_file_sema);
                        gn_dirent_put(de);
-                       return -ENOENT;
+                       return -EIO;
                }
        }
        else

Modified: gnunet-fuse/gnfs.h
===================================================================
--- gnunet-fuse/gnfs.h  2007-06-28 03:34:55 UTC (rev 5152)
+++ gnunet-fuse/gnfs.h  2007-06-28 05:10:01 UTC (rev 5153)
@@ -34,6 +34,7 @@
 
 #define URI_FILE       ".uri"
 #define URI_LEN                4
+#define GN_MKSTEMP_FILE        "/tmp/gnfs.XXXXXX"
 
 struct dirent
 {
@@ -81,6 +82,8 @@
 void gn_dirent_cache_init(void);
 void gn_dirent_cache(struct dirent *de);
 struct dirent *gn_dirent_find(const gchar *path);
+int gn_dirent_upload_locked(struct dirent *de);
+int gn_dirent_download_locked(struct dirent *de);
 
 /* directory.c */
 int gn_directory_for_each(struct dirent *de, gn_dir_for_each_callback cb,
@@ -91,11 +94,15 @@
 int gn_getattr(const char *path, struct stat *stbuf);
 int gn_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
        off_t offset, struct fuse_file_info *fi);
+int gn_mknod(const char *path, mode_t mode, dev_t rdev);
 int gn_open(const char *path, struct fuse_file_info *fi);
 int gn_read(const char *path, char *buf, size_t size, off_t offset,
        struct fuse_file_info *fi);
+int gn_write(const char *path, char *buf, size_t size, off_t offset,
+       struct fuse_file_info *fi);
 
 /* special_file.c */
+char *gn_dirname(const char *path, char **file);
 int gn_exists_special_file(const char *path);
 char *gn_get_special_file(const char *path);
 

Modified: gnunet-fuse/main.c
===================================================================
--- gnunet-fuse/main.c  2007-06-28 03:34:55 UTC (rev 5152)
+++ gnunet-fuse/main.c  2007-06-28 05:10:01 UTC (rev 5153)
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <errno.h>
 #include <glib.h>
 #include <fuse.h>
 #include <GNUnet/gnunet_directories.h>
@@ -59,7 +60,6 @@
        (void)scls;
        (void)cmdLineOption;
 
-       fuse_argv = REALLOC(fuse_argv, sizeof(char *) * (fuse_argc + 2));
        fuse_argv[fuse_argc] = (char *)value;
        fuse_argc++;
        fuse_argv[fuse_argc] = NULL;
@@ -70,8 +70,10 @@
 {
        .getattr = gn_getattr,
        .readdir = gn_readdir,
+       .mknod = gn_mknod,
        .open = gn_open,
        .read = gn_read,
+       .write = gn_write,
 };
 
 static struct CommandLineOption gn_options[] =
@@ -102,7 +104,7 @@
 
        /* Initialize fuse options */
        fuse_argc = 1;
-       fuse_argv = MALLOC(sizeof(char *) * (fuse_argc + 1));
+       fuse_argv = MALLOC(sizeof(char *) * argc);
        fuse_argv[0] = argv[0];
        fuse_argv[1] = NULL;
 

Added: gnunet-fuse/mknod.c
===================================================================
--- gnunet-fuse/mknod.c                         (rev 0)
+++ gnunet-fuse/mknod.c 2007-06-28 05:10:01 UTC (rev 5153)
@@ -0,0 +1,77 @@
+/*
+ * mknod.c - FUSE mknod function
+ *
+ * This file is part of gnunet-fuse.
+ * Copyright (C) 2007 David Barksdale
+ *
+ * gnunet-fuse is free software; you can redistribute it and/or
+ * modify if under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * gnunet-fuse is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fuse.h>
+#include "gnfs.h"
+
+int gn_mknod(const char *path, mode_t mode, dev_t rdev)
+{
+       struct dirent *de, *newde;
+       struct ECRS_MetaData *meta;
+       char *parent, *file;
+
+       (void)rdev;
+       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: for '%s'\n",
+               __FUNCTION__, path);
+
+       /* We only support regular files */
+       if(!S_ISREG(mode))
+               return -ENOTSUP;
+
+       /* Check for special file */
+       if(gn_exists_special_file(path))
+               return -EEXIST;
+
+       /* Check for existing file */
+       de = gn_dirent_find(path);
+       if(de != NULL)
+       {
+               gn_dirent_put(de);
+               return -EEXIST;
+       }
+
+       /* Create new file */
+       parent = gn_dirname(path, &file);
+       de = gn_dirent_find(parent);
+       if(de == NULL)
+       {
+               FREE(parent);
+               return -ENOENT;
+       }
+       meta = ECRS_createMetaData();
+       ECRS_addToMetaData(meta, EXTRACTOR_FILENAME, file);
+       newde = gn_dirent_new(path, NULL, meta, DE_FILE);
+       ECRS_freeMetaData(meta);
+       if(gn_directory_insert(de, newde) == -1)
+       {
+               gn_dirent_put(de);
+               gn_dirent_put(newde);
+               FREE(parent);
+               return -EIO;
+       }
+       gn_dirent_put(de);
+       gn_dirent_put(newde);
+       FREE(parent);
+       return 0;
+}

Modified: gnunet-fuse/open.c
===================================================================
--- gnunet-fuse/open.c  2007-06-28 03:34:55 UTC (rev 5152)
+++ gnunet-fuse/open.c  2007-06-28 05:10:01 UTC (rev 5153)
@@ -18,31 +18,34 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <stdio.h>
-#include <fuse.h>
 #include <string.h>
 #include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fuse.h>
 #include "gnfs.h"
 
 int gn_open(const char *path, struct fuse_file_info *fi)
 {
        struct dirent *de;
 
-       (void)fi;
        GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: for '%s'\n",
                __FUNCTION__, path);
        
        /* Check for special file */
        if(gn_exists_special_file(path))
+       {
+               if(fi->flags & O_WRONLY)
+                       return -EACCES;
+               if((fi->flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+                       return -EEXIST;
                return 0;
+       }
 
+       /* Check for existing file */
        de = gn_dirent_find(path);
        if(de == NULL)
-       {
-               GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
-                       "%s: file not found\n", __FUNCTION__);
                return -ENOENT;
-       }
        if(de->de_type != DE_FILE)
        {
                GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
@@ -51,5 +54,7 @@
                return -ENOENT;
        }
        gn_dirent_put(de);
+       if((fi->flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+               return -EEXIST;
        return 0;
 }

Modified: gnunet-fuse/read.c
===================================================================
--- gnunet-fuse/read.c  2007-06-28 03:34:55 UTC (rev 5152)
+++ gnunet-fuse/read.c  2007-06-28 05:10:01 UTC (rev 5153)
@@ -82,8 +82,8 @@
 
        (void)fi;
 
-       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "read '%s' %d bytes\n",
-               path, size);
+       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+               "%s: called for '%s' %d bytes\n", __FUNCTION__, path, size);
 
        /* Check for special file */
        special = gn_get_special_file(path);
@@ -109,19 +109,19 @@
        if(de == NULL)
        {
                GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
-                       "read: file not found\n");
+                       "%s: file not found\n", __FUNCTION__);
                return -ENOENT;
        }
        if(de->de_type != DE_FILE)
        {
                GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
-                       "read: not a file\n");
+                       "%s: not a file\n", __FUNCTION__);
                size = -ENOENT;
                goto out;
        }
        if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
        {
-               size = -EINTR;
+               size = -EIO;
                goto out;
        }
        if(de->de_dirty)
@@ -151,7 +151,7 @@
        if(ret != OK)
        {
                GE_LOG(ectx, GE_BULK | GE_USER | GE_ERROR,
-                       "%s: failed to download directory\n", __FUNCTION__);
+                       "%s: failed to download file\n", __FUNCTION__);
                size = -ENODATA;
        }
 out_sema_up:

Modified: gnunet-fuse/special_file.c
===================================================================
--- gnunet-fuse/special_file.c  2007-06-28 03:34:55 UTC (rev 5152)
+++ gnunet-fuse/special_file.c  2007-06-28 05:10:01 UTC (rev 5153)
@@ -23,6 +23,22 @@
 #include <GNUnet/gnunet_ecrs_lib.h>
 #include "gnfs.h"
 
+char *gn_dirname(const char *path, char **file)
+{
+       char *parent, *slash;
+
+       parent = STRDUP(path);
+       slash = strrchr(parent, G_DIR_SEPARATOR);
+       if(slash != NULL)
+       {
+               slash[0] = '\0';
+               slash++;
+       }
+       if(file != NULL)
+               *file = slash;
+       return parent;
+}
+
 /* Checks to see if path is the path to a special file */
 int gn_exists_special_file(const char *path)
 {
@@ -30,13 +46,7 @@
        char *file, *parent;
        int ret = 0;
 
-       /* Break path into parent and file (dirname and basename kinda) */
-       parent = STRDUP(path);
-       file = strrchr(parent, G_DIR_SEPARATOR);
-       if(file == NULL)
-               goto out;
-       file[0] = '\0';
-       file++;
+       parent = gn_dirname(path, &file);
 
        /* Check for special file name */
        if(strcmp(file, URI_FILE) == 0)
@@ -71,13 +81,7 @@
        struct dirent *de;
        char *buf = NULL, *file, *parent;
 
-       /* Break path into parent and file (dirname and basename kinda) */
-       parent = STRDUP(path);
-       file = strrchr(parent, G_DIR_SEPARATOR);
-       if(file == NULL)
-               goto out;
-       file[0] = '\0';
-       file++;
+       parent = gn_dirname(path, &file);
 
        /* Check for special file name */
        if(strcmp(file, URI_FILE) == 0)

Added: gnunet-fuse/write.c
===================================================================
--- gnunet-fuse/write.c                         (rev 0)
+++ gnunet-fuse/write.c 2007-06-28 05:10:01 UTC (rev 5153)
@@ -0,0 +1,85 @@
+/*
+ * write.c - FUSE write function
+ *
+ * This file is part of gnunet-fuse.
+ * Copyright (C) 2007 David Barksdale
+ *
+ * gnunet-fuse is free software; you can redistribute it and/or
+ * modify if under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * gnunet-fuse is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define _XOPEN_SOURCE 500
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fuse.h>
+#include "gnfs.h"
+
+int gn_write(const char *path, char *buf, size_t size, off_t offset,
+       struct fuse_file_info *fi)
+{
+       struct dirent *de;
+       ssize_t slen;
+
+       (void)fi;
+
+       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+               "%s: called for '%s' %d bytes\n", __FUNCTION__, path, size);
+
+       /* Check for special file */
+       if(gn_exists_special_file(path))
+               return -EACCES;
+
+       /* Lookup dirent for path */
+       de = gn_dirent_find(path);
+       if(de == NULL)
+       {
+               GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+                       "%s: file not found\n", __FUNCTION__);
+               return -ENOENT;
+       }
+       if(de->de_type != DE_FILE)
+       {
+               GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+                       "%s: not a file\n", __FUNCTION__);
+               size = -ENOENT;
+               goto out;
+       }
+
+       /* We must be dirty */
+       if(SEMAPHORE_DOWN(de->de_file_sema, YES) == SYSERR)
+       {
+               size = -EIO;
+               goto out;
+       }
+       if(!de->de_dirty)
+       {
+               if(gn_dirent_download_locked(de) == -1)
+               {
+                       size = -EIO;
+                       goto out_unlock;
+               }
+       }
+
+       /* Perform write on temp file */
+       slen = pwrite(de->de_fd, buf, size, offset);
+       if(slen == -1)
+               size = -errno;
+       else
+               size = slen;
+out_unlock:
+       SEMAPHORE_UP(de->de_file_sema);
+out:
+       gn_dirent_put(de);
+       return size;
+}





reply via email to

[Prev in Thread] Current Thread [Next in Thread]