busybox/e2fsprogs/old_e2fsprogs/ext2fs/namei.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * namei.c --- ext2fs directory lookup operations
   4 *
   5 * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
   6 *
   7 * %Begin-Header%
   8 * This file may be redistributed under the terms of the GNU Public
   9 * License.
  10 * %End-Header%
  11 */
  12
  13#include <stdio.h>
  14#include <string.h>
  15#if HAVE_UNISTD_H
  16#include <unistd.h>
  17#endif
  18
  19/* #define NAMEI_DEBUG */
  20
  21#include "ext2_fs.h"
  22#include "ext2fs.h"
  23
  24static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
  25                            const char *pathname, size_t pathlen, int follow,
  26                            int link_count, char *buf, ext2_ino_t *res_inode);
  27
  28static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
  29                             ext2_ino_t inode, int link_count,
  30                             char *buf, ext2_ino_t *res_inode)
  31{
  32        char *pathname;
  33        char *buffer = 0;
  34        errcode_t retval;
  35        struct ext2_inode ei;
  36
  37#ifdef NAMEI_DEBUG
  38        printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n",
  39               root, dir, inode, link_count);
  40
  41#endif
  42        retval = ext2fs_read_inode (fs, inode, &ei);
  43        if (retval) return retval;
  44        if (!LINUX_S_ISLNK (ei.i_mode)) {
  45                *res_inode = inode;
  46                return 0;
  47        }
  48        if (link_count++ > 5) {
  49                return EXT2_ET_SYMLINK_LOOP;
  50        }
  51        if (ext2fs_inode_data_blocks(fs,&ei)) {
  52                retval = ext2fs_get_mem(fs->blocksize, &buffer);
  53                if (retval)
  54                        return retval;
  55                retval = io_channel_read_blk(fs->io, ei.i_block[0], 1, buffer);
  56                if (retval) {
  57                        ext2fs_free_mem(&buffer);
  58                        return retval;
  59                }
  60                pathname = buffer;
  61        } else
  62                pathname = (char *)&(ei.i_block[0]);
  63        retval = open_namei(fs, root, dir, pathname, ei.i_size, 1,
  64                            link_count, buf, res_inode);
  65        ext2fs_free_mem(&buffer);
  66        return retval;
  67}
  68
  69/*
  70 * This routine interprets a pathname in the context of the current
  71 * directory and the root directory, and returns the inode of the
  72 * containing directory, and a pointer to the filename of the file
  73 * (pointing into the pathname) and the length of the filename.
  74 */
  75static errcode_t dir_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
  76                           const char *pathname, int pathlen,
  77                           int link_count, char *buf,
  78                           const char **name, int *namelen,
  79                           ext2_ino_t *res_inode)
  80{
  81        char c;
  82        const char *thisname;
  83        int len;
  84        ext2_ino_t inode;
  85        errcode_t retval;
  86
  87        if ((c = *pathname) == '/') {
  88                dir = root;
  89                pathname++;
  90                pathlen--;
  91        }
  92        while (1) {
  93                thisname = pathname;
  94                for (len=0; --pathlen >= 0;len++) {
  95                        c = *(pathname++);
  96                        if (c == '/')
  97                                break;
  98                }
  99                if (pathlen < 0)
 100                        break;
 101                retval = ext2fs_lookup (fs, dir, thisname, len, buf, &inode);
 102                if (retval) return retval;
 103                retval = follow_link (fs, root, dir, inode,
 104                                      link_count, buf, &dir);
 105                if (retval) return retval;
 106        }
 107        *name = thisname;
 108        *namelen = len;
 109        *res_inode = dir;
 110        return 0;
 111}
 112
 113static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
 114                            const char *pathname, size_t pathlen, int follow,
 115                            int link_count, char *buf, ext2_ino_t *res_inode)
 116{
 117        const char *basename;
 118        int namelen;
 119        ext2_ino_t dir, inode;
 120        errcode_t retval;
 121
 122#ifdef NAMEI_DEBUG
 123        printf("open_namei: root=%lu, dir=%lu, path=%*s, lc=%d\n",
 124               root, base, pathlen, pathname, link_count);
 125#endif
 126        retval = dir_namei(fs, root, base, pathname, pathlen,
 127                           link_count, buf, &basename, &namelen, &dir);
 128        if (retval) return retval;
 129        if (!namelen) {                     /* special case: '/usr/' etc */
 130                *res_inode=dir;
 131                return 0;
 132        }
 133        retval = ext2fs_lookup (fs, dir, basename, namelen, buf, &inode);
 134        if (retval)
 135                return retval;
 136        if (follow) {
 137                retval = follow_link(fs, root, dir, inode, link_count,
 138                                     buf, &inode);
 139                if (retval)
 140                        return retval;
 141        }
 142#ifdef NAMEI_DEBUG
 143        printf("open_namei: (link_count=%d) returns %lu\n",
 144               link_count, inode);
 145#endif
 146        *res_inode = inode;
 147        return 0;
 148}
 149
 150errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
 151                       const char *name, ext2_ino_t *inode)
 152{
 153        char *buf;
 154        errcode_t retval;
 155
 156        EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 157
 158        retval = ext2fs_get_mem(fs->blocksize, &buf);
 159        if (retval)
 160                return retval;
 161
 162        retval = open_namei(fs, root, cwd, name, strlen(name), 0, 0,
 163                            buf, inode);
 164
 165        ext2fs_free_mem(&buf);
 166        return retval;
 167}
 168
 169errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
 170                              const char *name, ext2_ino_t *inode)
 171{
 172        char *buf;
 173        errcode_t retval;
 174
 175        EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 176
 177        retval = ext2fs_get_mem(fs->blocksize, &buf);
 178        if (retval)
 179                return retval;
 180
 181        retval = open_namei(fs, root, cwd, name, strlen(name), 1, 0,
 182                            buf, inode);
 183
 184        ext2fs_free_mem(&buf);
 185        return retval;
 186}
 187
 188errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
 189                        ext2_ino_t inode, ext2_ino_t *res_inode)
 190{
 191        char *buf;
 192        errcode_t retval;
 193
 194        EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 195
 196        retval = ext2fs_get_mem(fs->blocksize, &buf);
 197        if (retval)
 198                return retval;
 199
 200        retval = follow_link(fs, root, cwd, inode, 0, buf, res_inode);
 201
 202        ext2fs_free_mem(&buf);
 203        return retval;
 204}
 205
 206