4 #include <minix/vfsif.h>
8 static char *get_name(char *name
, char string
[NAME_MAX
+1]);
9 static int parse_path(ino_t dir_ino
, ino_t root_ino
, int flags
, struct
10 dir_record
**res_inop
, size_t *offsetp
);
13 /*===========================================================================*
15 *===========================================================================*/
20 ino_t dir_ino
, root_ino
;
21 struct dir_record
*dir
;
23 grant
= fs_m_in
.m_vfs_fs_lookup
.grant_path
;
24 len
= fs_m_in
.m_vfs_fs_lookup
.path_len
; /* including terminating nul */
25 dir_ino
= fs_m_in
.m_vfs_fs_lookup
.dir_ino
;
26 root_ino
= fs_m_in
.m_vfs_fs_lookup
.root_ino
;
27 flags
= fs_m_in
.m_vfs_fs_lookup
.flags
;
28 caller_uid
= fs_m_in
.m_vfs_fs_lookup
.uid
;
29 caller_gid
= fs_m_in
.m_vfs_fs_lookup
.gid
;
32 if(len
> sizeof(user_path
)) return(E2BIG
); /* too big for buffer */
33 if(len
< 1) return(EINVAL
); /* too small */
35 /* Copy the pathname and set up caller's user and group id */
36 r
= sys_safecopyfrom(VFS_PROC_NR
, grant
, 0, (vir_bytes
) user_path
,
39 printf("ISOFS %s:%d sys_safecopyfrom failed: %d\n",
40 __FILE__
, __LINE__
, r
);
44 /* Verify this is a null-terminated path. */
45 if(user_path
[len
-1] != '\0') return(EINVAL
);
50 r
= parse_path(dir_ino
, root_ino
, flags
, &dir
, &offset
);
52 if (r
== ELEAVEMOUNT
) {
53 /* Report offset and the error */
54 fs_m_out
.m_fs_vfs_lookup
.offset
= offset
;
55 fs_m_out
.m_fs_vfs_lookup
.symloop
= 0;
59 if (r
!= OK
&& r
!= EENTERMOUNT
) return(r
);
61 fs_m_out
.m_fs_vfs_lookup
.inode
= ID_DIR_RECORD(dir
);
62 fs_m_out
.m_fs_vfs_lookup
.mode
= dir
->d_mode
;
63 fs_m_out
.m_fs_vfs_lookup
.file_size
= dir
->d_file_size
;
64 fs_m_out
.m_fs_vfs_lookup
.symloop
= 0;
65 fs_m_out
.m_fs_vfs_lookup
.uid
= SYS_UID
; /* root */
66 fs_m_out
.m_fs_vfs_lookup
.gid
= SYS_GID
; /* operator */
68 if (r
== EENTERMOUNT
) {
69 fs_m_out
.m_fs_vfs_lookup
.offset
= offset
;
70 release_dir_record(dir
);
76 /* The search dir actually performs the operation of searching for the
77 * compoent ``string" in ldir_ptr. It returns the response and the number of
78 * the inode in numb. */
79 /*===========================================================================*
81 *===========================================================================*/
83 register struct dir_record
*ldir_ptr
, /* dir record parent */
84 char string
[NAME_MAX
], /* component to search for */
85 ino_t
*numb
/* pointer to new dir record */
87 struct dir_record
*dir_tmp
;
88 register struct buf
*bp
;
90 char* comma_pos
= NULL
;
91 char tmp_string
[NAME_MAX
];
93 /* This function search a particular element (in string) in a inode and
94 * return its number */
96 /* Initialize the tmp array */
97 memset(tmp_string
,'\0',NAME_MAX
);
99 if ((ldir_ptr
->d_mode
& I_TYPE
) != I_DIRECTORY
) {
103 if (strcmp(string
,".") == 0) {
104 *numb
= ID_DIR_RECORD(ldir_ptr
);
108 if (strcmp(string
,"..") == 0 && ldir_ptr
->loc_extent_l
== v_pri
.dir_rec_root
->loc_extent_l
) {
110 /* *numb = ID_DIR_RECORD(ldir_ptr); */
114 /* Read the dir's content */
115 pos
= ldir_ptr
->ext_attr_rec_length
;
116 bp
= get_block(ldir_ptr
->loc_extent_l
);
121 while (pos
< v_pri
.logical_block_size_l
) {
122 if ((dir_tmp
= get_free_dir_record()) == NULL
) {
127 if (create_dir_record(dir_tmp
,b_data(bp
) + pos
,
128 ldir_ptr
->loc_extent_l
*v_pri
.logical_block_size_l
+ pos
) == EINVAL
)
131 if (dir_tmp
->length
== 0) {
132 release_dir_record(dir_tmp
);
137 memcpy(tmp_string
,dir_tmp
->file_id
,dir_tmp
->length_file_id
);
138 comma_pos
= strchr(tmp_string
,';');
139 if (comma_pos
!= NULL
)
142 tmp_string
[dir_tmp
->length_file_id
] = 0;
143 if (tmp_string
[strlen(tmp_string
) - 1] == '.')
144 tmp_string
[strlen(tmp_string
) - 1] = '\0';
146 if (strcmp(tmp_string
,string
) == 0 ||
147 (dir_tmp
->file_id
[0] == 1 && strcmp(string
,"..") == 0)) {
149 /* If the element is found or we are searchig for... */
151 if (dir_tmp
->loc_extent_l
== dir_records
->loc_extent_l
) {
152 /* In this case the inode is a root because the parent
153 * points to the same location than the inode. */
155 release_dir_record(dir_tmp
);
160 if (dir_tmp
->ext_attr_rec_length
!= 0) {
161 dir_tmp
->ext_attr
= get_free_ext_attr();
162 create_ext_attr(dir_tmp
->ext_attr
,b_data(bp
));
165 *numb
= ID_DIR_RECORD(dir_tmp
);
166 release_dir_record(dir_tmp
);
172 pos
+= dir_tmp
->length
;
173 release_dir_record(dir_tmp
);
181 /*===========================================================================*
183 *===========================================================================*/
184 static int parse_path(
188 struct dir_record
**res_inop
,
192 char string
[NAME_MAX
+1];
194 struct dir_record
*start_dir
, *old_dir
;
196 /* Find starting inode inode according to the request message */
197 if ((start_dir
= get_dir_record(dir_ino
)) == NULL
) {
198 printf("ISOFS: couldn't find starting inode %llu\n", dir_ino
);
204 /* Scan the path component by component. */
208 *res_inop
= start_dir
;
209 *offsetp
+= cp
-user_path
;
211 /* Return EENTERMOUNT if we are at a mount point */
212 if (start_dir
->d_mountpoint
)
219 /* Special case code. If the remaining path consists of just
220 * slashes, we need to look up '.'
225 strlcpy(string
, ".", NAME_MAX
+ 1);
229 ncp
= get_name(cp
, string
);
231 /* Just get the first component */
232 ncp
= get_name(cp
, string
);
234 /* Special code for '..'. A process is not allowed to leave a chrooted
235 * environment. A lookup of '..' at the root of a mounted filesystem
236 * has to return ELEAVEMOUNT.
238 if (strcmp(string
, "..") == 0) {
240 /* This condition is not necessary since it will never be the root filesystem */
241 /* if (start_dir == dir_records) { */
243 /* continue; /\* Just ignore the '..' at a process' */
248 if (start_dir
== dir_records
) {
249 /* Climbing up mountpoint */
250 release_dir_record(start_dir
);
252 *offsetp
+= cp
-user_path
;
256 /* Only check for a mount point if we are not looking for '..'. */
257 if (start_dir
->d_mountpoint
) {
258 *res_inop
= start_dir
;
259 *offsetp
+= cp
-user_path
;
264 /* There is more path. Keep parsing. */
267 r
= advance(old_dir
, string
, &start_dir
);
270 release_dir_record(old_dir
);
274 release_dir_record(old_dir
);
280 /*===========================================================================*
282 *===========================================================================*/
283 int advance(dirp
, string
, resp
)
284 struct dir_record
*dirp
; /* inode for directory to be searched */
285 char string
[NAME_MAX
]; /* component name to look for */
286 struct dir_record
**resp
; /* resulting inode */
288 /* Given a directory and a component of a path, look up the component in
289 * the directory, find the inode, open it, and return a pointer to its inode
293 register struct dir_record
*rip
= NULL
;
297 /* If 'string' is empty, yield same inode straight away. */
298 if (string
[0] == '\0') {
302 /* Check for NULL. */
307 /* If 'string' is not present in the directory, signal error. */
308 if ( (r
= search_dir(dirp
, string
, &numb
)) != OK
) {
312 /* The component has been found in the directory. Get inode. */
313 if ( (rip
= get_dir_record((int) numb
)) == NULL
) {
322 /*===========================================================================*
324 *===========================================================================*/
325 static char *get_name(path_name
, string
)
326 char *path_name
; /* path name to parse */
327 char string
[NAME_MAX
+1]; /* component extracted from 'old_name' */
329 /* Given a pointer to a path name in fs space, 'path_name', copy the first
330 * component to 'string' (truncated if necessary, always nul terminated).
331 * A pointer to the string after the first component of the name as yet
332 * unparsed is returned. Roughly speaking,
333 * 'get_name' = 'path_name' - 'string'.
335 * This routine follows the standard convention that /usr/ast, /usr//ast,
336 * //usr///ast and /usr/ast/ are all equivalent.
343 /* Skip leading slashes */
347 /* Find the end of the first component */
349 while(ep
[0] != '\0' && ep
[0] != '/')
354 /* Truncate the amount to be copied if it exceeds NAME_MAX */
358 /* Special case of the string at cp is empty */
362 strlcpy(string
, ".", NAME_MAX
+ 1);
366 memcpy(string
, cp
, len
);