8 #include <minix/vfsif.h>
10 FORWARD
_PROTOTYPE( struct inode
*new_node
, (struct inode
*ldirp
,
11 char *string
, mode_t bits
, zone_t z0
));
14 /*===========================================================================*
16 *===========================================================================*/
17 PUBLIC
int fs_create()
26 /* Read request message */
27 omode
= (mode_t
) fs_m_in
.REQ_MODE
;
28 caller_uid
= (uid_t
) fs_m_in
.REQ_UID
;
29 caller_gid
= (gid_t
) fs_m_in
.REQ_GID
;
31 /* Try to make the file. */
33 /* Copy the last component (i.e., file name) */
34 len
= min( (unsigned) fs_m_in
.REQ_PATH_LEN
, sizeof(lastc
));
35 err_code
= sys_safecopyfrom(FS_PROC_NR
, (cp_grant_id_t
) fs_m_in
.REQ_GRANT
,
36 (vir_bytes
) 0, (vir_bytes
) lastc
, (size_t) len
, D
);
37 if (err_code
!= OK
) return err_code
;
38 NUL(lastc
, len
, sizeof(lastc
));
40 /* Get last directory inode (i.e., directory that will hold the new inode) */
41 if ((ldirp
= get_inode(fs_dev
, (ino_t
) fs_m_in
.REQ_INODE_NR
)) == NULL
)
44 /* Create a new inode by calling new_node(). */
45 rip
= new_node(ldirp
, lastc
, omode
, NO_ZONE
);
48 /* If an error occurred, release inode. */
56 fs_m_out
.RES_INODE_NR
= rip
->i_num
;
57 fs_m_out
.RES_MODE
= rip
->i_mode
;
58 fs_m_out
.RES_FILE_SIZE_LO
= rip
->i_size
;
60 /* This values are needed for the execution */
61 fs_m_out
.RES_UID
= rip
->i_uid
;
62 fs_m_out
.RES_GID
= rip
->i_gid
;
71 /*===========================================================================*
73 *===========================================================================*/
76 struct inode
*ip
, *ldirp
;
80 /* Copy the last component and set up caller's user and group id */
81 len
= min( (unsigned) fs_m_in
.REQ_PATH_LEN
, sizeof(lastc
));
82 err_code
= sys_safecopyfrom(FS_PROC_NR
, (cp_grant_id_t
) fs_m_in
.REQ_GRANT
,
83 (vir_bytes
) 0, (vir_bytes
) lastc
, (size_t) len
, D
);
84 if (err_code
!= OK
) return err_code
;
85 NUL(lastc
, len
, sizeof(lastc
));
87 caller_uid
= (uid_t
) fs_m_in
.REQ_UID
;
88 caller_gid
= (gid_t
) fs_m_in
.REQ_GID
;
90 /* Get last directory inode */
91 if((ldirp
= get_inode(fs_dev
, (ino_t
) fs_m_in
.REQ_INODE_NR
)) == NULL
)
94 /* Try to create the new node */
95 ip
= new_node(ldirp
, lastc
, (mode_t
) fs_m_in
.REQ_MODE
,
96 (zone_t
) fs_m_in
.REQ_DEV
);
104 /*===========================================================================*
106 *===========================================================================*/
107 PUBLIC
int fs_mkdir()
109 int r1
, r2
; /* status codes */
110 ino_t dot
, dotdot
; /* inode numbers for . and .. */
111 struct inode
*rip
, *ldirp
;
112 char lastc
[NAME_MAX
]; /* last component */
115 /* Copy the last component and set up caller's user and group id */
116 len
= min( (unsigned) fs_m_in
.REQ_PATH_LEN
, sizeof(lastc
));
117 err_code
= sys_safecopyfrom(FS_PROC_NR
, (cp_grant_id_t
) fs_m_in
.REQ_GRANT
,
118 (vir_bytes
) 0, (vir_bytes
) lastc
, (size_t) len
, D
);
119 if(err_code
!= OK
) return(err_code
);
120 NUL(lastc
, len
, sizeof(lastc
));
122 caller_uid
= (uid_t
) fs_m_in
.REQ_UID
;
123 caller_gid
= (gid_t
) fs_m_in
.REQ_GID
;
125 /* Get last directory inode */
126 if((ldirp
= get_inode(fs_dev
, (ino_t
) fs_m_in
.REQ_INODE_NR
)) == NULL
)
129 /* Next make the inode. If that fails, return error code. */
130 rip
= new_node(ldirp
, lastc
, (mode_t
) fs_m_in
.REQ_MODE
, (zone_t
) 0);
132 if(rip
== NULL
|| err_code
== EEXIST
) {
133 put_inode(rip
); /* can't make dir: it already exists */
138 /* Get the inode numbers for . and .. to enter in the directory. */
139 dotdot
= ldirp
->i_num
; /* parent's inode number */
140 dot
= rip
->i_num
; /* inode number of the new dir itself */
142 /* Now make dir entries for . and .. unless the disk is completely full. */
143 /* Use dot1 and dot2, so the mode of the directory isn't important. */
144 rip
->i_mode
= (mode_t
) fs_m_in
.REQ_MODE
; /* set mode */
145 r1
= search_dir(rip
, dot1
, &dot
, ENTER
, IGN_PERM
);/* enter . in the new dir*/
146 r2
= search_dir(rip
, dot2
, &dotdot
, ENTER
, IGN_PERM
); /* enter .. in the new
149 /* If both . and .. were successfully entered, increment the link counts. */
150 if (r1
== OK
&& r2
== OK
) {
151 /* Normal case. It was possible to enter . and .. in the new dir. */
152 rip
->i_nlinks
++; /* this accounts for . */
153 ldirp
->i_nlinks
++; /* this accounts for .. */
154 ldirp
->i_dirt
= DIRTY
; /* mark parent's inode as dirty */
156 /* It was not possible to enter . or .. probably disk was full -
157 * links counts haven't been touched. */
158 if(search_dir(ldirp
, lastc
, (ino_t
*) 0, DELETE
, IGN_PERM
) != OK
)
159 panic("Dir disappeared: %ul", rip
->i_num
);
160 rip
->i_nlinks
--; /* undo the increment done in new_node() */
162 rip
->i_dirt
= DIRTY
; /* either way, i_nlinks has changed */
164 put_inode(ldirp
); /* return the inode of the parent dir */
165 put_inode(rip
); /* return the inode of the newly made dir */
166 return(err_code
); /* new_node() always sets 'err_code' */
170 /*===========================================================================*
172 *===========================================================================*/
173 PUBLIC
int fs_slink()
176 struct inode
*sip
; /* inode containing symbolic link */
177 struct inode
*ldirp
; /* directory containing link */
178 register int r
; /* error code */
179 char string
[NAME_MAX
]; /* last component of the new dir's path name */
180 struct buf
*bp
; /* disk buffer for link */
182 caller_uid
= (uid_t
) fs_m_in
.REQ_UID
;
183 caller_gid
= (gid_t
) fs_m_in
.REQ_GID
;
185 /* Copy the link name's last component */
186 len
= min( (unsigned) fs_m_in
.REQ_PATH_LEN
, sizeof(string
));
187 r
= sys_safecopyfrom(FS_PROC_NR
, (cp_grant_id_t
) fs_m_in
.REQ_GRANT
,
188 (vir_bytes
) 0, (vir_bytes
) string
, (size_t) len
, D
);
189 if (r
!= OK
) return(r
);
190 NUL(string
, len
, sizeof(string
));
192 /* Temporarily open the dir. */
193 if( (ldirp
= get_inode(fs_dev
, (ino_t
) fs_m_in
.REQ_INODE_NR
)) == NULL
)
196 /* Create the inode for the symlink. */
197 sip
= new_node(ldirp
, string
, (mode_t
) (I_SYMBOLIC_LINK
| RWX_MODES
),
200 /* Allocate a disk block for the contents of the symlink.
201 * Copy contents of symlink (the name pointed to) into first disk block. */
202 if( (r
= err_code
) == OK
) {
203 bp
= new_block(sip
, (off_t
) 0);
207 r
= sys_safecopyfrom(FS_PROC_NR
,
208 (cp_grant_id_t
) fs_m_in
.REQ_GRANT3
,
209 (vir_bytes
) 0, (vir_bytes
) bp
->b_data
,
210 (size_t) fs_m_in
.REQ_MEM_SIZE
, D
);
212 if(bp
!= NULL
&& r
== OK
) {
213 bp
->b_data
[_MIN_BLOCK_SIZE
-1] = '\0';
214 sip
->i_size
= (off_t
) strlen(bp
->b_data
);
215 if(sip
->i_size
!= fs_m_in
.REQ_MEM_SIZE
) {
216 /* This can happen if the user provides a buffer
217 * with a \0 in it. This can cause a lot of trouble
218 * when the symlink is used later. We could just use
219 * the strlen() value, but we want to let the user
220 * know he did something wrong. ENAMETOOLONG doesn't
221 * exactly describe the error, but there is no
228 put_block(bp
, DIRECTORY_BLOCK
); /* put_block() accepts NULL. */
231 sip
->i_nlinks
= NO_LINK
;
232 if(search_dir(ldirp
, string
, NULL
, DELETE
, IGN_PERM
) != OK
)
233 panic("Symbolic link vanished");
237 /* put_inode() accepts NULL as a noop, so the below are safe. */
244 /*===========================================================================*
246 *===========================================================================*/
247 PRIVATE
struct inode
*new_node(struct inode
*ldirp
,
248 char *string
, mode_t bits
, zone_t z0
)
250 /* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir().
251 * In all cases it allocates a new inode, makes a directory entry for it in
252 * the ldirp directory with string name, and initializes it.
253 * It returns a pointer to the inode if it can do this;
254 * otherwise it returns NULL. It always sets 'err_code'
255 * to an appropriate value (OK or an error code).
257 * The parsed path rest is returned in 'parsed' if parsed is nonzero. It
258 * has to hold at least NAME_MAX bytes.
261 register struct inode
*rip
;
264 /* Get final component of the path. */
265 rip
= advance(ldirp
, string
, IGN_PERM
);
267 if (S_ISDIR(bits
) && (ldirp
->i_nlinks
>= LINK_MAX
)) {
268 /* New entry is a directory, alas we can't give it a ".." */
274 if ( rip
== NULL
&& err_code
== ENOENT
) {
275 /* Last path component does not exist. Make new directory entry. */
276 if ( (rip
= alloc_inode((ldirp
)->i_dev
, bits
)) == NULL
) {
277 /* Can't creat new inode: out of inodes. */
281 /* Force inode to the disk before making directory entry to make
282 * the system more robust in the face of a crash: an inode with
283 * no directory entry is much better than the opposite.
286 rip
->i_zone
[0] = z0
; /* major/minor device numbers */
287 rw_inode(rip
, WRITING
); /* force inode to disk now */
289 /* New inode acquired. Try to make directory entry. */
290 if((r
=search_dir(ldirp
, string
, &rip
->i_num
, ENTER
, IGN_PERM
)) != OK
) {
291 rip
->i_nlinks
--; /* pity, have to free disk inode */
292 rip
->i_dirt
= DIRTY
; /* dirty inodes are written out */
293 put_inode(rip
); /* this call frees the inode */
298 } else if (err_code
== EENTERMOUNT
|| err_code
== ELEAVEMOUNT
) {
301 /* Either last component exists, or there is some problem. */
308 /* The caller has to return the directory inode (*ldirp). */
314 /*===========================================================================*
316 *===========================================================================*/
317 PUBLIC
int fs_inhibread()
321 if((rip
= find_inode(fs_dev
, (ino_t
) fs_m_in
.REQ_INODE_NR
)) == NULL
)
324 /* inhibit read ahead */