1.1 --- a/libe2access/host/e2access.c Thu Mar 03 22:42:55 2022 +0100
1.2 +++ b/libe2access/host/e2access.c Thu Mar 03 23:40:20 2022 +0100
1.3 @@ -206,28 +206,123 @@
1.4
1.5
1.6
1.7 +/* Copy a source file from the external environment into the filesystem. */
1.8 +
1.9 +static int _copy_in(ext2_filsys fs, const char *filename, ext2_ino_t ino_target,
1.10 + const char *basename)
1.11 +{
1.12 + errcode_t retval;
1.13 + int flags;
1.14 +
1.15 + /* By default, treat the target as a new object. */
1.16 +
1.17 + ext2_ino_t ino_parent = ino_target;
1.18 + int target_is_new = 1;
1.19 +
1.20 + /* Source file details. */
1.21 +
1.22 + struct stat st;
1.23 +
1.24 + /* Without a basename, the target exists and is either a directory, into
1.25 + which the source file shall be copied, or it is a file that shall be
1.26 + overwritten. */
1.27 +
1.28 + if (basename == NULL)
1.29 + {
1.30 + basename = path_basename(filename);
1.31 + target_is_new = image_isdir_by_inode(fs, ino_target);
1.32 + }
1.33 +
1.34 + /* Directories are created with the same metadata. */
1.35 +
1.36 + if (isdir(filename))
1.37 + {
1.38 + if (!target_is_new)
1.39 + {
1.40 + fprintf(stderr, "Directory cannot be copied as it already exists: %s\n", filename);
1.41 + return 1;
1.42 + }
1.43 +
1.44 + /* Obtain the metadata. */
1.45 +
1.46 + if (lstat(filename, &st))
1.47 + {
1.48 + fprintf(stderr, "Failed to read object metadata: %s\n", filename);
1.49 + return 1;
1.50 + }
1.51 +
1.52 + retval = image_make_dir(fs, ino_parent, basename,
1.53 + st.st_mode & ~md.mask,
1.54 + md.have_uid ? md.uid : st.st_uid,
1.55 + md.have_gid ? md.gid : st.st_gid,
1.56 + &ino_target);
1.57 +
1.58 + if (retval)
1.59 + {
1.60 + fprintf(stderr, "Failed to create directory: %s\n", filename);
1.61 + return 1;
1.62 + }
1.63 + }
1.64 +
1.65 + /* Files are copied. */
1.66 +
1.67 + else if (isfile(filename))
1.68 + {
1.69 + flags = EXT2_FILE_WRITE;
1.70 +
1.71 + /* Obtain the inode for the target file. */
1.72 +
1.73 + if (target_is_new)
1.74 + {
1.75 + /* Populate the inode details. */
1.76 +
1.77 + if (lstat(filename, &st))
1.78 + {
1.79 + fprintf(stderr, "Failed to read object metadata: %s\n", filename);
1.80 + return 1;
1.81 + }
1.82 +
1.83 + retval = image_create_file(fs, ino_parent, basename,
1.84 + st.st_mode & ~md.mask,
1.85 + md.have_uid ? md.uid : st.st_uid,
1.86 + md.have_gid ? md.gid : st.st_gid,
1.87 + &ino_target);
1.88 + if (retval)
1.89 + {
1.90 + fprintf(stderr, "Failed to create file: %s\n", filename);
1.91 + return 1;
1.92 + }
1.93 +
1.94 + flags |= EXT2_FILE_CREATE;
1.95 + }
1.96 +
1.97 + /* NOTE: Overwrite/update metadata where appropriate. */
1.98 +
1.99 + if (copy_file_in(filename, fs, ino_target, flags))
1.100 + {
1.101 + fprintf(stderr, "Failed to copy file: %s\n", filename);
1.102 + return 1;
1.103 + }
1.104 + }
1.105 +}
1.106 +
1.107 /* Copy source files from the external environment into the filesystem image. */
1.108
1.109 int copy_in(ext2_filsys fs, int argc, char *argv[])
1.110 {
1.111 errcode_t retval;
1.112 + int i;
1.113
1.114 /* Target filename details. */
1.115
1.116 const char *target = argv[argc - 1];
1.117 - const char *target_remaining = argv[argc - 1];
1.118 + const char *target_remaining = target;
1.119 const char *basename;
1.120
1.121 /* Target file and directory details. */
1.122
1.123 - int target_is_file, target_is_new;
1.124 - ext2_ino_t ino_file, ino_target;
1.125 - int flags;
1.126 -
1.127 - /* Source file details. */
1.128 -
1.129 - struct stat st;
1.130 - int i;
1.131 + int target_is_file;
1.132 + ext2_ino_t ino_target;
1.133
1.134 /* Locate the target and test whether it is a file or a directory. */
1.135
1.136 @@ -241,13 +336,19 @@
1.137 return 1;
1.138 }
1.139
1.140 - target_is_file = 1;
1.141 - target_is_new = 1;
1.142 + /* Any absent target leaves the basename remaining.
1.143 + The resolved target is the parent directory. */
1.144 +
1.145 + target_is_file = 0;
1.146 + basename = target_remaining;
1.147 }
1.148 else
1.149 {
1.150 + /* Any present target can be a file or directory.
1.151 + The resolved target is the actual target. */
1.152 +
1.153 target_is_file = image_isfile_by_inode(fs, ino_target);
1.154 - target_is_new = 0;
1.155 + basename = NULL;
1.156 }
1.157
1.158 /* Only permit a target file when one source file is given. */
1.159 @@ -269,87 +370,8 @@
1.160 /* Copy each source object to the target directory. */
1.161
1.162 for (i = 0; i < argc - 1; i++)
1.163 - {
1.164 - if (target_is_file)
1.165 - basename = target_remaining;
1.166 - else
1.167 - {
1.168 - basename = path_basename(argv[i]);
1.169 - target_is_new = image_find_file(fs, target, basename, &ino_file);
1.170 - }
1.171 -
1.172 - /* Directories are created with the same metadata. */
1.173 -
1.174 - if (isdir(argv[i]))
1.175 - {
1.176 - if (!target_is_new)
1.177 - {
1.178 - fprintf(stderr, "Target cannot be created since it already exists: %s\n", target);
1.179 - return 1;
1.180 - }
1.181 -
1.182 - /* Obtain the metadata. */
1.183 -
1.184 - if (lstat(argv[i], &st))
1.185 - {
1.186 - fprintf(stderr, "Failed to read object metadata: %s\n", argv[i]);
1.187 - return 1;
1.188 - }
1.189 -
1.190 - retval = image_make_dir(fs, ino_target, basename,
1.191 - st.st_mode & ~md.mask,
1.192 - md.have_uid ? md.uid : st.st_uid,
1.193 - md.have_gid ? md.gid : st.st_gid,
1.194 - &ino_file);
1.195 -
1.196 - if (retval)
1.197 - {
1.198 - fprintf(stderr, "Failed to create directory: %s\n", argv[i]);
1.199 - return 1;
1.200 - }
1.201 - }
1.202 -
1.203 - /* Files are copied. */
1.204 -
1.205 - else if (isfile(argv[i]))
1.206 - {
1.207 - flags = EXT2_FILE_WRITE;
1.208 -
1.209 - /* Obtain the inode for the target file. */
1.210 -
1.211 - if (target_is_new)
1.212 - {
1.213 - /* Populate the inode details. */
1.214 -
1.215 - if (lstat(argv[i], &st))
1.216 - {
1.217 - fprintf(stderr, "Failed to read object metadata: %s\n", argv[i]);
1.218 - return 1;
1.219 - }
1.220 -
1.221 - retval = image_create_file(fs, ino_target, basename,
1.222 - st.st_mode & ~md.mask,
1.223 - md.have_uid ? md.uid : st.st_uid,
1.224 - md.have_gid ? md.gid : st.st_gid,
1.225 - &ino_file);
1.226 - if (retval)
1.227 - {
1.228 - fprintf(stderr, "Failed to create file: %s\n", argv[i]);
1.229 - return 1;
1.230 - }
1.231 -
1.232 - flags |= EXT2_FILE_CREATE;
1.233 - }
1.234 -
1.235 - /* NOTE: Overwrite/update metadata where appropriate. */
1.236 -
1.237 - if (copy_file_in(argv[i], fs, ino_file, flags))
1.238 - {
1.239 - fprintf(stderr, "Failed to write to file: %s\n", argv[i]);
1.240 - return 1;
1.241 - }
1.242 - }
1.243 - }
1.244 + if (_copy_in(fs, argv[i], ino_target, basename))
1.245 + return 1;
1.246
1.247 return 0;
1.248 }