home *** CD-ROM | disk | FTP | other *** search
Wrap
/* * Program mkisofs.c - generate iso9660 filesystem based upon directory * tree on hard disk. Written by Eric Youngdale (1993). Copyright 1993 Yggdrasil Computing, Incorporated This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "mkisofs.h" #ifdef linux #include <getopt.h> #endif #include "iso9660.h" #include <ctype.h> #include <time.h> #include <stdlib.h> #ifndef AMIGA #include <sys/stat.h> #endif #ifndef VMS #ifndef AMIGA #include <unistd.h> #endif #endif #ifdef AMIGA #ifdef LATTICE #include <proto/exec.h> #include <proto/utility.h> #endif #if defined(__GNUC__) || defined(AZTEC_C) #include <clib/exec_protos.h> #include <clib/utility_protos.h> #endif #endif struct Library *UtilityBase = NULL; #include "exclude.h" struct directory * root = NULL; static char version_string[] = "$VER: mkisofs-1.00-Amiga 1.5 (23.06.94)"; FILE * discimage; unsigned int next_extent = 0; unsigned int last_extent = 0; unsigned int path_table_size = 0; unsigned int path_table[4] = {0,}; unsigned int path_blocks = 0; struct iso_directory_record root_record; int use_RockRidge = 0; int verbose = 0; int all_files = 0; int follow_links = 0; int generate_tables = 0; static int timezone_offset; char * extension_record = NULL; int extension_record_extent = 0; static int extension_record_size = 0; int cdtv_trademark_file = 0; int convert_filenames = 1; int inhibit_relocation = 0; int sort_extents = 0; int progress_indicator = 1; int short_filenames = 1; int map_filenames = 1; int preallocate = 0; char * preparer = NULL; char * publisher = NULL; char * system_identifier = NULL; char * path_table_l = NULL; char * path_table_m = NULL; int goof = 0; void usage(void){ fprintf(stderr, "Usage:\n" "mkisofs [-RvaTcres12AB] [-o outfile] [-V volid] [-p preparer]\n" " [-P publisher] [-S systemid] [-D path -D path ...]\n" " [-x path -x path ...] [--cdtv] path\n" ); exit(1); } int get_iso9660_timezone_offset(void){ #ifdef AMIGA return 0; #else struct tm gm; struct tm * pt; time_t ctime; int local_min, gmt_min; time(&ctime); pt = gmtime(&ctime); gm = *pt; pt = localtime(&ctime); if(gm.tm_year < pt->tm_year) gm.tm_yday = -1; if(gm.tm_year > pt->tm_year) pt->tm_yday = -1; gmt_min = gm.tm_min + 60*(gm.tm_hour + 24*gm.tm_yday); local_min = pt->tm_min + 60*(pt->tm_hour + 24*pt->tm_yday); return (gmt_min - local_min)/15; #endif } /* Fill in date in the iso9660 format */ int FDECL2(iso9660_date,char *, result, time_t, ctime){ struct tm *local; #ifdef AMIGA local = gmtime(&ctime); #else local = localtime(&ctime); #endif result[0] = local->tm_year; result[1] = local->tm_mon + 1; result[2] = local->tm_mday; result[3] = local->tm_hour; result[4] = local->tm_min; result[5] = local->tm_sec; result[6] = timezone_offset; return 0; } int FDECL3(iso9660_file_length,const char*, name, struct directory_entry *, sresult, int, dirflag){ char buf[33]; char *result = buf; const char * pnt; #if 0 int seen_dot = 0; int priority = 32767; int tildes = 0; int ignore = 0; int extra = 0; int chars_after_dot = 0; int chars_before_dot = 0; #endif if(strcmp(name,".") == 0){ sresult->isorec.iso_name = ""; return 1; }; if(strcmp(name,"..") == 0){ sresult->isorec.iso_name = "\1"; return 1; }; if (!convert_filenames) { int i; for (pnt=name, i=0; *pnt && i < 30; i++) *result++ = *pnt++; if (!dirflag) { *result++ = ';'; *result++ = '1'; } *result++ = 0; sresult->isorec.iso_name = strdup_forever (buf); return i+(dirflag?0:2); } sresult->isorec.iso_name = strdup_forever (dirflag ? convert_dirname (name) : convert_filename (name)); sresult->priority = 32767; return (int) strlen (sresult->isorec.iso_name); #if 0 pnt = name; while(*pnt){ if(*pnt == '#') {priority = 1; pnt++; continue; }; if(*pnt == '~') {priority = 1; tildes++; pnt++; continue;}; if(ignore) {pnt++; continue;}; if(*pnt == '.') { if (seen_dot) {ignore++; continue;} *result++ = '.'; seen_dot++; } else if (seen_dot) { if(chars_after_dot < 3) { chars_after_dot++; *result++ = toupper(*pnt); } } else { if(chars_before_dot < 8) { chars_before_dot++; *result++ = toupper(*pnt); }; }; pnt++; }; if(tildes == 2){ int prio1 = 0; pnt = name; while (*pnt && *pnt != '~') pnt++; if (*pnt) pnt++; while(*pnt && *pnt != '~'){ prio1 = 10*prio1 + *pnt - '0'; pnt++; }; priority = prio1; }; if (!dirflag){ if (!seen_dot) { *result++ = '.'; extra++; }; *result++ = ';'; *result++ = '1'; extra += 2; }; *result++ = 0; sresult->priority = priority; sresult->isorec.iso_name = strdup_forever (buf); return chars_before_dot + chars_after_dot + seen_dot + extra; #endif } #ifdef AMIGA static void Cleanup (void) { if (UtilityBase) CloseLibrary (UtilityBase); } #endif int FDECL2(main, int, argc, char **, argv){ char * outfile, *volid; struct directory_entry de; #ifndef AMIGA unsigned int mem_start; struct stat statbuf; #endif char * scan_tree; int c; char * trademark_filename; if (argc < 2) usage(); #ifdef AMIGA UtilityBase = OpenLibrary ((UBYTE*) "utility.library", 0); if (!UtilityBase) { fprintf (stderr, "cannot open utility.library!\n"); exit (10); } atexit (Cleanup); #endif outfile = NULL; volid = "CDROM"; while ((c = getopt(argc, argv, "acefo:p:rsvx:ABCD:P:RS:TV:-:12")) != EOF) switch (c) { case '-': if (strcmp (optarg, "cdtv") == 0) { convert_filenames = 0; cdtv_trademark_file = 1; inhibit_relocation = 1; system_identifier = "CDTV"; all_files++; } else { fprintf (stderr, "unknown option --%s\n", optarg); exit (1); } break; case 'c': convert_filenames = 0; break; case 'C': cdtv_trademark_file = 1; break; case 'D': convert_filenames = 0; include_conv (optarg); break; case 'r': inhibit_relocation = 1; break; case 'e': sort_extents = 1; break; case 's': preallocate = 1; break; case 'p': preparer = optarg; if(strlen(preparer) > 128) { fprintf(stderr,"Preparer string too long\n"); exit(1); }; break; case 'P': publisher = optarg; if(strlen(publisher) > 128) { fprintf(stderr,"Publisher string too long\n"); exit(1); }; break; case 'S': system_identifier = optarg; if(strlen(system_identifier) > 32) { fprintf(stderr,"System identifier string too long\n"); exit (1); } break; case 'o': outfile = optarg; break; case 'f': follow_links++; break; case 'R': use_RockRidge++; break; case 'V': #ifdef AMIGA if (strlen (optarg) > 30) { fprintf (stderr, "volume name too long (max. 30 characters)\n"); exit (1); } #endif volid = optarg; break; case 'v': verbose++; progress_indicator=0; break; case 'a': all_files++; break; case 'T': generate_tables++; break; case 'x': exclude(optarg); break; case '1': short_filenames = 1; break; case '2': short_filenames = 0; break; case 'A': map_filenames = 1; break; case 'B': map_filenames = 0; break; default: usage(); exit(1); } #ifndef AMIGA mem_start = (unsigned int) sbrk(0); #endif if (volid && convert_filenames && map_filenames && strspn (volid, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_") != strlen (volid)) fprintf (stderr, "WARNING: volume id contains illegal characters!\n"); if(verbose) fprintf(stderr,"%s\n", version_string + 6); /* Now find the timezone offset */ timezone_offset = get_iso9660_timezone_offset(); /* The first step is to scan the directory tree, and take some notes */ scan_tree = argv[optind]; if(!scan_tree){ usage(); exit(1); } if(scan_tree[strlen(scan_tree)-1] != '/' #ifdef AMIGA && scan_tree[strlen(scan_tree)-1] != ':' #endif ) { scan_tree = (char *) malloc(strlen(argv[optind])+2); strcpy(scan_tree, argv[optind]); strcat(scan_tree, "/"); } /* Test if trademark file is present: */ if (cdtv_trademark_file) { struct stat sbuf; trademark_filename = (char *) malloc (strlen (scan_tree) + 10); strcpy (trademark_filename, scan_tree); strcat (trademark_filename, "cdtv.tm"); if (stat (trademark_filename, &sbuf) == -1) { fprintf (stderr, "ERROR: file %s missing\n", trademark_filename); exit (1); } free (trademark_filename); } if(use_RockRidge){ extension_record = generate_rr_extension_record("RRIP_1991A", "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS", "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION.", &extension_record_size); } #ifndef AMIGA stat(argv[optind], &statbuf); add_directory_hash(statbuf.st_dev, statbuf.st_ino); #endif de.filedir = root; /* We need this to bootstrap */ if (!scan_directory_tree(argv[optind], &de)) exit (1); if (progress_indicator) putchar ('\n'); root->self = root->contents; /* Fix this up so that the path tables get done right */ if(reloc_dir) sort_n_finish(reloc_dir); if (goof) exit(1); if (outfile){ discimage = fopen(outfile, "w"); if (!discimage){ fprintf(stderr,"Unable to open disc image file\n"); exit(1); } } else discimage = stdout; /* Now assign addresses on the disc for the path table. */ path_blocks = (path_table_size + (SECTOR_SIZE - 1)) >> 11; if (path_blocks & 1) path_blocks++; path_table[0] = 0x14; path_table[1] = path_table[0] + path_blocks; path_table[2] = path_table[1] + path_blocks; path_table[3] = path_table[2] + path_blocks; last_extent = path_table[3] + path_blocks; /* The next free block */ /* The next step is to go through the directory tree and assign extent numbers for all of the directories */ if (verbose) printf ("assigning directory addresses\n"); assign_directory_addresses(root); if (progress_indicator) putchar ('\n'); if(extension_record) { struct directory_entry * s_entry; extension_record_extent = last_extent++; s_entry = root->contents; set_733(s_entry->rr_attributes + s_entry->rr_attr_size - 24, extension_record_extent); set_733(s_entry->rr_attributes + s_entry->rr_attr_size - 8, extension_record_size); }; if (use_RockRidge && reloc_dir) finish_cl_pl_entries(); if (verbose) printf ("generating path tables\n"); /* Now we generate the path tables that are used by DOS to improve directory access times. */ generate_path_tables(); /* Generate root record for volume descriptor. */ generate_root_record(); if (verbose) dump_tree(root); iso_write(discimage, volid); #ifndef AMIGA fprintf(stderr,"Max brk space used %x\n", ((unsigned int)sbrk(0)) - mem_start); #endif fprintf(stderr,"%d extents written (%d Mb)\n", last_extent, last_extent >> 9); return 0; }