* better
[mascara-docs.git] / i386 / linux-2.3.21 / fs / hpfs / namei.c
blobfe9b66e3da8874447d156ebf896b2704032c163d
1 /*
2 * linux/fs/hpfs/namei.c
4 * Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
6 * adding & removing files & directories
7 */
9 #include <linux/string.h>
10 #include "hpfs_fn.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;
19 struct fnode *fnode;
20 struct dnode *dnode;
21 struct inode *result;
22 fnode_secno fno;
23 dnode_secno dno;
24 int r;
25 struct hpfs_dirent dee;
26 int err;
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);
31 dee.directory = 1;
32 if (!(mode & 0222)) dee.read_only = 1;
33 /*dee.archive = 0;*/
34 dee.hidden = name[0] == '.';
35 dee.fnode = fno;
36 dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, CURRENT_TIME);
37 hpfs_lock_inode(dir);
38 r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
39 if (r == 1) goto bail2;
40 if (r == -1) {
41 brelse(bh);
42 hpfs_brelse4(&qbh0);
43 hpfs_free_sectors(dir->i_sb, fno, 1);
44 hpfs_free_dnode(dir->i_sb, dno);
45 hpfs_unlock_inode(dir);
46 return -EEXIST;
48 fnode->len = len;
49 memcpy(fnode->name, name, len > 15 ? 15 : len);
50 fnode->up = dir->i_ino;
51 fnode->dirflag = 1;
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;
58 dnode->up = fno;
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;*/
64 de->fnode = fno;
65 mark_buffer_dirty(bh, 1);
66 brelse(bh);
67 hpfs_mark_4buffers_dirty(&qbh0);
68 hpfs_brelse4(&qbh0);
69 dir->i_nlink++;
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);
88 return 0;
89 bail2:
90 hpfs_brelse4(&qbh0);
91 hpfs_free_dnode(dir->i_sb, dno);
92 hpfs_unlock_inode(dir);
93 bail1:
94 brelse(bh);
95 hpfs_free_sectors(dir->i_sb, fno, 1);
96 bail:
97 return -ENOSPC;
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;
106 struct fnode *fnode;
107 fnode_secno fno;
108 int r;
109 struct hpfs_dirent dee;
110 int err;
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;
115 dee.archive = 1;
116 dee.hidden = name[0] == '.';
117 dee.fnode = fno;
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;
122 if (r == -1) {
123 brelse(bh);
124 hpfs_free_sectors(dir->i_sb, fno, 1);
125 hpfs_unlock_inode(dir);
126 return -EEXIST;
128 fnode->len = len;
129 memcpy(fnode->name, name, len > 15 ? 15 : len);
130 fnode->up = dir->i_ino;
131 mark_buffer_dirty(bh, 1);
132 brelse(bh);
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);
154 return 0;
155 bail1:
156 brelse(bh);
157 hpfs_free_sectors(dir->i_sb, fno, 1);
158 hpfs_unlock_inode(dir);
159 bail:
160 return -ENOSPC;
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;
168 struct fnode *fnode;
169 fnode_secno fno;
170 int r;
171 struct hpfs_dirent dee;
172 struct inode *result = NULL;
173 int err;
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;
179 dee.archive = 1;
180 dee.hidden = name[0] == '.';
181 dee.fnode = fno;
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;
186 if (r == -1) {
187 brelse(bh);
188 hpfs_free_sectors(dir->i_sb, fno, 1);
189 hpfs_unlock_inode(dir);
190 return -EEXIST;
192 fnode->len = len;
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;
205 result->i_nlink = 1;
206 result->i_size = 0;
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);
214 brelse(bh);
215 return 0;
216 bail1:
217 brelse(bh);
218 hpfs_free_sectors(dir->i_sb, fno, 1);
219 hpfs_unlock_inode(dir);
220 bail:
221 return -ENOSPC;
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;
231 struct fnode *fnode;
232 fnode_secno fno;
233 int r;
234 struct hpfs_dirent dee;
235 struct inode *result;
236 int err;
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);
241 dee.archive = 1;
242 dee.hidden = name[0] == '.';
243 dee.fnode = fno;
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;
248 if (r == -1) {
249 brelse(bh);
250 hpfs_free_sectors(dir->i_sb, fno, 1);
251 hpfs_unlock_inode(dir);
252 return -EEXIST;
254 fnode->len = len;
255 memcpy(fnode->name, name, len > 15 ? 15 : len);
256 fnode->up = dir->i_ino;
257 mark_buffer_dirty(bh, 1);
258 brelse(bh);
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);
275 brelse(bh);
277 hpfs_write_inode_nolock(result);
278 d_instantiate(dentry, result);
280 hpfs_unlock_iget(dir->i_sb);
281 hpfs_unlock_inode(dir);
282 return 0;
283 bail1:
284 brelse(bh);
285 hpfs_free_sectors(dir->i_sb, fno, 1);
286 hpfs_unlock_inode(dir);
287 bail:
288 return -ENOSPC;
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;
298 dnode_secno dno;
299 fnode_secno fno;
300 int r;
301 int rep = 0;
302 hpfs_adjust_length((char *)name, &len);
303 again:
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);
307 return -ENOENT;
309 if (de->first) {
310 hpfs_brelse4(&qbh);
311 hpfs_unlock_2inodes(dir, inode);
312 return -EPERM;
314 if (de->directory) {
315 hpfs_brelse4(&qbh);
316 hpfs_unlock_2inodes(dir, inode);
317 return -EISDIR;
319 fno = de->fnode;
320 if ((r = hpfs_remove_dirent(dir, dno, de, &qbh, 1)) == 1) hpfs_error(dir->i_sb, "there was error when removing dirent");
321 if (r != 2) {
322 inode->i_nlink--;
323 hpfs_unlock_2inodes(dir, inode);
324 d_delete(dentry);
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)) {
334 up(&inode->i_sem);
335 put_write_access(inode);
336 goto ret;
338 vmtruncate(inode, 0);
339 if (inode->i_op && inode->i_op->truncate) inode->i_op->truncate(inode);
340 up(&inode->i_sem);
341 put_write_access(inode);
342 rep = 1;
343 goto again;
345 ret:
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;
356 dnode_secno dno;
357 fnode_secno fno;
358 int n_items = 0;
359 int r;
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);
364 return -ENOENT;
366 if (de->first) {
367 hpfs_brelse4(&qbh);
368 hpfs_unlock_2inodes(dir, inode);
369 return -EPERM;
371 if (!de->directory) {
372 hpfs_brelse4(&qbh);
373 hpfs_unlock_2inodes(dir, inode);
374 return -ENOTDIR;
376 if (!list_empty(&dentry->d_hash)) {
377 hpfs_brelse4(&qbh);
378 hpfs_unlock_2inodes(dir, inode);
379 return -EBUSY;
381 hpfs_count_dnodes(dir->i_sb, inode->i_hpfs_dno, NULL, NULL, &n_items);
382 if (n_items) {
383 hpfs_brelse4(&qbh);
384 hpfs_unlock_2inodes(dir, inode);
385 return -ENOTEMPTY;
387 fno = de->fnode;
388 if ((r = hpfs_remove_dirent(dir, dno, de, &qbh, 1)) == 1)
389 hpfs_error(dir->i_sb, "there was error when removing dirent");
390 if (r != 2) {
391 dir->i_nlink--;
392 inode->i_nlink = 0;
393 hpfs_unlock_2inodes(dir, inode);
394 d_delete(dentry);
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;
402 struct fnode *fnode;
403 struct buffer_head *bh;
404 char *symlink;
405 int slen;
406 if (!S_ISLNK(i->i_mode)) {
407 return -EINVAL;
409 if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
410 return -EIO;
412 if (!(symlink = hpfs_get_ea(i->i_sb, fnode, "SYMLINK", &slen))) {
413 brelse(bh);
414 return -EFSERROR;
416 brelse(bh);
417 if (slen > len) slen = len;
418 memcpy_tofs(buf, symlink, slen);
419 kfree(symlink);
420 return slen;
423 struct dentry *hpfs_follow_link(struct dentry *dinode, struct dentry *ddir,
424 unsigned int follow)
426 struct inode *inode = dinode->d_inode;
427 char *link;
428 unsigned len;
429 struct buffer_head *bh;
430 struct fnode *fnode;
431 if (!(fnode = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) {
432 dput(dinode);
433 return ERR_PTR(-EIO);
435 if (!(link = hpfs_get_ea(inode->i_sb, fnode, "SYMLINK", &len))) {
436 brelse(bh);
437 dput(dinode);
438 return ERR_PTR(-EIO);
440 brelse(bh);
441 UPDATE_ATIME(inode);
442 ddir = lookup_dentry(link, ddir, follow);
443 kfree(link);
444 return ddir;
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;
459 dnode_secno dno;
460 int r;
461 struct buffer_head *bh;
462 struct fnode *fnode;
463 int err;
464 if ((err = hpfs_chk_name((char *)new_name, &new_len))) return err;
465 err = 0;
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)) {
472 err = -EINVAL;
473 goto end1;
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");
478 err = -ENOENT;
479 goto end1;
481 copy_de(&de, dep);
482 de.hidden = new_name[0] == '.';
484 if (new_inode) {
485 int r;
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;
489 copy_de(nde, &de);
490 memcpy(nde->name, new_name, new_len);
491 hpfs_mark_4buffers_dirty(&qbh1);
492 hpfs_brelse4(&qbh1);
493 goto end;
495 hpfs_error(new_dir->i_sb, "hpfs_rename: could not find dirent");
496 err = -EFSERROR;
497 goto end1;
499 err = r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
500 goto end1;
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);
511 goto end1;
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");
518 err = -ENOENT;
519 goto end1;
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;
526 goto end1;
528 hpfs_unlock_creation(i->i_sb);
530 end:
531 i->i_hpfs_parent_dir = new_dir->i_ino;
532 if (S_ISDIR(i->i_mode)) {
533 new_dir->i_nlink++;
534 old_dir->i_nlink--;
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);
542 brelse(bh);
544 i->i_hpfs_conv = i->i_sb->s_hpfs_conv;
545 hpfs_decide_conv(i, (char *)new_name, new_len);
546 end1:
547 hpfs_unlock_3inodes(old_dir, new_dir, i);
548 return err;