8 #include <minix/vfsif.h>
10 static struct inode
*new_node(struct inode
*ldirp
, char *string
, mode_t
13 /*===========================================================================*
15 *===========================================================================*/
23 char lastc
[MFS_NAME_MAX
];
25 /* Read request message */
26 omode
= (mode_t
) fs_m_in
.REQ_MODE
;
27 caller_uid
= (uid_t
) fs_m_in
.REQ_UID
;
28 caller_gid
= (gid_t
) fs_m_in
.REQ_GID
;
30 /* Try to make the file. */
32 /* Copy the last component (i.e., file name) */
33 len
= min( (unsigned) fs_m_in
.REQ_PATH_LEN
, sizeof(lastc
));
34 err_code
= sys_safecopyfrom(VFS_PROC_NR
, (cp_grant_id_t
) fs_m_in
.REQ_GRANT
,
35 (vir_bytes
) 0, (vir_bytes
) lastc
, len
);
36 if (err_code
!= OK
) return err_code
;
37 NUL(lastc
, len
, sizeof(lastc
));
39 /* Get last directory inode (i.e., directory that will hold the new inode) */
40 if ((ldirp
= get_inode(fs_dev
, (ino_t
) fs_m_in
.REQ_INODE_NR
)) == NULL
)
43 /* Create a new inode by calling new_node(). */
44 rip
= new_node(ldirp
, lastc
, omode
, NO_ZONE
);
47 /* If an error occurred, release inode. */
55 fs_m_out
.RES_INODE_NR
= rip
->i_num
;
56 fs_m_out
.RES_MODE
= rip
->i_mode
;
57 fs_m_out
.RES_FILE_SIZE_LO
= rip
->i_size
;
59 /* These values are needed for the execution */
60 fs_m_out
.RES_UID
= rip
->i_uid
;
61 fs_m_out
.RES_GID
= rip
->i_gid
;
70 /*===========================================================================*
72 *===========================================================================*/
75 struct inode
*ip
, *ldirp
;
76 char lastc
[MFS_NAME_MAX
];
79 /* Copy the last component and set up caller's user and group id */
80 len
= min( (unsigned) fs_m_in
.REQ_PATH_LEN
, sizeof(lastc
));
81 err_code
= sys_safecopyfrom(VFS_PROC_NR
, (cp_grant_id_t
) fs_m_in
.REQ_GRANT
,
82 (vir_bytes
) 0, (vir_bytes
) lastc
, (size_t) len
);
83 if (err_code
!= OK
) return err_code
;
84 NUL(lastc
, len
, sizeof(lastc
));
86 caller_uid
= (uid_t
) fs_m_in
.REQ_UID
;
87 caller_gid
= (gid_t
) fs_m_in
.REQ_GID
;
89 /* Get last directory inode */
90 if((ldirp
= get_inode(fs_dev
, (ino_t
) fs_m_in
.REQ_INODE_NR
)) == NULL
)
93 /* Try to create the new node */
94 ip
= new_node(ldirp
, lastc
, (mode_t
) fs_m_in
.REQ_MODE
,
95 (zone_t
) fs_m_in
.REQ_DEV
);
103 /*===========================================================================*
105 *===========================================================================*/
108 int r1
, r2
; /* status codes */
109 ino_t dot
, dotdot
; /* inode numbers for . and .. */
110 struct inode
*rip
, *ldirp
;
111 char lastc
[MFS_NAME_MAX
]; /* last component */
114 /* Copy the last component and set up caller's user and group id */
115 len
= min( (unsigned) fs_m_in
.REQ_PATH_LEN
, sizeof(lastc
));
116 err_code
= sys_safecopyfrom(VFS_PROC_NR
, (cp_grant_id_t
) fs_m_in
.REQ_GRANT
,
117 (vir_bytes
) 0, (vir_bytes
) lastc
, (size_t) len
);
118 if(err_code
!= OK
) return(err_code
);
119 NUL(lastc
, len
, sizeof(lastc
));
121 caller_uid
= (uid_t
) fs_m_in
.REQ_UID
;
122 caller_gid
= (gid_t
) fs_m_in
.REQ_GID
;
124 /* Get last directory inode */
125 if((ldirp
= get_inode(fs_dev
, (ino_t
) fs_m_in
.REQ_INODE_NR
)) == NULL
)
128 /* Next make the inode. If that fails, return error code. */
129 rip
= new_node(ldirp
, lastc
, (mode_t
) fs_m_in
.REQ_MODE
, (zone_t
) 0);
131 if(rip
== NULL
|| err_code
== EEXIST
) {
132 put_inode(rip
); /* can't make dir: it already exists */
137 /* Get the inode numbers for . and .. to enter in the directory. */
138 dotdot
= ldirp
->i_num
; /* parent's inode number */
139 dot
= rip
->i_num
; /* inode number of the new dir itself */
141 /* Now make dir entries for . and .. unless the disk is completely full. */
142 /* Use dot1 and dot2, so the mode of the directory isn't important. */
143 rip
->i_mode
= (mode_t
) fs_m_in
.REQ_MODE
; /* set mode */
144 r1
= search_dir(rip
, dot1
, &dot
, ENTER
, IGN_PERM
);/* enter . in the new dir*/
145 r2
= search_dir(rip
, dot2
, &dotdot
, ENTER
, IGN_PERM
); /* enter .. in the new
148 /* If both . and .. were successfully entered, increment the link counts. */
149 if (r1
== OK
&& r2
== OK
) {
150 /* Normal case. It was possible to enter . and .. in the new dir. */
151 rip
->i_nlinks
++; /* this accounts for . */
152 ldirp
->i_nlinks
++; /* this accounts for .. */
153 IN_MARKDIRTY(ldirp
); /* mark parent's inode as dirty */
155 /* It was not possible to enter . or .. probably disk was full -
156 * links counts haven't been touched. */
157 if(search_dir(ldirp
, lastc
, NULL
, DELETE
, IGN_PERM
) != OK
)
158 panic("Dir disappeared: %ul", rip
->i_num
);
159 rip
->i_nlinks
--; /* undo the increment done in new_node() */
161 IN_MARKDIRTY(rip
); /* either way, i_nlinks has changed */
163 put_inode(ldirp
); /* return the inode of the parent dir */
164 put_inode(rip
); /* return the inode of the newly made dir */
165 return(err_code
); /* new_node() always sets 'err_code' */
169 /*===========================================================================*
171 *===========================================================================*/
175 struct inode
*sip
; /* inode containing symbolic link */
176 struct inode
*ldirp
; /* directory containing link */
177 register int r
; /* error code */
178 char string
[MFS_NAME_MAX
]; /* last component of the new dir's path name */
179 struct buf
*bp
; /* disk buffer for link */
181 caller_uid
= (uid_t
) fs_m_in
.REQ_UID
;
182 caller_gid
= (gid_t
) fs_m_in
.REQ_GID
;
184 /* Copy the link name's last component */
185 len
= min( (unsigned) fs_m_in
.REQ_PATH_LEN
, sizeof(string
));
186 r
= sys_safecopyfrom(VFS_PROC_NR
, (cp_grant_id_t
) fs_m_in
.REQ_GRANT
,
187 (vir_bytes
) 0, (vir_bytes
) string
, (size_t) len
);
188 if (r
!= OK
) return(r
);
189 NUL(string
, len
, sizeof(string
));
191 /* Temporarily open the dir. */
192 if( (ldirp
= get_inode(fs_dev
, (ino_t
) fs_m_in
.REQ_INODE_NR
)) == NULL
)
195 /* Create the inode for the symlink. */
196 sip
= new_node(ldirp
, string
, (mode_t
) (I_SYMBOLIC_LINK
| RWX_MODES
),
199 /* Allocate a disk block for the contents of the symlink.
200 * Copy contents of symlink (the name pointed to) into first disk block. */
201 if( (r
= err_code
) == OK
) {
202 bp
= new_block(sip
, (off_t
) 0);
206 r
= sys_safecopyfrom(VFS_PROC_NR
,
207 (cp_grant_id_t
) fs_m_in
.REQ_GRANT3
,
208 (vir_bytes
) 0, (vir_bytes
) b_data(bp
),
209 (size_t) fs_m_in
.REQ_MEM_SIZE
);
211 if(bp
!= NULL
&& r
== OK
) {
212 b_data(bp
)[_MIN_BLOCK_SIZE
-1] = '\0';
213 sip
->i_size
= (off_t
) strlen(b_data(bp
));
214 if(sip
->i_size
!= fs_m_in
.REQ_MEM_SIZE
) {
215 /* This can happen if the user provides a buffer
216 * with a \0 in it. This can cause a lot of trouble
217 * when the symlink is used later. We could just use
218 * the strlen() value, but we want to let the user
219 * know he did something wrong. ENAMETOOLONG doesn't
220 * exactly describe the error, but there is no
227 put_block(bp
, DIRECTORY_BLOCK
); /* put_block() accepts NULL. */
230 sip
->i_nlinks
= NO_LINK
;
231 if(search_dir(ldirp
, string
, NULL
, DELETE
, IGN_PERM
) != OK
)
232 panic("Symbolic link vanished");
236 /* put_inode() accepts NULL as a noop, so the below are safe. */
243 /*===========================================================================*
245 *===========================================================================*/
246 static struct inode
*new_node(struct inode
*ldirp
,
247 char *string
, mode_t bits
, zone_t z0
)
249 /* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir().
250 * In all cases it allocates a new inode, makes a directory entry for it in
251 * the ldirp directory with string name, and initializes it.
252 * It returns a pointer to the inode if it can do this;
253 * otherwise it returns NULL. It always sets 'err_code'
254 * to an appropriate value (OK or an error code).
256 * The parsed path rest is returned in 'parsed' if parsed is nonzero. It
257 * has to hold at least MFS_NAME_MAX bytes.
260 register struct inode
*rip
;
263 if (ldirp
->i_nlinks
== NO_LINK
) { /* Dir does not actually exist */
268 /* Get final component of the path. */
269 rip
= advance(ldirp
, string
, IGN_PERM
);
271 if (S_ISDIR(bits
) && (ldirp
->i_nlinks
>= LINK_MAX
)) {
272 /* New entry is a directory, alas we can't give it a ".." */
278 if ( rip
== NULL
&& err_code
== ENOENT
) {
279 /* Last path component does not exist. Make new directory entry. */
280 if ( (rip
= alloc_inode((ldirp
)->i_dev
, bits
)) == NULL
) {
281 /* Can't creat new inode: out of inodes. */
285 /* Force inode to the disk before making directory entry to make
286 * the system more robust in the face of a crash: an inode with
287 * no directory entry is much better than the opposite.
290 rip
->i_zone
[0] = z0
; /* major/minor device numbers */
291 rw_inode(rip
, WRITING
); /* force inode to disk now */
293 /* New inode acquired. Try to make directory entry. */
294 if((r
=search_dir(ldirp
, string
, &rip
->i_num
, ENTER
, IGN_PERM
)) != OK
) {
295 rip
->i_nlinks
--; /* pity, have to free disk inode */
296 IN_MARKDIRTY(rip
); /* dirty inodes are written out */
297 put_inode(rip
); /* this call frees the inode */
302 } else if (err_code
== EENTERMOUNT
|| err_code
== ELEAVEMOUNT
) {
305 /* Either last component exists, or there is some problem. */
312 /* The caller has to return the directory inode (*ldirp). */
318 /*===========================================================================*
320 *===========================================================================*/
325 if((rip
= find_inode(fs_dev
, (ino_t
) fs_m_in
.REQ_INODE_NR
)) == NULL
)
328 /* inhibit read ahead */