2.1 --- a/libe2access/host/e2access.c Wed Feb 16 00:02:37 2022 +0100
2.2 +++ b/libe2access/host/e2access.c Wed Feb 16 01:25:39 2022 +0100
2.3 @@ -574,11 +574,11 @@
2.4 return 1;
2.5 }
2.6
2.7 - /* Remove the directory. */
2.8 + /* Test for an empty directory. */
2.9
2.10 - if (image_remove_by_path(fs, path))
2.11 + if (image_dir_empty_by_path(fs, path, &ino))
2.12 {
2.13 - fprintf(stderr, "Could not remove directory: %s\n", path);
2.14 + fprintf(stderr, "Directory not empty: %s\n", path);
2.15 return 1;
2.16 }
2.17
2.18 @@ -589,6 +589,14 @@
2.19 fprintf(stderr, "Could not unlink directory: %s\n", path);
2.20 return 1;
2.21 }
2.22 +
2.23 + /* Remove the directory. */
2.24 +
2.25 + if (image_remove_by_inode(fs, ino))
2.26 + {
2.27 + fprintf(stderr, "Could not remove directory: %s\n", path);
2.28 + return 1;
2.29 + }
2.30 }
2.31
2.32 return 0;
3.1 --- a/libe2access/include/e2access/image.h Wed Feb 16 00:02:37 2022 +0100
3.2 +++ b/libe2access/include/e2access/image.h Wed Feb 16 01:25:39 2022 +0100
3.3 @@ -31,10 +31,22 @@
3.4
3.5 /* Filesystem operations. */
3.6
3.7 +errcode_t image_access_by_path(ext2_filsys fs, const char *path,
3.8 + errcode_t (*op)(ext2_filsys, ext2_ino_t),
3.9 + ext2_ino_t *ino);
3.10 +
3.11 errcode_t image_create_file(ext2_filsys fs, ext2_ino_t ino_target,
3.12 const char *basename, __u16 mode,
3.13 __u16 uid, __u16 gid, ext2_ino_t *ino_file);
3.14
3.15 +errcode_t image_dir_empty_by_inode(ext2_filsys fs, ext2_ino_t ino);
3.16 +
3.17 +errcode_t image_dir_empty_by_path(ext2_filsys fs, const char *path,
3.18 + ext2_ino_t *ino);
3.19 +
3.20 +errcode_t image_dir_get_parent(ext2_filsys fs, ext2_ino_t ino,
3.21 + ext2_ino_t *ino_parent);
3.22 +
3.23 int image_file_type(int mode);
3.24
3.25 errcode_t image_find_next(ext2_filsys fs, ext2_ino_t ino_dir,
3.26 @@ -49,6 +61,8 @@
3.27 errcode_t image_inode(ext2_filsys fs, const char *pathname,
3.28 struct ext2_inode *inode);
3.29
3.30 +errcode_t image_inode_decrement(ext2_filsys fs, ext2_ino_t ino);
3.31 +
3.32 errcode_t image_list_dir(ext2_filsys fs, const char *path,
3.33 int (*proc)(struct ext2_dir_entry *, int, int, char *,
3.34 void *),
3.35 @@ -68,11 +82,8 @@
3.36
3.37 errcode_t image_remove_by_inode(ext2_filsys fs, ext2_ino_t ino);
3.38
3.39 -errcode_t image_remove_by_path(ext2_filsys fs, const char *path);
3.40 -
3.41 -errcode_t image_remove_directory_test(ext2_filsys fs, ext2_ino_t ino);
3.42 -
3.43 -errcode_t image_remove_parent_decrement(ext2_filsys fs, ext2_ino_t ino);
3.44 +errcode_t image_remove_by_path(ext2_filsys fs, const char *path,
3.45 + ext2_ino_t *ino);
3.46
3.47 errcode_t image_rename(ext2_filsys fs, ext2_ino_t source,
3.48 ext2_ino_t source_parent, const char *source_basename,
3.49 @@ -109,3 +120,6 @@
3.50
3.51
3.52 #endif /* __IMAGE_H__ */
3.53 +
3.54 +/* vim: tabstop=4 expandtab shiftwidth=4
3.55 +*/
4.1 --- a/libe2access/lib/src/image.c Wed Feb 16 00:02:37 2022 +0100
4.2 +++ b/libe2access/lib/src/image.c Wed Feb 16 01:25:39 2022 +0100
4.3 @@ -126,6 +126,23 @@
4.4
4.5
4.6
4.7 +/* Adapter function. */
4.8 +
4.9 +errcode_t image_access_by_path(ext2_filsys fs, const char *path,
4.10 + errcode_t (*op)(ext2_filsys, ext2_ino_t),
4.11 + ext2_ino_t *ino)
4.12 +{
4.13 + const char *remaining = path;
4.14 + errcode_t retval = image_find_path(fs, &remaining, ino);
4.15 +
4.16 + if (retval)
4.17 + return retval;
4.18 +
4.19 + return op(fs, *ino);
4.20 +}
4.21 +
4.22 +
4.23 +
4.24 /* Create an inode for a file. */
4.25
4.26 errcode_t image_create_file(ext2_filsys fs, ext2_ino_t ino_target,
4.27 @@ -155,6 +172,52 @@
4.28 return ext2fs_write_new_inode(fs, *ino_file, &inode_file);
4.29 }
4.30
4.31 +/* Test for an empty directory. */
4.32 +
4.33 +errcode_t image_dir_empty_by_inode(ext2_filsys fs, ext2_ino_t ino)
4.34 +{
4.35 + /* Initialise the directory listing processing state. */
4.36 +
4.37 + struct _image_parent_entry_state state = {.nonempty = 0};
4.38 + errcode_t retval = ext2fs_dir_iterate(fs, ino, 0, NULL,
4.39 + _image_test_directory, &state);
4.40 +
4.41 + if (retval)
4.42 + return retval;
4.43 +
4.44 + /* NOTE: Need a proper error here. */
4.45 +
4.46 + return state.nonempty;
4.47 +}
4.48 +
4.49 +/* Test for an empty directory using its path. */
4.50 +
4.51 +errcode_t image_dir_empty_by_path(ext2_filsys fs, const char *path,
4.52 + ext2_ino_t *ino)
4.53 +{
4.54 + return image_access_by_path(fs, path, image_dir_empty_by_inode, ino);
4.55 +}
4.56 +
4.57 +/* Find any parent reference. */
4.58 +
4.59 +errcode_t image_dir_get_parent(ext2_filsys fs, ext2_ino_t ino, ext2_ino_t *ino_parent)
4.60 +{
4.61 + /* Initialise the directory listing processing state. */
4.62 +
4.63 + struct _image_parent_entry_state state = {.ino = 0};
4.64 +
4.65 + /* A directory needs to be inspected for files and for the .. entry
4.66 + to be queried to obtain the parent directory. */
4.67 +
4.68 + errcode_t retval = ext2fs_dir_iterate(fs, ino, 0, NULL,
4.69 + _image_get_parent_entry, &state);
4.70 +
4.71 + if (!retval)
4.72 + *ino_parent = state.ino;
4.73 +
4.74 + return retval;
4.75 +}
4.76 +
4.77 /* Return the appropriate ext2 file type value for the given mode value. */
4.78
4.79 int image_file_type(int mode)
4.80 @@ -273,6 +336,32 @@
4.81 return ext2fs_read_inode(fs, ino, inode);
4.82 }
4.83
4.84 +/* Decrement the reference count on an inode. */
4.85 +
4.86 +errcode_t image_inode_decrement(ext2_filsys fs, ext2_ino_t ino)
4.87 +{
4.88 + struct ext2_inode_large inode;
4.89 + errcode_t retval;
4.90 +
4.91 + retval = ext2fs_read_inode_full(fs, ino,
4.92 + (struct ext2_inode *) &inode,
4.93 + sizeof(inode));
4.94 +
4.95 + if (retval)
4.96 + return retval;
4.97 +
4.98 + /* NOTE: FUSE implementation tests for > 1. */
4.99 +
4.100 + if (inode.i_links_count)
4.101 + inode.i_links_count--;
4.102 +
4.103 + /* NOTE: Update modification time. */
4.104 +
4.105 + return ext2fs_write_inode_full(fs, ino,
4.106 + (struct ext2_inode *) &inode,
4.107 + sizeof(inode));
4.108 +}
4.109 +
4.110 /* List a directory in the filesystem image. */
4.111
4.112 errcode_t image_list_dir(ext2_filsys fs, const char *path,
4.113 @@ -403,11 +492,12 @@
4.114 errcode_t image_remove_by_inode(ext2_filsys fs, ext2_ino_t ino)
4.115 {
4.116 struct ext2_inode_large inode;
4.117 + ext2_ino_t ino_parent = 0;
4.118 errcode_t retval;
4.119
4.120 if (_image_isdir(fs, ino))
4.121 {
4.122 - retval = image_remove_directory_test(fs, ino);
4.123 + retval = image_dir_get_parent(fs, ino, &ino_parent);
4.124 if (retval)
4.125 return retval;
4.126 }
4.127 @@ -430,11 +520,6 @@
4.128
4.129 if (!inode.i_links_count)
4.130 {
4.131 - retval = image_remove_parent_decrement(fs, ino);
4.132 -
4.133 - if (retval)
4.134 - return retval;
4.135 -
4.136 /* NOTE: Update deletion time. */
4.137
4.138 retval = ext2fs_free_ext_attr(fs, ino, &inode);
4.139 @@ -446,8 +531,8 @@
4.140
4.141 if (ext2fs_inode_has_valid_blocks2(fs, (struct ext2_inode *) &inode))
4.142 {
4.143 - retval = ext2fs_punch(fs, ino, (struct ext2_inode *) &inode, NULL,
4.144 - 0, ~0ULL);
4.145 + retval = ext2fs_punch(fs, ino, (struct ext2_inode *) &inode,
4.146 + NULL, 0, ~0ULL);
4.147
4.148 /* Update allocation statistics. */
4.149
4.150 @@ -458,83 +543,23 @@
4.151 }
4.152 }
4.153
4.154 - return ext2fs_write_inode_full(fs, ino, (struct ext2_inode *) &inode,
4.155 - sizeof(inode));
4.156 + retval = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *) &inode,
4.157 + sizeof(inode));
4.158 +
4.159 + /* Decrement the parent reference count for directories. */
4.160 +
4.161 + if (!retval && !inode.i_links_count && ino_parent)
4.162 + retval = image_inode_decrement(fs, ino_parent);
4.163 +
4.164 + return retval;
4.165 }
4.166
4.167 /* Remove a directory entry using its full path. */
4.168
4.169 -errcode_t image_remove_by_path(ext2_filsys fs, const char *path)
4.170 -{
4.171 - const char *remaining = path;
4.172 - ext2_ino_t ino;
4.173 - errcode_t retval = image_find_path(fs, &remaining, &ino);
4.174 -
4.175 - if (retval)
4.176 - return retval;
4.177 -
4.178 - return image_remove_by_inode(fs, ino);
4.179 -}
4.180 -
4.181 -/* Test for an empty directory. */
4.182 -
4.183 -errcode_t image_remove_directory_test(ext2_filsys fs, ext2_ino_t ino)
4.184 -{
4.185 - /* Initialise the directory listing processing state. */
4.186 -
4.187 - struct _image_parent_entry_state state = {.nonempty = 0};
4.188 - errcode_t retval = ext2fs_dir_iterate(fs, ino, 0, NULL,
4.189 - _image_test_directory, &state);
4.190 -
4.191 - if (retval)
4.192 - return retval;
4.193 -
4.194 - /* NOTE: Need a proper error here. */
4.195 -
4.196 - return state.nonempty;
4.197 -}
4.198 -
4.199 -/* Find any parent reference and decrement the parent reference count. */
4.200 -
4.201 -errcode_t image_remove_parent_decrement(ext2_filsys fs, ext2_ino_t ino)
4.202 +errcode_t image_remove_by_path(ext2_filsys fs, const char *path,
4.203 + ext2_ino_t *ino)
4.204 {
4.205 - struct ext2_inode_large inode;
4.206 -
4.207 - /* Initialise the directory listing processing state. */
4.208 -
4.209 - struct _image_parent_entry_state state = {.ino = 0};
4.210 -
4.211 - /* A directory needs to be inspected for files and for the .. entry
4.212 - to be queried to obtain the parent directory. */
4.213 -
4.214 - errcode_t retval = ext2fs_dir_iterate(fs, ino, 0, NULL,
4.215 - _image_get_parent_entry, &state);
4.216 -
4.217 - if (retval)
4.218 - return retval;
4.219 -
4.220 - /* Reduce the reference count on the parent directory. */
4.221 -
4.222 - if (state.ino)
4.223 - {
4.224 - retval = ext2fs_read_inode_full(fs, state.ino,
4.225 - (struct ext2_inode *) &inode,
4.226 - sizeof(inode));
4.227 -
4.228 - if (retval)
4.229 - return retval;
4.230 -
4.231 - if (inode.i_links_count)
4.232 - inode.i_links_count--;
4.233 -
4.234 - /* NOTE: Update modification time. */
4.235 -
4.236 - retval = ext2fs_write_inode_full(fs, state.ino,
4.237 - (struct ext2_inode *) &inode,
4.238 - sizeof(inode));
4.239 - }
4.240 -
4.241 - return retval;
4.242 + return image_access_by_path(fs, path, image_remove_by_inode, ino);
4.243 }
4.244
4.245 /* Rename a file. */