gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r5305 - gnunet-fuse


From: gnunet
Subject: [GNUnet-SVN] r5305 - gnunet-fuse
Date: Thu, 12 Jul 2007 21:05:51 -0600 (MDT)

Author: amatus
Date: 2007-07-12 21:05:50 -0600 (Thu, 12 Jul 2007)
New Revision: 5305

Added:
   gnunet-fuse/mkdir.c
   gnunet-fuse/rmdir.c
   gnunet-fuse/unlink.c
   gnunet-fuse/utimens.c
Modified:
   gnunet-fuse/ChangeLog
   gnunet-fuse/Makefile.am
   gnunet-fuse/directory.c
   gnunet-fuse/dirent.c
   gnunet-fuse/getattr.c
   gnunet-fuse/gnfs.h
   gnunet-fuse/main.c
   gnunet-fuse/mknod.c
   gnunet-fuse/read.c
Log:
Added support for unlinking files, creating directories, and removing 
directories

Modified: gnunet-fuse/ChangeLog
===================================================================
--- gnunet-fuse/ChangeLog       2007-07-12 11:48:20 UTC (rev 5304)
+++ gnunet-fuse/ChangeLog       2007-07-13 03:05:50 UTC (rev 5305)
@@ -1,3 +1,6 @@
+2007-07-12 David Barksdale <address@hidden> 0.7.2-3
+* Added support for unlinking files, creating directories, and removing
+directories
 2007-07-12 David Barksdale <address@hidden> 0.7.2-2
 * Added support for creating and modifying files
 2007-06-18 David Barksdale <address@hidden> 0.7.2-1

Modified: gnunet-fuse/Makefile.am
===================================================================
--- gnunet-fuse/Makefile.am     2007-07-12 11:48:20 UTC (rev 5304)
+++ gnunet-fuse/Makefile.am     2007-07-13 03:05:50 UTC (rev 5305)
@@ -4,12 +4,16 @@
        dirent.c \
        getattr.c \
        main.c \
+       mkdir.c \
        mknod.c \
        open.c \
        read.c \
        readdir.c \
        release.c \
+       rmdir.c \
        special_file.c \
+       unlink.c \
+       utimens.c \
        write.c \
        gnfs.h \
        gettext.h

Modified: gnunet-fuse/directory.c
===================================================================
--- gnunet-fuse/directory.c     2007-07-12 11:48:20 UTC (rev 5304)
+++ gnunet-fuse/directory.c     2007-07-13 03:05:50 UTC (rev 5305)
@@ -96,7 +96,7 @@
                /* NB: the lock on deparent is enough to guarantee that another
                 * thread hasn't added this dirent to the cache in the time
                 * between the above check and this insert */
-               gn_dirent_cache(de);
+               gn_dirent_cache_insert(de);
        }
 
        /* Add it to the directory's list (steals our ref)*/
@@ -245,13 +245,54 @@
        g_hash_table_replace(de->de_dir_hash, dechild->de_basename, dechild);
 
        /* Cache the dirent */
-       gn_dirent_cache(dechild);
+       gn_dirent_cache_insert(dechild);
 
        /* Mark our path dirty */
        gn_unlock_path(de, GN_UNLOCK_ALL_DIRTY);
        return 0;
 }
 
+int gn_directory_remove(struct dirent *de, struct dirent *dechild)
+{
+       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: for '%s'\n",
+               __FUNCTION__, dechild->de_path);
+
+       /* Lock our path */
+       if(gn_lock_path(de) == -1)
+               return -1;
+
+       /* Cache ourselfs (because we're going to become dirty) */
+       if(!de->de_cached)
+       {
+               if(directory_cache_locked(de) == -1)
+               {
+                       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR,
+                               "%s: failed to cache parent dir\n",
+                               __FUNCTION__);
+                       goto out_err;
+               }
+       }
+
+       /* Remove from dir_hash */
+       if(!g_hash_table_remove(de->de_dir_hash, dechild->de_basename))
+       {
+               GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_ERROR,
+                       "%s: not found in dir_hash\n",
+                       __FUNCTION__);
+               goto out_err;
+       }
+
+       /* Remove from dirent cache */
+       gn_dirent_cache_remove(dechild);
+
+       /* Mark our path dirty */
+       gn_unlock_path(de, GN_UNLOCK_ALL_DIRTY);
+       return 0;
+out_err:
+       gn_unlock_path(de, GN_UNLOCK_CLEAN);
+       return -1;
+}
+
 static void upcb(guint64 totalBytes, guint64 completedBytes, cron_t eta,
        void *closure)
 {

Modified: gnunet-fuse/dirent.c
===================================================================
--- gnunet-fuse/dirent.c        2007-07-12 11:48:20 UTC (rev 5304)
+++ gnunet-fuse/dirent.c        2007-07-13 03:05:50 UTC (rev 5305)
@@ -133,7 +133,8 @@
                }
                else
                {
-                       g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+                       de->de_dir_hash = g_hash_table_new_full(g_str_hash,
+                               g_str_equal, NULL,
                                (GDestroyNotify)gn_dirent_put);
                }
        }
@@ -147,7 +148,7 @@
 /*
  * Add a dirent to the cache
  */
-void gn_dirent_cache(struct dirent *de)
+void gn_dirent_cache_insert(struct dirent *de)
 {
        /* TODO: Here we need to see if the cache has gotten too big and empty
         * it.
@@ -161,6 +162,17 @@
 }
 
 /*
+ * Remove a dirent from the cache
+ */
+void gn_dirent_cache_remove(struct dirent *de)
+{
+       if(SEMAPHORE_DOWN(path_sema, YES) == SYSERR)
+               return;
+       g_hash_table_remove(path_hash, de->de_path);
+       SEMAPHORE_UP(path_sema);
+}
+
+/*
  * Call 'cb' for each element in 'path', treats the empty string as "/"
  */
 int gn_path_foreach(const gchar *path, gn_dir_foreach_callback cb, void *data)

Modified: gnunet-fuse/getattr.c
===================================================================
--- gnunet-fuse/getattr.c       2007-07-12 11:48:20 UTC (rev 5304)
+++ gnunet-fuse/getattr.c       2007-07-13 03:05:50 UTC (rev 5305)
@@ -27,7 +27,7 @@
 int gn_getattr(const char *path, struct stat *stbuf)
 {
        struct dirent *de;
-       guint64 size = 0;
+       int ret = 0;
 
        GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG, "%s: for '%s'\n",
                __FUNCTION__, path);
@@ -52,31 +52,35 @@
                return -ENOENT;
        }
 
-       memset(stbuf, 0, sizeof(*stbuf));
-       stbuf->st_mode = 0777;
-       stbuf->st_mode |= de->de_type == DE_DIR ? S_IFDIR : S_IFREG;
-       stbuf->st_nlink = 1;
+       /* If it's a cached file just call stat */
        if(SEMAPHORE_DOWN(de->de_sema, YES) == SYSERR)
+       {
+               gn_dirent_put(de);
                return -EIO;
-       if(de->de_cached)
+       }
+       if(de->de_cached && de->de_type == DE_FILE)
        {
-               if(de->de_type == DE_FILE && disk_file_size(ectx,
-                       de->de_filename, &size, NO) == SYSERR)
+               ret = stat(path, stbuf);
+               if(ret == -1)
                {
-                       GE_LOG(ectx, GE_BULK | GE_USER | GE_ERROR,
-                               "%s: disk_file_size failed for '%s'\n",
-                               __FUNCTION__, de->de_filename);
-                       SEMAPHORE_UP(de->de_sema);
-                       gn_dirent_put(de);
-                       return -EIO;
+                       ret = -errno;
+                       GE_LOG_STRERROR(ectx, GE_BULK | GE_USER | GE_ERROR,
+                               "stat");
+                       goto out;
                }
+               goto out;
        }
+
+       memset(stbuf, 0, sizeof(*stbuf));
+       stbuf->st_mode = 0777;
+       stbuf->st_mode |= de->de_type == DE_DIR ? S_IFDIR : S_IFREG;
+       stbuf->st_nlink = 1;
+       if(de->de_fi.uri != NULL)
+               stbuf->st_size = ECRS_fileSize(de->de_fi.uri);
        else
-       {
-               size = ECRS_fileSize(de->de_fi.uri);
-       }
+               stbuf->st_size = 0;
+out:
        SEMAPHORE_UP(de->de_sema);
        gn_dirent_put(de);
-       stbuf->st_size = size;
-       return 0;
+       return ret;
 }

Modified: gnunet-fuse/gnfs.h
===================================================================
--- gnunet-fuse/gnfs.h  2007-07-12 11:48:20 UTC (rev 5304)
+++ gnunet-fuse/gnfs.h  2007-07-13 03:05:50 UTC (rev 5305)
@@ -87,7 +87,8 @@
 void gn_dirent_ref(struct dirent *de);
 void gn_dirent_put(struct dirent *de);
 void gn_dirent_cache_init(void);
-void gn_dirent_cache(struct dirent *de);
+void gn_dirent_cache_insert(struct dirent *de);
+void gn_dirent_cache_remove(struct dirent *de);
 struct dirent *gn_dirent_find(const gchar *path);
 int gn_lock_path(struct dirent *de);
 int gn_unlock_path(struct dirent *de, int dirty);
@@ -101,6 +102,7 @@
         void *data);
 struct dirent *gn_directory_find(struct dirent *de, const gchar *filename);
 int gn_directory_insert(struct dirent *de, struct dirent *dechild);
+int gn_directory_remove(struct dirent *de, struct dirent *dechild);
 int gn_directory_upload_locked(struct dirent *de);
 
 /* FUSE function files */
@@ -108,6 +110,10 @@
 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_mkdir(const char *path, mode_t mode);
+int gn_unlink(const char *path);
+int gn_rmdir(const char *path);
+int gn_utimens(const char *path, const struct timespec ts[2]);
 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);

Modified: gnunet-fuse/main.c
===================================================================
--- gnunet-fuse/main.c  2007-07-12 11:48:20 UTC (rev 5304)
+++ gnunet-fuse/main.c  2007-07-13 03:05:50 UTC (rev 5305)
@@ -74,6 +74,10 @@
        .getattr = gn_getattr,
        .readdir = gn_readdir,
        .mknod = gn_mknod,
+       .mkdir = gn_mkdir,
+       .unlink = gn_unlink,
+       .rmdir = gn_rmdir,
+       .utimens = gn_utimens,
        .open = gn_open,
        .read = gn_read,
        .write = gn_write,

Added: gnunet-fuse/mkdir.c
===================================================================
--- gnunet-fuse/mkdir.c                         (rev 0)
+++ gnunet-fuse/mkdir.c 2007-07-13 03:05:50 UTC (rev 5305)
@@ -0,0 +1,71 @@
+/*
+ * mkdir.c - FUSE mkdir 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_mkdir(const char *path, mode_t mode)
+{
+       struct dirent *de, *newde;
+       struct ECRS_MetaData *meta;
+       char *parent, *file;
+       int ret;
+
+       (void)mode;
+       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))
+               return -EEXIST;
+
+       /* Check for existing file */
+       de = gn_dirent_find(path);
+       if(de != NULL)
+       {
+               gn_dirent_put(de);
+               return -EEXIST;
+       }
+
+       /* Create new directory */
+       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);
+       ECRS_addToMetaData(meta, EXTRACTOR_MIMETYPE, GNUNET_DIRECTORY_MIME);
+       newde = gn_dirent_new(path, NULL, meta, DE_DIR);
+       ECRS_freeMetaData(meta);
+       ret = gn_directory_insert(de, newde);
+       gn_dirent_put(de);
+       gn_dirent_put(newde);
+       FREE(parent);
+       if(ret == -1)
+               return -EIO;
+       return 0;
+}

Modified: gnunet-fuse/mknod.c
===================================================================
--- gnunet-fuse/mknod.c 2007-07-12 11:48:20 UTC (rev 5304)
+++ gnunet-fuse/mknod.c 2007-07-13 03:05:50 UTC (rev 5305)
@@ -64,13 +64,13 @@
        uri = ECRS_stringToUri(ectx, GN_EMPTY_FILE_URI);
        meta = ECRS_createMetaData();
        ECRS_addToMetaData(meta, EXTRACTOR_FILENAME, file);
+       FREE(parent);
        newde = gn_dirent_new(path, uri, meta, DE_FILE);
        ECRS_freeMetaData(meta);
        ECRS_freeUri(uri);
        ret = gn_directory_insert(de, newde);
        gn_dirent_put(de);
        gn_dirent_put(newde);
-       FREE(parent);
        if(ret == -1)
                return -EIO;
        return 0;

Modified: gnunet-fuse/read.c
===================================================================
--- gnunet-fuse/read.c  2007-07-12 11:48:20 UTC (rev 5304)
+++ gnunet-fuse/read.c  2007-07-13 03:05:50 UTC (rev 5305)
@@ -45,9 +45,18 @@
        (void)completedBytes;
        (void)eta;
 
-       GE_ASSERT(ectx, !(block_end < d->offset));
-       GE_ASSERT(ectx, !(lastBlockOffset > buf_end));
+       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+               "%s: lastBlockOffset %llu lastBlockSize %d\n", __FUNCTION__,
+               lastBlockOffset, lastBlockSize);
 
+       /* Check if this block is entirely before the buffer */
+       if(block_end < d->offset)
+               return;
+       
+       /* Check if this block is entirely after the buffer */
+       if(lastBlockOffset > buf_end)
+               return;
+
        /* Chop off residue at beginning of block */
        if(lastBlockOffset < d->offset)
        {
@@ -83,7 +92,8 @@
        (void)fi;
 
        GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
-               "%s: called for '%s' %d bytes\n", __FUNCTION__, path, size);
+               "%s: called for '%s' %u bytes %lld offset\n", __FUNCTION__,
+               path, size, offset);
 
        /* Check for special file */
        special = gn_get_special_file(path);
@@ -146,8 +156,14 @@
        d.buf = buf;
        d.size = size;
        d.offset = offset;
+       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+               "%s: calling ECRS_downloadPartialFile %u bytes %lld offset\n",
+               __FUNCTION__, size, offset);
        ret = ECRS_downloadPartialFile(ectx, cfg, de->de_fi.uri, "/dev/null",
                anonymity, offset, size, YES, dpcb, &d, tt, NULL);
+       GE_LOG(ectx, GE_BULK | GE_DEVELOPER | GE_DEBUG,
+               "%s: ECRS_downloadPartialFile returned %d\n",
+               __FUNCTION__, ret);
        if(ret != OK)
        {
                GE_LOG(ectx, GE_BULK | GE_USER | GE_ERROR,

Added: gnunet-fuse/rmdir.c
===================================================================
--- gnunet-fuse/rmdir.c                         (rev 0)
+++ gnunet-fuse/rmdir.c 2007-07-13 03:05:50 UTC (rev 5305)
@@ -0,0 +1,78 @@
+/*
+ * rmdir.c - FUSE rmdir 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"
+
+static gboolean rmdir_callback(struct dirent *de, void *data)
+{
+       int *empty = data;
+
+       (void)de;
+       *empty = 0;
+       return 1;
+}
+
+int gn_rmdir(const char *path)
+{
+       struct dirent *de, *dechild;
+       char *parent, *file;
+       int ret, empty = 1;
+
+       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))
+               return -ENOTDIR;
+
+       /* Check for existing file */
+       dechild = gn_dirent_find(path);
+       if(dechild == NULL)
+               return -ENOENT;
+
+       /* Can't rmdir a non-empty directory */
+       gn_directory_foreach(dechild, rmdir_callback, &empty);
+       if(!empty)
+       {
+               gn_dirent_put(dechild);
+               return -ENOTEMPTY;
+       }
+
+       /* Remove directory */
+       parent = gn_dirname(path, &file);
+       de = gn_dirent_find(parent);
+       FREE(parent);
+       if(de == NULL)
+       {
+               gn_dirent_put(dechild);
+               return -ENOENT;
+       }
+       ret = gn_directory_remove(de, dechild);
+       gn_dirent_put(dechild);
+       gn_dirent_put(de);
+       if(ret == -1)
+               return -EIO;
+       return 0;
+}

Added: gnunet-fuse/unlink.c
===================================================================
--- gnunet-fuse/unlink.c                                (rev 0)
+++ gnunet-fuse/unlink.c        2007-07-13 03:05:50 UTC (rev 5305)
@@ -0,0 +1,68 @@
+/*
+ * unlink.c - FUSE unlink 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_unlink(const char *path)
+{
+       struct dirent *de, *dechild;
+       char *parent, *file;
+       int ret;
+
+       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))
+               return -EPERM;
+
+       /* Check for existing file */
+       dechild = gn_dirent_find(path);
+       if(dechild == NULL)
+               return -ENOENT;
+       
+       /* Can't unlink a directory */
+       if(dechild->de_type != DE_FILE)
+       {
+               gn_dirent_put(dechild);
+               return -EPERM;
+       }
+
+       /* Remove file from parent dir */
+       parent = gn_dirname(path, &file);
+       de = gn_dirent_find(parent);
+       FREE(parent);
+       if(de == NULL)
+       {
+               gn_dirent_put(dechild);
+               return -ENOENT;
+       }
+       ret = gn_directory_remove(de, dechild);
+       gn_dirent_put(dechild);
+       gn_dirent_put(de);
+       if(ret == -1)
+               return -EIO;
+       return 0;
+}

Added: gnunet-fuse/utimens.c
===================================================================
--- gnunet-fuse/utimens.c                               (rev 0)
+++ gnunet-fuse/utimens.c       2007-07-13 03:05:50 UTC (rev 5305)
@@ -0,0 +1,72 @@
+/*
+ * utimens.c - FUSE utimens 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 _GNU_SOURCE
+#include <sys/time.h>
+#include <string.h>
+#include <errno.h>
+#include <fuse.h>
+#include "gnfs.h"
+
+int gn_utimens(const char *path, const struct timespec ts[2])
+{
+       struct dirent *de;
+       struct timeval tv[2];
+       int ret = 0;
+
+       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))
+               return -EACCES;
+
+       /* Get file or dir */
+       de = gn_dirent_find(path);
+       if(de == NULL)
+               return -ENOENT;
+
+       /* If it's a cached file just call utime */
+       if(SEMAPHORE_DOWN(de->de_sema, YES) == SYSERR)
+       {
+               gn_dirent_put(de);
+               return -EIO;
+       }
+       if(de->de_cached && de->de_type == DE_FILE)
+       {
+               TIMESPEC_TO_TIMEVAL(&tv[0], &ts[0]);
+               TIMESPEC_TO_TIMEVAL(&tv[1], &ts[1]);
+               ret = utimes(path, tv);
+               if(ret == -1)
+               {
+                       ret = -errno;
+                       GE_LOG_STRERROR(ectx, GE_BULK | GE_USER | GE_ERROR,
+                               "utimes");
+                       goto out;
+               }
+               goto out;
+       }
+
+       /* For now we do nothing otherwise */
+out:
+       SEMAPHORE_UP(de->de_sema);
+       gn_dirent_put(de);
+       return ret;
+}





reply via email to

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