[9] | 1 |
|
---|
| 2 | /* writeisofs - simple ISO9660-format-image writing utility */
|
---|
| 3 |
|
---|
| 4 | #include <errno.h>
|
---|
| 5 | #include <stdio.h>
|
---|
| 6 | #include <time.h>
|
---|
| 7 | #include <stdlib.h>
|
---|
| 8 | #include <fcntl.h>
|
---|
| 9 | #include <string.h>
|
---|
| 10 | #include <unistd.h>
|
---|
| 11 | #include <dirent.h>
|
---|
| 12 | #include <ctype.h>
|
---|
| 13 | #include <ibm/partition.h>
|
---|
| 14 |
|
---|
| 15 | #include <sys/stat.h>
|
---|
| 16 |
|
---|
| 17 | #define Writefield(fd, f) Write(fd, &(f), sizeof(f))
|
---|
| 18 |
|
---|
| 19 | extern char *optarg;
|
---|
| 20 | extern int optind;
|
---|
| 21 |
|
---|
| 22 | typedef unsigned char u_int8_t;
|
---|
| 23 | typedef unsigned short int u_int16_t;
|
---|
| 24 | typedef unsigned long int u_int32_t;
|
---|
| 25 |
|
---|
| 26 | #ifndef min
|
---|
| 27 | #define min(a,b) ((a) < (b) ? (a) : (b))
|
---|
| 28 | #endif
|
---|
| 29 |
|
---|
| 30 | #define FLAG_DIR 2
|
---|
| 31 |
|
---|
| 32 | #include <sys/types.h>
|
---|
| 33 | #include <sys/stat.h>
|
---|
| 34 |
|
---|
| 35 | #define NAMELEN (DIRSIZ+5)
|
---|
| 36 | #define ISONAMELEN 12
|
---|
| 37 | #define PLATFORM_80X86 0
|
---|
| 38 |
|
---|
| 39 | #define ISO_SECTOR 2048
|
---|
| 40 | #define VIRTUAL_SECTOR 512
|
---|
| 41 |
|
---|
| 42 | #define CURRENTDIR "."
|
---|
| 43 | #define PARENTDIR ".."
|
---|
| 44 |
|
---|
| 45 | /* *** CD (disk) data structures ********************* */
|
---|
| 46 |
|
---|
| 47 | /* primary volume descriptor */
|
---|
| 48 |
|
---|
| 49 | struct pvd {
|
---|
| 50 | u_int8_t one;
|
---|
| 51 | char set[6];
|
---|
| 52 | u_int8_t zero;
|
---|
| 53 | char system[32];
|
---|
| 54 | char volume[32];
|
---|
| 55 | u_int8_t zeroes1[8];
|
---|
| 56 | u_int32_t sectors[2];
|
---|
| 57 | u_int8_t zeroes2[32];
|
---|
| 58 | u_int16_t setsize[2];
|
---|
| 59 | u_int16_t seq[2];
|
---|
| 60 | u_int16_t sectorsize[2];
|
---|
| 61 | u_int32_t pathtable[2];
|
---|
| 62 | u_int32_t first_little_pathtable_start;
|
---|
| 63 | u_int32_t second_little_pathtable_start;
|
---|
| 64 | u_int32_t first_big_pathtable_start;
|
---|
| 65 | u_int32_t second_big_pathtable_start;
|
---|
| 66 | u_int8_t rootrecord[34];
|
---|
| 67 | u_int8_t volumeset[128];
|
---|
| 68 | u_int8_t publisher[128];
|
---|
| 69 | u_int8_t preparer[128];
|
---|
| 70 | u_int8_t application[128];
|
---|
| 71 | u_int8_t copyrightfile[37];
|
---|
| 72 | u_int8_t abstractfile[37];
|
---|
| 73 | u_int8_t bibliofile[37];
|
---|
| 74 | u_int8_t create[17];
|
---|
| 75 | u_int8_t modified[17];
|
---|
| 76 | char expiry[17];
|
---|
| 77 | u_int8_t effective[17];
|
---|
| 78 | u_int8_t one2;
|
---|
| 79 | u_int8_t zero2;
|
---|
| 80 | u_int8_t zeroes3[512];
|
---|
| 81 | u_int8_t zeroes4[653];
|
---|
| 82 | };
|
---|
| 83 |
|
---|
| 84 | /* boot record volume descriptor */
|
---|
| 85 |
|
---|
| 86 | struct bootrecord {
|
---|
| 87 | u_int8_t indicator; /* 0 */
|
---|
| 88 | char set[5]; /* "CD001" */
|
---|
| 89 | u_int8_t version; /* 1 */
|
---|
| 90 | char ident[32]; /* "EL TORITO SPECIFICATION" */
|
---|
| 91 | u_int8_t zero[32]; /* unused, must be 0 */
|
---|
| 92 | u_int32_t bootcatalog; /* starting sector of boot catalog */
|
---|
| 93 | u_int8_t zero2[1973]; /* unused, must be 0 */
|
---|
| 94 | };
|
---|
| 95 |
|
---|
| 96 | /* boot catalog validation entry */
|
---|
| 97 |
|
---|
| 98 | struct bc_validation {
|
---|
| 99 | u_int8_t headerid; /* 1 */
|
---|
| 100 | u_int8_t platform; /* 0: 80x86; 1: powerpc; 2: mac */
|
---|
| 101 | u_int8_t zero[2]; /* unused, must be 0 */
|
---|
| 102 | char idstring[24]; /* id string */
|
---|
| 103 | u_int16_t checksum;
|
---|
| 104 | u_int8_t keys[2]; /* 0x55AA */
|
---|
| 105 | };
|
---|
| 106 |
|
---|
| 107 | /* boot catalog initial/default entry */
|
---|
| 108 |
|
---|
| 109 | #define INDICATE_BOOTABLE 0x88
|
---|
| 110 |
|
---|
| 111 | #define BOOTMEDIA_NONE 0
|
---|
| 112 | #define BOOTMEDIA_120M 1
|
---|
| 113 | #define BOOTMEDIA_144M 2
|
---|
| 114 | #define BOOTMEDIA_288M 3
|
---|
| 115 | #define BOOTMEDIA_HARDDISK 4
|
---|
| 116 |
|
---|
| 117 | struct bc_initial {
|
---|
| 118 | u_int8_t indicator; /* INDICATE_BOOTABLE */
|
---|
| 119 | u_int8_t media; /* BOOTMEDIA_* */
|
---|
| 120 | u_int16_t seg; /* load segment or 0 for default */
|
---|
| 121 | u_int8_t type; /* system type (from part. table) */
|
---|
| 122 | u_int8_t zero;
|
---|
| 123 | u_int16_t sectors;
|
---|
| 124 | u_int32_t startsector;
|
---|
| 125 | u_int8_t zero2[20];
|
---|
| 126 | };
|
---|
| 127 |
|
---|
| 128 | /* directory entry */
|
---|
| 129 |
|
---|
| 130 | struct dir {
|
---|
| 131 | u_int8_t recordsize;
|
---|
| 132 | u_int8_t extended;
|
---|
| 133 | u_int32_t datasector[2];
|
---|
| 134 | u_int32_t filesize[2];
|
---|
| 135 | u_int8_t year;
|
---|
| 136 | u_int8_t month;
|
---|
| 137 | u_int8_t day;
|
---|
| 138 | u_int8_t hour;
|
---|
| 139 | u_int8_t minute;
|
---|
| 140 | u_int8_t second;
|
---|
| 141 | u_int8_t offset;
|
---|
| 142 | u_int8_t flags;
|
---|
| 143 | u_int8_t interleaved;
|
---|
| 144 | u_int8_t interleavegap;
|
---|
| 145 | u_int16_t sequence[2];
|
---|
| 146 | u_int8_t namelen;
|
---|
| 147 | char name[NAMELEN];
|
---|
| 148 | };
|
---|
| 149 |
|
---|
| 150 | /* *** program (memory) data structures ********************* */
|
---|
| 151 |
|
---|
| 152 | struct node {
|
---|
| 153 | char name[NAMELEN];
|
---|
| 154 | int isdir;
|
---|
| 155 | int pathtablerecord;
|
---|
| 156 | struct node *firstchild, *nextchild;
|
---|
| 157 |
|
---|
| 158 | /* filled out at i/o time */
|
---|
| 159 | u_int32_t startsector, bytesize;
|
---|
| 160 | };
|
---|
| 161 |
|
---|
| 162 | int n_reserved_pathtableentries = 0, n_used_pathtableentries = 0;
|
---|
| 163 | int harddisk_emulation = 0;
|
---|
| 164 | int system_type = 0;
|
---|
| 165 |
|
---|
| 166 | int get_system_type(int fd);
|
---|
| 167 |
|
---|
| 168 | ssize_t
|
---|
| 169 | Write(int fd, void *buf, ssize_t len)
|
---|
| 170 | {
|
---|
| 171 | ssize_t r;
|
---|
| 172 | if((r=write(fd, buf, len)) != len) {
|
---|
| 173 | if(r < 0) { perror("write"); }
|
---|
| 174 | fprintf(stderr, "failed or short write - aborting.\n");
|
---|
| 175 | exit(1);
|
---|
| 176 | }
|
---|
| 177 | return len;
|
---|
| 178 | }
|
---|
| 179 |
|
---|
| 180 | off_t
|
---|
| 181 | Lseek(int fd, off_t pos, int rel)
|
---|
| 182 | {
|
---|
| 183 | off_t r;
|
---|
| 184 |
|
---|
| 185 | if((r=lseek(fd, pos, rel)) < 0) {
|
---|
| 186 | perror("lseek");
|
---|
| 187 | fprintf(stderr, "lseek failed - aborting.\n");
|
---|
| 188 | exit(1);
|
---|
| 189 | }
|
---|
| 190 |
|
---|
| 191 | return r;
|
---|
| 192 | }
|
---|
| 193 |
|
---|
| 194 | void
|
---|
| 195 | writesector(int fd, char *block, int *currentsector)
|
---|
| 196 | {
|
---|
| 197 | Write(fd, block, ISO_SECTOR);
|
---|
| 198 | (*currentsector)++;
|
---|
| 199 | return;
|
---|
| 200 | }
|
---|
| 201 |
|
---|
| 202 | void
|
---|
| 203 | seeksector(int fd, int sector, int *currentsector)
|
---|
| 204 | {
|
---|
| 205 | Lseek(fd, sector*ISO_SECTOR, SEEK_SET);
|
---|
| 206 | *currentsector = sector;
|
---|
| 207 | }
|
---|
| 208 |
|
---|
| 209 | void
|
---|
| 210 | seekwritesector(int fd, int sector, char *block, int *currentsector)
|
---|
| 211 | {
|
---|
| 212 | seeksector(fd, sector, currentsector);
|
---|
| 213 | writesector(fd, block, currentsector);
|
---|
| 214 | }
|
---|
| 215 |
|
---|
| 216 | ssize_t
|
---|
| 217 | Read(int fd, void *buf, ssize_t len)
|
---|
| 218 | {
|
---|
| 219 | ssize_t r;
|
---|
| 220 | if((r=read(fd, buf, len)) != len) {
|
---|
| 221 | if(r < 0) { perror("read"); }
|
---|
| 222 | fprintf(stderr, "failed or short read.\n");
|
---|
| 223 | exit(1);
|
---|
| 224 | }
|
---|
| 225 |
|
---|
| 226 | return len;
|
---|
| 227 | }
|
---|
| 228 |
|
---|
| 229 | void both16(unsigned char *both, unsigned short i16)
|
---|
| 230 | {
|
---|
| 231 | unsigned char *little, *big;
|
---|
| 232 |
|
---|
| 233 | little = both;
|
---|
| 234 | big = both + 2;
|
---|
| 235 |
|
---|
| 236 | little[0] = big[1] = i16 & 0xFF;
|
---|
| 237 | little[1] = big[0] = (i16 >> 8) & 0xFF;
|
---|
| 238 | }
|
---|
| 239 |
|
---|
| 240 | void both32(unsigned char *both, unsigned long i32)
|
---|
| 241 | {
|
---|
| 242 | unsigned char *little, *big;
|
---|
| 243 |
|
---|
| 244 | little = both;
|
---|
| 245 | big = both + 4;
|
---|
| 246 |
|
---|
| 247 | little[0] = big[3] = i32 & 0xFF;
|
---|
| 248 | little[1] = big[2] = (i32 >> 8) & 0xFF;
|
---|
| 249 | little[2] = big[1] = (i32 >> 16) & 0xFF;
|
---|
| 250 | little[3] = big[0] = (i32 >> 24) & 0xFF;
|
---|
| 251 | }
|
---|
| 252 |
|
---|
| 253 | #define MINDIRLEN 1
|
---|
| 254 | #define MAXDIRLEN 31
|
---|
| 255 |
|
---|
| 256 | #define MAXLEVEL 8
|
---|
| 257 |
|
---|
| 258 | static int cmpf(const void *v1, const void *v2)
|
---|
| 259 | {
|
---|
| 260 | struct node *n1, *n2;
|
---|
| 261 | int i;
|
---|
| 262 | char f1[NAMELEN], f2[NAMELEN];
|
---|
| 263 |
|
---|
| 264 | n1 = (struct node *) v1;
|
---|
| 265 | n2 = (struct node *) v2;
|
---|
| 266 | strcpy(f1, n1->name);
|
---|
| 267 | strcpy(f2, n2->name);
|
---|
| 268 | for(i = 0; i < strlen(f1); i++) f1[i] = toupper(f1[i]);
|
---|
| 269 | for(i = 0; i < strlen(f2); i++) f2[i] = toupper(f2[i]);
|
---|
| 270 |
|
---|
| 271 |
|
---|
| 272 | return -strcmp(f1, f2);
|
---|
| 273 | }
|
---|
| 274 |
|
---|
| 275 | void
|
---|
| 276 | maketree(struct node *thisdir, char *name, int level)
|
---|
| 277 | {
|
---|
| 278 | DIR *dir;
|
---|
| 279 | struct dirent *e;
|
---|
| 280 | struct node *dirnodes = NULL;
|
---|
| 281 | int reserved_dirnodes = 0, used_dirnodes = 0;
|
---|
| 282 | struct node *child;
|
---|
| 283 |
|
---|
| 284 | thisdir->firstchild = NULL;
|
---|
| 285 | thisdir->isdir = 1;
|
---|
| 286 | thisdir->startsector = 0xdeadbeef;
|
---|
| 287 |
|
---|
| 288 | if(level >= MAXLEVEL) {
|
---|
| 289 | fprintf(stderr, "ignoring entries in %s (too deep for iso9660)\n",
|
---|
| 290 | name);
|
---|
| 291 | return;
|
---|
| 292 | }
|
---|
| 293 |
|
---|
| 294 | if(!(dir = opendir(CURRENTDIR))) {
|
---|
| 295 | perror("opendir");
|
---|
| 296 | return;
|
---|
| 297 | }
|
---|
| 298 |
|
---|
| 299 | /* how many entries do we need to allocate? */
|
---|
| 300 | while(readdir(dir)) reserved_dirnodes++;
|
---|
| 301 | if(!reserved_dirnodes) {
|
---|
| 302 | closedir(dir);
|
---|
| 303 | return;
|
---|
| 304 | }
|
---|
| 305 |
|
---|
| 306 | if(!(dirnodes = malloc(sizeof(*dirnodes)*reserved_dirnodes))) {
|
---|
| 307 | fprintf(stderr, "couldn't allocate dirnodes (%d bytes)\n",
|
---|
| 308 | sizeof(*dirnodes)*reserved_dirnodes);
|
---|
| 309 | exit(1);
|
---|
| 310 | }
|
---|
| 311 |
|
---|
| 312 |
|
---|
| 313 | /* remember all entries in this dir */
|
---|
| 314 | rewinddir(dir);
|
---|
| 315 |
|
---|
| 316 | child = dirnodes;
|
---|
| 317 | while((e=readdir(dir))) {
|
---|
| 318 | struct stat st;
|
---|
| 319 | mode_t type;
|
---|
| 320 | if(!strcmp(e->d_name, CURRENTDIR) || !strcmp(e->d_name, PARENTDIR))
|
---|
| 321 | continue;
|
---|
| 322 | if(stat(e->d_name, &st) < 0) {
|
---|
| 323 | perror(e->d_name);
|
---|
| 324 | fprintf(stderr, "failed to stat file/dir\n");
|
---|
| 325 | exit(1);
|
---|
| 326 | }
|
---|
| 327 |
|
---|
| 328 | type = st.st_mode & S_IFMT;
|
---|
| 329 |
|
---|
| 330 | /*
|
---|
| 331 | printf("%s type: %x dir: %x file: %x\n",
|
---|
| 332 | e->d_name, type, S_IFDIR, S_IFREG);
|
---|
| 333 | */
|
---|
| 334 | if(type != S_IFDIR && type != S_IFREG)
|
---|
| 335 | continue;
|
---|
| 336 |
|
---|
| 337 | used_dirnodes++;
|
---|
| 338 | if(used_dirnodes > reserved_dirnodes) {
|
---|
| 339 | fprintf(stderr, "huh, directory entries appeared "
|
---|
| 340 | "(not enough pre-allocated nodes; this can't happen) ?\n");
|
---|
| 341 | exit(1);
|
---|
| 342 | }
|
---|
| 343 |
|
---|
| 344 | if(type == S_IFDIR) {
|
---|
| 345 | child->isdir = 1;
|
---|
| 346 | } else {
|
---|
| 347 | child->isdir = 0;
|
---|
| 348 | child->firstchild = NULL;
|
---|
| 349 | }
|
---|
| 350 | strncpy(child->name, e->d_name, sizeof(child->name));
|
---|
| 351 |
|
---|
| 352 | child++;
|
---|
| 353 | }
|
---|
| 354 |
|
---|
| 355 | closedir(dir);
|
---|
| 356 |
|
---|
| 357 | if(!used_dirnodes)
|
---|
| 358 | return;
|
---|
| 359 |
|
---|
| 360 | if(!(dirnodes=realloc(dirnodes, used_dirnodes*sizeof(*dirnodes)))) {
|
---|
| 361 | fprintf(stderr, "realloc() of dirnodes failed - aborting\n");
|
---|
| 362 | exit(1);
|
---|
| 363 | }
|
---|
| 364 |
|
---|
| 365 | qsort(dirnodes, used_dirnodes, sizeof(*dirnodes), cmpf);
|
---|
| 366 |
|
---|
| 367 | child = dirnodes;
|
---|
| 368 |
|
---|
| 369 | while(used_dirnodes--) {
|
---|
| 370 | child->nextchild = thisdir->firstchild;
|
---|
| 371 | thisdir->firstchild = child;
|
---|
| 372 | if(child->isdir) {
|
---|
| 373 | if(chdir(child->name) < 0) {
|
---|
| 374 | perror(child->name);
|
---|
| 375 | } else {
|
---|
| 376 | maketree(child, child->name, level+1);
|
---|
| 377 | if(chdir(PARENTDIR) < 0) {
|
---|
| 378 | perror("chdir() failed");
|
---|
| 379 | fprintf(stderr, "couldn't chdir() to parent, aborting\n");
|
---|
| 380 | exit(1);
|
---|
| 381 | }
|
---|
| 382 | }
|
---|
| 383 | }
|
---|
| 384 |
|
---|
| 385 | child++;
|
---|
| 386 | }
|
---|
| 387 |
|
---|
| 388 | }
|
---|
| 389 |
|
---|
| 390 | void
|
---|
| 391 | little32(unsigned char *dest, u_int32_t src)
|
---|
| 392 | {
|
---|
| 393 | dest[0] = ((src >> 0) & 0xFF);
|
---|
| 394 | dest[1] = ((src >> 8) & 0xFF);
|
---|
| 395 | dest[2] = ((src >> 16) & 0xFF);
|
---|
| 396 | dest[3] = ((src >> 24) & 0xFF);
|
---|
| 397 |
|
---|
| 398 | return;
|
---|
| 399 | }
|
---|
| 400 |
|
---|
| 401 | void
|
---|
| 402 | little16(unsigned char *dest, u_int16_t src)
|
---|
| 403 | {
|
---|
| 404 | dest[0] = ((src >> 0) & 0xFF);
|
---|
| 405 | dest[1] = ((src >> 8) & 0xFF);
|
---|
| 406 |
|
---|
| 407 | return;
|
---|
| 408 | }
|
---|
| 409 |
|
---|
| 410 | void
|
---|
| 411 | big32(unsigned char *dest, u_int32_t src)
|
---|
| 412 | {
|
---|
| 413 | dest[3] = ((src >> 0) & 0xFF);
|
---|
| 414 | dest[2] = ((src >> 8) & 0xFF);
|
---|
| 415 | dest[1] = ((src >> 16) & 0xFF);
|
---|
| 416 | dest[0] = ((src >> 24) & 0xFF);
|
---|
| 417 | return;
|
---|
| 418 | }
|
---|
| 419 |
|
---|
| 420 | void
|
---|
| 421 | big16(unsigned char *dest, u_int16_t src)
|
---|
| 422 | {
|
---|
| 423 | dest[1] = ((src >> 0) & 0xFF);
|
---|
| 424 | dest[0] = ((src >> 8) & 0xFF);
|
---|
| 425 | return;
|
---|
| 426 | }
|
---|
| 427 |
|
---|
| 428 |
|
---|
| 429 | void
|
---|
| 430 | traversetree(struct node *root, int level, int littleendian,
|
---|
| 431 | int maxlevel, int *bytes, int fd, int parentrecord, int *recordno)
|
---|
| 432 | {
|
---|
| 433 | struct node *child;
|
---|
| 434 | struct pte {
|
---|
| 435 | u_int8_t len;
|
---|
| 436 | u_int8_t zero;
|
---|
| 437 | u_int32_t startsector;
|
---|
| 438 | u_int16_t parent;
|
---|
| 439 | } pte;
|
---|
| 440 |
|
---|
| 441 | if(level == maxlevel) {
|
---|
| 442 | int i;
|
---|
| 443 | char newname[NAMELEN];
|
---|
| 444 | if(!root->isdir)
|
---|
| 445 | return;
|
---|
| 446 | pte.zero = 0;
|
---|
| 447 | if(level == 1) {
|
---|
| 448 | /* root */
|
---|
| 449 | pte.len = 1;
|
---|
| 450 | pte.parent = 1;
|
---|
| 451 | root->name[0] = root->name[1] = '\0';
|
---|
| 452 | } else {
|
---|
| 453 | pte.len = strlen(root->name);
|
---|
| 454 | pte.parent = parentrecord;
|
---|
| 455 | }
|
---|
| 456 | pte.startsector = root->startsector;
|
---|
| 457 | root->pathtablerecord = (*recordno)++;
|
---|
| 458 |
|
---|
| 459 | if(littleendian) {
|
---|
| 460 | little32((unsigned char *) &pte.startsector, pte.startsector);
|
---|
| 461 | little16((unsigned char *) &pte.parent, pte.parent);
|
---|
| 462 | } else {
|
---|
| 463 | big32((unsigned char *) &pte.startsector, pte.startsector);
|
---|
| 464 | big16((unsigned char *) &pte.parent, pte.parent);
|
---|
| 465 | }
|
---|
| 466 |
|
---|
| 467 | *bytes += Write(fd, &pte.len, sizeof(pte.len));
|
---|
| 468 | *bytes += Write(fd, &pte.zero, sizeof(pte.zero));
|
---|
| 469 | *bytes += Write(fd, &pte.startsector, sizeof(pte.startsector));
|
---|
| 470 | *bytes += Write(fd, &pte.parent, sizeof(pte.parent));
|
---|
| 471 | if(!(pte.len%2))
|
---|
| 472 | root->name[pte.len++] = '\0';
|
---|
| 473 | for(i = 0; i < pte.len; i++)
|
---|
| 474 | newname[i] = toupper(root->name[i]);
|
---|
| 475 | *bytes += Write(fd, newname, pte.len);
|
---|
| 476 | return;
|
---|
| 477 | }
|
---|
| 478 |
|
---|
| 479 | for(child = root->firstchild; child; child = child->nextchild)
|
---|
| 480 | if(child->isdir)
|
---|
| 481 | traversetree(child, level+1, littleendian,
|
---|
| 482 | maxlevel, bytes, fd, root->pathtablerecord,
|
---|
| 483 | recordno);
|
---|
| 484 |
|
---|
| 485 | return;
|
---|
| 486 | }
|
---|
| 487 |
|
---|
| 488 | int
|
---|
| 489 | makepathtables(struct node *root, int littleendian, int *bytes, int fd)
|
---|
| 490 | {
|
---|
| 491 | int level;
|
---|
| 492 | static char block[ISO_SECTOR];
|
---|
| 493 | int recordno;
|
---|
| 494 |
|
---|
| 495 | recordno = 1;
|
---|
| 496 |
|
---|
| 497 | *bytes = 0;
|
---|
| 498 |
|
---|
| 499 | for(level = 1; level <= MAXLEVEL; level++)
|
---|
| 500 | traversetree(root, 1, littleendian, level, bytes, fd, 1, &recordno);
|
---|
| 501 |
|
---|
| 502 | if(*bytes % ISO_SECTOR) {
|
---|
| 503 | ssize_t x;
|
---|
| 504 | x = ISO_SECTOR-(*bytes % ISO_SECTOR);
|
---|
| 505 | write(fd, block, x);
|
---|
| 506 | *bytes += x;
|
---|
| 507 | }
|
---|
| 508 |
|
---|
| 509 | return *bytes/ISO_SECTOR;
|
---|
| 510 | }
|
---|
| 511 |
|
---|
| 512 | ssize_t
|
---|
| 513 | write_direntry(char *origname, u_int32_t sector, u_int32_t size, int isdir,
|
---|
| 514 | int fd)
|
---|
| 515 | {
|
---|
| 516 | int namelen, total = 0;
|
---|
| 517 | struct dir entry;
|
---|
| 518 | char copyname[NAMELEN];
|
---|
| 519 |
|
---|
| 520 | memset(&entry, 0, sizeof(entry));
|
---|
| 521 |
|
---|
| 522 | if(!strcmp(origname, CURRENTDIR)) {
|
---|
| 523 | namelen = 1;
|
---|
| 524 | } else if(!strcmp(origname, PARENTDIR)) {
|
---|
| 525 | entry.name[0] = '\001';
|
---|
| 526 | namelen = 1;
|
---|
| 527 | } else {
|
---|
| 528 | int i;
|
---|
| 529 | strcpy(copyname, origname);
|
---|
| 530 | namelen = strlen(copyname);
|
---|
| 531 |
|
---|
| 532 | if(namelen > ISONAMELEN) {
|
---|
| 533 | fprintf(stderr, "%s: truncated, too long for iso9660\n", copyname);
|
---|
| 534 | namelen = ISONAMELEN;
|
---|
| 535 | copyname[namelen] = '\0';
|
---|
| 536 | }
|
---|
| 537 |
|
---|
| 538 | strcpy(entry.name, copyname);
|
---|
| 539 | for(i = 0; i < namelen; i++)
|
---|
| 540 | entry.name[i] = toupper(entry.name[i]);
|
---|
| 541 |
|
---|
| 542 | /* padding byte + system field */
|
---|
| 543 | entry.name[namelen] = '\0';
|
---|
| 544 | entry.name[namelen+1] = '\0';
|
---|
| 545 | entry.name[namelen+2] = '\0';
|
---|
| 546 | }
|
---|
| 547 | entry.namelen = namelen; /* original length */
|
---|
| 548 | if(!(namelen%2)) namelen++; /* length with padding byte */
|
---|
| 549 |
|
---|
| 550 |
|
---|
| 551 | /* XXX 2 extra bytes for 'system use'.. */
|
---|
| 552 | entry.recordsize = 33 + namelen;
|
---|
| 553 | both32((unsigned char *) entry.datasector, sector);
|
---|
| 554 | both32((unsigned char *) entry.filesize, size);
|
---|
| 555 |
|
---|
| 556 | if(isdir) entry.flags = FLAG_DIR;
|
---|
| 557 |
|
---|
| 558 | /* XXX node date */
|
---|
| 559 |
|
---|
| 560 | both16((unsigned char *) entry.sequence, 1);
|
---|
| 561 |
|
---|
| 562 | total = Write(fd, &entry.recordsize, sizeof(entry.recordsize));
|
---|
| 563 | total += Write(fd, &entry.extended, sizeof(entry.extended));
|
---|
| 564 | total += Write(fd, entry.datasector, sizeof(entry.datasector));
|
---|
| 565 | total += Write(fd, entry.filesize, sizeof(entry.filesize));
|
---|
| 566 | total += Write(fd, &entry.year, sizeof(entry.year));
|
---|
| 567 | total += Write(fd, &entry.month, sizeof(entry.month));
|
---|
| 568 | total += Write(fd, &entry.day, sizeof(entry.day));
|
---|
| 569 | total += Write(fd, &entry.hour, sizeof(entry.hour));
|
---|
| 570 | total += Write(fd, &entry.minute, sizeof(entry.minute));
|
---|
| 571 | total += Write(fd, &entry.second, sizeof(entry.second));
|
---|
| 572 | total += Write(fd, &entry.offset, sizeof(entry.offset));
|
---|
| 573 | total += Write(fd, &entry.flags, sizeof(entry.flags));
|
---|
| 574 | total += Write(fd, &entry.interleaved, sizeof(entry.interleaved));
|
---|
| 575 | total += Write(fd, &entry.interleavegap, sizeof(entry.interleavegap));
|
---|
| 576 | total += Write(fd, entry.sequence, sizeof(entry.sequence));
|
---|
| 577 | total += Write(fd, &entry.namelen, sizeof(entry.namelen));
|
---|
| 578 | total += Write(fd, entry.name, namelen);
|
---|
| 579 |
|
---|
| 580 | if(total != entry.recordsize || (total % 2) != 0) {
|
---|
| 581 | printf("%2d, %2d! ", total, entry.recordsize);
|
---|
| 582 | printf("%3d = %3d - %2d + %2d\n",
|
---|
| 583 | entry.recordsize, sizeof(entry), sizeof(entry.name), namelen);
|
---|
| 584 | }
|
---|
| 585 |
|
---|
| 586 | return entry.recordsize;
|
---|
| 587 | }
|
---|
| 588 |
|
---|
| 589 | void
|
---|
| 590 | writedata(struct node *parent, struct node *root,
|
---|
| 591 | int fd, int *currentsector, int dirs, struct dir *rootentry,
|
---|
| 592 | int rootsize, int remove_after)
|
---|
| 593 | {
|
---|
| 594 | static char buf[1024*1024];
|
---|
| 595 | struct node *c;
|
---|
| 596 | ssize_t written = 0, rest;
|
---|
| 597 |
|
---|
| 598 | for(c = root->firstchild; c; c = c->nextchild) {
|
---|
| 599 | if(c->isdir && chdir(c->name) < 0) {
|
---|
| 600 | perror(c->name);
|
---|
| 601 | fprintf(stderr, "couldn't chdir to %s - aborting\n",
|
---|
| 602 | c->name);
|
---|
| 603 | exit(1);
|
---|
| 604 | }
|
---|
| 605 | writedata(root, c, fd, currentsector, dirs, rootentry, rootsize, remove_after);
|
---|
| 606 | if(c->isdir && chdir(PARENTDIR) < 0) {
|
---|
| 607 | perror("chdir to ..");
|
---|
| 608 | fprintf(stderr, "couldn't chdir to parent - "
|
---|
| 609 | "aborting\n");
|
---|
| 610 | exit(1);
|
---|
| 611 | }
|
---|
| 612 | }
|
---|
| 613 |
|
---|
| 614 | /* write nodes depth-first, down-top */
|
---|
| 615 |
|
---|
| 616 | if(root->isdir && dirs) {
|
---|
| 617 | /* dir */
|
---|
| 618 | written = 0;
|
---|
| 619 | root->startsector = *currentsector;
|
---|
| 620 | written += write_direntry(CURRENTDIR, root->startsector,
|
---|
| 621 | root->bytesize, root->isdir, fd);
|
---|
| 622 | if(parent) {
|
---|
| 623 | written += write_direntry(PARENTDIR, parent->startsector,
|
---|
| 624 | root->bytesize, root->isdir, fd);
|
---|
| 625 | } else {
|
---|
| 626 | written += write_direntry(PARENTDIR, root->startsector,
|
---|
| 627 | root->bytesize, root->isdir, fd);
|
---|
| 628 | }
|
---|
| 629 | for(c = root->firstchild; c; c = c->nextchild) {
|
---|
| 630 | off_t cur1, cur2;
|
---|
| 631 | ssize_t written_before;
|
---|
| 632 | cur1 = Lseek(fd, 0, SEEK_CUR);
|
---|
| 633 | written_before = written;
|
---|
| 634 | written += write_direntry(c->name,
|
---|
| 635 | c->startsector, c->bytesize, c->isdir, fd);
|
---|
| 636 | cur2 = Lseek(fd, 0, SEEK_CUR);
|
---|
| 637 | if(cur1/ISO_SECTOR != (cur2-1)/ISO_SECTOR) {
|
---|
| 638 | /* passed a sector boundary, argh! */
|
---|
| 639 | Lseek(fd, cur1, SEEK_SET);
|
---|
| 640 | written = written_before;
|
---|
| 641 | rest=(ISO_SECTOR-(written % ISO_SECTOR));
|
---|
| 642 | memset(buf, 0, rest);
|
---|
| 643 | Write(fd, buf, rest);
|
---|
| 644 | written += rest;
|
---|
| 645 | written += write_direntry(c->name,
|
---|
| 646 | c->startsector, c->bytesize, c->isdir, fd);
|
---|
| 647 | }
|
---|
| 648 | }
|
---|
| 649 | root->bytesize = written;
|
---|
| 650 | } else if(!root->isdir && !dirs) {
|
---|
| 651 | /* file */
|
---|
| 652 | struct stat st;
|
---|
| 653 | ssize_t rem;
|
---|
| 654 | int filefd;
|
---|
| 655 |
|
---|
| 656 | if(stat(root->name, &st) < 0) {
|
---|
| 657 | perror(root->name);
|
---|
| 658 | fprintf(stderr, "couldn't stat %s - aborting\n", root->name);
|
---|
| 659 | exit(1);
|
---|
| 660 | }
|
---|
| 661 |
|
---|
| 662 | if((filefd = open(root->name, O_RDONLY)) < 0) {
|
---|
| 663 | perror(root->name);
|
---|
| 664 | fprintf(stderr, "couldn't open %s - aborting\n", root->name);
|
---|
| 665 | exit(1);
|
---|
| 666 | }
|
---|
| 667 |
|
---|
| 668 | rem = st.st_size;
|
---|
| 669 |
|
---|
| 670 | root->startsector = *currentsector;
|
---|
| 671 |
|
---|
| 672 | while(rem > 0) {
|
---|
| 673 | ssize_t chunk;
|
---|
| 674 | chunk = min(sizeof(buf), rem);
|
---|
| 675 | Read(filefd, buf, chunk);
|
---|
| 676 | Write(fd, buf, chunk);
|
---|
| 677 | rem -= chunk;
|
---|
| 678 | }
|
---|
| 679 |
|
---|
| 680 | close(filefd);
|
---|
| 681 |
|
---|
| 682 | root->bytesize = written = st.st_size;
|
---|
| 683 | if(remove_after && unlink(root->name) < 0) {
|
---|
| 684 | perror("unlink");
|
---|
| 685 | fprintf(stderr, "couldn't remove %s\n", root->name);
|
---|
| 686 | }
|
---|
| 687 | } else {
|
---|
| 688 | /* nothing to be done */
|
---|
| 689 | return;
|
---|
| 690 | }
|
---|
| 691 |
|
---|
| 692 | /* fill out sector with zero bytes */
|
---|
| 693 |
|
---|
| 694 | if((rest=(ISO_SECTOR-(written % ISO_SECTOR)))) {
|
---|
| 695 | memset(buf, 0, rest);
|
---|
| 696 | Write(fd, buf, rest);
|
---|
| 697 | written += rest;
|
---|
| 698 | }
|
---|
| 699 |
|
---|
| 700 | /* update dir size with padded size */
|
---|
| 701 |
|
---|
| 702 | if(root->isdir) { root->bytesize = written; }
|
---|
| 703 |
|
---|
| 704 | *currentsector += written/ISO_SECTOR;
|
---|
| 705 | }
|
---|
| 706 |
|
---|
| 707 | void
|
---|
| 708 | writebootcatalog(int fd, int *currentsector, int imagesector, int imagesectors)
|
---|
| 709 | {
|
---|
| 710 | static char buf[ISO_SECTOR];
|
---|
| 711 | struct bc_validation validate;
|
---|
| 712 | struct bc_initial initial;
|
---|
| 713 |
|
---|
| 714 | ssize_t written, rest;
|
---|
| 715 | u_int16_t *v, sum = 0;
|
---|
| 716 | int i;
|
---|
| 717 |
|
---|
| 718 | /* write validation entry */
|
---|
| 719 |
|
---|
| 720 | memset(&validate, 0, sizeof(validate));
|
---|
| 721 | validate.headerid = 1;
|
---|
| 722 | validate.platform = PLATFORM_80X86;
|
---|
| 723 | strcpy(validate.idstring, "");
|
---|
| 724 | validate.keys[0] = 0x55;
|
---|
| 725 | validate.keys[1] = 0xaa;
|
---|
| 726 |
|
---|
| 727 | v = (u_int16_t *) &validate;
|
---|
| 728 | for(i = 0; i < sizeof(validate)/2; i++)
|
---|
| 729 | sum += v[i];
|
---|
| 730 | validate.checksum = 65535 - sum + 1; /* sum must be 0 */
|
---|
| 731 |
|
---|
| 732 | written = Write(fd, &validate, sizeof(validate));
|
---|
| 733 |
|
---|
| 734 | /* write initial/default entry */
|
---|
| 735 |
|
---|
| 736 | memset(&initial, 0, sizeof(initial));
|
---|
| 737 |
|
---|
| 738 | initial.indicator = INDICATE_BOOTABLE;
|
---|
| 739 | if (harddisk_emulation)
|
---|
| 740 | {
|
---|
| 741 | initial.media = BOOTMEDIA_HARDDISK;
|
---|
| 742 | initial.type = system_type;
|
---|
| 743 | }
|
---|
| 744 | else
|
---|
| 745 | initial.media = BOOTMEDIA_144M;
|
---|
| 746 | /* initial.sectors = imagesectors; */
|
---|
| 747 | initial.sectors = 1;
|
---|
| 748 | initial.startsector = imagesector;
|
---|
| 749 |
|
---|
| 750 | written += Write(fd, &initial, sizeof(initial));
|
---|
| 751 |
|
---|
| 752 | /* fill out the rest of the sector with 0's */
|
---|
| 753 |
|
---|
| 754 | if((rest = ISO_SECTOR - (written % 2048))) {
|
---|
| 755 | memset(buf, 0, sizeof(buf));
|
---|
| 756 | written += Write(fd, buf, rest);
|
---|
| 757 | }
|
---|
| 758 |
|
---|
| 759 | (*currentsector) += written / ISO_SECTOR;
|
---|
| 760 |
|
---|
| 761 | return;
|
---|
| 762 | }
|
---|
| 763 |
|
---|
| 764 | int
|
---|
| 765 | writebootimage(char *bootimage, int bootfd, int fd, int *currentsector)
|
---|
| 766 | {
|
---|
| 767 | static char buf[1024*64];
|
---|
| 768 | ssize_t chunk, written = 0, rest;
|
---|
| 769 | int virtuals;
|
---|
| 770 |
|
---|
| 771 | while((chunk=read(bootfd, buf, sizeof(buf))) > 0)
|
---|
| 772 | written += Write(fd, buf, chunk);
|
---|
| 773 |
|
---|
| 774 | if(chunk < 0) {
|
---|
| 775 | perror("read boot image");
|
---|
| 776 | exit(1);
|
---|
| 777 | }
|
---|
| 778 |
|
---|
| 779 | virtuals = written / VIRTUAL_SECTOR;
|
---|
| 780 |
|
---|
| 781 | if((rest = ISO_SECTOR - (written % 2048))) {
|
---|
| 782 | memset(buf, 0, sizeof(buf));
|
---|
| 783 | written += Write(fd, buf, rest);
|
---|
| 784 | }
|
---|
| 785 |
|
---|
| 786 | (*currentsector) += written/ISO_SECTOR;
|
---|
| 787 |
|
---|
| 788 | return virtuals;
|
---|
| 789 | }
|
---|
| 790 |
|
---|
| 791 | void
|
---|
| 792 | writebootrecord(int fd, int *currentsector, int bootcatalogsector)
|
---|
| 793 | {
|
---|
| 794 | int i;
|
---|
| 795 | static struct bootrecord bootrecord;
|
---|
| 796 | ssize_t w = 0;
|
---|
| 797 | /* boot record volume descriptor */
|
---|
| 798 |
|
---|
| 799 | memset(&bootrecord, 0, sizeof(bootrecord));
|
---|
| 800 | bootrecord.set[0] = 'C';
|
---|
| 801 | bootrecord.set[1] = 'D';
|
---|
| 802 | bootrecord.set[2] = '0';
|
---|
| 803 | bootrecord.set[3] = '0';
|
---|
| 804 | bootrecord.set[4] = '1';
|
---|
| 805 | bootrecord.version = 1;
|
---|
| 806 | bootrecord.bootcatalog = bootcatalogsector;
|
---|
| 807 | strcpy(bootrecord.ident, "EL TORITO SPECIFICATION");
|
---|
| 808 | for(i = strlen(bootrecord.ident);
|
---|
| 809 | i < sizeof(bootrecord.ident); i++)
|
---|
| 810 | bootrecord.ident[i] = '\0';
|
---|
| 811 |
|
---|
| 812 | w = Writefield(fd, bootrecord.indicator);
|
---|
| 813 | w += Writefield(fd, bootrecord.set);
|
---|
| 814 | w += Writefield(fd, bootrecord.version);
|
---|
| 815 | w += Writefield(fd, bootrecord.ident);
|
---|
| 816 | w += Writefield(fd, bootrecord.zero);
|
---|
| 817 | w += Writefield(fd, bootrecord.bootcatalog);
|
---|
| 818 | w += Writefield(fd, bootrecord.zero2);
|
---|
| 819 |
|
---|
| 820 | if(w != ISO_SECTOR) {
|
---|
| 821 | fprintf(stderr, "WARNING: something went wrong - boot record (%d) isn't a sector size (%d)\n",
|
---|
| 822 | w, ISO_SECTOR);
|
---|
| 823 | }
|
---|
| 824 |
|
---|
| 825 | (*currentsector)++;
|
---|
| 826 | }
|
---|
| 827 |
|
---|
| 828 | int
|
---|
| 829 | main(int argc, char *argv[])
|
---|
| 830 | {
|
---|
| 831 | int currentsector = 0;
|
---|
| 832 | int imagesector, imagesectors;
|
---|
| 833 | int bootfd, fd, i, ch, nsectors;
|
---|
| 834 | int remove_after = 0;
|
---|
| 835 | static char block[ISO_SECTOR];
|
---|
| 836 | static struct pvd pvd;
|
---|
| 837 | char *label = "ISO9660";
|
---|
| 838 | struct tm *now;
|
---|
| 839 | time_t nowtime;
|
---|
| 840 | char timestr[20], *prog;
|
---|
| 841 | char *bootimage = NULL;
|
---|
| 842 | struct node root;
|
---|
| 843 | int pvdsector;
|
---|
| 844 | int bigpath, littlepath, pathbytes = 0, dirsector, filesector, enddir;
|
---|
| 845 | int bootvolumesector, bootcatalogsector;
|
---|
| 846 |
|
---|
| 847 | prog = argv[0];
|
---|
| 848 |
|
---|
| 849 | /* This check is to prevent compiler padding screwing up
|
---|
| 850 | * our format.
|
---|
| 851 | */
|
---|
| 852 |
|
---|
| 853 | if(sizeof(struct pvd) != ISO_SECTOR) {
|
---|
| 854 | fprintf(stderr, "Something confusing happened at\n"
|
---|
| 855 | "compile-time; pvd should be a sector size. %d != %d\n",
|
---|
| 856 | sizeof(struct pvd), ISO_SECTOR);
|
---|
| 857 | return 1;
|
---|
| 858 | }
|
---|
| 859 |
|
---|
| 860 | while ((ch = getopt(argc, argv, "Rb:hl:")) != -1) {
|
---|
| 861 | switch(ch) {
|
---|
| 862 | case 'h':
|
---|
| 863 | harddisk_emulation= 1;
|
---|
| 864 | break;
|
---|
| 865 | case 'l':
|
---|
| 866 | label = optarg;
|
---|
| 867 | break;
|
---|
| 868 | case 'r':
|
---|
| 869 | remove_after = 1;
|
---|
| 870 | break;
|
---|
| 871 | case 'b':
|
---|
| 872 | bootimage = optarg;
|
---|
| 873 | if((bootfd = open(bootimage, O_RDONLY)) < 0) {
|
---|
| 874 | perror(bootimage);
|
---|
| 875 | return 1;
|
---|
| 876 | }
|
---|
| 877 | break;
|
---|
| 878 | }
|
---|
| 879 | }
|
---|
| 880 |
|
---|
| 881 | argc -= optind;
|
---|
| 882 | argv += optind;
|
---|
| 883 |
|
---|
| 884 | if(argc != 2) {
|
---|
| 885 | fprintf(stderr, "usage: %s [-l <label>] [-b <bootfloppyimage>] <dir> <isofile>\n",
|
---|
| 886 | prog);
|
---|
| 887 | return 1;
|
---|
| 888 | }
|
---|
| 889 |
|
---|
| 890 | /* create .iso file */
|
---|
| 891 |
|
---|
| 892 | if((fd=open(argv[1], O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0) {
|
---|
| 893 | perror(argv[1]);
|
---|
| 894 | return 1;
|
---|
| 895 | }
|
---|
| 896 |
|
---|
| 897 | /* go to where the iso has to be made from */
|
---|
| 898 |
|
---|
| 899 | if(chdir(argv[0]) < 0) {
|
---|
| 900 | perror(argv[0]);
|
---|
| 901 | return 1;
|
---|
| 902 | }
|
---|
| 903 |
|
---|
| 904 | /* collect dirs and files */
|
---|
| 905 |
|
---|
| 906 | fprintf(stderr, " * traversing input tree\n");
|
---|
| 907 |
|
---|
| 908 | maketree(&root, "", 1);
|
---|
| 909 |
|
---|
| 910 | fprintf(stderr, " * writing initial zeroes and pvd\n");
|
---|
| 911 |
|
---|
| 912 | /* first sixteen sectors are zero */
|
---|
| 913 |
|
---|
| 914 | memset(block, 0, sizeof(block));
|
---|
| 915 |
|
---|
| 916 | for(i = 0; i < 16; i++)
|
---|
| 917 | writesector(fd, block, ¤tsector);
|
---|
| 918 |
|
---|
| 919 | /* Primary Volume Descriptor */
|
---|
| 920 | memset(&pvd, 0, sizeof(pvd));
|
---|
| 921 | pvd.one = 1;
|
---|
| 922 | pvd.set[0] = 67;
|
---|
| 923 | pvd.set[1] = 68;
|
---|
| 924 | pvd.set[2] = 48;
|
---|
| 925 | pvd.set[3] = 48;
|
---|
| 926 | pvd.set[4] = 49;
|
---|
| 927 | pvd.set[5] = 1;
|
---|
| 928 | pvd.set[5] = 1;
|
---|
| 929 |
|
---|
| 930 | strncpy(pvd.volume, label, sizeof(pvd.volume)-1);
|
---|
| 931 | for(i = strlen(pvd.volume); i < sizeof(pvd.volume); i++)
|
---|
| 932 | pvd.volume[i] = ' ';
|
---|
| 933 | for(i = 0; i < sizeof(pvd.system); i++)
|
---|
| 934 | pvd.system[i] = ' ';
|
---|
| 935 |
|
---|
| 936 | both16((unsigned char *) pvd.setsize, 1);
|
---|
| 937 | both16((unsigned char *) pvd.seq, 1);
|
---|
| 938 | both16((unsigned char *) pvd.sectorsize, ISO_SECTOR);
|
---|
| 939 |
|
---|
| 940 | /* fill time fields */
|
---|
| 941 | time(&nowtime);
|
---|
| 942 | now = gmtime(&nowtime);
|
---|
| 943 | strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S000", now);
|
---|
| 944 | memcpy(pvd.create, timestr, strlen(timestr));
|
---|
| 945 | memcpy(pvd.modified, timestr, strlen(timestr));
|
---|
| 946 | memcpy(pvd.effective, timestr, strlen(timestr));
|
---|
| 947 | strcpy(pvd.expiry, "0000000000000000"); /* not specified */
|
---|
| 948 | pvdsector = currentsector;
|
---|
| 949 |
|
---|
| 950 | writesector(fd, (char *) &pvd, ¤tsector);
|
---|
| 951 |
|
---|
| 952 | if(bootimage) {
|
---|
| 953 | fprintf(stderr, " * writing boot record volume descriptor\n");
|
---|
| 954 | bootvolumesector = currentsector;
|
---|
| 955 | writebootrecord(fd, ¤tsector, 0);
|
---|
| 956 | }
|
---|
| 957 |
|
---|
| 958 | /* volume descriptor set terminator */
|
---|
| 959 | memset(block, 0, sizeof(block));
|
---|
| 960 | block[0] = 255;
|
---|
| 961 | block[1] = 67;
|
---|
| 962 | block[2] = 68;
|
---|
| 963 | block[3] = 48;
|
---|
| 964 | block[4] = 48;
|
---|
| 965 | block[5] = 49;
|
---|
| 966 | block[6] = 1;
|
---|
| 967 |
|
---|
| 968 | writesector(fd, block, ¤tsector);
|
---|
| 969 |
|
---|
| 970 | if(bootimage) {
|
---|
| 971 | /* write the boot catalog */
|
---|
| 972 | fprintf(stderr, " * writing the boot catalog\n");
|
---|
| 973 | bootcatalogsector = currentsector;
|
---|
| 974 | if (harddisk_emulation)
|
---|
| 975 | system_type = get_system_type(bootfd);
|
---|
| 976 | writebootcatalog(fd, ¤tsector, imagesector, imagesectors);
|
---|
| 977 |
|
---|
| 978 | /* write boot image */
|
---|
| 979 | fprintf(stderr, " * writing the boot image\n");
|
---|
| 980 | imagesector = currentsector;
|
---|
| 981 | imagesectors = writebootimage(bootimage, bootfd,
|
---|
| 982 | fd, ¤tsector);
|
---|
| 983 | fprintf(stderr, " * image: %d virtual sectors @ sector 0x%x\n",
|
---|
| 984 | imagesectors, imagesector);
|
---|
| 985 |
|
---|
| 986 | close(bootfd);
|
---|
| 987 | }
|
---|
| 988 |
|
---|
| 989 | /* write out all the file data */
|
---|
| 990 |
|
---|
| 991 | filesector = currentsector;
|
---|
| 992 | fprintf(stderr, " * writing file data\n");
|
---|
| 993 | writedata(NULL, &root, fd, ¤tsector, 0,
|
---|
| 994 | (struct dir *) &pvd.rootrecord, sizeof(pvd.rootrecord),
|
---|
| 995 | remove_after);
|
---|
| 996 |
|
---|
| 997 | /* write out all the dir data */
|
---|
| 998 |
|
---|
| 999 | dirsector = currentsector;
|
---|
| 1000 | fprintf(stderr, " * writing dir data\n");
|
---|
| 1001 | writedata(NULL, &root, fd, ¤tsector, 1,
|
---|
| 1002 | (struct dir *) &pvd.rootrecord, sizeof(pvd.rootrecord),
|
---|
| 1003 | remove_after);
|
---|
| 1004 | enddir = currentsector;
|
---|
| 1005 | seeksector(fd, dirsector, ¤tsector);
|
---|
| 1006 | fprintf(stderr, " * rewriting dir data\n");
|
---|
| 1007 | fflush(NULL);
|
---|
| 1008 | writedata(NULL, &root, fd, ¤tsector, 1,
|
---|
| 1009 | (struct dir *) &pvd.rootrecord, sizeof(pvd.rootrecord),
|
---|
| 1010 | remove_after);
|
---|
| 1011 | if(currentsector != enddir) {
|
---|
| 1012 | fprintf(stderr, "warning: inconsistent directories - "
|
---|
| 1013 | "I have a bug! iso may be broken.\n");
|
---|
| 1014 | }
|
---|
| 1015 |
|
---|
| 1016 | /* now write the path table in both formats */
|
---|
| 1017 |
|
---|
| 1018 | fprintf(stderr, " * writing big-endian path table\n");
|
---|
| 1019 | bigpath = currentsector;
|
---|
| 1020 | currentsector += makepathtables(&root, 0, &pathbytes, fd);
|
---|
| 1021 |
|
---|
| 1022 | fprintf(stderr, " * writing little-endian path table\n");
|
---|
| 1023 | littlepath = currentsector;
|
---|
| 1024 | currentsector += makepathtables(&root, 1, &pathbytes, fd);
|
---|
| 1025 |
|
---|
| 1026 | /* this is the size of the iso filesystem for use in the pvd later */
|
---|
| 1027 |
|
---|
| 1028 | nsectors = currentsector;
|
---|
| 1029 | both32((unsigned char *) pvd.sectors, nsectors);
|
---|
| 1030 |
|
---|
| 1031 | /* *********** Filesystem writing done ************************* */
|
---|
| 1032 |
|
---|
| 1033 | /* finish and rewrite the pvd. */
|
---|
| 1034 | fprintf(stderr, " * rewriting pvd\n");
|
---|
| 1035 | seekwritesector(fd, pvdsector, (char *) &pvd, ¤tsector);
|
---|
| 1036 |
|
---|
| 1037 | both32((unsigned char *) pvd.pathtable, pathbytes);
|
---|
| 1038 | little32((unsigned char *) &pvd.first_little_pathtable_start, littlepath);
|
---|
| 1039 | little32((unsigned char *) &pvd.first_big_pathtable_start, bigpath);
|
---|
| 1040 |
|
---|
| 1041 | /* write root dir entry in pvd */
|
---|
| 1042 | seeksector(fd, pvdsector, ¤tsector);
|
---|
| 1043 | Lseek(fd, (int)((char *) &pvd.rootrecord - (char *) &pvd), SEEK_CUR);
|
---|
| 1044 | if(write_direntry(CURRENTDIR, root.startsector, root.bytesize,
|
---|
| 1045 | root.isdir, fd) > sizeof(pvd.rootrecord)) {
|
---|
| 1046 | fprintf(stderr, "warning: unexpectedly large root record\n");
|
---|
| 1047 | }
|
---|
| 1048 |
|
---|
| 1049 | if(bootimage) {
|
---|
| 1050 | fprintf(stderr, " * rewriting boot catalog\n");
|
---|
| 1051 | seeksector(fd, bootcatalogsector, ¤tsector);
|
---|
| 1052 | writebootcatalog(fd, ¤tsector, imagesector, imagesectors);
|
---|
| 1053 |
|
---|
| 1054 | /* finish and rewrite the boot record volume descriptor */
|
---|
| 1055 | fprintf(stderr, " * rewriting the boot rvd\n");
|
---|
| 1056 | seeksector(fd, bootvolumesector, ¤tsector);
|
---|
| 1057 | writebootrecord(fd, ¤tsector, bootcatalogsector);
|
---|
| 1058 | }
|
---|
| 1059 |
|
---|
| 1060 | fprintf(stderr, " * all ok\n");
|
---|
| 1061 |
|
---|
| 1062 | return 0;
|
---|
| 1063 | }
|
---|
| 1064 |
|
---|
| 1065 | int get_system_type(int fd)
|
---|
| 1066 | {
|
---|
| 1067 | off_t old_pos;
|
---|
| 1068 | size_t size;
|
---|
| 1069 | ssize_t r;
|
---|
| 1070 | int type;
|
---|
| 1071 | struct part_entry *partp;
|
---|
| 1072 | unsigned char bootsector[512];
|
---|
| 1073 |
|
---|
| 1074 | errno= 0;
|
---|
| 1075 | old_pos= lseek(fd, SEEK_SET, 0);
|
---|
| 1076 | if (old_pos == -1 && errno != 0)
|
---|
| 1077 | {
|
---|
| 1078 | fprintf(stderr, "bootimage file is not seekable: %s\n",
|
---|
| 1079 | strerror(errno));
|
---|
| 1080 | exit(1);
|
---|
| 1081 | }
|
---|
| 1082 | size= sizeof(bootsector);
|
---|
| 1083 | r= read(fd, bootsector, size);
|
---|
| 1084 | if (r != size)
|
---|
| 1085 | {
|
---|
| 1086 | fprintf(stderr, "error reading bootimage file: %s\n",
|
---|
| 1087 | r < 0 ? strerror(errno) : "unexpected EOF");
|
---|
| 1088 | exit(1);
|
---|
| 1089 | }
|
---|
| 1090 | if (bootsector[size-2] != 0x55 && bootsector[size-1] != 0xAA)
|
---|
| 1091 | {
|
---|
| 1092 | fprintf(stderr, "bad magic in bootimage file\n");
|
---|
| 1093 | exit(1);
|
---|
| 1094 | }
|
---|
| 1095 |
|
---|
| 1096 | partp= (struct part_entry *)&bootsector[PART_TABLE_OFF];
|
---|
| 1097 | type= partp->sysind;
|
---|
| 1098 | if (type == NO_PART)
|
---|
| 1099 | {
|
---|
| 1100 | fprintf(stderr, "first partition table entry is unused\n");
|
---|
| 1101 | exit(1);
|
---|
| 1102 | }
|
---|
| 1103 | if (!(partp->bootind & ACTIVE_FLAG))
|
---|
| 1104 | {
|
---|
| 1105 | fprintf(stderr, "first partition table entry is not active\n");
|
---|
| 1106 | exit(1);
|
---|
| 1107 | }
|
---|
| 1108 |
|
---|
| 1109 | lseek(fd, SEEK_SET, old_pos);
|
---|
| 1110 | return type;
|
---|
| 1111 | }
|
---|