#define EXT2FS_BITMAPS_INODE 0x0004
#define EXT2FS_BITMAPS_VALID_FLAGS 0x0007
+/*
+ * flags for ext2fs_unlink()
+ */
+
+/* Forcefully unlink even if the inode number doesn't match the dirent */
+#define EXT2FS_UNLINK_FORCE 0x1
+
+/*
+ * flags for ext2fs_link()
+ *
+ */
+#define EXT2FS_LINK_FT_MASK 0x0007
+#define EXT2FS_LINK_APPEND 0x0010
+
/*
* function prototypes
*/
char **name);
/* link.c */
-#define EXT2FS_UNLINK_FORCE 0x1 /* Forcefully unlink even if
- * the inode number doesn't
- * match the dirent
- */
errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
ext2_ino_t ino, int flags);
errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, const char *name,
ext2fs_dirent_set_name_len(dirent, ls->namelen);
strncpy(dirent->name, ls->name, ls->namelen);
if (ext2fs_has_feature_filetype(ls->sb))
- ext2fs_dirent_set_file_type(dirent, ls->flags & 0x7);
+ ext2fs_dirent_set_file_type(dirent,
+ ls->flags & EXT2FS_LINK_FT_MASK);
ls->done++;
return DIRENT_ABORT|DIRENT_CHANGED;
ls.blocksize = fs->blocksize;
ls.err = 0;
- retval = ext2fs_dir_iterate2(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
- NULL, link_proc, &ls);
+ if ((flags & EXT2FS_LINK_APPEND) &&
+ !(inode.i_flags & EXT4_INLINE_DATA_FL)) {
+ blk64_t lblk, pblk = 0;
+ struct dir_context ctx;
+
+ lblk = (inode.i_size / fs->blocksize) - 1;
+ retval = ext2fs_bmap2(fs, ino, &inode, NULL, 0, lblk,
+ NULL, &pblk);
+ if (retval)
+ return retval;
+
+ ctx.dir = dir;
+ ctx.flags = flags;
+ ctx.func = link_proc;
+ ctx.priv_data = &ls;
+ ctx.errcode = 0;
+ retval = ext2fs_get_mem(fs->blocksize, &ctx.buf);
+ if (retval)
+ return retval;
+
+ ext2fs_process_dir_block(fs, &pblk, lblk, 0, 0, &ctx);
+ retval = ctx.errcode;
+ ext2fs_free_mem(&ctx.buf);
+ } else {
+ retval = ext2fs_dir_iterate2(fs, dir,
+ DIRENT_FLAG_INCLUDE_EMPTY,
+ NULL, link_proc, &ls);
+ }
if (retval)
return retval;
if (ls.err)