2 * linux/fs/hpfs/namei.c
4 * Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
6 * adding & removing files & directories
11 int hpfs_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
13 const char *name
= dentry
->d_name
.name
;
14 unsigned len
= dentry
->d_name
.len
;
15 struct quad_buffer_head qbh0
;
16 struct buffer_head
*bh
;
17 struct hpfs_dirent
*de
;
24 struct hpfs_dirent dee
;
26 if ((err
= hpfs_chk_name((char *)name
, &len
))) return err
==-ENOENT
? -EINVAL
: err
;
27 if (!(fnode
= hpfs_alloc_fnode(dir
->i_sb
, dir
->i_hpfs_dno
, &fno
, &bh
))) goto bail
;
28 if (!(dnode
= hpfs_alloc_dnode(dir
->i_sb
, fno
, &dno
, &qbh0
, 1))) goto bail1
;
29 memset(&dee
, 0, sizeof dee
);
31 if (!(mode
& 0222)) dee
.read_only
= 1;
33 dee
.hidden
= name
[0] == '.';
35 dee
.creation_date
= dee
.write_date
= dee
.read_date
= gmt_to_local(dir
->i_sb
, CURRENT_TIME
);
37 r
= hpfs_add_dirent(dir
, (char *)name
, len
, &dee
, 0);
38 if (r
== 1) goto bail2
;
42 hpfs_free_sectors(dir
->i_sb
, fno
, 1);
43 hpfs_free_dnode(dir
->i_sb
, dno
);
44 hpfs_unlock_inode(dir
);
48 memcpy(fnode
->name
, name
, len
> 15 ? 15 : len
);
49 fnode
->up
= dir
->i_ino
;
51 fnode
->btree
.n_free_nodes
= 7;
52 fnode
->btree
.n_used_nodes
= 1;
53 fnode
->btree
.first_free
= 0x14;
54 fnode
->u
.external
[0].disk_secno
= dno
;
55 fnode
->u
.external
[0].file_secno
= -1;
56 dnode
->root_dnode
= 1;
58 de
= hpfs_add_de(dir
->i_sb
, dnode
, "\001\001", 2, 0);
59 de
->creation_date
= de
->write_date
= de
->read_date
= gmt_to_local(dir
->i_sb
, CURRENT_TIME
);
60 if (!(mode
& 0222)) de
->read_only
= 1;
61 de
->first
= de
->directory
= 1;
62 /*de->hidden = de->system = 0;*/
64 mark_buffer_dirty(bh
, 1);
66 hpfs_mark_4buffers_dirty(&qbh0
);
69 hpfs_lock_iget(dir
->i_sb
, 1);
70 if ((result
= iget(dir
->i_sb
, fno
))) {
71 result
->i_hpfs_parent_dir
= dir
->i_ino
;
72 result
->i_ctime
= result
->i_mtime
= result
->i_atime
= local_to_gmt(dir
->i_sb
, dee
.creation_date
);
73 result
->i_hpfs_ea_size
= 0;
74 if (dee
.read_only
) result
->i_mode
&= ~0222;
75 if (result
->i_uid
!= current
->fsuid
||
76 result
->i_gid
!= current
->fsgid
||
77 result
->i_mode
!= (mode
| S_IFDIR
)) {
78 result
->i_uid
= current
->fsuid
;
79 result
->i_gid
= current
->fsgid
;
80 result
->i_mode
= mode
| S_IFDIR
;
81 hpfs_write_inode_nolock(result
);
83 d_instantiate(dentry
, result
);
85 hpfs_unlock_iget(dir
->i_sb
);
86 hpfs_unlock_inode(dir
);
90 hpfs_free_dnode(dir
->i_sb
, dno
);
91 hpfs_unlock_inode(dir
);
94 hpfs_free_sectors(dir
->i_sb
, fno
, 1);
99 int hpfs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
)
101 const char *name
= dentry
->d_name
.name
;
102 unsigned len
= dentry
->d_name
.len
;
103 struct inode
*result
= NULL
;
104 struct buffer_head
*bh
;
108 struct hpfs_dirent dee
;
110 if ((err
= hpfs_chk_name((char *)name
, &len
))) return err
==-ENOENT
? -EINVAL
: err
;
111 if (!(fnode
= hpfs_alloc_fnode(dir
->i_sb
, dir
->i_hpfs_dno
, &fno
, &bh
))) goto bail
;
112 memset(&dee
, 0, sizeof dee
);
113 if (!(mode
& 0222)) dee
.read_only
= 1;
115 dee
.hidden
= name
[0] == '.';
117 dee
.creation_date
= dee
.write_date
= dee
.read_date
= gmt_to_local(dir
->i_sb
, CURRENT_TIME
);
118 hpfs_lock_inode(dir
);
119 r
= hpfs_add_dirent(dir
, (char *)name
, len
, &dee
, 0);
120 if (r
== 1) goto bail1
;
123 hpfs_free_sectors(dir
->i_sb
, fno
, 1);
124 hpfs_unlock_inode(dir
);
128 memcpy(fnode
->name
, name
, len
> 15 ? 15 : len
);
129 fnode
->up
= dir
->i_ino
;
130 mark_buffer_dirty(bh
, 1);
132 hpfs_lock_iget(dir
->i_sb
, 2);
133 if ((result
= iget(dir
->i_sb
, fno
))) {
134 hpfs_decide_conv(result
, (char *)name
, len
);
135 result
->i_hpfs_parent_dir
= dir
->i_ino
;
136 result
->i_ctime
= result
->i_mtime
= result
->i_atime
= local_to_gmt(dir
->i_sb
, dee
.creation_date
);
137 result
->i_hpfs_ea_size
= 0;
138 if (dee
.read_only
) result
->i_mode
&= ~0222;
139 if (result
->i_blocks
== -1) result
->i_blocks
= 1;
140 if (result
->i_size
== -1) result
->i_size
= 0;
141 if (result
->i_uid
!= current
->fsuid
||
142 result
->i_gid
!= current
->fsgid
||
143 result
->i_mode
!= (mode
| S_IFREG
)) {
144 result
->i_uid
= current
->fsuid
;
145 result
->i_gid
= current
->fsgid
;
146 result
->i_mode
= mode
| S_IFREG
;
147 hpfs_write_inode_nolock(result
);
149 d_instantiate(dentry
, result
);
151 hpfs_unlock_iget(dir
->i_sb
);
152 hpfs_unlock_inode(dir
);
156 hpfs_free_sectors(dir
->i_sb
, fno
, 1);
157 hpfs_unlock_inode(dir
);
162 int hpfs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
, int rdev
)
164 const char *name
= dentry
->d_name
.name
;
165 unsigned len
= dentry
->d_name
.len
;
166 struct buffer_head
*bh
;
170 struct hpfs_dirent dee
;
171 struct inode
*result
= NULL
;
173 if ((err
= hpfs_chk_name((char *)name
, &len
))) return err
==-ENOENT
? -EINVAL
: err
;
174 if (dir
->i_sb
->s_hpfs_eas
< 2) return -EPERM
;
175 if (!(fnode
= hpfs_alloc_fnode(dir
->i_sb
, dir
->i_hpfs_dno
, &fno
, &bh
))) goto bail
;
176 memset(&dee
, 0, sizeof dee
);
177 if (!(mode
& 0222)) dee
.read_only
= 1;
179 dee
.hidden
= name
[0] == '.';
181 dee
.creation_date
= dee
.write_date
= dee
.read_date
= gmt_to_local(dir
->i_sb
, CURRENT_TIME
);
182 hpfs_lock_inode(dir
);
183 r
= hpfs_add_dirent(dir
, (char *)name
, len
, &dee
, 0);
184 if (r
== 1) goto bail1
;
187 hpfs_free_sectors(dir
->i_sb
, fno
, 1);
188 hpfs_unlock_inode(dir
);
192 memcpy(fnode
->name
, name
, len
> 15 ? 15 : len
);
193 fnode
->up
= dir
->i_ino
;
194 mark_buffer_dirty(bh
, 1);
195 hpfs_lock_iget(dir
->i_sb
, 2);
196 if ((result
= iget(dir
->i_sb
, fno
))) {
197 result
->i_hpfs_parent_dir
= dir
->i_ino
;
198 result
->i_ctime
= result
->i_mtime
= result
->i_atime
= local_to_gmt(dir
->i_sb
, dee
.creation_date
);
199 result
->i_hpfs_ea_size
= 0;
200 /*if (result->i_blocks == -1) result->i_blocks = 1;
201 if (result->i_size == -1) result->i_size = 0;*/
202 result
->i_uid
= current
->fsuid
;
203 result
->i_gid
= current
->fsgid
;
206 result
->i_blocks
= 1;
207 init_special_inode(result
, mode
, rdev
);
208 hpfs_write_inode_nolock(result
);
209 d_instantiate(dentry
, result
);
211 hpfs_unlock_iget(dir
->i_sb
);
212 hpfs_unlock_inode(dir
);
217 hpfs_free_sectors(dir
->i_sb
, fno
, 1);
218 hpfs_unlock_inode(dir
);
223 extern const struct inode_operations hpfs_symlink_iops
;
225 int hpfs_symlink(struct inode
*dir
, struct dentry
*dentry
, const char *symlink
)
227 const char *name
= dentry
->d_name
.name
;
228 unsigned len
= dentry
->d_name
.len
;
229 struct buffer_head
*bh
;
233 struct hpfs_dirent dee
;
234 struct inode
*result
;
236 if ((err
= hpfs_chk_name((char *)name
, &len
))) return err
==-ENOENT
? -EINVAL
: err
;
237 if (dir
->i_sb
->s_hpfs_eas
< 2) return -EPERM
;
238 if (!(fnode
= hpfs_alloc_fnode(dir
->i_sb
, dir
->i_hpfs_dno
, &fno
, &bh
))) goto bail
;
239 memset(&dee
, 0, sizeof dee
);
241 dee
.hidden
= name
[0] == '.';
243 dee
.creation_date
= dee
.write_date
= dee
.read_date
= gmt_to_local(dir
->i_sb
, CURRENT_TIME
);
244 hpfs_lock_inode(dir
);
245 r
= hpfs_add_dirent(dir
, (char *)name
, len
, &dee
, 0);
246 if (r
== 1) goto bail1
;
249 hpfs_free_sectors(dir
->i_sb
, fno
, 1);
250 hpfs_unlock_inode(dir
);
254 memcpy(fnode
->name
, name
, len
> 15 ? 15 : len
);
255 fnode
->up
= dir
->i_ino
;
256 mark_buffer_dirty(bh
, 1);
258 hpfs_lock_iget(dir
->i_sb
, 2);
259 if ((result
= iget(dir
->i_sb
, fno
))) {
260 result
->i_hpfs_parent_dir
= dir
->i_ino
;
261 result
->i_ctime
= result
->i_mtime
= result
->i_atime
= local_to_gmt(dir
->i_sb
, dee
.creation_date
);
262 result
->i_hpfs_ea_size
= 0;
263 /*if (result->i_blocks == -1) result->i_blocks = 1;
264 if (result->i_size == -1) result->i_size = 0;*/
265 result
->i_mode
= S_IFLNK
| 0777;
266 result
->i_uid
= current
->fsuid
;
267 result
->i_gid
= current
->fsgid
;
268 result
->i_blocks
= 1;
269 result
->i_size
= strlen(symlink
);
270 result
->i_op
= (struct inode_operations
*) &hpfs_symlink_iops
;
271 if ((fnode
= hpfs_map_fnode(dir
->i_sb
, fno
, &bh
))) {
272 hpfs_set_ea(result
, fnode
, "SYMLINK", (char *)symlink
, strlen(symlink
));
273 mark_buffer_dirty(bh
, 1);
276 hpfs_write_inode_nolock(result
);
277 d_instantiate(dentry
, result
);
279 hpfs_unlock_iget(dir
->i_sb
);
280 hpfs_unlock_inode(dir
);
284 hpfs_free_sectors(dir
->i_sb
, fno
, 1);
285 hpfs_unlock_inode(dir
);
290 int hpfs_unlink(struct inode
*dir
, struct dentry
*dentry
)
292 const char *name
= dentry
->d_name
.name
;
293 unsigned len
= dentry
->d_name
.len
;
294 struct quad_buffer_head qbh
;
295 struct hpfs_dirent
*de
;
296 struct inode
*inode
= dentry
->d_inode
;
301 hpfs_adjust_length((char *)name
, &len
);
303 hpfs_lock_2inodes(dir
, inode
);
304 if (!(de
= map_dirent(dir
, dir
->i_hpfs_dno
, (char *)name
, len
, &dno
, &qbh
))) {
305 hpfs_unlock_2inodes(dir
, inode
);
310 hpfs_unlock_2inodes(dir
, inode
);
315 hpfs_unlock_2inodes(dir
, inode
);
319 if ((r
= hpfs_remove_dirent(dir
, dno
, de
, &qbh
, 1)) == 1) hpfs_error(dir
->i_sb
, "there was error when removing dirent");
322 hpfs_unlock_2inodes(dir
, inode
);
324 } else { /* no space for deleting, try to truncate file */
325 struct iattr newattrs
;
326 hpfs_unlock_2inodes(dir
, inode
);
327 if (rep
|| dentry
->d_count
> 1 || permission(inode
, MAY_WRITE
) || get_write_access(inode
)) goto ret
;
328 /*printk("HPFS: truncating file before delete.\n");*/
329 down(&inode
->i_sem
); /* do_truncate should be called here, but it's */
330 newattrs
.ia_size
= 0; /* not exported */
331 newattrs
.ia_valid
= ATTR_SIZE
| ATTR_CTIME
;
332 if (notify_change(dentry
, &newattrs
)) {
334 put_write_access(inode
);
337 vmtruncate(inode
, 0);
338 if (inode
->i_op
&& inode
->i_op
->truncate
) inode
->i_op
->truncate(inode
);
340 put_write_access(inode
);
345 return r
== 2 ? -ENOSPC
: r
== 1 ? -EFSERROR
: 0;
348 int hpfs_rmdir(struct inode
*dir
, struct dentry
*dentry
)
350 const char *name
= dentry
->d_name
.name
;
351 unsigned len
= dentry
->d_name
.len
;
352 struct quad_buffer_head qbh
;
353 struct hpfs_dirent
*de
;
354 struct inode
*inode
= dentry
->d_inode
;
359 hpfs_adjust_length((char *)name
, &len
);
360 hpfs_lock_2inodes(dir
, inode
);
361 if (!(de
= map_dirent(dir
, dir
->i_hpfs_dno
, (char *)name
, len
, &dno
, &qbh
))) {
362 hpfs_unlock_2inodes(dir
, inode
);
367 hpfs_unlock_2inodes(dir
, inode
);
370 if (!de
->directory
) {
372 hpfs_unlock_2inodes(dir
, inode
);
375 if (!list_empty(&dentry
->d_hash
)) {
377 hpfs_unlock_2inodes(dir
, inode
);
380 hpfs_count_dnodes(dir
->i_sb
, inode
->i_hpfs_dno
, NULL
, NULL
, &n_items
);
383 hpfs_unlock_2inodes(dir
, inode
);
387 if ((r
= hpfs_remove_dirent(dir
, dno
, de
, &qbh
, 1)) == 1)
388 hpfs_error(dir
->i_sb
, "there was error when removing dirent");
392 hpfs_unlock_2inodes(dir
, inode
);
394 } else hpfs_unlock_2inodes(dir
, inode
);
395 return r
== 2 ? -ENOSPC
: r
== 1 ? -EFSERROR
: 0;
398 int hpfs_readlink(struct dentry
*dentry
, char *buf
, int len
)
400 struct inode
*i
= dentry
->d_inode
;
402 struct buffer_head
*bh
;
405 if (!S_ISLNK(i
->i_mode
)) {
408 if (!(fnode
= hpfs_map_fnode(i
->i_sb
, i
->i_ino
, &bh
))) {
411 if (!(symlink
= hpfs_get_ea(i
->i_sb
, fnode
, "SYMLINK", &slen
))) {
416 if (slen
> len
) slen
= len
;
417 memcpy_tofs(buf
, symlink
, slen
);
422 struct dentry
*hpfs_follow_link(struct dentry
*dinode
, struct dentry
*ddir
,
425 struct inode
*inode
= dinode
->d_inode
;
428 struct buffer_head
*bh
;
430 if (!(fnode
= hpfs_map_fnode(inode
->i_sb
, inode
->i_ino
, &bh
))) {
432 return ERR_PTR(-EIO
);
434 if (!(link
= hpfs_get_ea(inode
->i_sb
, fnode
, "SYMLINK", &len
))) {
437 return ERR_PTR(-EIO
);
441 ddir
= lookup_dentry(link
, ddir
, follow
);
446 int hpfs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
447 struct inode
*new_dir
, struct dentry
*new_dentry
)
449 char *old_name
= (char *)old_dentry
->d_name
.name
;
450 int old_len
= old_dentry
->d_name
.len
;
451 char *new_name
= (char *)new_dentry
->d_name
.name
;
452 int new_len
= new_dentry
->d_name
.len
;
453 struct inode
*i
= old_dentry
->d_inode
;
454 struct inode
*new_inode
= new_dentry
->d_inode
;
455 struct quad_buffer_head qbh
, qbh1
;
456 struct hpfs_dirent
*dep
, *nde
;
457 struct hpfs_dirent de
;
460 struct buffer_head
*bh
;
463 if ((err
= hpfs_chk_name((char *)new_name
, &new_len
))) return err
;
465 hpfs_adjust_length((char *)old_name
, &old_len
);
467 hpfs_lock_3inodes(old_dir
, new_dir
, i
);
469 /* Erm? Moving over the empty non-busy directory is perfectly legal */
470 if (new_inode
&& S_ISDIR(new_inode
->i_mode
)) {
475 if (!(dep
= map_dirent(old_dir
, old_dir
->i_hpfs_dno
, (char *)old_name
, old_len
, &dno
, &qbh
))) {
476 hpfs_error(i
->i_sb
, "lookup succeeded but map dirent failed");
481 de
.hidden
= new_name
[0] == '.';
485 if ((nde
= map_dirent(new_dir
, new_dir
->i_hpfs_dno
, (char *)new_name
, new_len
, NULL
, &qbh1
))) {
487 if ((r
= hpfs_remove_dirent(old_dir
, dno
, dep
, &qbh
, 1)) != 2) {
488 if (!(nde
= map_dirent(new_dir
, new_dir
->i_hpfs_dno
, (char *)new_name
, new_len
, NULL
, &qbh1
))) {
489 hpfs_error(new_dir
->i_sb
, "hpfs_rename: could not find dirent #2");
492 new_inode
->i_nlink
= 0;
494 memcpy(nde
->name
, new_name
, new_len
);
495 hpfs_mark_4buffers_dirty(&qbh1
);
499 err
= r
== 2 ? -ENOSPC
: r
== 1 ? -EFSERROR
: 0;
502 hpfs_error(new_dir
->i_sb
, "hpfs_rename: could not find dirent");
507 if (new_dir
== old_dir
) hpfs_brelse4(&qbh
);
509 hpfs_lock_creation(i
->i_sb
);
510 if ((r
= hpfs_add_dirent(new_dir
, new_name
, new_len
, &de
, 1))) {
511 hpfs_unlock_creation(i
->i_sb
);
512 if (r
== -1) hpfs_error(new_dir
->i_sb
, "hpfs_rename: dirent already exists!");
513 err
= r
== 1 ? -ENOSPC
: -EFSERROR
;
514 if (new_dir
!= old_dir
) hpfs_brelse4(&qbh
);
518 if (new_dir
== old_dir
)
519 if (!(dep
= map_dirent(old_dir
, old_dir
->i_hpfs_dno
, (char *)old_name
, old_len
, &dno
, &qbh
))) {
520 hpfs_unlock_creation(i
->i_sb
);
521 hpfs_error(i
->i_sb
, "lookup succeeded but map dirent failed at #2");
526 if ((r
= hpfs_remove_dirent(old_dir
, dno
, dep
, &qbh
, 0))) {
527 hpfs_unlock_creation(i
->i_sb
);
528 hpfs_error(i
->i_sb
, "hpfs_rename: could not remove dirent");
529 err
= r
== 2 ? -ENOSPC
: -EFSERROR
;
532 hpfs_unlock_creation(i
->i_sb
);
535 i
->i_hpfs_parent_dir
= new_dir
->i_ino
;
536 if (S_ISDIR(i
->i_mode
)) {
540 if ((fnode
= hpfs_map_fnode(i
->i_sb
, i
->i_ino
, &bh
))) {
541 fnode
->up
= new_dir
->i_ino
;
542 fnode
->len
= new_len
;
543 memcpy(fnode
->name
, new_name
, new_len
>15?15:new_len
);
544 if (new_len
< 15) memset(&fnode
->name
[new_len
], 0, 15 - new_len
);
545 mark_buffer_dirty(bh
, 1);
548 i
->i_hpfs_conv
= i
->i_sb
->s_hpfs_conv
;
549 hpfs_decide_conv(i
, (char *)new_name
, new_len
);
551 hpfs_unlock_3inodes(old_dir
, new_dir
, i
);