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
.REQ_GRANT
;
24 len
= fs_m_in
.REQ_PATH_LEN
; /* including terminating nul */
25 dir_ino
= fs_m_in
.REQ_DIR_INO
;
26 root_ino
= fs_m_in
.REQ_ROOT_INO
;
27 flags
= fs_m_in
.REQ_FLAGS
;
28 caller_uid
= fs_m_in
.REQ_UID
;
29 caller_gid
= fs_m_in
.REQ_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
.RES_OFFSET
= offset
;
55 fs_m_out
.RES_SYMLOOP
= 0;
59 if (r
!= OK
&& r
!= EENTERMOUNT
) return(r
);
61 fs_m_out
.RES_INODE_NR
= ID_DIR_RECORD(dir
);
62 fs_m_out
.RES_MODE
= dir
->d_mode
;
63 fs_m_out
.RES_FILE_SIZE_LO
= dir
->d_file_size
;
64 fs_m_out
.RES_SYMLOOP
= 0;
65 fs_m_out
.RES_UID
= SYS_UID
; /* root */
66 fs_m_out
.RES_GID
= SYS_GID
; /* operator */
69 if (r
== EENTERMOUNT
) {
70 fs_m_out
.RES_OFFSET
= offset
;
71 release_dir_record(dir
);
77 /* The search dir actually performs the operation of searching for the
78 * compoent ``string" in ldir_ptr. It returns the response and the number of
79 * the inode in numb. */
80 /*===========================================================================*
82 *===========================================================================*/
83 int search_dir(ldir_ptr
,string
,numb
)
84 register struct dir_record
*ldir_ptr
; /* dir record parent */
85 char string
[NAME_MAX
]; /* component to search for */
86 ino_t
*numb
; /* pointer to new dir record */
88 struct dir_record
*dir_tmp
;
89 register struct buf
*bp
;
91 char* comma_pos
= NULL
;
92 char tmp_string
[NAME_MAX
];
94 /* This function search a particular element (in string) in a inode and
95 * return its number */
97 /* Initialize the tmp array */
98 memset(tmp_string
,'\0',NAME_MAX
);
100 if ((ldir_ptr
->d_mode
& I_TYPE
) != I_DIRECTORY
) {
104 if (strcmp(string
,".") == 0) {
105 *numb
= ID_DIR_RECORD(ldir_ptr
);
109 if (strcmp(string
,"..") == 0 && ldir_ptr
->loc_extent_l
== v_pri
.dir_rec_root
->loc_extent_l
) {
111 /* *numb = ID_DIR_RECORD(ldir_ptr); */
115 /* Read the dir's content */
116 pos
= ldir_ptr
->ext_attr_rec_length
;
117 bp
= get_block(ldir_ptr
->loc_extent_l
);
122 while (pos
< v_pri
.logical_block_size_l
) {
123 if ((dir_tmp
= get_free_dir_record()) == NULL
) {
128 if (create_dir_record(dir_tmp
,b_data(bp
) + pos
,
129 ldir_ptr
->loc_extent_l
*v_pri
.logical_block_size_l
+ pos
) == EINVAL
)
132 if (dir_tmp
->length
== 0) {
133 release_dir_record(dir_tmp
);
138 memcpy(tmp_string
,dir_tmp
->file_id
,dir_tmp
->length_file_id
);
139 comma_pos
= strchr(tmp_string
,';');
140 if (comma_pos
!= NULL
)
143 tmp_string
[dir_tmp
->length_file_id
] = 0;
144 if (tmp_string
[strlen(tmp_string
) - 1] == '.')
145 tmp_string
[strlen(tmp_string
) - 1] = '\0';
147 if (strcmp(tmp_string
,string
) == 0 ||
148 (dir_tmp
->file_id
[0] == 1 && strcmp(string
,"..") == 0)) {
150 /* If the element is found or we are searchig for... */
152 if (dir_tmp
->loc_extent_l
== dir_records
->loc_extent_l
) {
153 /* In this case the inode is a root because the parent
154 * points to the same location than the inode. */
156 release_dir_record(dir_tmp
);
161 if (dir_tmp
->ext_attr_rec_length
!= 0) {
162 dir_tmp
->ext_attr
= get_free_ext_attr();
163 create_ext_attr(dir_tmp
->ext_attr
,b_data(bp
));
166 *numb
= ID_DIR_RECORD(dir_tmp
);
167 release_dir_record(dir_tmp
);
173 pos
+= dir_tmp
->length
;
174 release_dir_record(dir_tmp
);
182 /*===========================================================================*
184 *===========================================================================*/
185 static int parse_path(dir_ino
, root_ino
, flags
, res_inop
, offsetp
)
189 struct dir_record
**res_inop
;
193 char string
[NAME_MAX
+1];
195 struct dir_record
*start_dir
, *old_dir
;
197 /* Find starting inode inode according to the request message */
198 if ((start_dir
= get_dir_record(dir_ino
)) == NULL
) {
199 printf("ISOFS: couldn't find starting inode %u\n", dir_ino
);
205 /* Scan the path component by component. */
209 *res_inop
= start_dir
;
210 *offsetp
+= cp
-user_path
;
212 /* Return EENTERMOUNT if we are at a mount point */
213 if (start_dir
->d_mountpoint
)
220 /* Special case code. If the remaining path consists of just
221 * slashes, we need to look up '.'
226 strlcpy(string
, ".", NAME_MAX
+ 1);
230 ncp
= get_name(cp
, string
);
232 /* Just get the first component */
233 ncp
= get_name(cp
, string
);
235 /* Special code for '..'. A process is not allowed to leave a chrooted
236 * environment. A lookup of '..' at the root of a mounted filesystem
237 * has to return ELEAVEMOUNT.
239 if (strcmp(string
, "..") == 0) {
241 /* This condition is not necessary since it will never be the root filesystem */
242 /* if (start_dir == dir_records) { */
244 /* continue; /\* Just ignore the '..' at a process' */
249 if (start_dir
== dir_records
) {
250 /* Climbing up mountpoint */
251 release_dir_record(start_dir
);
253 *offsetp
+= cp
-user_path
;
257 /* Only check for a mount point if we are not looking for '..'. */
258 if (start_dir
->d_mountpoint
) {
259 *res_inop
= start_dir
;
260 *offsetp
+= cp
-user_path
;
265 /* There is more path. Keep parsing. */
268 r
= advance(old_dir
, string
, &start_dir
);
271 release_dir_record(old_dir
);
275 release_dir_record(old_dir
);
281 /*===========================================================================*
283 *===========================================================================*/
284 int advance(dirp
, string
, resp
)
285 struct dir_record
*dirp
; /* inode for directory to be searched */
286 char string
[NAME_MAX
]; /* component name to look for */
287 struct dir_record
**resp
; /* resulting inode */
289 /* Given a directory and a component of a path, look up the component in
290 * the directory, find the inode, open it, and return a pointer to its inode
294 register struct dir_record
*rip
= NULL
;
298 /* If 'string' is empty, yield same inode straight away. */
299 if (string
[0] == '\0') {
303 /* Check for NULL. */
308 /* If 'string' is not present in the directory, signal error. */
309 if ( (r
= search_dir(dirp
, string
, &numb
)) != OK
) {
313 /* The component has been found in the directory. Get inode. */
314 if ( (rip
= get_dir_record((int) numb
)) == NULL
) {
323 /*===========================================================================*
325 *===========================================================================*/
326 static char *get_name(path_name
, string
)
327 char *path_name
; /* path name to parse */
328 char string
[NAME_MAX
+1]; /* component extracted from 'old_name' */
330 /* Given a pointer to a path name in fs space, 'path_name', copy the first
331 * component to 'string' (truncated if necessary, always nul terminated).
332 * A pointer to the string after the first component of the name as yet
333 * unparsed is returned. Roughly speaking,
334 * 'get_name' = 'path_name' - 'string'.
336 * This routine follows the standard convention that /usr/ast, /usr//ast,
337 * //usr///ast and /usr/ast/ are all equivalent.
344 /* Skip leading slashes */
348 /* Find the end of the first component */
350 while(ep
[0] != '\0' && ep
[0] != '/')
355 /* Truncate the amount to be copied if it exceeds NAME_MAX */
359 /* Special case of the string at cp is empty */
363 strlcpy(string
, ".", NAME_MAX
+ 1);
367 memcpy(string
, cp
, len
);