/[hurdextras]/libfuse/netfs.c
ViewVC logotype

Diff of /libfuse/netfs.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.37 by stesie, Sun Dec 4 18:20:44 2005 UTC revision 1.38 by stesie, Fri Dec 9 14:58:30 2005 UTC
# Line 50  struct fuse_dirhandle { Line 50  struct fuse_dirhandle {
50    char *filename;    char *filename;
51  };  };
52    
 static int fuse_dirent_helper(fuse_dirh_t handle, const char *name,  
                               int type, ino_t ino);  
 static int fuse_dirent_helper_compat(fuse_dirh_t handle, const char *name,  
                                      int type);  
   
   
53  /* Check whether to allow access to a node, testing the allow_root and  /* Check whether to allow access to a node, testing the allow_root and
54   * allow_other flag.  This does not check whether default permissions   * allow_other flag.  This does not check whether default permissions
55   * are okay to allow access.   * are okay to allow access.
# Line 1147  error_t netfs_attempt_read (struct iouse Line 1141  error_t netfs_attempt_read (struct iouse
1141    ((DIRENT_NAME_OFFS + (name_len) + 1 + (DIRENT_ALIGN - 1))                   \    ((DIRENT_NAME_OFFS + (name_len) + 1 + (DIRENT_ALIGN - 1))                   \
1142     & ~(DIRENT_ALIGN - 1))     & ~(DIRENT_ALIGN - 1))
1143    
1144    /* fuse_get_inode
1145     *
1146     * look up the inode of the named file (full path) in fuse_use_ino mode,
1147     * where we don't have the inode number of parent directories in our structs
1148     */
1149    static ino_t
1150    fuse_get_inode(const char *name)
1151    {
1152      struct stat stat;
1153      
1154      assert(fuse_ops);
1155      assert(fuse_ops->getattr);
1156      
1157      fuse_ops->getattr(name, &stat);
1158      return stat.st_ino;
1159    }
1160    
1161  /* callback handler used by netfs_get_dirents to write our dirents  /* callback handler used by netfs_get_dirents to write our dirents
1162   * to the mmaped memory   * to the mmaped memory (getdir case)
  *  
  * version for new fuse api  
1163   */   */
1164  static int  static int
1165  fuse_dirent_helper(fuse_dirh_t handle, const char *name, int type, ino_t ino)  get_dirents_getdir_helper(fuse_dirh_t handle, const char *name,
1166                              int type, ino_t ino)
1167  {  {
1168    ino_t inode;    ino_t inode;
1169    
   /* if(! fuse_use_ino)  
    *   return fuse_dirent_helper_compat(handle, name, type);  
    */  
   
   /* fuse_get_inode  
    *  
    * look up the inode of the named file (full path) in fuse_use_ino mode,  
    * where we don't have the inode number of parent directories in our structs  
    */  
   ino_t fuse_get_inode(const char *name)  
     {  
       struct stat stat;  
   
       assert(fuse_ops);  
       assert(fuse_ops->getattr);  
   
       fuse_ops->getattr(name, &stat);  
       return stat.st_ino;  
     }  
   
1170    if(handle->first_entry)    if(handle->first_entry)
1171      {      {
1172        /* skip this entry, it's before the first one we got to write out ... */        /* skip this entry, it's before the first one we got to write out ... */
# Line 1240  fuse_dirent_helper(fuse_dirh_t handle, c Line 1229  fuse_dirent_helper(fuse_dirh_t handle, c
1229            strcpy(handle->filename, name);            strcpy(handle->filename, name);
1230            struct netnode *nn = fuse_make_netnode(handle->parent,            struct netnode *nn = fuse_make_netnode(handle->parent,
1231                                                   handle->abspath);                                                   handle->abspath);
1232    
1233              if(! nn)
1234                return ENOMEM;
1235    
1236            inode = nn->inode;            inode = nn->inode;
1237          }          }
1238      }      }
# Line 1261  fuse_dirent_helper(fuse_dirh_t handle, c Line 1254  fuse_dirent_helper(fuse_dirh_t handle, c
1254  }  }
1255    
1256    
   
1257  /* callback handler used by netfs_get_dirents to write our dirents  /* callback handler used by netfs_get_dirents to write our dirents
1258   * to the mmaped memory   * to the mmaped memory
1259   *   *
1260   * version for old api   * version for old api
1261   */   */
1262  static int  static int
1263  fuse_dirent_helper_compat(fuse_dirh_t handle, const char *name, int type)  get_dirents_getdir_helper_compat(fuse_dirh_t hdl, const char *name, int type)
1264  {  {
1265    return fuse_dirent_helper(handle, name, type, 0);    return get_dirents_getdir_helper(hdl, name, type, 0);
1266  }  }
1267    
1268    
1269  error_t  static error_t
1270  netfs_get_dirents (struct iouser *cred, struct node *dir,  get_dirents_getdir(struct node *dir, int first_entry, int num_entries,
1271                     int first_entry, int num_entries, char **data,                     char **data, mach_msg_type_number_t *data_len,
1272                     mach_msg_type_number_t *data_len,                     int *data_entries)
                    vm_size_t max_data_len, int *data_entries)  
1273  {  {
1274    (void) max_data_len; /* we live with the supplied mmap area in any case,    FUNC_PROLOGUE_NODE("get_dirents_getdir", dir);
1275                          * i.e. never allocate any further memory */  
1276      if(! FUSE_OP_HAVE(getdir))
1277        FUNC_RETURN(EOPNOTSUPP);
1278    
   FUNC_PROLOGUE_NODE("netfs_get_dirents", dir);  
   error_t err;  
1279    fuse_dirh_t handle;    fuse_dirh_t handle;
1280      if(! (handle = malloc(sizeof(struct fuse_dirhandle))))
1281        FUNC_RETURN(ENOMEM);
1282      
1283      handle->first_entry = first_entry;
1284      handle->num_entries = num_entries;
1285      handle->count = 0;
1286      handle->size = *data_len;
1287    
1288    if((err = netfs_validate_stat(dir, cred))    /* allocate handle->abspath */
1289       || (err = fshelp_access(&dir->nn_stat, S_IREAD, cred))    size_t path_len = strlen(dir->nn->path);
1290       || (err = fshelp_access(&dir->nn_stat, S_IEXEC, cred)))    if(! (handle->abspath = malloc((handle->maxlen = 256) + path_len + 2)))
1291      goto out;      {
1292          free(handle);
1293          FUNC_RETURN(ENOMEM);
1294        }
1295    
1296    if(! FUSE_OP_HAVE(getdir))    memcpy(handle->abspath, dir->nn->path, path_len);
1297      handle->filename = handle->abspath + path_len;
1298    
1299      /* add a delimiting slash if there are parent directories */
1300      if(dir->nn->parent)
1301        *(handle->filename ++) = '/';
1302    
1303      handle->parent = dir->nn;
1304      handle->hdrpos = (struct dirent*) *data;
1305    
1306      if(fuse_ops)
1307        fuse_ops->getdir(dir->nn->path, handle, get_dirents_getdir_helper);
1308      else
1309        fuse_ops_compat->getdir(dir->nn->path, handle,
1310                                get_dirents_getdir_helper_compat);
1311                                
1312    
1313      *data_len -= handle->size; /* subtract number of bytes left in the
1314                                  * buffer from the length of the buffer we
1315                                  * got. */
1316      *data_entries = handle->count;
1317    
1318      free(handle->abspath);
1319      free(handle);
1320    
1321      FUNC_EPILOGUE(0);
1322    }
1323    
1324    
1325    /* callback handler used by netfs_get_dirents to write our dirents
1326     * to the mmaped memory (in readdir case)
1327     *
1328     * be careful, according to fuse.h `stat' may be NULL!
1329     */
1330    static int
1331    get_dirents_readdir_helper(void *buf, const char *name,
1332                               const struct stat *stat, off_t off)
1333    {
1334      fuse_dirh_t handle = buf;
1335      ino_t inode;
1336    
1337      if(handle->first_entry && !off)
1338      {      {
1339        err = EOPNOTSUPP;        /* skip this entry, it's before the first one
1340        goto out;         * we got to write out ... */
1341          handle->first_entry --;
1342          return 0;
1343      }      }
1344    
1345    if(! (handle = malloc(sizeof(struct fuse_dirhandle))))    if(! (handle->num_entries --))
1346        return 1;
1347    
1348      size_t name_len = strlen(name);
1349      size_t dirent_len = DIRENT_LEN(name_len);
1350    
1351      if(dirent_len > handle->size)
1352      {      {
1353        err = ENOMEM; /* sorry, translator not available ... */        handle->num_entries = 0; /* don't write any further data, e.g. in case */
1354        goto out;        return ENOMEM;           /* next filename's shorter */
1355        }
1356      else
1357        handle->size -= dirent_len;
1358    
1359      /* look the inode of this element up ... */
1360      if(libfuse_params.use_ino)
1361        {
1362          /* using the inode based api */
1363          if(! strcmp(name, "."))
1364            inode = fuse_get_inode(handle->parent->path);
1365    
1366          else if(handle->parent->parent && ! strcmp(name, ".."))
1367            inode = fuse_get_inode(handle->parent->parent->path);
1368    
1369          if(! stat)
1370            {
1371              DEBUG("critical", "use_ino flag set, but stat ptr not available.\n");
1372              inode = 0;
1373            }
1374    
1375          else
1376            inode = stat->st_ino;
1377      }      }
1378      else
1379        {
1380          /* using the old (lookup) method ... */
1381    
1382          if(! strcmp(name, "."))
1383            inode = handle->parent->inode;
1384    
1385          else if(handle->parent->parent && ! strcmp(name, ".."))
1386            inode = handle->parent->parent->inode;
1387    
1388          else
1389            {
1390              if(name_len > handle->maxlen)
1391                {
1392                  /* allocated field in handle structure is to small, enlarge it */
1393                  handle->maxlen = name_len << 1;
1394                  void *a = realloc(handle->abspath, handle->maxlen +
1395                                    (handle->filename - handle->abspath) + 1);
1396                  if(! a)
1397                    return ENOMEM;
1398    
1399                  handle->filename = a + (handle->filename - handle->abspath);
1400                  handle->abspath = a;
1401                }
1402    
1403              strcpy(handle->filename, name);
1404              struct netnode *nn = fuse_make_netnode(handle->parent,
1405                                                     handle->abspath);
1406    
1407              if(! nn)
1408                return ENOMEM;
1409    
1410              inode = nn->inode;
1411            }
1412        }
1413    
1414      /* write out struct dirent ... */
1415      handle->hdrpos->d_fileno = inode;
1416      handle->hdrpos->d_reclen = dirent_len;
1417      handle->hdrpos->d_type = stat ? (stat->st_mode >> 12) : 0;
1418      handle->hdrpos->d_namlen = name_len;
1419    
1420      /* copy file's name ... */
1421      memcpy(((void *) handle->hdrpos) + DIRENT_NAME_OFFS, name, name_len + 1);
1422    
1423      /* update hdrpos pointer */
1424      handle->hdrpos = ((void *) handle->hdrpos) + dirent_len;
1425    
1426      handle->count ++;
1427      return 0;
1428    }
1429    
1430    
1431    static error_t
1432    get_dirents_readdir(struct node *dir, int first_entry, int num_entries,
1433                        char **data, mach_msg_type_number_t *data_len,
1434                        int *data_entries)
1435    {
1436      error_t err;
1437      FUNC_PROLOGUE_NODE("get_dirents_readdir", dir);
1438    
1439      if(! (fuse_ops
1440            && fuse_ops->readdir
1441            && fuse_ops->opendir
1442            && fuse_ops->releasedir))
1443        FUNC_RETURN(EOPNOTSUPP);
1444    
1445      fuse_dirh_t handle;
1446      if(! (handle = malloc(sizeof(struct fuse_dirhandle))))
1447        FUNC_RETURN(ENOMEM);
1448      
1449    handle->first_entry = first_entry;    handle->first_entry = first_entry;
1450    handle->num_entries = num_entries;    handle->num_entries = num_entries;
1451    handle->count = 0;    handle->count = 0;
# Line 1313  netfs_get_dirents (struct iouser *cred, Line 1455  netfs_get_dirents (struct iouser *cred,
1455    size_t path_len = strlen(dir->nn->path);    size_t path_len = strlen(dir->nn->path);
1456    if(! (handle->abspath = malloc((handle->maxlen = 256) + path_len + 2)))    if(! (handle->abspath = malloc((handle->maxlen = 256) + path_len + 2)))
1457      {      {
       free(handle);  
1458        err = ENOMEM;        err = ENOMEM;
1459        goto out;        goto out;
1460      }      }
# Line 1328  netfs_get_dirents (struct iouser *cred, Line 1469  netfs_get_dirents (struct iouser *cred,
1469    handle->parent = dir->nn;    handle->parent = dir->nn;
1470    handle->hdrpos = (struct dirent*) *data;    handle->hdrpos = (struct dirent*) *data;
1471    
1472    if(fuse_ops)    if((err = fuse_ops->opendir(dir->nn->path, &dir->nn->info)))
1473      fuse_ops->getdir(dir->nn->path, handle, fuse_dirent_helper);      goto out;
1474    else  
1475      fuse_ops_compat->getdir(dir->nn->path, handle, fuse_dirent_helper_compat);    if((err = fuse_ops->readdir(dir->nn->path, handle,
1476                                                              get_dirents_readdir_helper, first_entry,
1477                                  &dir->nn->info)))
1478        {
1479          fuse_ops->releasedir(dir->nn->path, &dir->nn->info);
1480          goto out;
1481        }
1482    
1483      if((err = fuse_ops->releasedir(dir->nn->path, &dir->nn->info)))
1484        goto out;
1485    
1486    *data_len -= handle->size; /* subtract number of bytes left in the    *data_len -= handle->size; /* subtract number of bytes left in the
1487                                * buffer from the length of the buffer we                                * buffer from the length of the buffer we
1488                                * got. */                                * got. */
1489    *data_entries = handle->count;    *data_entries = handle->count;
1490    
1491    /* TODO: fshelp_touch ATIME here */   out:
1492    free(handle->abspath);    free(handle->abspath);
1493    free(handle);    free(handle);
1494    
1495      FUNC_EPILOGUE(err);
1496    }
1497    
1498    error_t
1499    netfs_get_dirents (struct iouser *cred, struct node *dir,
1500                       int first_entry, int num_entries, char **data,
1501                       mach_msg_type_number_t *data_len,
1502                       vm_size_t max_data_len, int *data_entries)
1503    {
1504      (void) max_data_len; /* we live with the supplied mmap area in any case,
1505                            * i.e. never allocate any further memory */
1506    
1507      FUNC_PROLOGUE_NODE("netfs_get_dirents", dir);
1508      error_t err;
1509    
1510      if((err = netfs_validate_stat(dir, cred))
1511         || (err = fshelp_access(&dir->nn_stat, S_IREAD, cred))
1512         || (err = fshelp_access(&dir->nn_stat, S_IEXEC, cred)))
1513        goto out;
1514    
1515    
1516      if(fuse_ops && fuse_ops->readdir)
1517        err = get_dirents_readdir(dir, first_entry, num_entries, data, data_len,
1518                                  data_entries);
1519    
1520      else if(FUSE_OP_HAVE(getdir))
1521        err = get_dirents_getdir(dir, first_entry, num_entries, data, data_len,
1522                                 data_entries);
1523    
1524      else
1525        err = EOPNOTSUPP;
1526    
1527      /* TODO: fshelp_touch ATIME here */
1528    
1529   out:   out:
1530    FUNC_EPILOGUE_FMT(err, "%d entries.", *data_entries);    FUNC_EPILOGUE_FMT(err, "%d entries.", *data_entries);
1531  }  }

Legend:
Removed from v.1.37  
changed lines
  Added in v.1.38

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26