Rev 2404 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2404 | Rev 2435 | ||
---|---|---|---|
1 | /* This file contains the procedures that look up path names in the directory |
- | |
2 | * system and determine the inode number that goes with a given path name. |
- | |
3 | */ |
- | |
4 | /* |
1 | /* |
5 | * Copyright (c) 1987,1997, Prentice Hall |
2 | * Copyright (c) 1987,1997, Prentice Hall |
6 | * All rights reserved. |
3 | * All rights reserved. |
7 | * |
4 | * |
8 | * Redistribution and use of the MINIX operating system in source and |
5 | * Redistribution and use of the MINIX operating system in source and |
9 | * binary forms, with or without modification, are permitted provided |
6 | * binary forms, with or without modification, are permitted provided |
10 | * that the following conditions are met: |
7 | * that the following conditions are met: |
11 | 8 | ||
12 | * - Redistributions of source code must retain the above copyright |
9 | * - Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. |
10 | * notice, this list of conditions and the following disclaimer. |
14 | 11 | ||
15 | * - Redistributions in binary form must reproduce the above |
12 | * - Redistributions in binary form must reproduce the above |
16 | * copyright notice, this list of conditions and the following |
13 | * copyright notice, this list of conditions and the following |
17 | * disclaimer in the documentation and/or other materials provided |
14 | * disclaimer in the documentation and/or other materials provided |
18 | * with the distribution. |
15 | * with the distribution. |
19 | 16 | ||
20 | * - Neither the name of Prentice Hall nor the names of the software |
17 | * - Neither the name of Prentice Hall nor the names of the software |
21 | * authors or contributors may be used to endorse or promote |
18 | * authors or contributors may be used to endorse or promote |
22 | * products derived from this software without specific prior |
19 | * products derived from this software without specific prior |
23 | * written permission. |
20 | * written permission. |
24 | 21 | ||
25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND |
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND |
26 | * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, |
23 | * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, |
27 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
24 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
28 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
25 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
29 | * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE |
26 | * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE |
30 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
33 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
30 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
34 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
31 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
35 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
32 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
36 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
33 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
37 | */ |
34 | */ |
38 | 35 | ||
- | 36 | /** @addtogroup FileSystemImpl |
|
- | 37 | * @{ |
|
- | 38 | */ |
|
39 | 39 | ||
- | 40 | /** |
|
40 | /* Methods: |
41 | * @file path.c |
41 | * eat_path: the 'main' routine of the path-to-inode conversion mechanism |
42 | * @brief This file contains the procedures that look up path names in the directory |
42 | * last_dir: find the final directory on a given path |
43 | * system and determine the inode number that goes with a given path name. |
43 | * advance: parse one component of a path name |
- | |
44 | * search_dir: search a directory for a string and return its inode number |
- | |
45 | * search_dir_ex: used for extended versions |
- | |
46 | */ |
44 | */ |
47 | 45 | ||
48 | 46 | ||
49 | #include <string.h> |
47 | #include <string.h> |
50 | #include "fs.h" |
48 | #include "fs.h" |
51 | #include "block.h" |
49 | #include "block.h" |
52 | #include "file.h" |
50 | #include "file.h" |
53 | #include "fproc.h" |
51 | #include "fproc.h" |
54 | #include "inode.h" |
52 | #include "inode.h" |
55 | #include "super.h" |
53 | #include "super.h" |
56 | 54 | ||
57 | 55 | ||
58 | static char *get_name(char *old_name, char *string, int string_length); |
56 | static char *get_name(char *old_name, char *string, int string_length); |
59 | 57 | ||
- | 58 | /** |
|
- | 59 | * The 'main' routine of the path-to-inode conversion mechanism |
|
- | 60 | */ |
|
60 | inode_t *eat_path(char *path) |
61 | inode_t *eat_path(char *path) |
61 | { |
62 | { |
62 | 63 | ||
63 | /* Parse the path 'path' and put its inode in the inode table. If not possible, |
64 | /* Parse the path 'path' and put its inode in the inode table. If not possible, |
64 | * return NIL_INODE as function value and an error code in 'err_code'. |
65 | * return NIL_INODE as function value and an error code in 'err_code'. |
65 | */ |
66 | */ |
66 | 67 | ||
67 | register inode_t *ldip, *rip; |
68 | register inode_t *ldip, *rip; |
68 | super_block_t *sp; |
69 | super_block_t *sp; |
69 | int name_len; |
70 | int name_len; |
70 | char string[name_len]; /* hold 1 path component name here */ |
71 | char string[name_len]; /* hold 1 path component name here */ |
71 | 72 | ||
72 | name_len = NAME_MAX; |
73 | name_len = NAME_MAX; |
73 | if ((sp = get_super()) == NIL_SUPER) |
74 | if ((sp = get_super()) == NIL_SUPER) |
74 | return NIL_INODE; |
75 | return NIL_INODE; |
75 | 76 | ||
76 | if (sp->s_extend) { |
77 | if (sp->s_extend) { |
77 | name_len = NAME_MAX_EX; |
78 | name_len = NAME_MAX_EX; |
78 | } |
79 | } |
79 | 80 | ||
80 | /* First open the path down to the final directory. */ |
81 | /* First open the path down to the final directory. */ |
81 | if ( (ldip = last_dir(path, string, name_len)) == NIL_INODE) |
82 | if ( (ldip = last_dir(path, string, name_len)) == NIL_INODE) |
82 | return NIL_INODE; /* we couldn't open final directory */ |
83 | return NIL_INODE; /* we couldn't open final directory */ |
83 | 84 | ||
84 | 85 | ||
85 | /* The path consisting only of "/" is a special case, check for it. */ |
86 | /* The path consisting only of "/" is a special case, check for it. */ |
86 | if (string[0] == '\0') |
87 | if (string[0] == '\0') |
87 | return ldip; |
88 | return ldip; |
88 | 89 | ||
89 | /* Get final component of the path. */ |
90 | /* Get final component of the path. */ |
90 | rip = advance(ldip, string, name_len); |
91 | rip = advance(ldip, string, name_len); |
91 | put_inode(ldip); |
92 | put_inode(ldip); |
92 | 93 | ||
93 | return rip; |
94 | return rip; |
94 | } |
95 | } |
95 | 96 | ||
- | 97 | /** |
|
- | 98 | * Find the final directory on a given path |
|
- | 99 | */ |
|
96 | inode_t *last_dir(char *path, char *string, int string_length) |
100 | inode_t *last_dir(char *path, char *string, int string_length) |
97 | { |
101 | { |
98 | 102 | ||
99 | /* Given a path, 'path', located in the fs address space, parse it as |
103 | /* Given a path, 'path', located in the fs address space, parse it as |
100 | * far as the last directory, fetch the inode for the last directory into |
104 | * far as the last directory, fetch the inode for the last directory into |
101 | * the inode table, and return a pointer to the inode. In |
105 | * the inode table, and return a pointer to the inode. In |
102 | * addition, return the final component of the path in 'string'. |
106 | * addition, return the final component of the path in 'string'. |
103 | * If the last directory can't be opened, return NIL_INODE and |
107 | * If the last directory can't be opened, return NIL_INODE and |
104 | * the reason for failure in 'err_code'. |
108 | * the reason for failure in 'err_code'. |
105 | */ |
109 | */ |
106 | 110 | ||
107 | register inode_t *rip; |
111 | register inode_t *rip; |
108 | register char *new_name; |
112 | register char *new_name; |
109 | register inode_t *new_ip; |
113 | register inode_t *new_ip; |
110 | 114 | ||
111 | /* Is the path absolute or relative? Initialize 'rip' accordingly. */ |
115 | /* Is the path absolute or relative? Initialize 'rip' accordingly. */ |
112 | rip = (*path == '/' ? fp->fp_rootdir : fp->fp_workdir); |
116 | rip = (*path == '/' ? fp->fp_rootdir : fp->fp_workdir); |
113 | 117 | ||
114 | /* If dir has been removed or path is empty, return FS_ENOENT. */ |
118 | /* If dir has been removed or path is empty, return FS_ENOENT. */ |
115 | if (rip->i_nlinks == 0 || *path == '\0') { |
119 | if (rip->i_nlinks == 0 || *path == '\0') { |
116 | err_code = FS_ENOENT; |
120 | err_code = FS_ENOENT; |
117 | return NIL_INODE; |
121 | return NIL_INODE; |
118 | } |
122 | } |
119 | 123 | ||
120 | dup_inode(rip); /* inode will be returned with put_inode */ |
124 | dup_inode(rip); /* inode will be returned with put_inode */ |
121 | 125 | ||
122 | /* Scan the path component by component. */ |
126 | /* Scan the path component by component. */ |
123 | while (TRUE) { |
127 | while (TRUE) { |
124 | /* Extract one component. */ |
128 | /* Extract one component. */ |
125 | if ( (new_name = get_name(path, string, string_length)) == (char*) 0) { |
129 | if ( (new_name = get_name(path, string, string_length)) == (char*) 0) { |
126 | put_inode(rip); /* bad path in user space */ |
130 | put_inode(rip); /* bad path in user space */ |
127 | 131 | ||
128 | return NIL_INODE; |
132 | return NIL_INODE; |
129 | } |
133 | } |
130 | if (*new_name == '\0') |
134 | if (*new_name == '\0') |
131 | { |
135 | { |
132 | if ( (rip->i_mode & I_TYPE) == I_DIRECTORY) |
136 | if ( (rip->i_mode & I_TYPE) == I_DIRECTORY) |
133 | return rip; /* normal exit */ |
137 | return rip; /* normal exit */ |
134 | else { |
138 | else { |
135 | /* last file of path prefix is not a directory */ |
139 | /* last file of path prefix is not a directory */ |
136 | put_inode(rip); |
140 | put_inode(rip); |
137 | err_code = FS_ENOTDIR; |
141 | err_code = FS_ENOTDIR; |
138 | return NIL_INODE; |
142 | return NIL_INODE; |
139 | } |
143 | } |
140 | } |
144 | } |
141 | /* There is more path. Keep parsing. */ |
145 | /* There is more path. Keep parsing. */ |
142 | new_ip = advance(rip, string, string_length); |
146 | new_ip = advance(rip, string, string_length); |
143 | put_inode(rip); |
147 | put_inode(rip); |
144 | 148 | ||
145 | if (new_ip == NIL_INODE) { |
149 | if (new_ip == NIL_INODE) { |
146 | return NIL_INODE; |
150 | return NIL_INODE; |
147 | } |
151 | } |
148 | /* The call to advance() succeeded. Fetch next component. */ |
152 | /* The call to advance() succeeded. Fetch next component. */ |
149 | path = new_name; |
153 | path = new_name; |
150 | rip = new_ip; |
154 | rip = new_ip; |
151 | } |
155 | } |
152 | } |
156 | } |
153 | 157 | ||
- | 158 | /** |
|
- | 159 | * Parse one component of a path name |
|
- | 160 | */ |
|
154 | char *get_name(char *old_name, char *string, int string_length) |
161 | char *get_name(char *old_name, char *string, int string_length) |
155 | { |
162 | { |
156 | 163 | ||
157 | /* Given a pointer to a path name in fs space, 'old_name', copy the next |
164 | /* Given a pointer to a path name in fs space, 'old_name', copy the next |
158 | * component to 'string' and pad with zeros. A pointer to that part of |
165 | * component to 'string' and pad with zeros. A pointer to that part of |
159 | * the name as yet unparsed is returned. Roughly speaking, |
166 | * the name as yet unparsed is returned. Roughly speaking, |
160 | * 'get_name' = 'old_name' - 'string'. |
167 | * 'get_name' = 'old_name' - 'string'. |
161 | * |
168 | * |
162 | * This routine follows the standard convention that /usr/ast, /usr//ast, |
169 | * This routine follows the standard convention that /usr/ast, /usr//ast, |
163 | * //usr///ast and /usr/ast/ are all equivalent. |
170 | * //usr///ast and /usr/ast/ are all equivalent. |
164 | */ |
171 | */ |
165 | 172 | ||
166 | register int c; |
173 | register int c; |
167 | register char *np, *rnp; |
174 | register char *np, *rnp; |
168 | 175 | ||
169 | np = string; /* 'np' points to current position */ |
176 | np = string; /* 'np' points to current position */ |
170 | rnp = old_name; /* 'rnp' points to unparsed string */ |
177 | rnp = old_name; /* 'rnp' points to unparsed string */ |
171 | while ((c = *rnp) == '/') |
178 | while ((c = *rnp) == '/') |
172 | rnp++; /* skip leading slashes */ |
179 | rnp++; /* skip leading slashes */ |
173 | 180 | ||
174 | /* Copy the unparsed path, 'old_name', to the array, 'string'. */ |
181 | /* Copy the unparsed path, 'old_name', to the array, 'string'. */ |
175 | while ( rnp < &old_name[PATH_MAX] && c != '/' && c != '\0') { |
182 | while ( rnp < &old_name[PATH_MAX] && c != '/' && c != '\0') { |
176 | if (np < &string[string_length]) |
183 | if (np < &string[string_length]) |
177 | *np++ = c; |
184 | *np++ = c; |
178 | 185 | ||
179 | c = *++rnp; /* advance to next character */ |
186 | c = *++rnp; /* advance to next character */ |
180 | } |
187 | } |
181 | 188 | ||
182 | /* To make /usr/ast/ equivalent to /usr/ast, skip trailing slashes. */ |
189 | /* To make /usr/ast/ equivalent to /usr/ast, skip trailing slashes. */ |
183 | while (c == '/' && rnp < &old_name[PATH_MAX]) |
190 | while (c == '/' && rnp < &old_name[PATH_MAX]) |
184 | c = *++rnp; |
191 | c = *++rnp; |
185 | 192 | ||
186 | /* Padding with zeroes */ |
193 | /* Padding with zeroes */ |
187 | if (np < &string[string_length]) |
194 | if (np < &string[string_length]) |
188 | *np = '\0'; /* Terminate string */ |
195 | *np = '\0'; /* Terminate string */ |
189 | 196 | ||
190 | if (rnp >= &old_name[PATH_MAX]) { |
197 | if (rnp >= &old_name[PATH_MAX]) { |
191 | err_code = FS_ENAMETOOLONG; |
198 | err_code = FS_ENAMETOOLONG; |
192 | return((char *) 0); |
199 | return((char *) 0); |
193 | } |
200 | } |
194 | 201 | ||
195 | return rnp; |
202 | return rnp; |
196 | } |
203 | } |
197 | 204 | ||
- | 205 | /** |
|
- | 206 | * |
|
- | 207 | */ |
|
198 | inode_t *advance(inode_t *dirp, char *string, int string_length) |
208 | inode_t *advance(inode_t *dirp, char *string, int string_length) |
199 | { |
209 | { |
200 | 210 | ||
201 | /* Given a directory and a component of a path, look up the component in |
211 | /* Given a directory and a component of a path, look up the component in |
202 | * the directory, find the inode, open it, and return a pointer to its inode |
212 | * the directory, find the inode, open it, and return a pointer to its inode |
203 | * slot. If it can't be done, return NIL_INODE. |
213 | * slot. If it can't be done, return NIL_INODE. |
204 | */ |
214 | */ |
205 | 215 | ||
206 | register inode_t *rip; |
216 | register inode_t *rip; |
207 | int r; |
217 | int r; |
208 | ino_t numb; |
218 | ino_t numb; |
209 | 219 | ||
210 | /* If 'string' is empty, yield same inode straight away. */ |
220 | /* If 'string' is empty, yield same inode straight away. */ |
211 | if (string[0] == '\0') |
221 | if (string[0] == '\0') |
212 | return get_inode((int) dirp->i_num); |
222 | return get_inode((int) dirp->i_num); |
213 | 223 | ||
214 | /* Check for NIL_INODE. */ |
224 | /* Check for NIL_INODE. */ |
215 | if (dirp == NIL_INODE) |
225 | if (dirp == NIL_INODE) |
216 | return NIL_INODE; |
226 | return NIL_INODE; |
217 | 227 | ||
218 | /* If 'string' is not present in the directory, signal error. */ |
228 | /* If 'string' is not present in the directory, signal error. */ |
219 | if (dirp->i_sp->s_extend) { |
229 | if (dirp->i_sp->s_extend) { |
220 | r = search_dir_ex(dirp, string, &numb, LOOK_UP); |
230 | r = search_dir_ex(dirp, string, &numb, LOOK_UP); |
221 | } |
231 | } |
222 | else { |
232 | else { |
223 | r = search_dir(dirp, string, &numb, LOOK_UP); |
233 | r = search_dir(dirp, string, &numb, LOOK_UP); |
224 | } |
234 | } |
225 | if (r != OK) { |
235 | if (r != OK) { |
226 | err_code = r; |
236 | err_code = r; |
227 | return NIL_INODE; |
237 | return NIL_INODE; |
228 | } |
238 | } |
229 | 239 | ||
230 | /* Don't go beyond the current root directory */ |
240 | /* Don't go beyond the current root directory */ |
231 | if (dirp == fp->fp_rootdir && strcmp(string, "..") == 0) |
241 | if (dirp == fp->fp_rootdir && strcmp(string, "..") == 0) |
232 | return(get_inode((int) dirp->i_num)); |
242 | return(get_inode((int) dirp->i_num)); |
233 | 243 | ||
234 | /* The component has been found in the directory. Get inode. */ |
244 | /* The component has been found in the directory. Get inode. */ |
235 | if ( (rip = get_inode((int) numb)) == NIL_INODE) |
245 | if ( (rip = get_inode((int) numb)) == NIL_INODE) |
236 | return NIL_INODE; |
246 | return NIL_INODE; |
237 | 247 | ||
238 | return rip; /* return pointer to inode's component */ |
248 | return rip; /* return pointer to inode's component */ |
239 | } |
249 | } |
240 | 250 | ||
- | 251 | /** |
|
- | 252 | * Search a directory for a string and return its inode number |
|
- | 253 | */ |
|
241 | int search_dir(register inode_t *ldir_ptr, char string[NAME_MAX], ino_t *numb, int flag) |
254 | int search_dir(register inode_t *ldir_ptr, char string[NAME_MAX], ino_t *numb, int flag) |
242 | { |
255 | { |
243 | 256 | ||
244 | /* This function searches the directory whose inode is pointed to by 'ldip': |
257 | /* This function searches the directory whose inode is pointed to by 'ldip': |
245 | * if (flag == LOOK_UP) search for 'string' and return inode # in 'numb'; |
258 | * if (flag == LOOK_UP) search for 'string' and return inode # in 'numb'; |
246 | * if (flag == IS_EMPTY) return OK if only . and .. in dir else ENOTEMPTY; |
259 | * if (flag == IS_EMPTY) return OK if only . and .. in dir else ENOTEMPTY; |
247 | */ |
260 | */ |
248 | 261 | ||
249 | register direct_t *dp; |
262 | register direct_t *dp; |
250 | register block_t *bp; |
263 | register block_t *bp; |
251 | int r, match; |
264 | int r, match; |
252 | offset_t pos; |
265 | offset_t pos; |
253 | unsigned old_slots; |
266 | unsigned old_slots; |
254 | block_num_t b; |
267 | block_num_t b; |
255 | 268 | ||
256 | /* If 'ldir_ptr' is not a pointer to a dir inode, error. */ |
269 | /* If 'ldir_ptr' is not a pointer to a dir inode, error. */ |
257 | if ((ldir_ptr->i_mode & I_TYPE) != I_DIRECTORY) { |
270 | if ((ldir_ptr->i_mode & I_TYPE) != I_DIRECTORY) { |
258 | return FS_ENOTDIR; |
271 | return FS_ENOTDIR; |
259 | } |
272 | } |
260 | r = OK; |
273 | r = OK; |
261 | 274 | ||
262 | /* Step through the directory one block at a time. */ |
275 | /* Step through the directory one block at a time. */ |
263 | old_slots = (unsigned)(ldir_ptr->i_size/DIR_ENTRY_SIZE); |
276 | old_slots = (unsigned)(ldir_ptr->i_size/DIR_ENTRY_SIZE); |
264 | match = 0; /* set when a string match occurs */ |
277 | match = 0; /* set when a string match occurs */ |
265 | 278 | ||
266 | for (pos = 0; pos < ldir_ptr->i_size; pos += BLOCK_SIZE) { |
279 | for (pos = 0; pos < ldir_ptr->i_size; pos += BLOCK_SIZE) { |
267 | b = read_map(ldir_ptr, pos); /* get block number */ |
280 | b = read_map(ldir_ptr, pos); /* get block number */ |
268 | 281 | ||
269 | /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */ |
282 | /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */ |
270 | bp = get_block(b); /* get a dir block */ |
283 | bp = get_block(b); /* get a dir block */ |
271 | 284 | ||
272 | /* Search a directory block. */ |
285 | /* Search a directory block. */ |
273 | for (dp = &bp->b.b__dir[0]; dp < &bp->b.b__dir[NR_DIR_ENTRIES]; dp++) { |
286 | for (dp = &bp->b.b__dir[0]; dp < &bp->b.b__dir[NR_DIR_ENTRIES]; dp++) { |
274 | 287 | ||
275 | /* Match occurs if string found. */ |
288 | /* Match occurs if string found. */ |
276 | if (dp->d_ino != 0) { |
289 | if (dp->d_ino != 0) { |
277 | if (flag == IS_EMPTY) { |
290 | if (flag == IS_EMPTY) { |
278 | /* If this test succeeds, dir is not empty. */ |
291 | /* If this test succeeds, dir is not empty. */ |
279 | if (strcmp(dp->d_name, "." ) != 0 && |
292 | if (strcmp(dp->d_name, "." ) != 0 && |
280 | strcmp(dp->d_name, "..") != 0) |
293 | strcmp(dp->d_name, "..") != 0) |
281 | match = 1; |
294 | match = 1; |
282 | } |
295 | } |
283 | else { |
296 | else { |
284 | if (fs_strncmp(dp->d_name, string, NAME_MAX) == 0) { |
297 | if (fs_strncmp(dp->d_name, string, NAME_MAX) == 0) { |
285 | match = 1; |
298 | match = 1; |
286 | } |
299 | } |
287 | } |
300 | } |
288 | } |
301 | } |
289 | 302 | ||
290 | if (match) { |
303 | if (match) { |
291 | /* LOOK_UP or DELETE found what it wanted. */ |
304 | /* LOOK_UP or DELETE found what it wanted. */ |
292 | r = OK; |
305 | r = OK; |
293 | if (flag == IS_EMPTY) { |
306 | if (flag == IS_EMPTY) { |
294 | r = FS_ENOTEMPTY; |
307 | r = FS_ENOTEMPTY; |
295 | } |
308 | } |
296 | else { |
309 | else { |
297 | *numb = (int) dp->d_ino; |
310 | *numb = (int) dp->d_ino; |
298 | } |
311 | } |
299 | return r; |
312 | return r; |
300 | } |
313 | } |
301 | } |
314 | } |
302 | } |
315 | } |
303 | 316 | ||
304 | /* The whole directory has now been searched. */ |
317 | /* The whole directory has now been searched. */ |
305 | return(flag == IS_EMPTY ? OK : FS_ENOENT); |
318 | return(flag == IS_EMPTY ? OK : FS_ENOENT); |
306 | } |
319 | } |
307 | 320 | ||
- | 321 | /** |
|
- | 322 | * Used for extended versions |
|
- | 323 | */ |
|
308 | int search_dir_ex(register inode_t *ldir_ptr, char string[NAME_MAX_EX], ino_t *numb, int flag) |
324 | int search_dir_ex(register inode_t *ldir_ptr, char string[NAME_MAX_EX], ino_t *numb, int flag) |
309 | { |
325 | { |
310 | 326 | ||
311 | /* Same as above, but for extened directory etries - 30 chars in name of file. */ |
327 | /* Same as above, but for extened directory etries - 30 chars in name of file. */ |
312 | 328 | ||
313 | register directex_t *dp; |
329 | register directex_t *dp; |
314 | register block_t *bp; |
330 | register block_t *bp; |
315 | int r, match; |
331 | int r, match; |
316 | offset_t pos; |
332 | offset_t pos; |
317 | unsigned old_slots; |
333 | unsigned old_slots; |
318 | block_num_t b; |
334 | block_num_t b; |
319 | 335 | ||
320 | /* If 'ldir_ptr' is not a pointer to a dir inode, error. */ |
336 | /* If 'ldir_ptr' is not a pointer to a dir inode, error. */ |
321 | if ( (ldir_ptr->i_mode & I_TYPE) != I_DIRECTORY) { |
337 | if ( (ldir_ptr->i_mode & I_TYPE) != I_DIRECTORY) { |
322 | return FS_ENOTDIR; |
338 | return FS_ENOTDIR; |
323 | } |
339 | } |
324 | r = OK; |
340 | r = OK; |
325 | 341 | ||
326 | /* Step through the directory one block at a time. */ |
342 | /* Step through the directory one block at a time. */ |
327 | old_slots = (unsigned)(ldir_ptr->i_size/DIR_ENTRY_SIZE_EX); |
343 | old_slots = (unsigned)(ldir_ptr->i_size/DIR_ENTRY_SIZE_EX); |
328 | match = 0; /* set when a string match occurs */ |
344 | match = 0; /* set when a string match occurs */ |
329 | 345 | ||
330 | for (pos = 0; pos < ldir_ptr->i_size; pos += BLOCK_SIZE) { |
346 | for (pos = 0; pos < ldir_ptr->i_size; pos += BLOCK_SIZE) { |
331 | b = read_map(ldir_ptr, pos); /* get block number */ |
347 | b = read_map(ldir_ptr, pos); /* get block number */ |
332 | 348 | ||
333 | /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */ |
349 | /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */ |
334 | bp = get_block(b); /* get a dir block */ |
350 | bp = get_block(b); /* get a dir block */ |
335 | 351 | ||
336 | /* Search a directory block. */ |
352 | /* Search a directory block. */ |
337 | for (dp = &bp->b.b__direx[0]; dp < &bp->b.b__direx[NR_DIR_ENTRIES_EX]; dp++) { |
353 | for (dp = &bp->b.b__direx[0]; dp < &bp->b.b__direx[NR_DIR_ENTRIES_EX]; dp++) { |
338 | 354 | ||
339 | /* Match occurs if string found. */ |
355 | /* Match occurs if string found. */ |
340 | if (dp->d_ino != 0) { |
356 | if (dp->d_ino != 0) { |
341 | if (flag == IS_EMPTY) { |
357 | if (flag == IS_EMPTY) { |
342 | /* If this test succeeds, dir is not empty. */ |
358 | /* If this test succeeds, dir is not empty. */ |
343 | if (strcmp(dp->d_name, "." ) != 0 && |
359 | if (strcmp(dp->d_name, "." ) != 0 && |
344 | strcmp(dp->d_name, "..") != 0) match = 1; |
360 | strcmp(dp->d_name, "..") != 0) match = 1; |
345 | } |
361 | } |
346 | else { |
362 | else { |
347 | if (fs_strncmp(dp->d_name, string, NAME_MAX_EX) == 0) { |
363 | if (fs_strncmp(dp->d_name, string, NAME_MAX_EX) == 0) { |
348 | match = 1; |
364 | match = 1; |
349 | } |
365 | } |
350 | 366 | ||
351 | } |
367 | } |
352 | } |
368 | } |
353 | 369 | ||
354 | if (match) { |
370 | if (match) { |
355 | /* LOOK_UP or DELETE found what it wanted. */ |
371 | /* LOOK_UP or DELETE found what it wanted. */ |
356 | r = OK; |
372 | r = OK; |
357 | if (flag == IS_EMPTY) { |
373 | if (flag == IS_EMPTY) { |
358 | r = FS_ENOTEMPTY; |
374 | r = FS_ENOTEMPTY; |
359 | } |
375 | } |
360 | else { |
376 | else { |
361 | *numb = (int)dp->d_ino; |
377 | *numb = (int)dp->d_ino; |
362 | } |
378 | } |
363 | return r; |
379 | return r; |
364 | } |
380 | } |
365 | } |
381 | } |
366 | } |
382 | } |
367 | 383 | ||
368 | /* The whole directory has now been searched. */ |
384 | /* The whole directory has now been searched. */ |
369 | return(flag == IS_EMPTY ? OK : FS_ENOENT); |
385 | return(flag == IS_EMPTY ? OK : FS_ENOENT); |
370 | } |
386 | } |
371 | 387 | ||
- | 388 | ||
- | 389 | /** |
|
- | 390 | * } |
|
- | 391 | */ |
|
- | 392 | ||
372 | 393 |