Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * 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;