1/* vi: set sw=4 ts=4: */ 2/* 3 * See README for additional information 4 * 5 * Licensed under GPLv2, see file LICENSE in this tarball for details. 6 */ 7 8#include "libbb.h" 9#include "e2fs_lib.h" 10 11#define HAVE_EXT2_IOCTLS 1 12 13#if INT_MAX == LONG_MAX 14#define IF_LONG_IS_SAME(...) __VA_ARGS__ 15#define IF_LONG_IS_WIDER(...) 16#else 17#define IF_LONG_IS_SAME(...) 18#define IF_LONG_IS_WIDER(...) __VA_ARGS__ 19#endif 20 21static void close_silently(int fd) 22{ 23 int e = errno; 24 close(fd); 25 errno = e; 26} 27 28 29/* Iterate a function on each entry of a directory */ 30int iterate_on_dir(const char *dir_name, 31 int FAST_FUNC (*func)(const char *, struct dirent *, void *), 32 void *private) 33{ 34 DIR *dir; 35 struct dirent *de; 36 37 dir = opendir(dir_name); 38 if (dir == NULL) { 39 return -1; 40 } 41 while ((de = readdir(dir)) != NULL) { 42 func(dir_name, de, private); 43 } 44 closedir(dir); 45 return 0; 46} 47 48 49/* Get/set a file version on an ext2 file system */ 50int fgetsetversion(const char *name, unsigned long *get_version, unsigned long set_version) 51{ 52#if HAVE_EXT2_IOCTLS 53 int fd, r; 54 IF_LONG_IS_WIDER(int ver;) 55 56 fd = open(name, O_RDONLY | O_NONBLOCK); 57 if (fd == -1) 58 return -1; 59 if (!get_version) { 60 IF_LONG_IS_WIDER( 61 ver = (int) set_version; 62 r = ioctl(fd, EXT2_IOC_SETVERSION, &ver); 63 ) 64 IF_LONG_IS_SAME( 65 r = ioctl(fd, EXT2_IOC_SETVERSION, (void*)&set_version); 66 ) 67 } else { 68 IF_LONG_IS_WIDER( 69 r = ioctl(fd, EXT2_IOC_GETVERSION, &ver); 70 *get_version = ver; 71 ) 72 IF_LONG_IS_SAME( 73 r = ioctl(fd, EXT2_IOC_GETVERSION, (void*)get_version); 74 ) 75 } 76 close_silently(fd); 77 return r; 78#else /* ! HAVE_EXT2_IOCTLS */ 79 errno = EOPNOTSUPP; 80 return -1; 81#endif /* ! HAVE_EXT2_IOCTLS */ 82} 83 84 85/* Get/set a file flags on an ext2 file system */ 86int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_flags) 87{ 88#if HAVE_EXT2_IOCTLS 89 struct stat buf; 90 int fd, r; 91 IF_LONG_IS_WIDER(int f;) 92 93 if (stat(name, &buf) == 0 /* stat is ok */ 94 && !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode) 95 ) { 96 goto notsupp; 97 } 98 fd = open(name, O_RDONLY | O_NONBLOCK); /* neither read nor write asked for */ 99 if (fd == -1) 100 return -1; 101 102 if (!get_flags) { 103 IF_LONG_IS_WIDER( 104 f = (int) set_flags; 105 r = ioctl(fd, EXT2_IOC_SETFLAGS, &f); 106 ) 107 IF_LONG_IS_SAME( 108 r = ioctl(fd, EXT2_IOC_SETFLAGS, (void*)&set_flags); 109 ) 110 } else { 111 IF_LONG_IS_WIDER( 112 r = ioctl(fd, EXT2_IOC_GETFLAGS, &f); 113 *get_flags = f; 114 ) 115 IF_LONG_IS_SAME( 116 r = ioctl(fd, EXT2_IOC_GETFLAGS, (void*)get_flags); 117 ) 118 } 119 120 close_silently(fd); 121 return r; 122 notsupp: 123#endif /* HAVE_EXT2_IOCTLS */ 124 errno = EOPNOTSUPP; 125 return -1; 126} 127 128 129/* Print file attributes on an ext2 file system */ 130const uint32_t e2attr_flags_value[] = { 131#ifdef ENABLE_COMPRESSION 132 EXT2_COMPRBLK_FL, 133 EXT2_DIRTY_FL, 134 EXT2_NOCOMPR_FL, 135 EXT2_ECOMPR_FL, 136#endif 137 EXT2_INDEX_FL, 138 EXT2_SECRM_FL, 139 EXT2_UNRM_FL, 140 EXT2_SYNC_FL, 141 EXT2_DIRSYNC_FL, 142 EXT2_IMMUTABLE_FL, 143 EXT2_APPEND_FL, 144 EXT2_NODUMP_FL, 145 EXT2_NOATIME_FL, 146 EXT2_COMPR_FL, 147 EXT3_JOURNAL_DATA_FL, 148 EXT2_NOTAIL_FL, 149 EXT2_TOPDIR_FL 150}; 151 152const char e2attr_flags_sname[] = 153#ifdef ENABLE_COMPRESSION 154 "BZXE" 155#endif 156 "I" 157 "suSDiadAcjtT"; 158 159static const char e2attr_flags_lname[] = 160#ifdef ENABLE_COMPRESSION 161 "Compressed_File" "\0" 162 "Compressed_Dirty_File" "\0" 163 "Compression_Raw_Access" "\0" 164 "Compression_Error" "\0" 165#endif 166 "Indexed_directory" "\0" 167 "Secure_Deletion" "\0" 168 "Undelete" "\0" 169 "Synchronous_Updates" "\0" 170 "Synchronous_Directory_Updates" "\0" 171 "Immutable" "\0" 172 "Append_Only" "\0" 173 "No_Dump" "\0" 174 "No_Atime" "\0" 175 "Compression_Requested" "\0" 176 "Journaled_Data" "\0" 177 "No_Tailmerging" "\0" 178 "Top_of_Directory_Hierarchies" "\0" 179 /* Another trailing NUL is added by compiler */; 180 181void print_e2flags(FILE *f, unsigned long flags, unsigned options) 182{ 183 const uint32_t *fv; 184 const char *fn; 185 186 fv = e2attr_flags_value; 187 if (options & PFOPT_LONG) { 188 int first = 1; 189 fn = e2attr_flags_lname; 190 do { 191 if (flags & *fv) { 192 if (!first) 193 fputs(", ", f); 194 fputs(fn, f); 195 first = 0; 196 } 197 fv++; 198 fn += strlen(fn) + 1; 199 } while (*fn); 200 if (first) 201 fputs("---", f); 202 } else { 203 fn = e2attr_flags_sname; 204 do { 205 char c = '-'; 206 if (flags & *fv) 207 c = *fn; 208 fputc(c, f); 209 fv++; 210 fn++; 211 } while (*fn); 212 } 213} 214