URI:
       tpath.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tpath.c (3641B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <bio.h>
            4 #include <libsec.h>
            5 
            6 #include "iso9660.h"
            7 
            8 /*
            9  * Add the requisite path tables to the CD image.
           10  * They get put on the end once everything else is done.
           11  * We use the path table itself as a queue in the breadth-first
           12  * traversal of the tree.
           13  *
           14  * The only problem with this is that the path table does not
           15  * store the lengths of the directories.  So we keep an explicit
           16  * map in an array in memory.
           17  */
           18 
           19 enum {
           20         Big,
           21         Little
           22 };
           23 
           24 static void
           25 Crdpath(Cdimg *cd, Cpath *p)
           26 {
           27         p->namelen = Cgetc(cd);
           28         if(p->namelen == 0) {
           29                 Crseek(cd, (Croffset(cd)+Blocksize-1)/Blocksize * Blocksize);
           30                 p->namelen = Cgetc(cd);
           31                 assert(p->namelen != 0);
           32         }
           33 
           34         p->xlen = Cgetc(cd);
           35         assert(p->xlen == 0);        /* sanity, might not be true if we start using the extended fields */
           36 
           37         Cread(cd, p->dloc, 4);
           38         Cread(cd, p->parent, 2);
           39         p->name[0] = '\0';
           40         Crseek(cd, Croffset(cd)+p->namelen+p->xlen+(p->namelen&1));        /* skip name, ext data */
           41 }
           42 
           43 static void
           44 writepath(Cdimg *cd, Cdir *c, int parent, int size)
           45 {
           46 /*
           47         DO NOT UNCOMMENT THIS CODE.
           48         This commented-out code is here only so that no one comes
           49         along and adds it later.
           50 
           51         The ISO 9660 spec is silent about whether path table entries
           52         need to be padded so that they never cross block boundaries.
           53         It would be reasonable to assume that they are like every other
           54         data structure in the bloody spec; this code pads them out.
           55 
           56         Empirically, though, they're NOT padded.  Windows NT and
           57         derivatives are the only known current operating systems
           58         that actually read these things.
           59 
           60         int l;
           61 
           62         l = 1+1+4+2+c->namelen;
           63         if(Cwoffset(cd)/Blocksize != (Cwoffset(cd)+l)/Blocksize)
           64                 Cpadblock(cd);
           65 */
           66         Cputc(cd, c->namelen);
           67         Cputc(cd, 0);
           68         Cwrite(cd, c->dloc + (size==Little ? 0 : 4), 4);
           69         (size==Little ? Cputnl : Cputnm)(cd, parent, 2);
           70         Cwrite(cd, c->name, c->namelen);
           71         if(c->namelen & 1)
           72                 Cputc(cd, 0);
           73 }
           74 
           75 static ulong*
           76 addlength(ulong *a, ulong x, int n)
           77 {
           78         if(n%128==0)
           79                 a = erealloc(a, (n+128)*sizeof a[0]);
           80         a[n] = x;
           81         return a;
           82 }
           83 
           84 static ulong
           85 writepathtable(Cdimg *cd, ulong vdblock, int size)
           86 {
           87         int rp, wp;
           88         uchar buf[Blocksize];
           89         ulong bk, end, i, *len, n, rdoff, start;
           90         Cdir *c;
           91         Cpath p;
           92 
           93         Creadblock(cd, buf, vdblock, Blocksize);
           94         c = (Cdir*)(buf+offsetof(Cvoldesc, rootdir[0]));
           95 
           96         rp = 0;
           97         wp = 0;
           98         len = nil;
           99         start = cd->nextblock*Blocksize;
          100         Cwseek(cd, start);
          101         Crseek(cd, start);
          102         writepath(cd, c, 1, size);
          103         len = addlength(len, little(c->dlen, 4), wp);
          104         wp++;
          105 
          106         while(rp < wp) {
          107                 Crdpath(cd, &p);
          108                 n = (len[rp]+Blocksize-1)/Blocksize;
          109                 rp++;
          110                 bk = (size==Big ? big : little)(p.dloc, 4);
          111                 rdoff = Croffset(cd);
          112                 for(i=0; i<n; i++) {
          113                         Creadblock(cd, buf, bk+i, Blocksize);
          114                         c = (Cdir*)buf;
          115                         if(i != 0 && c->namelen == 1 && c->name[0] == '\0')        /* hit another directory; stop */
          116                                 break;
          117                         while(c->len && c->namelen && (uchar*)c+c->len < buf+Blocksize) {
          118                                 if((c->flags & 0x02) && (c->namelen > 1 || c->name[0] > '\001')) {        /* directory */
          119                                         writepath(cd, c, rp, size);
          120                                         len = addlength(len, little(c->dlen, 4), wp);
          121                                         wp++;
          122                                 }
          123                                 c = (Cdir*)((uchar*)c+c->len);
          124                         }
          125                 }
          126                 Crseek(cd, rdoff);
          127         }
          128         end = Cwoffset(cd);
          129         Cpadblock(cd);
          130         return end-start;
          131 }
          132 
          133 
          134 static void
          135 writepathtablepair(Cdimg *cd, ulong vdblock)
          136 {
          137         ulong bloc, lloc, sz, sz2;
          138 
          139         lloc = cd->nextblock;
          140         sz = writepathtable(cd, vdblock, Little);
          141         bloc = cd->nextblock;
          142         sz2 = writepathtable(cd, vdblock, Big);
          143         assert(sz == sz2);
          144         setpathtable(cd, vdblock, sz, lloc, bloc);
          145 }
          146 
          147 void
          148 writepathtables(Cdimg *cd)
          149 {
          150         cd->pathblock = cd->nextblock;
          151 
          152         writepathtablepair(cd, cd->iso9660pvd);
          153         if(cd->flags & CDjoliet)
          154                 writepathtablepair(cd, cd->jolietsvd);
          155 }