tdump9660.c - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tdump9660.c (9081B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <bio.h>
            4 #include <disk.h>
            5 #include <libsec.h>
            6 #include "iso9660.h"
            7 
            8 ulong now;
            9 int chatty;
           10 int doabort;
           11 int docolon;
           12 int mk9660;
           13 Conform *map;
           14 
           15 static void addprotofile(char *new, char *old, Dir *d, void *a);
           16 void usage(void);
           17 
           18 char *argv0;
           19 
           20 void
           21 usage(void)
           22 {
           23         if(mk9660)
           24                 fprint(2, "usage: mk9660 [-D:] [-9cjr] [-b bootfile] [-p proto] [-s src] cdimage\n");
           25         else
           26                 fprint(2, "usage: dump9660 [-D:] [-9cjr] [-m maxsize] [-n now] [-p proto] [-s src] cdimage\n");
           27         exits("usage");
           28 }
           29 
           30 int
           31 main(int argc, char **argv)
           32 {
           33         int fix;
           34         char buf[256], *dumpname, *proto, *s, *src, *status;
           35         ulong block, length, newnull, cblock, clength, maxsize;
           36         Cdimg *cd;
           37         Cdinfo info;
           38         XDir dir;
           39         Direc *iconform, idumproot, iroot, *jconform, jdumproot, jroot, *r;
           40         Dump *dump;
           41 
           42         fix = 0;
           43         status = nil;
           44         memset(&info, 0, sizeof info);
           45         proto = unsharp("#9/proto/allproto");
           46         src = "./";
           47 
           48         info.volumename = atom("9CD");
           49         info.volumeset = atom("9VolumeSet");
           50         info.publisher = atom("9Publisher");
           51         info.preparer = atom("dump9660");
           52         info.application = atom("dump9660");
           53         info.flags = CDdump;
           54         maxsize = 0;
           55         mk9660 = 0;
           56         fmtinstall('H', encodefmt);
           57 
           58         ARGBEGIN{
           59         case 'D':
           60                 chatty++;
           61                 break;
           62         case 'M':
           63                 mk9660 = 1;
           64                 argv0 = "disk/mk9660";
           65                 info.flags &= ~CDdump;
           66                 break;
           67         case '9':
           68                 info.flags |= CDplan9;
           69                 break;
           70         case ':':
           71                 docolon = 1;
           72                 break;
           73         case 'a':
           74                 doabort = 1;
           75                 break;
           76         case 'b':
           77                 if(!mk9660)
           78                         usage();
           79                 info.flags |= CDbootable;
           80                 info.bootimage = EARGF(usage());
           81                 break;
           82         case 'c':
           83                 info.flags |= CDconform;
           84                 break;
           85         case 'f':
           86                 fix = 1;
           87                 break;
           88         case 'j':
           89                 info.flags |= CDjoliet;
           90                 break;
           91         case 'n':
           92                 now = atoi(EARGF(usage()));
           93                 break;
           94         case 'm':
           95                 maxsize = strtoul(EARGF(usage()), 0, 0);
           96                 break;
           97         case 'p':
           98                 proto = EARGF(usage());
           99                 break;
          100         case 'r':
          101                 info.flags |= CDrockridge;
          102                 break;
          103         case 's':
          104                 src = EARGF(usage());
          105                 break;
          106         case 'v':
          107                 info.volumename = atom(EARGF(usage()));
          108                 break;
          109         default:
          110                 usage();
          111         }ARGEND
          112 
          113         if(mk9660 && (fix || now || maxsize))
          114                 usage();
          115 
          116         if(argc != 1)
          117                 usage();
          118 
          119         if(now == 0)
          120                 now = (ulong)time(0);
          121         if(mk9660){
          122                 if((cd = createcd(argv[0], info)) == nil)
          123                         sysfatal("cannot create '%s': %r", argv[0]);
          124         }else{
          125                 if((cd = opencd(argv[0], info)) == nil)
          126                         sysfatal("cannot open '%s': %r", argv[0]);
          127                 if(!(cd->flags & CDdump))
          128                         sysfatal("not a dump cd");
          129         }
          130 
          131         /* create ISO9660/Plan 9 tree in memory */
          132         memset(&dir, 0, sizeof dir);
          133         dir.name = atom("");
          134         dir.uid = atom("sys");
          135         dir.gid = atom("sys");
          136         dir.uidno = 0;
          137         dir.gidno = 0;
          138         dir.mode = DMDIR | 0755;
          139         dir.mtime = now;
          140         dir.atime = now;
          141         dir.ctime = now;
          142 
          143         mkdirec(&iroot, &dir);
          144         iroot.srcfile = src;
          145 
          146         /*
          147          * Read new files into memory
          148          */
          149         if(rdproto(proto, src, addprotofile, 0, &iroot) < 0)
          150                 sysfatal("rdproto: %r");
          151 
          152         if(mk9660){
          153                 dump = emalloc(sizeof *dump);
          154                 dumpname = nil;
          155         }else{
          156                 /*
          157                  * Read current dump tree and _conform.map.
          158                  */
          159                 idumproot = readdumpdirs(cd, &dir, isostring);
          160                 readdumpconform(cd);
          161                 if(cd->flags & CDjoliet)
          162                         jdumproot = readdumpdirs(cd, &dir, jolietstring);
          163 
          164                 if(fix){
          165                         dumpname = nil;
          166                         cd->nextblock = cd->nulldump+1;
          167                         cd->nulldump = 0;
          168                         Cwseek(cd, cd->nextblock*Blocksize);
          169                         goto Dofix;
          170                 }
          171 
          172                 dumpname = adddumpdir(&idumproot, now, &dir);
          173                 /* note that we assume all names are conforming and thus sorted */
          174                 if(cd->flags & CDjoliet) {
          175                         s = adddumpdir(&jdumproot, now, &dir);
          176                         if(s != dumpname)
          177                                 sysfatal("dumpnames don't match %s %s\n", dumpname, s);
          178                 }
          179                 dump = dumpcd(cd, &idumproot);
          180                 cd->nextblock = cd->nulldump+1;
          181         }
          182 
          183         /*
          184          * Write new files, starting where the dump tree was.
          185           * Must be done before creation of the Joliet tree so that
          186           * blocks and lengths are correct.
          187          */
          188         Cwseek(cd, cd->nextblock*Blocksize);
          189         writefiles(dump, cd, &iroot);
          190 
          191         if(cd->bootimage){
          192                 findbootimage(cd, &iroot);
          193                 Cupdatebootcat(cd);
          194         }
          195 
          196         /* create Joliet tree */
          197         if(cd->flags & CDjoliet)
          198                 copydirec(&jroot, &iroot);
          199 
          200         if(info.flags & CDconform) {
          201                 checknames(&iroot, isbadiso9660);
          202                 convertnames(&iroot, struprcpy);
          203         } else
          204                 convertnames(&iroot, (char* (*)(char*, char*))strcpy);
          205 
          206 /*        isoabstract = findconform(&iroot, abstract); */
          207 /*        isobiblio = findconform(&iroot, biblio); */
          208 /*        isonotice = findconform(&iroot, notice); */
          209 
          210         dsort(&iroot, isocmp);
          211 
          212         if(cd->flags & CDjoliet) {
          213         /*        jabstract = findconform(&jroot, abstract); */
          214         /*        jbiblio = findconform(&jroot, biblio); */
          215         /*        jnotice = findconform(&jroot, notice); */
          216 
          217                 checknames(&jroot, isbadjoliet);
          218                 convertnames(&jroot, (char* (*)(char*, char*))strcpy);
          219                 dsort(&jroot, jolietcmp);
          220         }
          221 
          222         /*
          223          * Write directories.
          224          */
          225         writedirs(cd, &iroot, Cputisodir);
          226         if(cd->flags & CDjoliet)
          227                 writedirs(cd, &jroot, Cputjolietdir);
          228 
          229         if(mk9660){
          230                 cblock = 0;
          231                 clength = 0;
          232                 newnull = 0;
          233         }else{
          234                 /*
          235                  * Write incremental _conform.map block.
          236                  */
          237                 wrconform(cd, cd->nconform, &cblock, &clength);
          238 
          239                 /* jump here if we're just fixing up the cd */
          240 Dofix:
          241                 /*
          242                  * Write null dump header block; everything after this will be
          243                  * overwritten at the next dump.  Because of this, it needs to be
          244                  * reconstructable.  We reconstruct the _conform.map and dump trees
          245                  * from the header blocks in dump.c, and we reconstruct the path
          246                  * tables by walking the cd.
          247                  */
          248                 newnull = Cputdumpblock(cd);
          249         }
          250 
          251         /*
          252          * Write _conform.map.
          253          */
          254         dir.mode = 0444;
          255         if(cd->flags & (CDconform|CDjoliet)) {
          256                 if(!mk9660 && cd->nconform == 0){
          257                         block = cblock;
          258                         length = clength;
          259                 }else
          260                         wrconform(cd, 0, &block, &length);
          261 
          262                 if(mk9660)
          263 {
          264                         idumproot = iroot;
          265                         jdumproot = jroot;
          266                 }
          267                 if(length) {
          268                         /* The ISO9660 name will get turned into uppercase when written. */
          269                         if((iconform = walkdirec(&idumproot, "_conform.map")) == nil)
          270                                 iconform = adddirec(&idumproot, "_conform.map", &dir);
          271                         jconform = nil;
          272                         if(cd->flags & CDjoliet) {
          273                                 if((jconform = walkdirec(&jdumproot, "_conform.map")) == nil)
          274                                         jconform = adddirec(&jdumproot, "_conform.map", &dir);
          275                         }
          276                         iconform->block = block;
          277                         iconform->length = length;
          278                         if(cd->flags & CDjoliet) {
          279                                 jconform->block = block;
          280                                 jconform->length = length;
          281                         }
          282                 }
          283                 if(mk9660) {
          284                         iroot = idumproot;
          285                         jroot = jdumproot;
          286                 }
          287         }
          288 
          289         if(mk9660){
          290                 /*
          291                  * Patch in root directories.
          292                  */
          293                 setroot(cd, cd->iso9660pvd, iroot.block, iroot.length);
          294                 setvolsize(cd, cd->iso9660pvd, cd->nextblock*Blocksize);
          295                 if(cd->flags & CDjoliet){
          296                         setroot(cd, cd->jolietsvd, jroot.block, jroot.length);
          297                         setvolsize(cd, cd->jolietsvd, cd->nextblock*Blocksize);
          298                 }
          299         }else{
          300                 /*
          301                  * Write dump tree at end.  We assume the name characters
          302                  * are all conforming, so everything is already sorted properly.
          303                  */
          304                 convertnames(&idumproot, (info.flags & CDconform) ? struprcpy : (char* (*)(char*, char*)) strcpy);
          305                 if(cd->nulldump) {
          306                         r = walkdirec(&idumproot, dumpname);
          307                         assert(r != nil);
          308                         copybutname(r, &iroot);
          309                 }
          310                 if(cd->flags & CDjoliet) {
          311                         convertnames(&jdumproot, (char* (*)(char*, char*))strcpy);
          312                         if(cd->nulldump) {
          313                                 r = walkdirec(&jdumproot, dumpname);
          314                                 assert(r != nil);
          315                                 copybutname(r, &jroot);
          316                         }
          317                 }
          318 
          319                 writedumpdirs(cd, &idumproot, Cputisodir);
          320                 if(cd->flags & CDjoliet)
          321                         writedumpdirs(cd, &jdumproot, Cputjolietdir);
          322 
          323                 /*
          324                  * Patch in new root directory entry.
          325                  */
          326                 setroot(cd, cd->iso9660pvd, idumproot.block, idumproot.length);
          327                 setvolsize(cd, cd->iso9660pvd, cd->nextblock*Blocksize);
          328                 if(cd->flags & CDjoliet){
          329                         setroot(cd, cd->jolietsvd, jdumproot.block, jdumproot.length);
          330                         setvolsize(cd, cd->jolietsvd, cd->nextblock*Blocksize);
          331                 }
          332         }
          333         writepathtables(cd);
          334 
          335         if(!mk9660){
          336                 /*
          337                  * If we've gotten too big, truncate back to what we started with,
          338                  * fix up the cd, and exit with a non-zero status.
          339                  */
          340                 Cwflush(cd);
          341                 if(cd->nulldump && maxsize && Cwoffset(cd) > maxsize){
          342                         fprint(2, "too big; writing old tree back\n");
          343                         status = "cd too big; aborted";
          344 
          345                         rmdumpdir(&idumproot, dumpname);
          346                         rmdumpdir(&jdumproot, dumpname);
          347 
          348                         cd->nextblock = cd->nulldump+1;
          349                         cd->nulldump = 0;
          350                         Cwseek(cd, cd->nextblock*Blocksize);
          351                         goto Dofix;
          352                 }
          353 
          354                 /*
          355                  * Write old null header block; this commits all our changes.
          356                  */
          357                 if(cd->nulldump){
          358                         Cwseek(cd, cd->nulldump*Blocksize);
          359                         sprint(buf, "plan 9 dump cd\n");
          360                         sprint(buf+strlen(buf), "%s %lud %lud %lud %lud %lud %lud",
          361                                 dumpname, now, newnull, cblock, clength, iroot.block,
          362                                 iroot.length);
          363                         if(cd->flags & CDjoliet)
          364                                 sprint(buf+strlen(buf), " %lud %lud",
          365                                         jroot.block, jroot.length);
          366                         strcat(buf, "\n");
          367                         Cwrite(cd, buf, strlen(buf));
          368                         Cpadblock(cd);
          369                         Cwflush(cd);
          370                 }
          371         }
          372         fdtruncate(cd->fd, cd->nextblock*Blocksize);
          373         exits(status);
          374         return 0;
          375 }
          376 
          377 static void
          378 addprotofile(char *new, char *old, Dir *d, void *a)
          379 {
          380         char *name, *p;
          381         Direc *direc;
          382         XDir xd;
          383 
          384         dirtoxdir(&xd, d);
          385         name = nil;
          386         if(docolon && strchr(new, ':')) {
          387                 name = emalloc(strlen(new)+1);
          388                 strcpy(name, new);
          389                 while((p=strchr(name, ':')))
          390                         *p=' ';
          391                 new = name;
          392         }
          393         if((direc = adddirec((Direc*)a, new, &xd))) {
          394                 direc->srcfile = atom(old);
          395 
          396                 /* BUG: abstract, biblio, notice */
          397         }
          398         if(name)
          399                 free(name);
          400 
          401 }