diff options
Diffstat (limited to 'e2fsprogs/ext2fs/namei.c')
-rw-r--r-- | e2fsprogs/ext2fs/namei.c | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/e2fsprogs/ext2fs/namei.c b/e2fsprogs/ext2fs/namei.c new file mode 100644 index 000000000..13d13adfe --- /dev/null +++ b/e2fsprogs/ext2fs/namei.c | |||
@@ -0,0 +1,205 @@ | |||
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 | |||
23 | static 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 | |||
27 | static 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 | if (buffer) | ||
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 | */ | ||
75 | static 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 | |||
113 | static 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 | |||
150 | errcode_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 | |||
169 | errcode_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 | |||
188 | errcode_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 | |||