2 * link.c --- create or delete links in a ext2fs directory
4 * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
5 * under the terms of the GNU Public License.
13 #include <linux/ext2_fs.h>
25 static int link_proc(struct ext2_dir_entry
*dirent
,
31 struct link_struct
*ls
= (struct link_struct
*) private;
32 struct ext2_dir_entry
*next
;
36 rec_len
= EXT2_DIR_REC_LEN(ls
->namelen
);
39 * See if the following directory entry (if any) is unused;
40 * if so, absorb it into this one.
42 next
= (struct ext2_dir_entry
*) (buf
+ offset
+ dirent
->rec_len
);
43 if ((offset
+ dirent
->rec_len
< blocksize
- 8) &&
45 (offset
+ dirent
->rec_len
+ next
->rec_len
<= blocksize
)) {
46 dirent
->rec_len
+= next
->rec_len
;
51 * If the directory entry is used, see if we can split the
52 * directory entry to make room for the new name. If so,
53 * truncate it and return.
56 if (dirent
->rec_len
< (EXT2_DIR_REC_LEN(dirent
->name_len
) +
59 rec_len
= dirent
->rec_len
- EXT2_DIR_REC_LEN(dirent
->name_len
);
60 dirent
->rec_len
= EXT2_DIR_REC_LEN(dirent
->name_len
);
61 next
= (struct ext2_dir_entry
*) (buf
+ offset
+
65 next
->rec_len
= rec_len
;
66 return DIRENT_CHANGED
;
70 * If we get this far, then the directory entry is not used.
71 * See if we can fit the request entry in. If so, do it.
73 if (dirent
->rec_len
< rec_len
)
75 dirent
->inode
= ls
->inode
;
76 dirent
->name_len
= ls
->namelen
;
77 strncpy(dirent
->name
, ls
->name
, ls
->namelen
);
80 return DIRENT_ABORT
|DIRENT_CHANGED
;
83 errcode_t
ext2fs_link(ext2_filsys fs
, ino_t dir
, const char *name
, ino_t ino
,
87 struct link_struct ls
;
89 if (!(fs
->flags
& EXT2_FLAG_RW
))
90 return EXT2_ET_RO_FILSYS
;
93 ls
.namelen
= name
? strlen(name
) : 0;
98 retval
= ext2fs_dir_iterate(fs
, dir
, DIRENT_FLAG_INCLUDE_EMPTY
,
103 return (ls
.done
) ? 0 : EXT2_ET_DIR_NO_SPACE
;
106 static int unlink_proc(struct ext2_dir_entry
*dirent
,
112 struct link_struct
*ls
= (struct link_struct
*) private;
114 if (ls
->name
&& (dirent
->name_len
!= ls
->namelen
))
116 if (ls
->name
&& strncmp(ls
->name
, dirent
->name
, dirent
->name_len
))
118 if (ls
->inode
&& (dirent
->inode
!= ls
->inode
))
123 return DIRENT_ABORT
|DIRENT_CHANGED
;
126 errcode_t
ext2fs_unlink(ext2_filsys fs
, ino_t dir
, const char *name
, ino_t ino
,
130 struct link_struct ls
;
132 if (!(fs
->flags
& EXT2_FLAG_RW
))
133 return EXT2_ET_RO_FILSYS
;
136 ls
.namelen
= name
? strlen(name
) : 0;
141 retval
= ext2fs_dir_iterate(fs
, dir
, 0, 0, unlink_proc
, &ls
);
145 return (ls
.done
) ? 0 : EXT2_ET_DIR_NO_SPACE
;