source: branches/stable/mindi-busybox/e2fsprogs/ext2fs/namei.c @ 821

Last change on this file since 821 was 821, checked in by Bruno Cornec, 14 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

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