6 #include <minix/callnr.h>
11 #include <minix/vfsif.h>
13 PRIVATE
char mode_map
[] = {R_BIT
, W_BIT
, R_BIT
|W_BIT
, 0};
14 FORWARD
_PROTOTYPE( struct inode
*new_node
, (struct inode
*ldirp
,
15 char *string
, mode_t bits
, zone_t z0
));
18 /*===========================================================================*
20 *===========================================================================*/
21 PUBLIC
int fs_create()
30 /* Read request message */
31 omode
= fs_m_in
.REQ_MODE
;
32 caller_uid
= fs_m_in
.REQ_UID
;
33 caller_gid
= fs_m_in
.REQ_GID
;
35 /* Try to make the file. */
37 /* Copy the last component (i.e., file name) */
38 len
= MFS_MIN(fs_m_in
.REQ_PATH_LEN
, sizeof(lastc
));
39 err_code
= sys_safecopyfrom(FS_PROC_NR
, fs_m_in
.REQ_GRANT
, 0,
40 (vir_bytes
) lastc
, (phys_bytes
) len
, D
);
41 if (err_code
!= OK
) return err_code
;
42 MFS_NUL(lastc
, len
, sizeof(lastc
));
44 /* Get last directory inode (i.e., directory that will hold the new inode) */
45 if ((ldirp
= get_inode(fs_dev
, fs_m_in
.REQ_INODE_NR
)) == NIL_INODE
)
48 /* Create a new inode by calling new_node(). */
49 rip
= new_node(ldirp
, lastc
, omode
, NO_ZONE
);
52 /* If an error occurred, release inode. */
60 fs_m_out
.m_source
= rip
->i_dev
; /* filled with FS endpoint by the system */
61 fs_m_out
.RES_INODE_NR
= rip
->i_num
;
62 fs_m_out
.RES_MODE
= rip
->i_mode
;
63 fs_m_out
.RES_FILE_SIZE_LO
= rip
->i_size
;
65 /* This values are needed for the execution */
66 fs_m_out
.RES_UID
= rip
->i_uid
;
67 fs_m_out
.RES_GID
= rip
->i_gid
;
76 /*===========================================================================*
78 *===========================================================================*/
81 struct inode
*ip
, *ldirp
;
85 /* Copy the last component and set up caller's user and group id */
86 len
= MFS_MIN(fs_m_in
.REQ_PATH_LEN
, sizeof(lastc
));
87 err_code
= sys_safecopyfrom(FS_PROC_NR
, fs_m_in
.REQ_GRANT
, 0,
88 (vir_bytes
) lastc
, (phys_bytes
) len
, D
);
89 if (err_code
!= OK
) return err_code
;
90 MFS_NUL(lastc
, len
, sizeof(lastc
));
92 caller_uid
= fs_m_in
.REQ_UID
;
93 caller_gid
= fs_m_in
.REQ_GID
;
95 /* Get last directory inode */
96 if((ldirp
= get_inode(fs_dev
, fs_m_in
.REQ_INODE_NR
)) == NIL_INODE
)
99 /* Try to create the new node */
100 ip
= new_node(ldirp
, lastc
, fs_m_in
.REQ_MODE
, (zone_t
) fs_m_in
.REQ_DEV
);
108 /*===========================================================================*
110 *===========================================================================*/
111 PUBLIC
int fs_mkdir()
113 int r1
, r2
; /* status codes */
114 ino_t dot
, dotdot
; /* inode numbers for . and .. */
115 struct inode
*rip
, *ldirp
;
116 char lastc
[NAME_MAX
]; /* last component */
119 /* Copy the last component and set up caller's user and group id */
120 len
= MFS_MIN(fs_m_in
.REQ_PATH_LEN
, sizeof(lastc
));
121 err_code
= sys_safecopyfrom(FS_PROC_NR
, fs_m_in
.REQ_GRANT
, 0,
122 (vir_bytes
) lastc
, (phys_bytes
) len
, D
);
123 if(err_code
!= OK
) return(err_code
);
124 MFS_NUL(lastc
, len
, sizeof(lastc
));
126 caller_uid
= fs_m_in
.REQ_UID
;
127 caller_gid
= fs_m_in
.REQ_GID
;
129 /* Get last directory inode */
130 if((ldirp
= get_inode(fs_dev
, fs_m_in
.REQ_INODE_NR
)) == NIL_INODE
)
133 /* Next make the inode. If that fails, return error code. */
134 rip
= new_node(ldirp
, lastc
, fs_m_in
.REQ_MODE
, (zone_t
) 0);
136 if(rip
== NIL_INODE
|| err_code
== EEXIST
) {
137 put_inode(rip
); /* can't make dir: it already exists */
142 /* Get the inode numbers for . and .. to enter in the directory. */
143 dotdot
= ldirp
->i_num
; /* parent's inode number */
144 dot
= rip
->i_num
; /* inode number of the new dir itself */
146 /* Now make dir entries for . and .. unless the disk is completely full. */
147 /* Use dot1 and dot2, so the mode of the directory isn't important. */
148 rip
->i_mode
= fs_m_in
.REQ_MODE
; /* set mode */
149 r1
= search_dir(rip
, dot1
, &dot
, ENTER
, IGN_PERM
);/* enter . in the new dir*/
150 r2
= search_dir(rip
, dot2
, &dotdot
, ENTER
, IGN_PERM
); /* enter .. in the new
153 /* If both . and .. were successfully entered, increment the link counts. */
154 if (r1
== OK
&& r2
== OK
) {
155 /* Normal case. It was possible to enter . and .. in the new dir. */
156 rip
->i_nlinks
++; /* this accounts for . */
157 ldirp
->i_nlinks
++; /* this accounts for .. */
158 ldirp
->i_dirt
= DIRTY
; /* mark parent's inode as dirty */
160 /* It was not possible to enter . or .. probably disk was full -
161 * links counts haven't been touched. */
162 if(search_dir(ldirp
, lastc
, (ino_t
*) 0, DELETE
, IGN_PERM
) != OK
)
163 panic(__FILE__
, "Dir disappeared ", rip
->i_num
);
164 rip
->i_nlinks
--; /* undo the increment done in new_node() */
166 rip
->i_dirt
= DIRTY
; /* either way, i_nlinks has changed */
168 put_inode(ldirp
); /* return the inode of the parent dir */
169 put_inode(rip
); /* return the inode of the newly made dir */
170 return(err_code
); /* new_node() always sets 'err_code' */
174 /*===========================================================================*
176 *===========================================================================*/
177 PUBLIC
int fs_slink()
180 struct inode
*sip
; /* inode containing symbolic link */
181 struct inode
*ldirp
; /* directory containing link */
182 register int r
; /* error code */
183 char string
[NAME_MAX
]; /* last component of the new dir's path name */
184 struct buf
*bp
; /* disk buffer for link */
186 caller_uid
= fs_m_in
.REQ_UID
;
187 caller_gid
= fs_m_in
.REQ_GID
;
189 /* Copy the link name's last component */
190 len
= MFS_MIN(fs_m_in
.REQ_PATH_LEN
, sizeof(string
));
191 r
= sys_safecopyfrom(FS_PROC_NR
, fs_m_in
.REQ_GRANT
, 0,
192 (vir_bytes
) string
, (phys_bytes
) len
, D
);
193 if (r
!= OK
) return(r
);
194 MFS_NUL(string
, len
, sizeof(string
));
196 /* Temporarily open the dir. */
197 if( (ldirp
= get_inode(fs_dev
, fs_m_in
.REQ_INODE_NR
)) == NIL_INODE
)
200 /* Create the inode for the symlink. */
201 sip
= new_node(ldirp
, string
, (mode_t
) (I_SYMBOLIC_LINK
| RWX_MODES
),
204 /* Allocate a disk block for the contents of the symlink.
205 * Copy contents of symlink (the name pointed to) into first disk block. */
206 if( (r
= err_code
) == OK
) {
207 r
= (bp
= new_block(sip
, (off_t
) 0)) == NIL_BUF
? err_code
:
208 sys_safecopyfrom(FS_PROC_NR
, fs_m_in
.REQ_GRANT3
, 0,
209 (vir_bytes
) bp
->b_data
,
210 (vir_bytes
) fs_m_in
.REQ_MEM_SIZE
, D
);
213 bp
->b_data
[_MIN_BLOCK_SIZE
-1] = '\0';
214 sip
->i_size
= 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 NIL_BUF. */
232 if(search_dir(ldirp
, string
, (ino_t
*) 0, DELETE
,
235 panic(__FILE__
, "Symbolic link vanished", NO_NUM
);
239 /* put_inode() accepts NIL_INODE as a noop, so the below are safe. */
247 /*===========================================================================*
249 *===========================================================================*/
250 PUBLIC
int fs_newnode()
256 caller_uid
= fs_m_in
.REQ_UID
;
257 caller_gid
= fs_m_in
.REQ_GID
;
258 bits
= fs_m_in
.REQ_MODE
;
260 /* Try to allocate the inode */
261 if( (rip
= alloc_inode(fs_dev
, bits
) ) == NIL_INODE
)
264 switch (bits
& S_IFMT
) {
267 rip
->i_zone
[0] = fs_m_in
.REQ_DEV
; /* major/minor dev numbers*/
271 rw_inode(rip
, WRITING
); /* mark inode as allocated */
272 rip
->i_update
= ATIME
| CTIME
| MTIME
;
274 /* Fill in the fields of the response message */
275 fs_m_out
.RES_INODE_NR
= rip
->i_num
;
276 fs_m_out
.RES_MODE
= rip
->i_mode
;
277 fs_m_out
.RES_FILE_SIZE_LO
= rip
->i_size
;
278 fs_m_out
.RES_UID
= rip
->i_uid
;
279 fs_m_out
.RES_GID
= rip
->i_gid
;
280 fs_m_out
.RES_DEV
= (dev_t
) rip
->i_zone
[0];
286 /*===========================================================================*
288 *===========================================================================*/
289 PRIVATE
struct inode
*new_node(struct inode
*ldirp
,
290 char *string
, mode_t bits
, zone_t z0
)
292 /* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir().
293 * In all cases it allocates a new inode, makes a directory entry for it in
294 * the ldirp directory with string name, and initializes it.
295 * It returns a pointer to the inode if it can do this;
296 * otherwise it returns NIL_INODE. It always sets 'err_code'
297 * to an appropriate value (OK or an error code).
299 * The parsed path rest is returned in 'parsed' if parsed is nonzero. It
300 * has to hold at least NAME_MAX bytes.
303 register struct inode
*rip
;
306 /* Get final component of the path. */
307 rip
= advance(ldirp
, string
, IGN_PERM
);
310 (ldirp
)->i_nlinks
>= ((ldirp
)->i_sp
->s_version
== V1
?
311 CHAR_MAX
: SHRT_MAX
)) {
312 /* New entry is a directory, alas we can't give it a ".." */
318 if ( rip
== NIL_INODE
&& err_code
== ENOENT
) {
319 /* Last path component does not exist. Make new directory entry. */
320 if ( (rip
= alloc_inode((ldirp
)->i_dev
, bits
)) == NIL_INODE
) {
321 /* Can't creat new inode: out of inodes. */
325 /* Force inode to the disk before making directory entry to make
326 * the system more robust in the face of a crash: an inode with
327 * no directory entry is much better than the opposite.
330 rip
->i_zone
[0] = z0
; /* major/minor device numbers */
331 rw_inode(rip
, WRITING
); /* force inode to disk now */
333 /* New inode acquired. Try to make directory entry. */
334 if((r
=search_dir(ldirp
, string
, &rip
->i_num
, ENTER
, IGN_PERM
)) != OK
) {
335 rip
->i_nlinks
--; /* pity, have to free disk inode */
336 rip
->i_dirt
= DIRTY
; /* dirty inodes are written out */
337 put_inode(rip
); /* this call frees the inode */
342 } else if (err_code
== EENTERMOUNT
|| err_code
== ELEAVEMOUNT
) {
345 /* Either last component exists, or there is some problem. */
346 if (rip
!= NIL_INODE
)
352 /* The caller has to return the directory inode (*ldirp). */
358 /*===========================================================================*
360 *===========================================================================*/
361 PUBLIC
int fs_inhibread()
365 if((rip
= find_inode(fs_dev
, fs_m_in
.REQ_INODE_NR
)) == NIL_INODE
)
368 /* inhibit read ahead */