4 #include <minix/vfsif.h>
8 FORWARD
_PROTOTYPE( char *get_name
, (char *name
, char string
[NAME_MAX
+1]) );
9 FORWARD
_PROTOTYPE( int parse_path
, (ino_t dir_ino
, ino_t root_ino
, int flags
,
10 struct dir_record
**res_inop
,
14 /*===========================================================================*
16 *===========================================================================*/
17 PUBLIC
int fs_lookup() {
19 int r
, r1
, len
, flags
;
21 ino_t dir_ino
, root_ino
;
22 struct dir_record
*dir
;
24 grant
= fs_m_in
.REQ_GRANT
;
25 size
= fs_m_in
.REQ_PATH_SIZE
; /* Size of the buffer */
26 len
= fs_m_in
.REQ_PATH_LEN
; /* including terminating nul */
27 dir_ino
= fs_m_in
.REQ_DIR_INO
;
28 root_ino
= fs_m_in
.REQ_ROOT_INO
;
29 flags
= fs_m_in
.REQ_FLAGS
;
30 caller_uid
= fs_m_in
.REQ_UID
;
31 caller_gid
= fs_m_in
.REQ_GID
;
34 if(len
> sizeof(user_path
)) return(E2BIG
); /* too big for buffer */
35 if(len
< 1) return(EINVAL
); /* too small */
37 /* Copy the pathname and set up caller's user and group id */
38 r
= sys_safecopyfrom(FS_PROC_NR
, grant
, 0, (vir_bytes
) user_path
,
41 printf("ISOFS %s:%d sys_safecopyfrom failed: %d\n",
42 __FILE__
, __LINE__
, r
);
46 /* Verify this is a null-terminated path. */
47 if(user_path
[len
-1] != '\0') return(EINVAL
);
52 r
= parse_path(dir_ino
, root_ino
, flags
, &dir
, &offset
);
54 if (r
== ELEAVEMOUNT
) {
55 /* Report offset and the error */
56 fs_m_out
.RES_OFFSET
= offset
;
57 fs_m_out
.RES_SYMLOOP
= 0;
61 if (r
!= OK
&& r
!= EENTERMOUNT
) return(r
);
63 fs_m_out
.RES_INODE_NR
= ID_DIR_RECORD(dir
);
64 fs_m_out
.RES_MODE
= dir
->d_mode
;
65 fs_m_out
.RES_FILE_SIZE_LO
= dir
->d_file_size
;
66 fs_m_out
.RES_SYMLOOP
= 0;
67 fs_m_out
.RES_UID
= SYS_UID
; /* root */
68 fs_m_out
.RES_GID
= SYS_GID
; /* operator */
71 if (r
== EENTERMOUNT
) {
72 fs_m_out
.RES_OFFSET
= offset
;
73 release_dir_record(dir
);
79 /* The search dir actually performs the operation of searching for the
80 * compoent ``string" in ldir_ptr. It returns the response and the number of
81 * the inode in numb. */
82 /*===========================================================================*
84 *===========================================================================*/
85 PUBLIC
int search_dir(ldir_ptr
,string
,numb
)
86 register struct dir_record
*ldir_ptr
; /* dir record parent */
87 char string
[NAME_MAX
]; /* component to search for */
88 ino_t
*numb
; /* pointer to new dir record */
90 struct dir_record
*dir_tmp
;
91 register struct buf
*bp
,*bp2
;
93 char* comma_pos
= NULL
;
94 char tmp_string
[NAME_MAX
];
96 /* This function search a particular element (in string) in a inode and
97 * return its number */
99 /* Initialize the tmp array */
100 memset(tmp_string
,'\0',NAME_MAX
);
102 if ((ldir_ptr
->d_mode
& I_TYPE
) != I_DIRECTORY
) {
108 if (strcmp(string
,".") == 0) {
109 *numb
= ID_DIR_RECORD(ldir_ptr
);
113 if (strcmp(string
,"..") == 0 && ldir_ptr
->loc_extent_l
== v_pri
.dir_rec_root
->loc_extent_l
) {
115 /* *numb = ID_DIR_RECORD(ldir_ptr); */
119 /* Read the dir's content */
120 pos
= ldir_ptr
->ext_attr_rec_length
;
121 bp
= get_block(ldir_ptr
->loc_extent_l
);
126 while (pos
< v_pri
.logical_block_size_l
) {
127 if ((dir_tmp
= get_free_dir_record()) == NULL
) {
132 if (create_dir_record(dir_tmp
,bp
->b_data
+ pos
,
133 ldir_ptr
->loc_extent_l
*v_pri
.logical_block_size_l
+ pos
) == EINVAL
)
136 if (dir_tmp
->length
== 0) {
137 release_dir_record(dir_tmp
);
142 memcpy(tmp_string
,dir_tmp
->file_id
,dir_tmp
->length_file_id
);
143 comma_pos
= strchr(tmp_string
,';');
144 if (comma_pos
!= NULL
)
147 tmp_string
[dir_tmp
->length_file_id
] = 0;
148 if (tmp_string
[strlen(tmp_string
) - 1] == '.')
149 tmp_string
[strlen(tmp_string
) - 1] = '\0';
151 if (strcmp(tmp_string
,string
) == 0 ||
152 (dir_tmp
->file_id
[0] == 1 && strcmp(string
,"..") == 0)) {
154 /* If the element is found or we are searchig for... */
156 if (dir_tmp
->loc_extent_l
== dir_records
->loc_extent_l
) {
157 /* In this case the inode is a root because the parent
158 * points to the same location than the inode. */
160 release_dir_record(dir_tmp
);
165 if (dir_tmp
->ext_attr_rec_length
!= 0) {
166 dir_tmp
->ext_attr
= get_free_ext_attr();
167 create_ext_attr(dir_tmp
->ext_attr
,bp
->b_data
);
170 *numb
= ID_DIR_RECORD(dir_tmp
);
171 release_dir_record(dir_tmp
);
177 pos
+= dir_tmp
->length
;
178 release_dir_record(dir_tmp
);
186 /*===========================================================================*
188 *===========================================================================*/
189 PRIVATE
int parse_path(dir_ino
, root_ino
, flags
, res_inop
, offsetp
)
193 struct dir_record
**res_inop
;
197 char string
[NAME_MAX
+1];
199 struct dir_record
*start_dir
, *old_dir
;
201 /* Find starting inode inode according to the request message */
202 if ((start_dir
= get_dir_record(dir_ino
)) == NULL
) {
203 printf("ISOFS: couldn't find starting inode %d\n", dir_ino
);
209 /* Scan the path component by component. */
213 *res_inop
= start_dir
;
214 *offsetp
+= cp
-user_path
;
216 /* Return EENTERMOUNT if we are at a mount point */
217 if (start_dir
->d_mountpoint
)
224 /* Special case code. If the remaining path consists of just
225 * slashes, we need to look up '.'
234 ncp
= get_name(cp
, string
);
236 /* Just get the first component */
237 ncp
= get_name(cp
, string
);
239 /* Special code for '..'. A process is not allowed to leave a chrooted
240 * environment. A lookup of '..' at the root of a mounted filesystem
241 * has to return ELEAVEMOUNT.
243 if (strcmp(string
, "..") == 0) {
245 /* This condition is not necessary since it will never be the root filesystem */
246 /* if (start_dir == dir_records) { */
248 /* continue; /\* Just ignore the '..' at a process' */
253 if (start_dir
== dir_records
) {
254 /* Climbing up mountpoint */
255 release_dir_record(start_dir
);
257 *offsetp
+= cp
-user_path
;
261 /* Only check for a mount point if we are not looking for '..'. */
262 if (start_dir
->d_mountpoint
) {
263 *res_inop
= start_dir
;
264 *offsetp
+= cp
-user_path
;
269 /* There is more path. Keep parsing. */
272 r
= advance(old_dir
, string
, &start_dir
);
275 release_dir_record(old_dir
);
279 release_dir_record(old_dir
);
285 /*===========================================================================*
287 *===========================================================================*/
288 PUBLIC
int advance(dirp
, string
, resp
)
289 struct dir_record
*dirp
; /* inode for directory to be searched */
290 char string
[NAME_MAX
]; /* component name to look for */
291 struct dir_record
**resp
; /* resulting inode */
293 /* Given a directory and a component of a path, look up the component in
294 * the directory, find the inode, open it, and return a pointer to its inode
298 register struct dir_record
*rip
= NULL
;
303 /* If 'string' is empty, yield same inode straight away. */
304 if (string
[0] == '\0') {
308 /* Check for NULL. */
313 /* If 'string' is not present in the directory, signal error. */
314 if ( (r
= search_dir(dirp
, string
, &numb
)) != OK
) {
318 /* The component has been found in the directory. Get inode. */
319 if ( (rip
= get_dir_record((int) numb
)) == NULL
) {
328 /*===========================================================================*
330 *===========================================================================*/
331 PRIVATE
char *get_name(path_name
, string
)
332 char *path_name
; /* path name to parse */
333 char string
[NAME_MAX
+1]; /* component extracted from 'old_name' */
335 /* Given a pointer to a path name in fs space, 'path_name', copy the first
336 * component to 'string' (truncated if necessary, always nul terminated).
337 * A pointer to the string after the first component of the name as yet
338 * unparsed is returned. Roughly speaking,
339 * 'get_name' = 'path_name' - 'string'.
341 * This routine follows the standard convention that /usr/ast, /usr//ast,
342 * //usr///ast and /usr/ast/ are all equivalent.
349 /* Skip leading slashes */
353 /* Find the end of the first component */
355 while(ep
[0] != '\0' && ep
[0] != '/')
360 /* Truncate the amount to be copied if it exceeds NAME_MAX */
364 /* Special case of the string at cp is empty */
372 memcpy(string
, cp
, len
);