/filesystems/unixfs/ancientfs/ancientfs_mainx.c
C | 420 lines | 388 code | 22 blank | 10 comment | 25 complexity | 41daf9c2278cdefe8a98630373984840 MD5 | raw file
1/* 2 * Ancient UNIX File Systems for MacFUSE 3 * Amit Singh 4 * http://osxbook.com 5 */ 6 7#include "unixfs.h" 8#include "ancientfs.h" 9 10#include <errno.h> 11#include <stddef.h> 12#include <stdio.h> 13#include <stdlib.h> 14#include <string.h> 15#include <unistd.h> 16#include <ctype.h> 17#include <fcntl.h> 18#if __linux__ || (__FreeBSD__ < 10) 19#define __USE_GNU 1 20#define __private_extern__ 21#endif 22#include <dlfcn.h> 23 24static const char* PROGNAME = "ancientfs"; 25static const char* PROGVERS = "1.0"; 26 27static struct filesystems { 28 int isalias; 29 char* fstypename; 30 char* fstypename_canonical; 31 uint32_t flags; 32 char* description; 33 uint32_t magicoffset; 34 char magicbytes[32]; 35 char magiclen; 36} filesystems[] = { 37 38 { 39 0, "v1tap", "tap", 40 ANCIENTFS_UNIX_V1 | ANCIENTFS_GENTAPE, 41 "DECtape 'tap' tape archive; UNIX V1", 42 0, { 0 }, 0, 43 }, 44 { 45 0, "v2tap", "tap", 46 ANCIENTFS_UNIX_V2 | ANCIENTFS_GENTAPE, 47 "DECtape 'tap' tape archive; UNIX V2", 48 0, { 0 }, 0, 49 }, 50 { 51 0, "v3tap", "tap", 52 ANCIENTFS_UNIX_V3 | ANCIENTFS_GENTAPE, 53 "DECtape 'tap' tape archive; UNIX V3", 54 0, { 0 }, 0, 55 }, 56 { 57 0, "ntap", "tap", 58 ANCIENTFS_GENTAPE, 59 "DECtape/magtape 'tap' tape archive; 1970 epoch", 60 0, { 0 }, 0, 61 }, 62 { 63 0, "tp", "tp", 64 ANCIENTFS_GENTAPE, 65 "DECtape/magtape 'tp' tape archive", 66 0, { 0 }, 0, 67 }, 68 { 69 0, "itp", "itp", 70 ANCIENTFS_GENTAPE, 71 "UNIX 'itp' tape archive", 72 0, { 0 }, 0, 73 }, 74 { 0, "dtp", "dtp", 75 ANCIENTFS_GENTAPE, 76 "UNIX 'dtp' tape archive", 77 0, { 0 }, 0, 78 }, 79 { 0, "dump", "dump", 80 0, 81 "Incremental file system dump (512-byte blocks, V7/bsd)", 82 0, { 0 }, 0, 83 }, 84 { 1, "dump512" , "dump", 85 0, 86 "Incremental file system dump (512-byte blocks, V7/bsd)", 87 0, { 0 }, 0, 88 }, 89 { 0, "dump1k", "dump1024", 90 ANCIENTFS_DUMP1KB, 91 "Incremental file system dump (1024-byte blocks, V7/bsd)", 92 0, { 0 }, 0, 93 }, 94 { 0, "dump-vn", "dumpvn", 95 0, 96 "Incremental file system dump (512-byte blocks, bsd-vn)", 97 0, { 0 }, 0, 98 }, 99 { 0, "dump1k-vn", "dumpvn1024", 100 ANCIENTFS_DUMP1KB, 101 "Incremental file system dump (1024-byte blocks, bsd-vn)", 102 0, { 0 }, 0, 103 }, 104 { 105 0, "v1ar", "voar", 106 ANCIENTFS_UNIX_V1, 107 "Very old (0177555) archive (.a) from First Edition UNIX", 108 0, { 0x6d, 0xff }, 2, 109 }, 110 { 111 0, "v2ar", "voar", 112 ANCIENTFS_UNIX_V2, 113 "Very old (0177555) archive (.a) from Second Edition UNIX", 114 0, { 0x6d, 0xff }, 2, 115 }, 116 { 117 0, "v3ar", "voar", 118 ANCIENTFS_UNIX_V3, 119 "Very old (0177555) archive (.a) from Third Edition UNIX", 120 0, { 0x6d, 0xff }, 2, 121 }, 122 { 123 1, "ar", "voar", 124 0, 125 "Very old (0177555) archive (.a)", 126 0, { 0x6d, 0xff }, 2, 127 }, 128 { 129 1, "ar", "oar", 130 0, 131 "Old (0177545) archive (.a)", 132 0, { 0x65, 0xff }, 2, 133 }, 134 { 135 1, "ar", "oar", 136 0, 137 "Old (0177545) archive (.a)", 138 0, { 0xff, 0x65 }, 2, 139 }, 140 { 141 0, "ar", "ar", 142 0, 143 "Current (!<arch>\\n), old (0177545), or very old (0177555)\n" 144 " archive (.a); use (v1|v2|v3)ar for UNIX V1/V2/V3 " 145 "archives", 146 0, { 0x21, 0x3c, 0x61, 0x72, 0x63, 0x68, 0x3e, 0x0a }, 8, 147 }, 148 { 149 0, "bcpio", "bcpio", 150 0, 151 "Binary cpio archive (old); may be byte-swapped", 152 0, { 0x71, 0xc7 }, 2, 153 }, 154 { 155 1, "bcpio", "bcpio", 156 0, 157 "Binary cpio archive (old); may be byte-swapped", 158 0, { 0xc7, 0x71 }, 2, 159 }, 160 { 161 0, "cpio_odc", "cpio_odc", 162 0, 163 "ASCII (odc) cpio archive", 164 0, { 0x30, 0x37, 0x30, 0x37, 0x30, 0x37 }, 6, 165 }, 166 { 167 0, "cpio_newc", "cpio_newc", 168 0, 169 "New ASCII (newc) cpio archive", 170 0, { 0x30, 0x37, 0x30, 0x37, 0x30, 0x31 }, 6, 171 }, 172 { 173 0, "cpio_newcrc", "cpio_newc", 174 ANCIENTFS_NEWCRC, 175 "New ASCII (newc) cpio archive with checksum", 176 0, { 0x30, 0x37, 0x30, 0x37, 0x30, 0x32 }, 6, 177 }, 178 { 179 0, "tar", "tar", 180 0, 181 "ustar, pre-POSIX ustar, or V7 tar archive", 182 257, { 0x75, 0x73, 0x74, 0x61, 0x72, 0x0 }, 6, /* POSIX ustar */ 183 }, 184 { 185 1, "tar", "tar", 186 0, 187 "ustar, pre-POSIX ustar, or V7 tar archive", 188 257, { 0x75, 0x73, 0x74, 0x61, 0x72, 0x20 }, 6, /* pre-POSIX ustar */ 189 }, 190 { 191 1, "tar", "tar", 192 0, 193 "ustar, pre-POSIX ustar, or V7 tar archive", 194 0, { 0 }, 0, /* V7 tar */ 195 }, 196 { 197 0, "v1", "v123", 198 ANCIENTFS_UNIX_V1, 199 "First Edition UNIX file system", 200 0, { 0 }, 0, 201 }, 202 { 203 0, "v2", "v123", 204 ANCIENTFS_UNIX_V2, 205 "Second Edition UNIX file system", 206 0, { 0 }, 0, 207 }, 208 { 209 0, "v3", "v123", 210 ANCIENTFS_UNIX_V3, 211 "Third Edition UNIX file system", 212 0, { 0 }, 0, 213 }, 214 { 215 0, "v4", "v456", 216 ANCIENTFS_UNIX_V4, 217 "Fourth Edition UNIX file system", 218 0, { 0 }, 0, 219 }, 220 { 221 0, "v5", "v456", 222 ANCIENTFS_UNIX_V5, 223 "Fifth Edition UNIX file system", 224 0, { 0 }, 0, 225 }, 226 { 227 0, "v6", "v456", 228 ANCIENTFS_UNIX_V6, 229 "Sixth Edition UNIX file system", 230 0, { 0 }, 0, 231 }, 232 { 233 0, "v7", "v7", 234 0, 235 "Seventh Edition UNIX file system", 236 0, { 0 }, 0, 237 }, 238 { 239 0, "v10", "v10", 240 ANCIENTFS_UNIX_V10, 241 "Tenth Edition UNIX file system", 242 0, { 0 }, 0, 243 }, 244 { 245 0, "32v", "32v", 246 0, 247 "UNIX/32V file system", 248 0, { 0 }, 0, 249 }, 250 { 251 1, "32/v", "32v", 252 0, 253 "UNIX/32V file system", 254 0, { 0 }, 0, 255 }, 256 { 257 1, "2.9bsd", "29bsd", 258 0, 259 "BSD file system (V7-style with fixed-length file names)", 260 0, { 0 }, 0, 261 }, 262 { 263 1, "29bsd", "29bsd", 264 0, 265 "BSD file system (V7-style with fixed-length file names;\n" 266 " e.g. 2.9BSD or 4.0BSD)", 267 0, { 0 }, 0, 268 }, 269 { 270 0, "bsd", "29bsd", 271 0, 272 "BSD file system (V7-style with fixed-length file names;\n" 273 " e.g. 2.9BSD or 4.0BSD)", 274 0, { 0 }, 0, 275 }, 276 { 277 1, "2.11bsd", "211bsd", 278 0, 279 "BSD file system (pre 'fast-file-system' \"UFS\" with\n" 280 " variable-length file names; e.g. 2.11BSD " 281 "for PDP-11)", 282 0, { 0 }, 0, 283 }, 284 { 285 1, "211bsd", "211bsd", 286 0, 287 "BSD file system (pre 'fast-file-system' \"UFS\" with\n" 288 " variable-length file names; e.g. 2.11BSD " 289 "for PDP-11)", 290 0, { 0 }, 0, 291 }, 292 { 293 0, "bsd-vn", "211bsd", 294 0, 295 "BSD file system (pre 'fast-file-system' \"UFS\" with\n" 296 " variable-length file names; e.g. 2.11BSD " 297 "for PDP-11)", 298 0, { 0 }, 0, 299 }, 300 /* done */ 301 { 0, NULL, NULL, 0 }, 302}; 303 304__private_extern__ 305void 306unixfs_usage(void) 307{ 308 fprintf(stderr, 309"AncientFS (%s): a MacFUSE file system to mount ancient Unix disks and tapes\n" 310"Amit Singh <http://osxbook.com>\n" 311"usage:\n" 312" %s [--force] [--fsendian pdp|big|little] --dmg DMG --type TYPE MOUNTPOINT [MacFUSE args...]\n" 313"where:\n" 314" . DMG is an ancient Unix disk or tape image of a valid type\n" 315" . TYPE is one of the following:\n\n", 316PROGVERS, PROGNAME); 317 318 int i; 319 for (i = 0; filesystems[i].fstypename != NULL; i++) { 320 if (!filesystems[i].isalias) 321 fprintf(stderr, " %-11s %s\n", filesystems[i].fstypename, 322 filesystems[i].description); 323 } 324 fprintf(stderr, "\n"); 325 326 fprintf(stderr, "%s", 327 " . --force attempts mounting even if there are warnings or errors\n" 328 ); 329} 330 331__private_extern__ 332struct unixfs* 333unixfs_preflight(char* dmg, char** type, struct unixfs** unixfsp) 334{ 335 int i; 336 *unixfsp = NULL; 337 338 if (!type) 339 goto out; 340 341 int fd; 342 char buf[512]; 343 344 if (!dmg) { 345 fprintf(stderr, "no image specified\n"); 346 goto out; 347 } 348 349 if ((fd = open(dmg, O_RDONLY)) < 0) { 350 fprintf(stderr, "failed to open %s\n", dmg); 351 goto out; 352 } 353 354 if (read(fd, buf, 512) != 512) { 355 close(fd); 356 fprintf(stderr, "failed to read data from %s\n", dmg); 357 } 358 359 close(fd); 360 361 if (!*type) { 362 363 /* no type; try some matching */ 364 for (i = 0; filesystems[i].fstypename != NULL; i++) { 365 if (filesystems[i].magiclen == 0) 366 continue; 367 /* ok, got something; try */ 368 if (memcmp(filesystems[i].magicbytes, 369 (char*)&buf[filesystems[i].magicoffset], 370 filesystems[i].magiclen) == 0) { 371 *type = filesystems[i].fstypename; 372 goto findhandler; 373 } 374 } 375 376 goto out; 377 } 378 379findhandler: 380 381 for (i = 0; filesystems[i].fstypename != NULL; i++) { 382 if (strcasecmp(*type, filesystems[i].fstypename) == 0) { 383 /* If this has a non-zero magic length, must do magic too. */ 384 if (filesystems[i].magiclen) { 385 if (memcmp(filesystems[i].magicbytes, 386 (char*)&buf[filesystems[i].magicoffset], 387 filesystems[i].magiclen) != 0) { 388 /* not this one */ 389 continue; 390 } 391 } 392 char symb[255]; 393 snprintf(symb, 255, "%s_%s", "unixfs", 394 filesystems[i].fstypename_canonical); 395 void* impl = dlsym(RTLD_DEFAULT, symb); 396 if (impl != NULL) { 397 *unixfsp = (struct unixfs*)impl; 398 (*unixfsp)->flags = filesystems[i].flags; 399 break; 400 } 401 } 402 } 403 404out: 405 return *unixfsp; 406} 407 408__private_extern__ 409void 410unixfs_postflight(char* fsname, char* volname, char* extra_args) 411{ 412#if __APPLE__ 413 snprintf(extra_args, UNIXFS_ARGLEN, 414 "-oro,defer_permissions,daemon_timeout=5," 415 "volname=%s,fsname=%s File System", 416 volname, fsname); 417#else 418 snprintf(extra_args, UNIXFS_ARGLEN, "-oro"); 419#endif 420}