void Cputisopvd(Cdimg *cd, Cdinfo info) { char buf[130]; Cputc(cd, 1); /* primary volume descriptor */ Cputs(cd, "CD001", 5); /* standard identifier */ Cputc(cd, 1); /* volume descriptor version */ Cputc(cd, 0); /* unused */ assert(~info.flags & (CDplan9|CDrockridge)); /* system identifier */ strcpy(buf, ""); if(info.flags & CDplan9) strcat(buf, "plan 9 "); if(info.flags & CDrockridge) strcat(buf, "rrip "); if(info.flags & CDbootable) strcat(buf, "boot "); if(info.flags & CDconform) strcat(buf, "iso9660"); else strcat(buf, "utf8"); struprcpy(buf, buf); Cputs(cd, buf, 32); Cputs(cd, mkisostring(buf, 32, info.volumename), 32); /* volume identifier */ Crepeat(cd, 0, 8); /* unused */ Cputn(cd, 0, 4); /* volume space size */ Crepeat(cd, 0, 32); /* unused */ Cputn(cd, 1, 2); /* volume set size */ Cputn(cd, 1, 2); /* volume sequence number */ Cputn(cd, Blocksize, 2); /* logical block size */ Cputn(cd, 0, 4); /* path table size */ Cputnl(cd, 0, 4); /* location of Lpath */ Cputnl(cd, 0, 4); /* location of optional Lpath */ Cputnm(cd, 0, 4); /* location of Mpath */ Cputnm(cd, 0, 4); /* location of optional Mpath */ Cputisodir(cd, nil, DTroot, 1, Cwoffset(cd)); /* root directory */ Cputs(cd, mkisostring(buf, 128, info.volumeset), 128); /* volume set identifier */ Cputs(cd, mkisostring(buf, 128, info.publisher), 128); /* publisher identifier */ Cputs(cd, mkisostring(buf, 128, info.preparer), 128); /* data preparer identifier */ Cputs(cd, mkisostring(buf, 128, info.application), 128); /* application identifier */ Cputs(cd, "", 37); /* copyright notice */ Cputs(cd, "", 37); /* abstract */ Cputs(cd, "", 37); /* bibliographic file */ Cputdate1(cd, now); /* volume creation date */ Cputdate1(cd, now); /* volume modification date */ Cputdate1(cd, 0); /* volume expiration date */ Cputdate1(cd, 0); /* volume effective date */ Cputc(cd, 1); /* file structure version */ Cpadblock(cd); }
void Cputs(Cdimg *cd, char *s, int size) { int n; if(s == nil) { Crepeat(cd, ' ', size); return; } for(n=0; n<size && *s; n++) Cputc(cd, *s++); if(n<size) Crepeat(cd, ' ', size-n); }
void Cputbootvol(Cdimg *cd) { Cputc(cd, 0x00); Cputs(cd, "CD001", 5); Cputc(cd, 0x01); Cputs(cd, "EL TORITO SPECIFICATION", 2+1+6+1+13); Crepeat(cd, 0, 2+16+16+7); cd->bootcatptr = Cwoffset(cd); Cpadblock(cd); }
/* * Write a Joliet secondary volume descriptor. */ void Cputjolietsvd(Cdimg *cd, Cdinfo info) { Cputc(cd, 2); /* secondary volume descriptor */ Cputs(cd, "CD001", 5); /* standard identifier */ Cputc(cd, 1); /* volume descriptor version */ Cputc(cd, 0); /* unused */ Cputrscvt(cd, "Joliet Plan 9", 32); /* system identifier */ Cputrscvt(cd, info.volumename, 32); /* volume identifier */ Crepeat(cd, 0, 8); /* unused */ Cputn(cd, 0, 4); /* volume space size */ Cputc(cd, 0x25); /* escape sequences: UCS-2 Level 2 */ Cputc(cd, 0x2F); Cputc(cd, 0x43); Crepeat(cd, 0, 29); Cputn(cd, 1, 2); /* volume set size */ Cputn(cd, 1, 2); /* volume sequence number */ Cputn(cd, Blocksize, 2); /* logical block size */ Cputn(cd, 0, 4); /* path table size */ Cputnl(cd, 0, 4); /* location of Lpath */ Cputnl(cd, 0, 4); /* location of optional Lpath */ Cputnm(cd, 0, 4); /* location of Mpath */ Cputnm(cd, 0, 4); /* location of optional Mpath */ Cputjolietdir(cd, nil, DTroot, 1, Cwoffset(cd)); /* root directory */ Cputrscvt(cd, info.volumeset, 128); /* volume set identifier */ Cputrscvt(cd, info.publisher, 128); /* publisher identifier */ Cputrscvt(cd, info.preparer, 128); /* data preparer identifier */ Cputrscvt(cd, info.application, 128); /* application identifier */ Cputrscvt(cd, "", 37); /* copyright notice */ Cputrscvt(cd, "", 37); /* abstract */ Cputrscvt(cd, "", 37); /* bibliographic file */ Cputdate1(cd, now); /* volume creation date */ Cputdate1(cd, now); /* volume modification date */ Cputdate1(cd, 0); /* volume expiration date */ Cputdate1(cd, 0); /* volume effective date */ Cputc(cd, 1); /* file structure version */ Cpadblock(cd); }
void Cputbootcat(Cdimg *cd) { cd->bootcatblock = Cwoffset(cd) / Blocksize; Cputc(cd, 0x01); Cputc(cd, 0x00); Cputc(cd, 0x00); Cputc(cd, 0x00); Crepeat(cd, 0, 12+12); /* * either the checksum doesn't include the header word * or it just doesn't matter. */ Cputc(cd, 0xAA); Cputc(cd, 0x55); Cputc(cd, 0x55); Cputc(cd, 0xAA); cd->bootimageptr = Cwoffset(cd); Cpadblock(cd); }
/* * It's not strictly conforming; instead it's enough to * get us up and running; presumably the real CD writing * will take care of being conforming. * * Things not conforming include: * - no path table * - root directories are of length zero */ Cdimg* createcd(char *file, Cdinfo info) { int fd, xfd; Cdimg *cd; if(access(file, AEXIST) == 0){ werrstr("file already exists"); return nil; } if((fd = create(file, ORDWR, 0666)) < 0) return nil; cd = emalloc(sizeof *cd); cd->file = atom(file); Binit(&cd->brd, fd, OREAD); if((xfd = open(file, ORDWR)) < 0) sysfatal("can't open file again: %r"); Binit(&cd->bwr, xfd, OWRITE); Crepeat(cd, 0, 16*Blocksize); Cputisopvd(cd, info); if(info.flags & CDbootable){ cd->bootimage = info.bootimage; cd->flags |= CDbootable; Cputbootvol(cd); } if(readisodesc(cd, &cd->iso) < 0) assert(0); if(info.flags & CDplan9) cd->flags |= CDplan9; else if(info.flags & CDrockridge) cd->flags |= CDrockridge; if(info.flags & CDjoliet) { Cputjolietsvd(cd, info); if(readjolietdesc(cd, &cd->joliet) < 0) assert(0); cd->flags |= CDjoliet; } Cputendvd(cd); if(info.flags & CDdump){ cd->nulldump = Cputdumpblock(cd); cd->flags |= CDdump; } if(cd->flags & CDbootable){ Cputbootcat(cd); Cupdatebootvol(cd); } if(info.flags & CDconform) cd->flags |= CDconform; cd->flags |= CDnew; cd->nextblock = Cwoffset(cd) / Blocksize; assert(cd->nextblock != 0); return cd; }