2 * linux/fs/hpfs/namei.c
4 * Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
6 * adding & removing files & directories
9 #include <linux/string.h>
12 int hpfs_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
14 const char *name
= dentry
->d_name
.name
;
15 unsigned len
= dentry
->d_name
.len
;
16 struct quad_buffer_head qbh0
;
17 struct buffer_head
*bh
;
18 struct hpfs_dirent
*de
;
25 struct hpfs_dirent dee
;
27 if ((err
= hpfs_chk_name((char *)name
, &len
))) return err
==-ENOENT
? -EINVAL
: err
;
28 if (!(fnode
= hpfs_alloc_fnode(dir
->i_sb
, dir
->i_hpfs_dno
, &fno
, &bh
))) goto bail
;
29 if (!(dnode
= hpfs_alloc_dnode(dir
->i_sb
, fno
, &dno
, &qbh0
, 1))) goto bail1
;
30 memset(&dee
, 0, sizeof dee
);
32 if (!(mode
& 0222)) dee
.read_only
= 1;
34 dee
.hidden
= name
[0] == '.';
36 dee
.creation_date
= dee
.write_date
= dee
.read_date
= gmt_to_local(dir
->i_sb
, CURRENT_TIME
);
38 r
= hpfs_add_dirent(dir
, (char *)name
, len
, &dee
, 0);
39 if (r
== 1) goto bail2
;
43 hpfs_free_sectors(dir
->i_sb
, fno
, 1);
44 hpfs_free_dnode(dir
->i_sb
, dno
);
45 hpfs_unlock_inode(dir
);
49 memcpy(fnode
->name
, name
, len
> 15 ? 15 : len
);
50 fnode
->up
= dir
->i_ino
;
52 fnode
->btree
.n_free_nodes
= 7;
53 fnode
->btree
.n_used_nodes
= 1;
54 fnode
->btree
.first_free
= 0x14;
55 fnode
->u
.external
[0].disk_secno
= dno
;
56 fnode
->u
.external
[0].file_secno
= -1;
57 dnode
->root_dnode
= 1;
59 de
= hpfs_add_de(dir
->i_sb
, dnode
, "\001\001", 2, 0);
60 de
->creation_date
= de
->write_date
= de
->read_date
= gmt_to_local(dir
->i_sb
, CURRENT_TIME
);
61 if (!(mode
& 0222)) de
->read_only
= 1;
62 de
->first
= de
->directory
= 1;
63 /*de->hidden = de->system = 0;*/
65 mark_buffer_dirty(bh
, 1);
67 hpfs_mark_4buffers_dirty(&qbh0
);
70 hpfs_lock_iget(dir
->i_sb
, 1);
71 if ((result
= iget(dir
->i_sb
, fno
))) {
72 result
->i_hpfs_parent_dir
= dir
->i_ino
;
73 result
->i_ctime
= result
->i_mtime
= result
->i_atime
= local_to_gmt(dir
->i_sb
, dee
.creation_date
);
74 result
->i_hpfs_ea_size
= 0;
75 if (dee
.read_only
) result
->i_mode
&= ~0222;
76 if (result
->i_uid
!= current
->fsuid
||
77 result
->i_gid
!= current
->fsgid
||
78 result
->i_mode
!= (mode
| S_IFDIR
)) {
79 result
->i_uid
= current
->fsuid
;
80 result
->i_gid
= current
->fsgid
;
81 result
->i_mode
= mode
| S_IFDIR
;
82 hpfs_write_inode_nolock(result
);
84 d_instantiate(dentry
, result
);
86 hpfs_unlock_iget(dir
->i_sb
);
87 hpfs_unlock_inode(dir
);
91 hpfs_free_dnode(dir
->i_sb
, dno
);
92 hpfs_unlock_inode(dir
);
95 hpfs_free_sectors(dir
->i_sb
, fno
, 1);
100 int hpfs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
)
102 const char *name
= dentry
->d_name
.name
;
103 unsigned len
= dentry
->d_name
.len
;
104 struct inode
*result
= NULL
;
105 struct buffer_head
*bh
;
109 struct hpfs_dirent dee
;
111 if ((err
= hpfs_chk_name((char *)name
, &len
))) return err
==-ENOENT
? -EINVAL
: err
;
112 if (!(fnode
= hpfs_alloc_fnode(dir
->i_sb
, dir
->i_hpfs_dno
, &fno
, &bh
))) goto bail
;
113 memset(&dee
, 0, sizeof dee
);
114 if (!(mode
& 0222)) dee
.read_only
= 1;
116 dee
.hidden
= name
[0] == '.';
118 dee
.creation_date
= dee
.write_date
= dee
.read_date
= gmt_to_local(dir
->i_sb
, CURRENT_TIME
);
119 hpfs_lock_inode(dir
);
120 r
= hpfs_add_dirent(dir
, (char *)name
, len
, &dee
, 0);
121 if (r
== 1) goto bail1
;
124 hpfs_free_sectors(dir
->i_sb
, fno
, 1);
125 hpfs_unlock_inode(dir
);
129 memcpy(fnode
->name
, name
, len
> 15 ? 15 : len
);
130 fnode
->up
= dir
->i_ino
;
131 mark_buffer_dirty(bh
, 1);
133 hpfs_lock_iget(dir
->i_sb
, 2);
134 if ((result
= iget(dir
->i_sb
, fno
))) {
135 hpfs_decide_conv(result
, (char *)name
, len
);
136 result
->i_hpfs_parent_dir
= dir
->i_ino
;
137 result
->i_ctime
= result
->i_mtime
= result
->i_atime
= local_to_gmt(dir
->i_sb
, dee
.creation_date
);
138 result
->i_hpfs_ea_size
= 0;
139 if (dee
.read_only
) result
->i_mode
&= ~0222;
140 if (result
->i_blocks
== -1) result
->i_blocks
= 1;
141 if (result
->i_size
== -1) result
->i_size
= 0;
142 if (result
->i_uid
!= current
->fsuid
||
143 result
->i_gid
!= current
->fsgid
||
144 result
->i_mode
!= (mode
| S_IFREG
)) {
145 result
->i_uid
= current
->fsuid
;
146 result
->i_gid
= current
->fsgid
;
147 result
->i_mode
= mode
| S_IFREG
;
148 hpfs_write_inode_nolock(result
);
150 d_instantiate(dentry
, result
);
152 hpfs_unlock_iget(dir
->i_sb
);
153 hpfs_unlock_inode(dir
);
157 hpfs_free_sectors(dir
->i_sb
, fno
, 1);
158 hpfs_unlock_inode(dir
);
163 int hpfs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
, int rdev
)
165 const char *name
= dentry
->d_name
.name
;
166 unsigned len
= dentry
->d_name
.len
;
167 struct buffer_head
*bh
;
171 struct hpfs_dirent dee
;
172 struct inode
*result
= NULL
;
174 if ((err
= hpfs_chk_name((char *)name
, &len
))) return err
==-ENOENT
? -EINVAL
: err
;
175 if (dir
->i_sb
->s_hpfs_eas
< 2) return -EPERM
;
176 if (!(fnode
= hpfs_alloc_fnode(dir
->i_sb
, dir
->i_hpfs_dno
, &fno
, &bh
))) goto bail
;
177 memset(&dee
, 0, sizeof dee
);
178 if (!(mode
& 0222)) dee
.read_only
= 1;
180 dee
.hidden
= name
[0] == '.';
182 dee
.creation_date
= dee
.write_date
= dee
.read_date
= gmt_to_local(dir
->i_sb
, CURRENT_TIME
);
183 hpfs_lock_inode(dir
);
184 r
= hpfs_add_dirent(dir
, (char *)name
, len
, &dee
, 0);
185 if (r
== 1) goto bail1
;
188 hpfs_free_sectors(dir
->i_sb
, fno
, 1);
189 hpfs_unlock_inode(dir
);
193 memcpy(fnode
->name
, name
, len
> 15 ? 15 : len
);
194 fnode
->up
= dir
->i_ino
;
195 mark_buffer_dirty(bh
, 1);
196 hpfs_lock_iget(dir
->i_sb
, 2);
197 if ((result
= iget(dir
->i_sb
, fno
))) {
198 result
->i_hpfs_parent_dir
= dir
->i_ino
;
199 result
->i_ctime
= result
->i_mtime
= result
->i_atime
= local_to_gmt(dir
->i_sb
, dee
.creation_date
);
200 result
->i_hpfs_ea_size
= 0;
201 /*if (result->i_blocks == -1) result->i_blocks = 1;
202 if (result->i_size == -1) result->i_size = 0;*/
203 result
->i_uid
= current
->fsuid
;
204 result
->i_gid
= current
->fsgid
;
207 result
->i_blocks
= 1;
208 init_special_inode(result
, mode
, rdev
);
209 hpfs_write_inode_nolock(result
);
210 d_instantiate(dentry
, result
);
212 hpfs_unlock_iget(dir
->i_sb
);
213 hpfs_unlock_inode(dir
);
218 hpfs_free_sectors(dir
->i_sb
, fno
, 1);
219 hpfs_unlock_inode(dir
);
224 extern const struct inode_operations hpfs_symlink_iops
;
226 int hpfs_symlink(struct inode
*dir
, struct dentry
*dentry
, const char *symlink
)
228 const char *name
= dentry
->d_name
.name
;
229 unsigned len
= dentry
->d_name
.len
;
230 struct buffer_head
*bh
;
234 struct hpfs_dirent dee
;
235 struct inode
*result
;
237 if ((err
= hpfs_chk_name((char *)name
, &len
))) return err
==-ENOENT
? -EINVAL
: err
;
238 if (dir
->i_sb
->s_hpfs_eas
< 2) return -EPERM
;
239 if (!(fnode
= hpfs_alloc_fnode(dir
->i_sb
, dir
->i_hpfs_dno
, &fno
, &bh
))) goto bail
;
240 memset(&dee
, 0, sizeof dee
);
242 dee
.hidden
= name
[0] == '.';
244 dee
.creation_date
= dee
.write_date
= dee
.read_date
= gmt_to_local(dir
->i_sb
, CURRENT_TIME
);
245 hpfs_lock_inode(dir
);
246 r
= hpfs_add_dirent(dir
, (char *)name
, len
, &dee
, 0);
247 if (r
== 1) goto bail1
;
250 hpfs_free_sectors(dir
->i_sb
, fno
, 1);
251 hpfs_unlock_inode(dir
);
255 memcpy(fnode
->name
, name
, len
> 15 ? 15 : len
);
256 fnode
->up
= dir
->i_ino
;
257 mark_buffer_dirty(bh
, 1);
259 hpfs_lock_iget(dir
->i_sb
, 2);
260 if ((result
= iget(dir
->i_sb
, fno
))) {
261 result
->i_hpfs_parent_dir
= dir
->i_ino
;
262 result
->i_ctime
= result
->i_mtime
= result
->i_atime
= local_to_gmt(dir
->i_sb
, dee
.creation_date
);
263 result
->i_hpfs_ea_size
= 0;
264 /*if (result->i_blocks == -1) result->i_blocks = 1;
265 if (result->i_size == -1) result->i_size = 0;*/
266 result
->i_mode
= S_IFLNK
| 0777;
267 result
->i_uid
= current
->fsuid
;
268 result
->i_gid
= current
->fsgid
;
269 result
->i_blocks
= 1;
270 result
->i_size
= strlen(symlink
);
271 result
->i_op
= (struct inode_operations
*) &hpfs_symlink_iops
;
272 if ((fnode
= hpfs_map_fnode(dir
->i_sb
, fno
, &bh
))) {
273 hpfs_set_ea(result
, fnode
, "SYMLINK", (char *)symlink
, strlen(symlink
));
274 mark_buffer_dirty(bh
, 1);
277 hpfs_write_inode_nolock(result
);
278 d_instantiate(dentry
, result
);
280 hpfs_unlock_iget(dir
->i_sb
);
281 hpfs_unlock_inode(dir
);
285 hpfs_free_sectors(dir
->i_sb
, fno
, 1);
286 hpfs_unlock_inode(dir
);
291 int hpfs_unlink(struct inode
*dir
, struct dentry
*dentry
)
293 const char *name
= dentry
->d_name
.name
;
294 unsigned len
= dentry
->d_name
.len
;
295 struct quad_buffer_head qbh
;
296 struct hpfs_dirent
*de
;
297 struct inode
*inode
= dentry
->d_inode
;
302 hpfs_adjust_length((char *)name
, &len
);
304 hpfs_lock_2inodes(dir
, inode
);
305 if (!(de
= map_dirent(dir
, dir
->i_hpfs_dno
, (char *)name
, len
, &dno
, &qbh
))) {
306 hpfs_unlock_2inodes(dir
, inode
);
311 hpfs_unlock_2inodes(dir
, inode
);
316 hpfs_unlock_2inodes(dir
, inode
);
320 if ((r
= hpfs_remove_dirent(dir
, dno
, de
, &qbh
, 1)) == 1) hpfs_error(dir
->i_sb
, "there was error when removing dirent");
323 hpfs_unlock_2inodes(dir
, inode
);
325 } else { /* no space for deleting, try to truncate file */
326 struct iattr newattrs
;
327 hpfs_unlock_2inodes(dir
, inode
);
328 if (rep
|| dentry
->d_count
> 1 || permission(inode
, MAY_WRITE
) || get_write_access(inode
)) goto ret
;
329 /*printk("HPFS: truncating file before delete.\n");*/
330 down(&inode
->i_sem
); /* do_truncate should be called here, but it's */
331 newattrs
.ia_size
= 0; /* not exported */
332 newattrs
.ia_valid
= ATTR_SIZE
| ATTR_CTIME
;
333 if (notify_change(dentry
, &newattrs
)) {
335 put_write_access(inode
);
338 vmtruncate(inode
, 0);
339 if (inode
->i_op
&& inode
->i_op
->truncate
) inode
->i_op
->truncate(inode
);
341 put_write_access(inode
);
346 return r
== 2 ? -ENOSPC
: r
== 1 ? -EFSERROR
: 0;
349 int hpfs_rmdir(struct inode
*dir
, struct dentry
*dentry
)
351 const char *name
= dentry
->d_name
.name
;
352 unsigned len
= dentry
->d_name
.len
;
353 struct quad_buffer_head qbh
;
354 struct hpfs_dirent
*de
;
355 struct inode
*inode
= dentry
->d_inode
;
360 hpfs_adjust_length((char *)name
, &len
);
361 hpfs_lock_2inodes(dir
, inode
);
362 if (!(de
= map_dirent(dir
, dir
->i_hpfs_dno
, (char *)name
, len
, &dno
, &qbh
))) {
363 hpfs_unlock_2inodes(dir
, inode
);
368 hpfs_unlock_2inodes(dir
, inode
);
371 if (!de
->directory
) {
373 hpfs_unlock_2inodes(dir
, inode
);
376 if (!list_empty(&dentry
->d_hash
)) {
378 hpfs_unlock_2inodes(dir
, inode
);
381 hpfs_count_dnodes(dir
->i_sb
, inode
->i_hpfs_dno
, NULL
, NULL
, &n_items
);
384 hpfs_unlock_2inodes(dir
, inode
);
388 if ((r
= hpfs_remove_dirent(dir
, dno
, de
, &qbh
, 1)) == 1)
389 hpfs_error(dir
->i_sb
, "there was error when removing dirent");
393 hpfs_unlock_2inodes(dir
, inode
);
395 } else hpfs_unlock_2inodes(dir
, inode
);
396 return r
== 2 ? -ENOSPC
: r
== 1 ? -EFSERROR
: 0;
399 int hpfs_readlink(struct dentry
*dentry
, char *buf
, int len
)
401 struct inode
*i
= dentry
->d_inode
;
403 struct buffer_head
*bh
;
406 if (!S_ISLNK(i
->i_mode
)) {
409 if (!(fnode
= hpfs_map_fnode(i
->i_sb
, i
->i_ino
, &bh
))) {
412 if (!(symlink
= hpfs_get_ea(i
->i_sb
, fnode
, "SYMLINK", &slen
))) {
417 if (slen
> len
) slen
= len
;
418 memcpy_tofs(buf
, symlink
, slen
);
423 struct dentry
*hpfs_follow_link(struct dentry
*dinode
, struct dentry
*ddir
,
426 struct inode
*inode
= dinode
->d_inode
;
429 struct buffer_head
*bh
;
431 if (!(fnode
= hpfs_map_fnode(inode
->i_sb
, inode
->i_ino
, &bh
))) {
433 return ERR_PTR(-EIO
);
435 if (!(link
= hpfs_get_ea(inode
->i_sb
, fnode
, "SYMLINK", &len
))) {
438 return ERR_PTR(-EIO
);
442 ddir
= lookup_dentry(link
, ddir
, follow
);
447 int hpfs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
448 struct inode
*new_dir
, struct dentry
*new_dentry
)
450 char *old_name
= (char *)old_dentry
->d_name
.name
;
451 int old_len
= old_dentry
->d_name
.len
;
452 char *new_name
= (char *)new_dentry
->d_name
.name
;
453 int new_len
= new_dentry
->d_name
.len
;
454 struct inode
*i
= old_dentry
->d_inode
;
455 struct inode
*new_inode
= new_dentry
->d_inode
;
456 struct quad_buffer_head qbh
, qbh1
;
457 struct hpfs_dirent
*dep
, *nde
;
458 struct hpfs_dirent de
;
461 struct buffer_head
*bh
;
464 if ((err
= hpfs_chk_name((char *)new_name
, &new_len
))) return err
;
466 hpfs_adjust_length((char *)old_name
, &old_len
);
468 hpfs_lock_3inodes(old_dir
, new_dir
, i
);
470 /* Erm? Moving over the empty non-busy directory is perfectly legal */
471 if (new_inode
&& S_ISDIR(new_inode
->i_mode
)) {
476 if (!(dep
= map_dirent(old_dir
, old_dir
->i_hpfs_dno
, (char *)old_name
, old_len
, &dno
, &qbh
))) {
477 hpfs_error(i
->i_sb
, "lookup succeeded but map dirent failed");
482 de
.hidden
= new_name
[0] == '.';
486 if ((r
= hpfs_remove_dirent(old_dir
, dno
, dep
, &qbh
, 1)) != 2) {
487 if ((nde
= map_dirent(new_dir
, new_dir
->i_hpfs_dno
, (char *)new_name
, new_len
, NULL
, &qbh1
))) {
488 new_inode
->i_nlink
= 0;
490 memcpy(nde
->name
, new_name
, new_len
);
491 hpfs_mark_4buffers_dirty(&qbh1
);
495 hpfs_error(new_dir
->i_sb
, "hpfs_rename: could not find dirent");
499 err
= r
== 2 ? -ENOSPC
: r
== 1 ? -EFSERROR
: 0;
503 if (new_dir
== old_dir
) hpfs_brelse4(&qbh
);
505 hpfs_lock_creation(i
->i_sb
);
506 if ((r
= hpfs_add_dirent(new_dir
, new_name
, new_len
, &de
, 1))) {
507 hpfs_unlock_creation(i
->i_sb
);
508 if (r
== -1) hpfs_error(new_dir
->i_sb
, "hpfs_rename: dirent already exists!");
509 err
= r
== 1 ? -ENOSPC
: -EFSERROR
;
510 if (new_dir
!= old_dir
) hpfs_brelse4(&qbh
);
514 if (new_dir
== old_dir
)
515 if (!(dep
= map_dirent(old_dir
, old_dir
->i_hpfs_dno
, (char *)old_name
, old_len
, &dno
, &qbh
))) {
516 hpfs_unlock_creation(i
->i_sb
);
517 hpfs_error(i
->i_sb
, "lookup succeeded but map dirent failed at #2");
522 if ((r
= hpfs_remove_dirent(old_dir
, dno
, dep
, &qbh
, 0))) {
523 hpfs_unlock_creation(i
->i_sb
);
524 hpfs_error(i
->i_sb
, "hpfs_rename: could not remove dirent");
525 err
= r
== 2 ? -ENOSPC
: -EFSERROR
;
528 hpfs_unlock_creation(i
->i_sb
);
531 i
->i_hpfs_parent_dir
= new_dir
->i_ino
;
532 if (S_ISDIR(i
->i_mode
)) {
536 if ((fnode
= hpfs_map_fnode(i
->i_sb
, i
->i_ino
, &bh
))) {
537 fnode
->up
= new_dir
->i_ino
;
538 fnode
->len
= new_len
;
539 memcpy(fnode
->name
, new_name
, new_len
>15?15:new_len
);
540 if (new_len
< 15) memset(&fnode
->name
[new_len
], 0, 15 - new_len
);
541 mark_buffer_dirty(bh
, 1);
544 i
->i_hpfs_conv
= i
->i_sb
->s_hpfs_conv
;
545 hpfs_decide_conv(i
, (char *)new_name
, new_len
);
547 hpfs_unlock_3inodes(old_dir
, new_dir
, i
);