/* * iso9660.h * * Routines and data structures to support reading and writing ISO 9660 CD images. * See the ISO 9660 or ECMA 119 standards. * * Also supports Rock Ridge extensions for long file names and Unix stuff. * Also supports Microsoft's Joliet extensions for Unicode and long file names. * Also supports El Torito bootable CD spec. */ typedef struct Cdimg Cdimg; typedef struct Cdinfo Cdinfo; typedef struct Conform Conform; typedef struct Direc Direc; typedef struct Dumproot Dumproot; typedef struct Voldesc Voldesc; typedef struct XDir XDir; #ifndef CHLINK #define CHLINK 0 #endif struct XDir { char *name; char *uid; char *gid; char *symlink; ulong uidno; /* Numeric uid */ ulong gidno; /* Numeric gid */ ulong mode; ulong atime; ulong mtime; ulong ctime; vlong length; }; /* * A directory entry in a ISO9660 tree. * The extra data (uid, etc.) here is put into the system use areas. */ struct Direc { char *name; /* real name */ char *confname; /* conformant name */ char *srcfile; /* file to copy onto the image */ ulong block; ulong length; int flags; char *uid; char *gid; char *symlink; ulong mode; long atime; long ctime; long mtime; ulong uidno; ulong gidno; Direc *child; int nchild; }; enum { /* Direc flags */ Dbadname = 1<<0, /* Non-conformant name */ }; /* * Data found in a volume descriptor. */ struct Voldesc { char *systemid; char *volumeset; char *publisher; char *preparer; char *application; /* file names for various parameters */ char *abstract; char *biblio; char *notice; /* path table */ ulong pathsize; ulong lpathloc; ulong mpathloc; /* root of file tree */ Direc root; }; /* * An ISO9660 CD image. Various parameters are kept in memory but the * real image file is opened for reading and writing on fd. * * The bio buffers brd and bwr moderate reading and writing to the image. * The routines we use are careful to flush one before or after using the other, * as necessary. */ struct Cdimg { char *file; int fd; ulong dumpblock; ulong nextblock; ulong iso9660pvd; ulong jolietsvd; ulong pathblock; uvlong rrcontin; /* rock ridge continuation offset */ ulong nulldump; /* next dump block */ ulong nconform; /* number of conform entries written already */ uvlong bootcatptr; ulong bootcatblock; uvlong bootimageptr; Direc *loaderdirec; Direc *bootdirec; char *bootimage; char *loader; Biobuf brd; Biobuf bwr; int flags; Voldesc iso; Voldesc joliet; }; enum { /* Cdimg->flags, Cdinfo->flags */ CDjoliet = 1<<0, CDplan9 = 1<<1, CDconform = 1<<2, CDrockridge = 1<<3, CDnew = 1<<4, CDdump = 1<<5, CDbootable = 1<<6, CDbootnoemu = 1<<7, CDpbs= 1<<8, }; typedef struct Tx Tx; struct Tx { char *bad; /* atoms */ char *good; }; struct Conform { Tx *t; int nt; /* delta = 32 */ }; struct Cdinfo { int flags; char *volumename; char *volumeset; char *publisher; char *preparer; char *application; char *bootimage; char *loader; }; /* * This is a doubly binary tree. * We have a tree keyed on the MD5 values * as well as a tree keyed on the block numbers. */ typedef struct Dump Dump; typedef struct Dumpdir Dumpdir; struct Dump { Cdimg *cd; Dumpdir *md5root; Dumpdir *blockroot; }; struct Dumpdir { char *name; uchar md5[MD5dlen]; ulong block; ulong length; Dumpdir *md5left; Dumpdir *md5right; Dumpdir *blockleft; Dumpdir *blockright; }; struct Dumproot { char *name; int nkid; Dumproot *kid; Direc root; Direc jroot; }; /* * ISO9660 on-CD structures. */ typedef struct Cdir Cdir; typedef struct Cpath Cpath; typedef struct Cvoldesc Cvoldesc; /* a volume descriptor block */ struct Cvoldesc { uchar magic[8]; /* 0x01, "CD001", 0x01, 0x00 */ uchar systemid[32]; /* system identifier */ uchar volumeid[32]; /* volume identifier */ uchar unused[8]; /* character set in secondary desc */ uchar volsize[8]; /* volume size */ uchar charset[32]; uchar volsetsize[4]; /* volume set size = 1 */ uchar volseqnum[4]; /* volume sequence number = 1 */ uchar blocksize[4]; /* logical block size */ uchar pathsize[8]; /* path table size */ uchar lpathloc[4]; /* Lpath */ uchar olpathloc[4]; /* optional Lpath */ uchar mpathloc[4]; /* Mpath */ uchar ompathloc[4]; /* optional Mpath */ uchar rootdir[34]; /* directory entry for root */ uchar volumeset[128]; /* volume set identifier */ uchar publisher[128]; uchar preparer[128]; /* data preparer identifier */ uchar application[128]; /* application identifier */ uchar notice[37]; /* copyright notice file */ uchar abstract[37]; /* abstract file */ uchar biblio[37]; /* bibliographic file */ uchar cdate[17]; /* creation date */ uchar mdate[17]; /* modification date */ uchar xdate[17]; /* expiration date */ uchar edate[17]; /* effective date */ uchar fsvers; /* file system version = 1 */ }; /* a directory entry */ struct Cdir { uchar len; uchar xlen; uchar dloc[8]; uchar dlen[8]; uchar date[7]; uchar flags; uchar unitsize; uchar gapsize; uchar volseqnum[4]; uchar namelen; uchar name[1]; /* chumminess */ }; /* a path table entry */ struct Cpath { uchar namelen; uchar xlen; uchar dloc[4]; uchar parent[2]; uchar name[1]; /* chumminess */ }; enum { /* Rockridge flags */ RR_PX = 1<<0, RR_PN = 1<<1, RR_SL = 1<<2, RR_NM = 1<<3, RR_CL = 1<<4, RR_PL = 1<<5, RR_RE = 1<<6, RR_TF = 1<<7, }; enum { /* CputrripTF type argument */ TFcreation = 1<<0, TFmodify = 1<<1, TFaccess = 1<<2, TFattributes = 1<<3, TFbackup = 1<<4, TFexpiration = 1<<5, TFeffective = 1<<6, TFlongform = 1<<7, }; enum { /* CputrripNM flag types */ NMcontinue = 1<<0, NMcurrent = 1<<1, NMparent = 1<<2, NMroot = 1<<3, NMvolroot = 1<<4, NMhost = 1<<5, }; /* boot.c */ void Cputbootvol(Cdimg*); void Cputbootcat(Cdimg*); void Cupdatebootvol(Cdimg*); void Cupdatebootcat(Cdimg*); void Cfillpbs(Cdimg*); void findbootimage(Cdimg*, Direc*); void findloader(Cdimg*, Direc*); /* cdrdwr.c */ Cdimg *createcd(char*, Cdinfo); Cdimg *opencd(char*, Cdinfo); void Creadblock(Cdimg*, void*, ulong, ulong); ulong big(void*, int); ulong little(void*, int); int parsedir(Cdimg*, Direc*, uchar*, int, char *(*)(uchar*, int)); void setroot(Cdimg*, ulong, ulong, ulong); void setvolsize(Cdimg*, uvlong, ulong); void setpathtable(Cdimg*, ulong, ulong, ulong, ulong); void Cputc(Cdimg*, int); void Cputnl(Cdimg*, uvlong, int); void Cputnm(Cdimg*, uvlong, int); void Cputn(Cdimg*, uvlong, int); void Crepeat(Cdimg*, int, int); void Cputs(Cdimg*, char*, int); void Cwrite(Cdimg*, void*, int); void Cputr(Cdimg*, Rune); void Crepeatr(Cdimg*, Rune, int); void Cputrs(Cdimg*, Rune*, int); void Cputrscvt(Cdimg*, char*, int); void Cpadblock(Cdimg*); void Cputdate(Cdimg*, ulong); void Cputdate1(Cdimg*, ulong); void Cread(Cdimg*, void*, int); void Cwflush(Cdimg*); void Cwseek(Cdimg*, vlong); uvlong Cwoffset(Cdimg*); uvlong Croffset(Cdimg*); int Cgetc(Cdimg*); void Crseek(Cdimg*, vlong); char *Crdline(Cdimg*, int); int Clinelen(Cdimg*); /* conform.c */ void rdconform(Cdimg*); char *conform(char*, int); void wrconform(Cdimg*, int, ulong*, uvlong*); /* direc.c */ void mkdirec(Direc*, XDir*); Direc *walkdirec(Direc*, char*); Direc *adddirec(Direc*, char*, XDir*); void copydirec(Direc*, Direc*); void checknames(Direc*, int (*)(char*)); void convertnames(Direc*, char* (*)(char*, char*)); void dsort(Direc*, int (*)(const void*, const void*)); void setparents(Direc*); /* dump.c */ ulong Cputdumpblock(Cdimg*); int hasdump(Cdimg*); Dump *dumpcd(Cdimg*, Direc*); Dumpdir *lookupmd5(Dump*, uchar*); void insertmd5(Dump*, char*, uchar*, ulong, ulong); Direc readdumpdirs(Cdimg*, XDir*, char*(*)(uchar*,int)); char *adddumpdir(Direc*, ulong, XDir*); void copybutname(Direc*, Direc*); void readkids(Cdimg*, Direc*, char*(*)(uchar*,int)); void freekids(Direc*); void readdumpconform(Cdimg*); void rmdumpdir(Direc*, char*); /* ichar.c */ char *isostring(uchar*, int); int isbadiso9660(char*); int isocmp(const void*, const void*); int isisofrog(char); void Cputisopvd(Cdimg*, Cdinfo); /* jchar.c */ char *jolietstring(uchar*, int); int isbadjoliet(char*); int jolietcmp(const void*, const void*); int isjolietfrog(Rune); void Cputjolietsvd(Cdimg*, Cdinfo); /* path.c */ void writepathtables(Cdimg*); /* util.c */ void *emalloc(ulong); void *erealloc(void*, ulong); char *atom(char*); char *struprcpy(char*, char*); int chat(char*, ...); /* unix.c, plan9.c */ void dirtoxdir(XDir*, Dir*); void fdtruncate(int, ulong); long uidno(char*); long gidno(char*); /* rune.c */ Rune *strtorune(Rune*, char*); Rune *runechr(Rune*, Rune); int runecmp(Rune*, Rune*); /* sysuse.c */ int Cputsysuse(Cdimg*, Direc*, int, int, int); /* write.c */ void writefiles(Dump*, Cdimg*, Direc*); void writedirs(Cdimg*, Direc*, int(*)(Cdimg*, Direc*, int, int, int)); void writedumpdirs(Cdimg*, Direc*, int(*)(Cdimg*, Direc*, int, int, int)); int Cputisodir(Cdimg*, Direc*, int, int, int); int Cputjolietdir(Cdimg*, Direc*, int, int, int); void Cputendvd(Cdimg*); enum { Blocksize = 2048, Ndirblock = 16, /* directory blocks allocated at once */ DTdot = 0, DTdotdot, DTiden, DTroot, DTrootdot, }; extern ulong now; extern Conform *map; extern int chatty; extern int docolon; extern int mk9660; extern int blocksize;