1 /*
2  * iso9660.h
3  *
4  * Routines and data structures to support reading and writing
5  * ISO 9660 CD images. See the ISO 9660 or ECMA 119 standards.
6  *
7  * Also supports Rock Ridge extensions for long file names and Unix stuff.
8  * Also supports Microsoft's Joliet extensions for Unicode and long file names.
9  * Also supports El Torito bootable CD spec.
10  */
11 
12 typedef struct Cdimg Cdimg;
13 typedef struct Cdinfo Cdinfo;
14 typedef struct Conform Conform;
15 typedef struct Direc Direc;
16 typedef struct Dumproot Dumproot;
17 typedef struct Voldesc Voldesc;
18 typedef struct XDir XDir;
19 
20 #ifndef CHLINK
21 #define CHLINK 0
22 #endif
23 
24 struct XDir {
25 	char	*name;
26 	char	*uid;
27 	char	*gid;
28 	char	*symlink;
29 	ulong   uidno;   /* Numeric uid */
30 	ulong   gidno;   /* Numeric gid */
31 
32 	ulong	mode;
33 	ulong	atime;
34 	ulong	mtime;
35 	ulong   ctime;
36 
37         vlong   length;
38 };
39 
40 /*
41  * A directory entry in a ISO9660 tree.
42  * The extra data (uid, etc.) here is put into the system use areas.
43  */
44 struct Direc {
45 	char *name;	/* real name */
46 	char *confname;	/* conformant name */
47 	char *srcfile;	/* file to copy onto the image */
48 
49 	ulong block;
50 	ulong length;
51 	int flags;
52 
53 	char *uid;
54 	char *gid;
55 	char *symlink;
56 	ulong mode;
57 	long atime;
58 	long ctime;
59 	long mtime;
60 
61 	ulong uidno;
62 	ulong gidno;
63 
64 	Direc *child;
65 	int nchild;
66 };
67 enum {  /* Direc flags */
68 	Dbadname = 1<<0  /* Non-conformant name     */
69 };
70 
71 /*
72  * Data found in a volume descriptor.
73  */
74 struct Voldesc {
75 	char *systemid;
76 	char *volumeset;
77 	char *publisher;
78 	char *preparer;
79 	char *application;
80 
81 	/* file names for various parameters */
82 	char *abstract;
83 	char *biblio;
84 	char *notice;
85 
86 	/* path table */
87 	ulong pathsize;
88 	ulong lpathloc;
89 	ulong mpathloc;
90 
91 	/* root of file tree */
92 	Direc root;
93 };
94 
95 /*
96  * An ISO9660 CD image.  Various parameters are kept in memory but the
97  * real image file is opened for reading and writing on fd.
98  *
99  * The bio buffers brd and bwr moderate reading and writing to the image.
100  * The routines we use are careful to flush one before or after using the other,
101  * as necessary.
102  */
103 struct Cdimg {
104 	char *file;
105 	int fd;
106 	ulong dumpblock;
107 	ulong nextblock;
108 	ulong iso9660pvd;
109 	ulong jolietsvd;
110 	ulong pathblock;
111 	ulong rrcontin; /* rock ridge continuation offset */
112 	ulong nulldump;	/* next dump block */
113 	ulong nconform;	/* number of conform entries written already */
114 	ulong bootcatptr;
115 	ulong bootcatblock;
116 	ulong bootimageptr;
117 	Direc *bootdirec;
118 	char *bootimage;
119 
120 	Biobuf brd;
121 	Biobuf bwr;
122 
123 	int flags;
124 
125 	Voldesc iso;
126 	Voldesc joliet;
127 };
128 enum {	/* Cdimg->flags, Cdinfo->flags */
129 	CDjoliet = 1<<0,
130 	CDplan9 = 1<<1,
131 	CDconform = 1<<2,
132 	CDrockridge = 1<<3,
133 	CDnew = 1<<4,
134 	CDdump = 1<<5,
135 	CDbootable = 1<<6
136 };
137 
138 typedef struct Tx Tx;
139 struct Tx {
140 	char *bad;	/* atoms */
141 	char *good;
142 };
143 
144 struct Conform {
145 	Tx *t;
146 	int nt;	/* delta = 32 */
147 };
148 
149 struct Cdinfo {
150 	int flags;
151 
152 	char *volumename;
153 
154 	char *volumeset;
155 	char *publisher;
156 	char *preparer;
157 	char *application;
158 	char *bootimage;
159 };
160 
161 enum {
162 	Blocklen = 2048
163 };
164 
165 /*
166  * This is a doubly binary tree.
167  * We have a tree keyed on the MD5 values
168  * as well as a tree keyed on the block numbers.
169  */
170 typedef struct Dump Dump;
171 typedef struct Dumpdir Dumpdir;
172 
173 struct Dump {
174 	Cdimg *cd;
175 	Dumpdir *md5root;
176 	Dumpdir *blockroot;
177 };
178 
179 struct Dumpdir {
180 	char *name;
181 	uchar md5[MD5dlen];
182 	ulong block;
183 	ulong length;
184 	Dumpdir *md5left;
185 	Dumpdir *md5right;
186 	Dumpdir *blockleft;
187 	Dumpdir *blockright;
188 };
189 
190 struct Dumproot {
191 	char *name;
192 	int nkid;
193 	Dumproot *kid;
194 	Direc root;
195 	Direc jroot;
196 };
197 
198 /*
199  * ISO9660 on-CD structures.
200  */
201 typedef struct Cdir Cdir;
202 typedef struct Cpath Cpath;
203 typedef struct Cvoldesc Cvoldesc;
204 
205 /* a volume descriptor block */
206 struct Cvoldesc {
207 	uchar	magic[8];	/* 0x01, "CD001", 0x01, 0x00 */
208 	uchar	systemid[32];	/* system identifier */
209 	uchar	volumeid[32];	/* volume identifier */
210 	uchar	unused[8];	/* character set in secondary desc */
211 	uchar	volsize[8];	/* volume size */
212 	uchar	charset[32];
213 	uchar	volsetsize[4];	/* volume set size = 1 */
214 	uchar	volseqnum[4];	/* volume sequence number = 1 */
215 	uchar	blocksize[4];	/* logical block size */
216 	uchar	pathsize[8];	/* path table size */
217 	uchar	lpathloc[4];	/* Lpath */
218 	uchar	olpathloc[4];	/* optional Lpath */
219 	uchar	mpathloc[4];	/* Mpath */
220 	uchar	ompathloc[4];	/* optional Mpath */
221 	uchar	rootdir[34];	/* directory entry for root */
222 	uchar	volumeset[128];	/* volume set identifier */
223 	uchar	publisher[128];
224 	uchar	preparer[128];	/* data preparer identifier */
225 	uchar	application[128];	/* application identifier */
226 	uchar	notice[37];	/* copyright notice file */
227 	uchar	abstract[37];	/* abstract file */
228 	uchar	biblio[37];	/* bibliographic file */
229 	uchar	cdate[17];	/* creation date */
230 	uchar	mdate[17];	/* modification date */
231 	uchar	xdate[17];	/* expiration date */
232 	uchar	edate[17];	/* effective date */
233 	uchar	fsvers;		/* file system version = 1 */
234 };
235 
236 /* a directory entry */
237 struct Cdir {
238 	uchar	len;
239 	uchar	xlen;
240 	uchar	dloc[8];
241 	uchar	dlen[8];
242 	uchar	date[7];
243 	uchar	flags;
244 	uchar	unitsize;
245 	uchar	gapsize;
246 	uchar	volseqnum[4];
247 	uchar	namelen;
248 	uchar	name[1];	/* chumminess */
249 };
250 
251 /* a path table entry */
252 struct Cpath {
253 	uchar   namelen;
254 	uchar   xlen;
255 	uchar   dloc[4];
256 	uchar   parent[2];
257 	uchar   name[1];        /* chumminess */
258 };
259 
260 enum { /* Rockridge flags */
261 	RR_PX = 1<<0,
262 	RR_PN = 1<<1,
263 	RR_SL = 1<<2,
264 	RR_NM = 1<<3,
265 	RR_CL = 1<<4,
266 	RR_PL = 1<<5,
267 	RR_RE = 1<<6,
268 	RR_TF = 1<<7
269 };
270 
271 enum { /* CputrripTF type argument */
272 	TFcreation = 1<<0,
273 	TFmodify = 1<<1,
274 	TFaccess = 1<<2,
275 	TFattributes = 1<<3,
276 	TFbackup = 1<<4,
277 	TFexpiration = 1<<5,
278 	TFeffective = 1<<6,
279 	TFlongform = 1<<7
280 };
281 
282 enum { /* CputrripNM flag types */
283 	NMcontinue = 1<<0,
284 	NMcurrent = 1<<1,
285 	NMparent = 1<<2,
286 	NMroot = 1<<3,
287 	NMvolroot = 1<<4,
288 	NMhost = 1<<5
289 };
290 
291 /* boot.c */
292 void Cputbootvol(Cdimg*);
293 void Cputbootcat(Cdimg*);
294 void Cupdatebootvol(Cdimg*);
295 void Cupdatebootcat(Cdimg*);
296 void findbootimage(Cdimg*, Direc*);
297 
298 /* cdrdwr.c */
299 Cdimg *createcd(char*, Cdinfo);
300 Cdimg *opencd(char*, Cdinfo);
301 void Creadblock(Cdimg*, void*, ulong, ulong);
302 ulong big(void*, int);
303 ulong little(void*, int);
304 int parsedir(Cdimg*, Direc*, uchar*, int, char *(*)(uchar*, int));
305 void setroot(Cdimg*, ulong, ulong, ulong);
306 void setvolsize(Cdimg*, ulong, ulong);
307 void setpathtable(Cdimg*, ulong, ulong, ulong, ulong);
308 void Cputc(Cdimg*, int);
309 void Cputnl(Cdimg*, ulong, int);
310 void Cputnm(Cdimg*, ulong, int);
311 void Cputn(Cdimg*, long, int);
312 void Crepeat(Cdimg*, int, int);
313 void Cputs(Cdimg*, char*, int);
314 void Cwrite(Cdimg*, void*, int);
315 void Cputr(Cdimg*, Rune);
316 void Crepeatr(Cdimg*, Rune, int);
317 void Cputrs(Cdimg*, Rune*, int);
318 void Cputrscvt(Cdimg*, char*, int);
319 void Cpadblock(Cdimg*);
320 void Cputdate(Cdimg*, ulong);
321 void Cputdate1(Cdimg*, ulong);
322 void Cread(Cdimg*, void*, int);
323 void Cwflush(Cdimg*);
324 void Cwseek(Cdimg*, ulong);
325 ulong Cwoffset(Cdimg*);
326 ulong Croffset(Cdimg*);
327 int Cgetc(Cdimg*);
328 void Crseek(Cdimg*, ulong);
329 char *Crdline(Cdimg*, int);
330 int Clinelen(Cdimg*);
331 
332 /* conform.c */
333 void rdconform(Cdimg*);
334 char *conform(char*, int);
335 void wrconform(Cdimg*, int, ulong*, ulong*);
336 
337 /* direc.c */
338 void mkdirec(Direc*, XDir*);
339 Direc *walkdirec(Direc*, char*);
340 Direc *adddirec(Direc*, char*, XDir*);
341 void copydirec(Direc*, Direc*);
342 void checknames(Direc*, int (*)(char*));
343 void convertnames(Direc*, char* (*)(char*, char*));
344 void dsort(Direc*, int (*)(const void*, const void*));
345 void setparents(Direc*);
346 
347 /* dump.c */
348 ulong Cputdumpblock(Cdimg*);
349 int hasdump(Cdimg*);
350 Dump *dumpcd(Cdimg*, Direc*);
351 Dumpdir *lookupmd5(Dump*, uchar*);
352 void insertmd5(Dump*, char*, uchar*, ulong, ulong);
353 
354 Direc readdumpdirs(Cdimg*, XDir*, char*(*)(uchar*,int));
355 char *adddumpdir(Direc*, ulong, XDir*);
356 void copybutname(Direc*, Direc*);
357 
358 void readkids(Cdimg*, Direc*, char*(*)(uchar*,int));
359 void freekids(Direc*);
360 void readdumpconform(Cdimg*);
361 void rmdumpdir(Direc*, char*);
362 
363 /* ichar.c */
364 char *isostring(uchar*, int);
365 int isbadiso9660(char*);
366 int isocmp(const void*, const void*);
367 int isisofrog(char);
368 void Cputisopvd(Cdimg*, Cdinfo);
369 
370 /* jchar.c */
371 char *jolietstring(uchar*, int);
372 int isbadjoliet(char*);
373 int jolietcmp(const void*, const void*);
374 int isjolietfrog(Rune);
375 void Cputjolietsvd(Cdimg*, Cdinfo);
376 
377 /* path.c */
378 void writepathtables(Cdimg*);
379 
380 /* util.c */
381 void *emalloc(ulong);
382 void *erealloc(void*, ulong);
383 char *atom(char*);
384 char *struprcpy(char*, char*);
385 int chat(char*, ...);
386 
387 /* unix.c, plan9.c */
388 void dirtoxdir(XDir*, Dir*);
389 void fdtruncate(int, ulong);
390 long uidno(char*);
391 long gidno(char*);
392 
393 /* rune.c */
394 Rune *strtorune(Rune*, char*);
395 Rune *runechr(Rune*, Rune);
396 int runecmp(Rune*, Rune*);
397 
398 /* sysuse.c */
399 int Cputsysuse(Cdimg*, Direc*, int, int, int);
400 
401 /* write.c */
402 void writefiles(Dump*, Cdimg*, Direc*);
403 void writedirs(Cdimg*, Direc*, int(*)(Cdimg*, Direc*, int, int, int));
404 void writedumpdirs(Cdimg*, Direc*, int(*)(Cdimg*, Direc*, int, int, int));
405 int Cputisodir(Cdimg*, Direc*, int, int, int);
406 int Cputjolietdir(Cdimg*, Direc*, int, int, int);
407 void Cputendvd(Cdimg*);
408 
409 enum {
410 	Blocksize = 2048,
411 	Ndirblock = 16,		/* directory blocks allocated at once */
412 
413 	DTdot = 0,
414 	DTdotdot,
415 	DTiden,
416 	DTroot,
417 	DTrootdot
418 };
419 
420 extern ulong now;
421 extern Conform *map;
422 extern int chatty;
423 extern int docolon;
424 extern int mk9660;
425