home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1998 February / PCOnline_02_1998.iso / filesbbs / win95 / ext2tool.exe / EXT2FS / NAMEI.C < prev    next >
C/C++ Source or Header  |  1995-05-10  |  4KB  |  215 lines

  1. /*
  2.  * namei.c --- ext2fs directory lookup operations
  3.  * 
  4.  * Copyright (C) 1993, 1994 Theodore Ts'o.  This file may be
  5.  * redistributed under the terms of the GNU Public License.
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <unistd.h>
  11. #include <stdlib.h>
  12. #include <errno.h>
  13.  
  14. #include <linux/ext2_fs.h>
  15.  
  16. #include "ext2fs.h"
  17.  
  18. struct dir_context {
  19.     ino_t        dir;
  20.     int        flags;
  21.     char        *buf;
  22.     int (*func)(struct ext2_dir_entry *dirent,
  23.             int    offset,
  24.             int    blocksize,
  25.             char    *buf,
  26.             void    *private);
  27.     void        *private;
  28.     errcode_t    errcode;
  29. };
  30.  
  31. static int process_dir_block(ext2_filsys fs,
  32.                  blk_t    *blocknr,
  33.                  int    blockcnt,
  34.                  void    *private);
  35.  
  36. errcode_t ext2fs_dir_iterate(ext2_filsys fs,
  37.                  ino_t dir,
  38.                  int flags,
  39.                  char *block_buf,
  40.                  int (*func)(struct ext2_dir_entry *dirent,
  41.                      int    offset,
  42.                      int    blocksize,
  43.                      char    *buf,
  44.                      void    *private),
  45.                  void *private)
  46. {
  47.     struct        dir_context    ctx;
  48.     errcode_t    retval;
  49.     
  50.     EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  51.  
  52.     retval = ext2fs_check_directory(fs, dir);
  53.     if (retval)
  54.         return retval;
  55.     
  56.     ctx.dir = dir;
  57.     ctx.flags = flags;
  58.     if (block_buf)
  59.         ctx.buf = block_buf;
  60.     else {
  61.         ctx.buf = malloc(fs->blocksize);
  62.         if (!ctx.buf)
  63.             return ENOMEM;
  64.     }
  65.     ctx.func = func;
  66.     ctx.private = private;
  67.     ctx.errcode = 0;
  68.     retval = ext2fs_block_iterate(fs, dir, 0, 0, process_dir_block, &ctx);
  69.     if (!block_buf)
  70.         free(ctx.buf);
  71.     if (retval)
  72.         return retval;
  73.     return ctx.errcode;
  74. }
  75.  
  76. static int process_dir_block(ext2_filsys  fs,
  77.                  blk_t    *blocknr,
  78.                  int    blockcnt,
  79.                  void    *private)
  80. {
  81.     struct dir_context *ctx = (struct dir_context *) private;
  82.     int        offset = 0;
  83.     int        ret;
  84.     int        changed = 0;
  85.     int        do_abort = 0;
  86.     struct ext2_dir_entry *dirent;
  87.  
  88.     if (blockcnt < 0)
  89.         return 0;
  90.  
  91.     ctx->errcode = io_channel_read_blk(fs->io, *blocknr, 1, ctx->buf);
  92.     if (ctx->errcode)
  93.         return BLOCK_ABORT;
  94.     
  95.     while (offset < fs->blocksize) {
  96.         dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
  97.         if (!dirent->inode &&
  98.             !(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
  99.             goto next;
  100.  
  101.         ret = (ctx->func)(dirent, offset, fs->blocksize,
  102.                   ctx->buf, ctx->private);
  103.         if (ret & DIRENT_CHANGED)
  104.             changed++;
  105.         if (ret & DIRENT_ABORT) {
  106.             do_abort++;
  107.             break;
  108.         }
  109. next:        
  110.         if (((offset + dirent->rec_len) > fs->blocksize) ||
  111.             (dirent->rec_len < 8) ||
  112.             ((dirent->name_len+8) > dirent->rec_len)) {
  113.             ctx->errcode = EXT2_ET_DIR_CORRUPTED;
  114.             return BLOCK_ABORT;
  115.         }
  116.         offset += dirent->rec_len;
  117.     }
  118.  
  119.     if (changed) {
  120.         ctx->errcode = io_channel_write_blk(fs->io, *blocknr, 1,
  121.                             ctx->buf);
  122.         if (ctx->errcode)
  123.             return BLOCK_ABORT;
  124.     }
  125.     if (do_abort)
  126.         return BLOCK_ABORT;
  127.     return 0;
  128. }
  129.  
  130. struct lookup_struct  {
  131.     const char    *name;
  132.     int        len;
  133.     ino_t        *inode;
  134.     int        found;
  135. };    
  136.  
  137. static int lookup_proc(struct ext2_dir_entry *dirent,
  138.                int    offset,
  139.                int    blocksize,
  140.                char    *buf,
  141.                void    *private)
  142. {
  143.     struct lookup_struct *ls = (struct lookup_struct *) private;
  144.  
  145.     if (ls->len != dirent->name_len)
  146.         return 0;
  147.     if (strncmp(ls->name, dirent->name, dirent->name_len))
  148.         return 0;
  149.     *ls->inode = dirent->inode;
  150.     ls->found++;
  151.     return DIRENT_ABORT;
  152. }
  153.  
  154.  
  155. errcode_t ext2fs_lookup(ext2_filsys fs, ino_t dir, const char *name,
  156.             int namelen, char *buf, ino_t *inode)
  157. {
  158.     errcode_t    retval;
  159.     struct lookup_struct ls;
  160.  
  161.     EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  162.  
  163.     ls.name = name;
  164.     ls.len = namelen;
  165.     ls.inode = inode;
  166.     ls.found = 0;
  167.  
  168.     retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls);
  169.     if (retval)
  170.         return retval;
  171.  
  172.     return (ls.found) ? 0 : ENOENT;
  173. }
  174.  
  175. errcode_t ext2fs_namei(ext2_filsys fs, ino_t root, ino_t cwd, const char *name,
  176.                ino_t *inode)
  177. {
  178.     ino_t        dir = cwd;
  179.     char        *buf;
  180.     const char    *p = name, *q;
  181.     int        len;
  182.     errcode_t    retval;
  183.  
  184.     EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
  185.  
  186.     buf = malloc(fs->blocksize);
  187.     if (!buf)
  188.         return ENOMEM;
  189.     if (*p == '/') {
  190.         p++;
  191.         dir = root;
  192.     }
  193.     while (*p) {
  194.         q = strchr(p, '/');
  195.         if (q)
  196.             len = q - p;
  197.         else
  198.             len = strlen(p);
  199.         if (len) {
  200.             retval = ext2fs_lookup(fs, dir, p, len, buf, &dir);
  201.             if (retval) {
  202.                 free(buf);
  203.                 return retval;
  204.             }
  205.         }
  206.         if (q)
  207.             p = q+1;
  208.         else
  209.             break;
  210.     }
  211.     *inode = dir;
  212.     free(buf);
  213.     return 0;
  214. }
  215.