blob: b5131a27c1cb2e566b7ebcce97f705c17cc27639 [file] [log] [blame]
/*
* 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;
ulong rrcontin; /* rock ridge continuation offset */
ulong nulldump; /* next dump block */
ulong nconform; /* number of conform entries written already */
ulong bootcatptr;
ulong bootcatblock;
ulong bootimageptr;
Direc *bootdirec;
char *bootimage;
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
};
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;
};
enum {
Blocklen = 2048
};
/*
* 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 findbootimage(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*, ulong, ulong);
void setpathtable(Cdimg*, ulong, ulong, ulong, ulong);
void Cputc(Cdimg*, int);
void Cputnl(Cdimg*, ulong, int);
void Cputnm(Cdimg*, ulong, int);
void Cputn(Cdimg*, long, 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*, ulong);
ulong Cwoffset(Cdimg*);
ulong Croffset(Cdimg*);
int Cgetc(Cdimg*);
void Crseek(Cdimg*, ulong);
char *Crdline(Cdimg*, int);
int Clinelen(Cdimg*);
/* conform.c */
void rdconform(Cdimg*);
char *conform(char*, int);
void wrconform(Cdimg*, int, ulong*, ulong*);
/* 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;