Subversion Repositories HelenOS

Rev

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