8 static struct inode
*new_node(struct inode
*ldirp
, char *string
, mode_t
9 bits
, uid_t uid
, gid_t gid
, zone_t z0
);
11 /*===========================================================================*
13 *===========================================================================*/
14 int fs_create(ino_t dir_nr
, char *name
, mode_t mode
, uid_t uid
, gid_t gid
,
15 struct fsdriver_node
*node
)
21 /* Try to make the file. */
23 /* Get last directory inode (i.e., directory that will hold the new inode) */
24 if ((ldirp
= get_inode(fs_dev
, dir_nr
)) == NULL
)
27 /* Create a new inode by calling new_node(). */
28 rip
= new_node(ldirp
, name
, mode
, uid
, gid
, NO_ZONE
);
31 /* If an error occurred, release inode. */
39 node
->fn_ino_nr
= rip
->i_num
;
40 node
->fn_mode
= rip
->i_mode
;
41 node
->fn_size
= rip
->i_size
;
42 node
->fn_uid
= rip
->i_uid
;
43 node
->fn_gid
= rip
->i_gid
;
44 node
->fn_dev
= NO_DEV
;
53 /*===========================================================================*
55 *===========================================================================*/
56 int fs_mknod(ino_t dir_nr
, char *name
, mode_t mode
, uid_t uid
, gid_t gid
,
59 struct inode
*ip
, *ldirp
;
61 /* Get last directory inode */
62 if((ldirp
= get_inode(fs_dev
, dir_nr
)) == NULL
)
65 /* Try to create the new node */
66 ip
= new_node(ldirp
, name
, mode
, uid
, gid
, (zone_t
) dev
);
74 /*===========================================================================*
76 *===========================================================================*/
77 int fs_mkdir(ino_t dir_nr
, char *name
, mode_t mode
, uid_t uid
, gid_t gid
)
79 int r1
, r2
; /* status codes */
80 ino_t dot
, dotdot
; /* inode numbers for . and .. */
81 struct inode
*rip
, *ldirp
;
83 /* Get last directory inode */
84 if((ldirp
= get_inode(fs_dev
, dir_nr
)) == NULL
)
87 /* Next make the inode. If that fails, return error code. */
88 rip
= new_node(ldirp
, name
, mode
, uid
, gid
, (zone_t
) 0);
90 if(rip
== NULL
|| err_code
== EEXIST
) {
91 put_inode(rip
); /* can't make dir: it already exists */
96 /* Get the inode numbers for . and .. to enter in the directory. */
97 dotdot
= ldirp
->i_num
; /* parent's inode number */
98 dot
= rip
->i_num
; /* inode number of the new dir itself */
100 /* Now make dir entries for . and .. unless the disk is completely full. */
101 r1
= search_dir(rip
, ".", &dot
, ENTER
); /* enter . in the new dir */
102 r2
= search_dir(rip
, "..", &dotdot
, ENTER
); /* enter .. in the new dir */
104 /* If both . and .. were successfully entered, increment the link counts. */
105 if (r1
== OK
&& r2
== OK
) {
106 /* Normal case. It was possible to enter . and .. in the new dir. */
107 rip
->i_nlinks
++; /* this accounts for . */
108 ldirp
->i_nlinks
++; /* this accounts for .. */
109 IN_MARKDIRTY(ldirp
); /* mark parent's inode as dirty */
111 /* It was not possible to enter . or .. probably disk was full -
112 * links counts haven't been touched. */
113 if(search_dir(ldirp
, name
, NULL
, DELETE
) != OK
)
114 panic("Dir disappeared: %llu", rip
->i_num
);
115 rip
->i_nlinks
--; /* undo the increment done in new_node() */
117 IN_MARKDIRTY(rip
); /* either way, i_nlinks has changed */
119 put_inode(ldirp
); /* return the inode of the parent dir */
120 put_inode(rip
); /* return the inode of the newly made dir */
121 return(err_code
); /* new_node() always sets 'err_code' */
125 /*===========================================================================*
127 *===========================================================================*/
128 int fs_slink(ino_t dir_nr
, char *name
, uid_t uid
, gid_t gid
,
129 struct fsdriver_data
*data
, size_t bytes
)
131 struct inode
*sip
; /* inode containing symbolic link */
132 struct inode
*ldirp
; /* directory containing link */
133 register int r
; /* error code */
134 struct buf
*bp
; /* disk buffer for link */
136 /* Temporarily open the dir. */
137 if( (ldirp
= get_inode(fs_dev
, dir_nr
)) == NULL
)
140 /* Create the inode for the symlink. */
141 sip
= new_node(ldirp
, name
, (I_SYMBOLIC_LINK
| RWX_MODES
), uid
, gid
, 0);
143 /* Allocate a disk block for the contents of the symlink.
144 * Copy contents of symlink (the name pointed to) into first disk block. */
145 if( (r
= err_code
) == OK
) {
146 bp
= new_block(sip
, (off_t
) 0);
150 if(get_block_size(sip
->i_dev
) <= bytes
) {
153 r
= fsdriver_copyin(data
, 0, b_data(bp
), bytes
);
154 b_data(bp
)[bytes
] = '\0';
158 if(bp
!= NULL
&& r
== OK
) {
159 sip
->i_size
= (off_t
) strlen(b_data(bp
));
160 if(sip
->i_size
!= bytes
) {
161 /* This can happen if the user provides a buffer
162 * with a \0 in it. This can cause a lot of trouble
163 * when the symlink is used later. We could just use
164 * the strlen() value, but we want to let the user
165 * know he did something wrong. ENAMETOOLONG doesn't
166 * exactly describe the error, but there is no
173 put_block(bp
); /* put_block() accepts NULL. */
176 sip
->i_nlinks
= NO_LINK
;
177 if(search_dir(ldirp
, name
, NULL
, DELETE
) != OK
)
178 panic("Symbolic link vanished");
182 /* put_inode() accepts NULL as a noop, so the below are safe. */
189 /*===========================================================================*
191 *===========================================================================*/
192 static struct inode
*new_node(struct inode
*ldirp
,
193 char *string
, mode_t bits
, uid_t uid
, gid_t gid
, zone_t z0
)
195 /* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir().
196 * In all cases it allocates a new inode, makes a directory entry for it in
197 * the ldirp directory with string name, and initializes it.
198 * It returns a pointer to the inode if it can do this;
199 * otherwise it returns NULL. It always sets 'err_code'
200 * to an appropriate value (OK or an error code).
202 * The parsed path rest is returned in 'parsed' if parsed is nonzero. It
203 * has to hold at least MFS_NAME_MAX bytes.
205 register struct inode
*rip
;
208 if (ldirp
->i_nlinks
== NO_LINK
) { /* Dir does not actually exist */
213 if (S_ISDIR(bits
) && (ldirp
->i_nlinks
>= LINK_MAX
)) {
214 /* New entry is a directory, alas we can't give it a ".." */
219 /* Get final component of the path. */
220 rip
= advance(ldirp
, string
);
222 if ( rip
== NULL
&& err_code
== ENOENT
) {
223 /* Last path component does not exist. Make new directory entry. */
224 if ( (rip
= alloc_inode((ldirp
)->i_dev
, bits
, uid
, gid
)) == NULL
) {
225 /* Can't creat new inode: out of inodes. */
229 /* Force inode to the disk before making directory entry to make
230 * the system more robust in the face of a crash: an inode with
231 * no directory entry is much better than the opposite.
234 rip
->i_zone
[0] = z0
; /* major/minor device numbers */
235 rw_inode(rip
, WRITING
); /* force inode to disk now */
237 /* New inode acquired. Try to make directory entry. */
238 if((r
=search_dir(ldirp
, string
, &rip
->i_num
, ENTER
)) != OK
) {
239 rip
->i_nlinks
--; /* pity, have to free disk inode */
240 IN_MARKDIRTY(rip
); /* dirty inodes are written out */
241 put_inode(rip
); /* this call frees the inode */
247 /* Either last component exists, or there is some problem. */
254 /* The caller has to return the directory inode (*ldirp). */
260 /*===========================================================================*
262 *===========================================================================*/
263 void fs_seek(ino_t ino_nr
)
267 /* inhibit read ahead */
268 if ((rip
= find_inode(fs_dev
, ino_nr
)) != NULL
)