1 /* 2 * Test file removal semantics. 3 * 4 * Copyright (C) 2019, 2021 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 26 #include <sys/types.h> 27 #include <sys/stat.h> 28 29 #include <ext2fs/ext2fs.h> 30 31 #include "file.h" 32 #include "format.h" 33 #include "image.h" 34 #include "path.h" 35 36 37 38 /* Buffer size for file access. */ 39 40 const int BUFSIZE = 4096; 41 42 /* Number of open files. */ 43 44 const int FILES = 20; 45 46 47 48 /* Show directory entries when iterating. */ 49 50 static int image_list_dir_proc(struct ext2_dir_entry *dirent, int offset, 51 int blocksize, char *buf, void *priv_data) 52 { 53 ext2_filsys fs = (ext2_filsys) priv_data; 54 struct ext2_inode inode; 55 ext2_file_t file; 56 __u64 size; 57 58 /* Obtain the inode details for metadata. */ 59 60 if (ext2fs_read_inode(fs, dirent->inode, &inode)) 61 return DIRENT_ABORT; 62 63 /* Output details in the style of "ls -l" showing directory, permissions, 64 owner, group and size information. */ 65 66 printf("%06d: %s%s %5d %5d %6d ", 67 offset, 68 _image_isdir(fs, dirent->inode) ? "d" : "-", 69 get_permission_string(inode.i_mode), 70 inode.i_uid, 71 inode.i_gid, 72 EXT2_I_SIZE(&inode)); 73 74 /* Output the name which is presumably not necessarily null-terminated. */ 75 76 fwrite(dirent->name, sizeof(char), ext2fs_dirent_name_len(dirent), stdout); 77 fputc((int) '\n', stdout); 78 79 return 0; 80 } 81 82 83 84 int main(int argc, char *argv[]) 85 { 86 int flags = EXT2_FLAG_RW; 87 char *fsname; 88 ext2_filsys fs = NULL; 89 errcode_t retval; 90 int exitcode = 0; 91 char basename[32]; 92 ext2_ino_t ino, inos[FILES]; 93 ext2_file_t file, files[FILES]; 94 char buf[BUFSIZE]; 95 unsigned int transferred; 96 int i; 97 98 if (argc < 2) 99 { 100 printf("Usage: %s <device or image file>\n", argv[0]); 101 return 1; 102 } 103 104 fsname = argv[1]; 105 106 /* Open the filesystem image using the POSIX file access mechanism. */ 107 108 retval = ext2fs_open(fsname, flags, 0, 0, unix_io_manager, &fs); 109 if (retval) 110 { 111 printf("Could not open filesystem using %s\n", fsname); 112 return 1; 113 } 114 115 retval = ext2fs_read_bitmaps(fs); 116 if (retval) 117 { 118 printf("Could not read bitmaps from %s\n", fsname); 119 return 1; 120 } 121 122 printf("Filesystem with blocksize %d\n", fs->blocksize); 123 124 /* Create some files. */ 125 126 for (i = 1; i <= FILES; i++) 127 { 128 sprintf(basename, "file%04d", i); 129 130 retval = image_create_file(fs, EXT2_ROOT_INO, basename, 0644, 131 1000, 1000, &ino); 132 133 if (retval) 134 { 135 printf("Could not create file %s\n", basename); 136 return 1; 137 } 138 139 if (ext2fs_file_open(fs, ino, EXT2_FILE_WRITE | EXT2_FILE_CREATE, &file)) 140 { 141 printf("Could not open file %s\n", basename); 142 return 1; 143 } 144 145 ext2fs_file_flush(file); 146 147 files[i - 1] = file; 148 inos[i - 1] = ino; 149 } 150 151 image_list_dir(fs, "", image_list_dir_proc, fs); 152 printf("----\n"); 153 154 /* Unlink the files. */ 155 156 for (i = 1; i <= FILES; i++) 157 { 158 sprintf(basename, "file%04d", i); 159 160 if (ext2fs_unlink(fs, EXT2_ROOT_INO, basename, 0, 0)) 161 { 162 printf("Could not unlink file %s\n", basename); 163 return 1; 164 } 165 } 166 167 image_list_dir(fs, "", image_list_dir_proc, fs); 168 printf("----\n"); 169 170 /* Access and close unlinked files. */ 171 172 for (i = 1; i <= FILES; i++) 173 { 174 sprintf(basename, "file%04d", i); 175 sprintf(buf, "writing to file%04d", i); 176 177 file = files[i - 1]; 178 179 if (ext2fs_file_write(file, buf, strlen(buf), &transferred)) 180 { 181 printf("Could not write to file %s\n", basename); 182 return 1; 183 } 184 185 ext2fs_file_flush(file); 186 ext2fs_file_close(file); 187 } 188 189 image_list_dir(fs, "", image_list_dir_proc, fs); 190 printf("----\n"); 191 192 /* Create some more files. */ 193 194 for (i = 1; i <= FILES; i++) 195 { 196 sprintf(basename, "file%04d", i + FILES); 197 198 retval = image_create_file(fs, EXT2_ROOT_INO, basename, 0644, 199 1000, 1000, &ino); 200 201 if (retval) 202 { 203 printf("Could not create file %s\n", basename); 204 return 1; 205 } 206 207 if (ext2fs_file_open(fs, ino, EXT2_FILE_WRITE | EXT2_FILE_CREATE, &file)) 208 { 209 printf("Could not write file %s\n", basename); 210 return 1; 211 } 212 213 ext2fs_file_flush(file); 214 ext2fs_file_close(file); 215 } 216 217 image_list_dir(fs, "", image_list_dir_proc, fs); 218 printf("----\n"); 219 220 /* Re-open the original files and read from them. */ 221 222 for (i = 1; i <= FILES; i++) 223 { 224 sprintf(basename, "file%04d", i); 225 226 ino = inos[i - 1]; 227 228 if (ext2fs_file_open(fs, ino, 0, &file)) 229 { 230 printf("Could not open file %s\n", basename); 231 return 1; 232 } 233 234 if (ext2fs_file_read(file, buf, BUFSIZE, &transferred)) 235 { 236 printf("Could not read from file %s\n", basename); 237 return 1; 238 } 239 240 buf[transferred] = '\0'; 241 printf("Read from %s: %s\n", basename, buf); 242 243 ext2fs_file_close(file); 244 } 245 246 /* Close the filesystem image. */ 247 248 retval = ext2fs_flush(fs); 249 if (retval) 250 { 251 printf("Error flushing filesystem in %s\n", fsname); 252 exitcode = 1; 253 } 254 255 retval = ext2fs_close(fs); 256 if (retval) 257 { 258 printf("Error closing filesystem in %s\n", fsname); 259 exitcode = 1; 260 } 261 262 ext2fs_free(fs); 263 return exitcode; 264 }