Linux-2.3.3 and a short hiatus..
[davej-history.git] / fs / hpfs / namei.c
blob5e4d7c9f441adb8a58dd430a5f9fe1ee286bbb28
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 "hpfs_fn.h"
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;
18 struct fnode *fnode;
19 struct dnode *dnode;
20 struct inode *result;
21 fnode_secno fno;
22 dnode_secno dno;
23 int r;
24 struct hpfs_dirent dee;
25 int err;
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);
30 dee.directory = 1;
31 if (!(mode & 0222)) dee.read_only = 1;
32 /*dee.archive = 0;*/
33 dee.hidden = name[0] == '.';
34 dee.fnode = fno;
35 dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, CURRENT_TIME);
36 hpfs_lock_inode(dir);
37 r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
38 if (r == 1) goto bail2;
39 if (r == -1) {
40 brelse(bh);
41 hpfs_brelse4(&qbh0);
42 hpfs_free_sectors(dir->i_sb, fno, 1);
43 hpfs_free_dnode(dir->i_sb, dno);
44 hpfs_unlock_inode(dir);
45 return -EEXIST;
47 fnode->len = len;
48 memcpy(fnode->name, name, len > 15 ? 15 : len);
49 fnode->up = dir->i_ino;
50 fnode->dirflag = 1;
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;
57 dnode->up = fno;
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;*/
63 de->fnode = fno;
64 mark_buffer_dirty(bh, 1);
65 brelse(bh);
66 hpfs_mark_4buffers_dirty(&qbh0);
67 hpfs_brelse4(&qbh0);
68 dir->i_nlink++;
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);
87 return 0;
88 bail2:
89 hpfs_brelse4(&qbh0);
90 hpfs_free_dnode(dir->i_sb, dno);
91 hpfs_unlock_inode(dir);
92 bail1:
93 brelse(bh);
94 hpfs_free_sectors(dir->i_sb, fno, 1);
95 bail:
96 return -ENOSPC;
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;
105 struct fnode *fnode;
106 fnode_secno fno;
107 int r;
108 struct hpfs_dirent dee;
109 int err;
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;
114 dee.archive = 1;
115 dee.hidden = name[0] == '.';
116 dee.fnode = fno;
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;
121 if (r == -1) {
122 brelse(bh);
123 hpfs_free_sectors(dir->i_sb, fno, 1);
124 hpfs_unlock_inode(dir);
125 return -EEXIST;
127 fnode->len = len;
128 memcpy(fnode->name, name, len > 15 ? 15 : len);
129 fnode->up = dir->i_ino;
130 mark_buffer_dirty(bh, 1);
131 brelse(bh);
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);
153 return 0;
154 bail1:
155 brelse(bh);
156 hpfs_free_sectors(dir->i_sb, fno, 1);
157 hpfs_unlock_inode(dir);
158 bail:
159 return -ENOSPC;
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;
167 struct fnode *fnode;
168 fnode_secno fno;
169 int r;
170 struct hpfs_dirent dee;
171 struct inode *result = NULL;
172 int err;
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;
178 dee.archive = 1;
179 dee.hidden = name[0] == '.';
180 dee.fnode = fno;
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;
185 if (r == -1) {
186 brelse(bh);
187 hpfs_free_sectors(dir->i_sb, fno, 1);
188 hpfs_unlock_inode(dir);
189 return -EEXIST;
191 fnode->len = len;
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;
204 result->i_nlink = 1;
205 result->i_size = 0;
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);
213 brelse(bh);
214 return 0;
215 bail1:
216 brelse(bh);
217 hpfs_free_sectors(dir->i_sb, fno, 1);
218 hpfs_unlock_inode(dir);
219 bail:
220 return -ENOSPC;
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;
230 struct fnode *fnode;
231 fnode_secno fno;
232 int r;
233 struct hpfs_dirent dee;
234 struct inode *result;
235 int err;
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);
240 dee.archive = 1;
241 dee.hidden = name[0] == '.';
242 dee.fnode = fno;
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;
247 if (r == -1) {
248 brelse(bh);
249 hpfs_free_sectors(dir->i_sb, fno, 1);
250 hpfs_unlock_inode(dir);
251 return -EEXIST;
253 fnode->len = len;
254 memcpy(fnode->name, name, len > 15 ? 15 : len);
255 fnode->up = dir->i_ino;
256 mark_buffer_dirty(bh, 1);
257 brelse(bh);
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);
274 brelse(bh);
276 hpfs_write_inode_nolock(result);
277 d_instantiate(dentry, result);
279 hpfs_unlock_iget(dir->i_sb);
280 hpfs_unlock_inode(dir);
281 return 0;
282 bail1:
283 brelse(bh);
284 hpfs_free_sectors(dir->i_sb, fno, 1);
285 hpfs_unlock_inode(dir);
286 bail:
287 return -ENOSPC;
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;
297 dnode_secno dno;
298 fnode_secno fno;
299 int r;
300 int rep = 0;
301 hpfs_adjust_length((char *)name, &len);
302 again:
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);
306 return -ENOENT;
308 if (de->first) {
309 hpfs_brelse4(&qbh);
310 hpfs_unlock_2inodes(dir, inode);
311 return -EPERM;
313 if (de->directory) {
314 hpfs_brelse4(&qbh);
315 hpfs_unlock_2inodes(dir, inode);
316 return -EISDIR;
318 fno = de->fnode;
319 if ((r = hpfs_remove_dirent(dir, dno, de, &qbh, 1)) == 1) hpfs_error(dir->i_sb, "there was error when removing dirent");
320 if (r != 2) {
321 inode->i_nlink--;
322 hpfs_unlock_2inodes(dir, inode);
323 d_delete(dentry);
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)) {
333 up(&inode->i_sem);
334 put_write_access(inode);
335 goto ret;
337 vmtruncate(inode, 0);
338 if (inode->i_op && inode->i_op->truncate) inode->i_op->truncate(inode);
339 up(&inode->i_sem);
340 put_write_access(inode);
341 rep = 1;
342 goto again;
344 ret:
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;
355 dnode_secno dno;
356 fnode_secno fno;
357 int n_items = 0;
358 int r;
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);
363 return -ENOENT;
365 if (de->first) {
366 hpfs_brelse4(&qbh);
367 hpfs_unlock_2inodes(dir, inode);
368 return -EPERM;
370 if (!de->directory) {
371 hpfs_brelse4(&qbh);
372 hpfs_unlock_2inodes(dir, inode);
373 return -ENOTDIR;
375 if (!list_empty(&dentry->d_hash)) {
376 hpfs_brelse4(&qbh);
377 hpfs_unlock_2inodes(dir, inode);
378 return -EBUSY;
380 hpfs_count_dnodes(dir->i_sb, inode->i_hpfs_dno, NULL, NULL, &n_items);
381 if (n_items) {
382 hpfs_brelse4(&qbh);
383 hpfs_unlock_2inodes(dir, inode);
384 return -ENOTEMPTY;
386 fno = de->fnode;
387 if ((r = hpfs_remove_dirent(dir, dno, de, &qbh, 1)) == 1)
388 hpfs_error(dir->i_sb, "there was error when removing dirent");
389 if (r != 2) {
390 dir->i_nlink--;
391 inode->i_nlink = 0;
392 hpfs_unlock_2inodes(dir, inode);
393 d_delete(dentry);
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;
401 struct fnode *fnode;
402 struct buffer_head *bh;
403 char *symlink;
404 int slen;
405 if (!S_ISLNK(i->i_mode)) {
406 return -EINVAL;
408 if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
409 return -EIO;
411 if (!(symlink = hpfs_get_ea(i->i_sb, fnode, "SYMLINK", &slen))) {
412 brelse(bh);
413 return -EFSERROR;
415 brelse(bh);
416 if (slen > len) slen = len;
417 memcpy_tofs(buf, symlink, slen);
418 kfree(symlink);
419 return slen;
422 struct dentry *hpfs_follow_link(struct dentry *dinode, struct dentry *ddir,
423 unsigned int follow)
425 struct inode *inode = dinode->d_inode;
426 char *link;
427 unsigned len;
428 struct buffer_head *bh;
429 struct fnode *fnode;
430 if (!(fnode = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) {
431 dput(dinode);
432 return ERR_PTR(-EIO);
434 if (!(link = hpfs_get_ea(inode->i_sb, fnode, "SYMLINK", &len))) {
435 brelse(bh);
436 dput(dinode);
437 return ERR_PTR(-EIO);
439 brelse(bh);
440 UPDATE_ATIME(inode);
441 ddir = lookup_dentry(link, ddir, follow);
442 kfree(link);
443 return ddir;
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;
458 dnode_secno dno;
459 int r;
460 struct buffer_head *bh;
461 struct fnode *fnode;
462 int err;
463 if ((err = hpfs_chk_name((char *)new_name, &new_len))) return err;
464 err = 0;
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)) {
471 err = -EINVAL;
472 goto end1;
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");
477 err = -ENOENT;
478 goto end1;
480 copy_de(&de, dep);
481 de.hidden = new_name[0] == '.';
483 if (new_inode) {
484 hpfs_brelse4(&qbh);
485 if ((nde = map_dirent(new_dir, new_dir->i_hpfs_dno, (char *)new_name, new_len, NULL, &qbh1))) {
486 int r;
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");
490 goto end1;
492 new_inode->i_nlink = 0;
493 copy_de(nde, &de);
494 memcpy(nde->name, new_name, new_len);
495 hpfs_mark_4buffers_dirty(&qbh1);
496 hpfs_brelse4(&qbh1);
497 goto end;
499 err = r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
500 goto end1;
502 hpfs_error(new_dir->i_sb, "hpfs_rename: could not find dirent");
503 err = -EFSERROR;
504 goto end1;
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);
515 goto end1;
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");
522 err = -ENOENT;
523 goto end1;
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;
530 goto end1;
532 hpfs_unlock_creation(i->i_sb);
534 end:
535 i->i_hpfs_parent_dir = new_dir->i_ino;
536 if (S_ISDIR(i->i_mode)) {
537 new_dir->i_nlink++;
538 old_dir->i_nlink--;
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);
546 brelse(bh);
548 i->i_hpfs_conv = i->i_sb->s_hpfs_conv;
549 hpfs_decide_conv(i, (char *)new_name, new_len);
550 end1:
551 hpfs_unlock_3inodes(old_dir, new_dir, i);
552 return err;