1 /* vi: set sw=4 ts=4: */
3 * link.c --- create links in a ext2fs directory
5 * Copyright (C) 1993, 1994 Theodore Ts'o.
8 * This file may be redistributed under the terms of the GNU Public
28 struct ext2_super_block
*sb
;
31 static int link_proc(struct ext2_dir_entry
*dirent
,
37 struct link_struct
*ls
= (struct link_struct
*) priv_data
;
38 struct ext2_dir_entry
*next
;
39 int rec_len
, min_rec_len
;
42 rec_len
= EXT2_DIR_REC_LEN(ls
->namelen
);
45 * See if the following directory entry (if any) is unused;
46 * if so, absorb it into this one.
48 next
= (struct ext2_dir_entry
*) (buf
+ offset
+ dirent
->rec_len
);
49 if ((offset
+ dirent
->rec_len
< blocksize
- 8) &&
51 (offset
+ dirent
->rec_len
+ next
->rec_len
<= blocksize
)) {
52 dirent
->rec_len
+= next
->rec_len
;
57 * If the directory entry is used, see if we can split the
58 * directory entry to make room for the new name. If so,
59 * truncate it and return.
62 min_rec_len
= EXT2_DIR_REC_LEN(dirent
->name_len
& 0xFF);
63 if (dirent
->rec_len
< (min_rec_len
+ rec_len
))
65 rec_len
= dirent
->rec_len
- min_rec_len
;
66 dirent
->rec_len
= min_rec_len
;
67 next
= (struct ext2_dir_entry
*) (buf
+ offset
+
71 next
->rec_len
= rec_len
;
72 return DIRENT_CHANGED
;
76 * If we get this far, then the directory entry is not used.
77 * See if we can fit the request entry in. If so, do it.
79 if (dirent
->rec_len
< rec_len
)
81 dirent
->inode
= ls
->inode
;
82 dirent
->name_len
= ls
->namelen
;
83 strncpy(dirent
->name
, ls
->name
, ls
->namelen
);
84 if (ls
->sb
->s_feature_incompat
& EXT2_FEATURE_INCOMPAT_FILETYPE
)
85 dirent
->name_len
|= (ls
->flags
& 0x7) << 8;
88 return DIRENT_ABORT
|DIRENT_CHANGED
;
92 * Note: the low 3 bits of the flags field are used as the directory
98 errcode_t
ext2fs_link(ext2_filsys fs
, ext2_ino_t dir
, const char *name
,
99 ext2_ino_t ino
, int flags
)
102 struct link_struct ls
;
103 struct ext2_inode inode
;
105 EXT2_CHECK_MAGIC(fs
, EXT2_ET_MAGIC_EXT2FS_FILSYS
);
107 if (!(fs
->flags
& EXT2_FLAG_RW
))
108 return EXT2_ET_RO_FILSYS
;
111 ls
.namelen
= name
? strlen(name
) : 0;
117 retval
= ext2fs_dir_iterate(fs
, dir
, DIRENT_FLAG_INCLUDE_EMPTY
,
123 return EXT2_ET_DIR_NO_SPACE
;
125 if ((retval
= ext2fs_read_inode(fs
, dir
, &inode
)) != 0)
128 if (inode
.i_flags
& EXT2_INDEX_FL
) {
129 inode
.i_flags
&= ~EXT2_INDEX_FL
;
130 if ((retval
= ext2fs_write_inode(fs
, dir
, &inode
)) != 0)