180ee5cbfSDavid du Colombier /*
280ee5cbfSDavid du Colombier * To understand this code, see Rock Ridge Interchange Protocol
380ee5cbfSDavid du Colombier * standard 1.12 and System Use Sharing Protocol version 1.12
480ee5cbfSDavid du Colombier * (search for rrip112.ps and susp112.ps on the web).
580ee5cbfSDavid du Colombier *
680ee5cbfSDavid du Colombier * Even better, go read something else.
780ee5cbfSDavid du Colombier */
880ee5cbfSDavid du Colombier
980ee5cbfSDavid du Colombier #include <u.h>
1080ee5cbfSDavid du Colombier #include <libc.h>
1180ee5cbfSDavid du Colombier #include <bio.h>
1280ee5cbfSDavid du Colombier #include <libsec.h>
1380ee5cbfSDavid du Colombier #include "iso9660.h"
1480ee5cbfSDavid du Colombier
1580ee5cbfSDavid du Colombier static long mode(Direc*, int);
1680ee5cbfSDavid du Colombier static long nlink(Direc*);
1780ee5cbfSDavid du Colombier static ulong suspdirflags(Direc*, int);
18*73ee67a1SDavid du Colombier static ulong CputsuspCE(Cdimg *cd, vlong offset);
1980ee5cbfSDavid du Colombier static int CputsuspER(Cdimg*, int);
2080ee5cbfSDavid du Colombier static int CputsuspRR(Cdimg*, int, int);
2180ee5cbfSDavid du Colombier static int CputsuspSP(Cdimg*, int);
2280ee5cbfSDavid du Colombier //static int CputsuspST(Cdimg*, int);
2380ee5cbfSDavid du Colombier static int Cputrripname(Cdimg*, char*, int, char*, int);
2480ee5cbfSDavid du Colombier static int CputrripSL(Cdimg*, int, int, char*, int);
2580ee5cbfSDavid du Colombier static int CputrripPX(Cdimg*, Direc*, int, int);
2680ee5cbfSDavid du Colombier static int CputrripTF(Cdimg*, Direc*, int, int);
2780ee5cbfSDavid du Colombier
2880ee5cbfSDavid du Colombier /*
2980ee5cbfSDavid du Colombier * Patch the length field in a CE record.
3080ee5cbfSDavid du Colombier */
3180ee5cbfSDavid du Colombier static void
setcelen(Cdimg * cd,vlong woffset,ulong len)32*73ee67a1SDavid du Colombier setcelen(Cdimg *cd, vlong woffset, ulong len)
3380ee5cbfSDavid du Colombier {
34*73ee67a1SDavid du Colombier vlong o;
3580ee5cbfSDavid du Colombier
3680ee5cbfSDavid du Colombier o = Cwoffset(cd);
3780ee5cbfSDavid du Colombier Cwseek(cd, woffset);
3880ee5cbfSDavid du Colombier Cputn(cd, len, 4);
3980ee5cbfSDavid du Colombier Cwseek(cd, o);
4080ee5cbfSDavid du Colombier }
4180ee5cbfSDavid du Colombier
4280ee5cbfSDavid du Colombier /*
4380ee5cbfSDavid du Colombier * Rock Ridge data is put into little blockettes, which can be
4480ee5cbfSDavid du Colombier * at most 256 bytes including a one-byte length. Some number
4580ee5cbfSDavid du Colombier * of blockettes get packed together into a normal 2048-byte block.
4680ee5cbfSDavid du Colombier * Blockettes cannot cross block boundaries.
4780ee5cbfSDavid du Colombier *
4880ee5cbfSDavid du Colombier * A Cbuf is a blockette buffer. Len contains
4980ee5cbfSDavid du Colombier * the length of the buffer written so far, and we can
5080ee5cbfSDavid du Colombier * write up to 254-28.
5180ee5cbfSDavid du Colombier *
5280ee5cbfSDavid du Colombier * We only have one active Cbuf at a time; cdimg.rrcontin is the byte
5380ee5cbfSDavid du Colombier * offset of the beginning of that Cbuf.
5480ee5cbfSDavid du Colombier *
5580ee5cbfSDavid du Colombier * The blockette can be at most 255 bytes. The last 28
5680ee5cbfSDavid du Colombier * will be (in the worst case) a CE record pointing at
5780ee5cbfSDavid du Colombier * a new blockette. If we do write 255 bytes though,
5880ee5cbfSDavid du Colombier * we'll try to pad it out to be even, and overflow.
5980ee5cbfSDavid du Colombier * So the maximum is 254-28.
6080ee5cbfSDavid du Colombier *
6180ee5cbfSDavid du Colombier * Ceoffset contains the offset to be used with setcelen
6280ee5cbfSDavid du Colombier * to patch the CE pointing at the Cbuf once we know how
6380ee5cbfSDavid du Colombier * long the Cbuf is.
6480ee5cbfSDavid du Colombier */
6580ee5cbfSDavid du Colombier typedef struct Cbuf Cbuf;
6680ee5cbfSDavid du Colombier struct Cbuf {
6780ee5cbfSDavid du Colombier int len; /* written so far, of 254-28 */
68*73ee67a1SDavid du Colombier uvlong ceoffset;
6980ee5cbfSDavid du Colombier };
7080ee5cbfSDavid du Colombier
7180ee5cbfSDavid du Colombier static int
freespace(Cbuf * cp)7280ee5cbfSDavid du Colombier freespace(Cbuf *cp)
7380ee5cbfSDavid du Colombier {
7480ee5cbfSDavid du Colombier return (254-28) - cp->len;
7580ee5cbfSDavid du Colombier }
7680ee5cbfSDavid du Colombier
7780ee5cbfSDavid du Colombier static Cbuf*
ensurespace(Cdimg * cd,int n,Cbuf * co,Cbuf * cn,int dowrite)7880ee5cbfSDavid du Colombier ensurespace(Cdimg *cd, int n, Cbuf *co, Cbuf *cn, int dowrite)
7980ee5cbfSDavid du Colombier {
80*73ee67a1SDavid du Colombier uvlong end;
8180ee5cbfSDavid du Colombier
8280ee5cbfSDavid du Colombier if(co->len+n <= 254-28) {
8380ee5cbfSDavid du Colombier co->len += n;
8480ee5cbfSDavid du Colombier return co;
8580ee5cbfSDavid du Colombier }
8680ee5cbfSDavid du Colombier
8780ee5cbfSDavid du Colombier co->len += 28;
8880ee5cbfSDavid du Colombier assert(co->len <= 254);
8980ee5cbfSDavid du Colombier
9080ee5cbfSDavid du Colombier if(dowrite == 0) {
9180ee5cbfSDavid du Colombier cn->len = n;
9280ee5cbfSDavid du Colombier return cn;
9380ee5cbfSDavid du Colombier }
9480ee5cbfSDavid du Colombier
9580ee5cbfSDavid du Colombier /*
9680ee5cbfSDavid du Colombier * the current blockette is full; update cd->rrcontin and then
9780ee5cbfSDavid du Colombier * write a CE record to finish it. Unfortunately we need to
9880ee5cbfSDavid du Colombier * figure out which block will be next before we write the CE.
9980ee5cbfSDavid du Colombier */
10080ee5cbfSDavid du Colombier end = Cwoffset(cd)+28;
10180ee5cbfSDavid du Colombier
10280ee5cbfSDavid du Colombier /*
10380ee5cbfSDavid du Colombier * if we're in a continuation blockette, update rrcontin.
10480ee5cbfSDavid du Colombier * also, write our length into the field of the CE record
10580ee5cbfSDavid du Colombier * that points at us.
10680ee5cbfSDavid du Colombier */
10780ee5cbfSDavid du Colombier if(cd->rrcontin+co->len == end) {
10880ee5cbfSDavid du Colombier assert(cd->rrcontin != 0);
10980ee5cbfSDavid du Colombier assert(co == cn);
11080ee5cbfSDavid du Colombier cd->rrcontin += co->len;
11180ee5cbfSDavid du Colombier setcelen(cd, co->ceoffset, co->len);
11280ee5cbfSDavid du Colombier } else
11380ee5cbfSDavid du Colombier assert(co != cn);
11480ee5cbfSDavid du Colombier
11580ee5cbfSDavid du Colombier /*
11680ee5cbfSDavid du Colombier * if the current continuation block can't fit another
11780ee5cbfSDavid du Colombier * blockette, then start a new continuation block.
11880ee5cbfSDavid du Colombier * rrcontin = 0 (mod Blocksize) means we just finished
11980ee5cbfSDavid du Colombier * one, not that we've just started one.
12080ee5cbfSDavid du Colombier */
12180ee5cbfSDavid du Colombier if(cd->rrcontin%Blocksize == 0
12280ee5cbfSDavid du Colombier || cd->rrcontin/Blocksize != (cd->rrcontin+256)/Blocksize) {
123*73ee67a1SDavid du Colombier cd->rrcontin = (vlong)cd->nextblock * Blocksize;
12480ee5cbfSDavid du Colombier cd->nextblock++;
12580ee5cbfSDavid du Colombier }
12680ee5cbfSDavid du Colombier
12780ee5cbfSDavid du Colombier cn->ceoffset = CputsuspCE(cd, cd->rrcontin);
12880ee5cbfSDavid du Colombier
12980ee5cbfSDavid du Colombier assert(Cwoffset(cd) == end);
13080ee5cbfSDavid du Colombier
13180ee5cbfSDavid du Colombier cn->len = n;
13280ee5cbfSDavid du Colombier Cwseek(cd, cd->rrcontin);
13380ee5cbfSDavid du Colombier assert(cd->rrcontin != 0);
13480ee5cbfSDavid du Colombier
13580ee5cbfSDavid du Colombier return cn;
13680ee5cbfSDavid du Colombier }
13780ee5cbfSDavid du Colombier
13880ee5cbfSDavid du Colombier /*
13980ee5cbfSDavid du Colombier * Put down the name, but we might need to break it
14080ee5cbfSDavid du Colombier * into chunks so that each chunk fits in 254-28-5 bytes.
14180ee5cbfSDavid du Colombier * What a crock.
14280ee5cbfSDavid du Colombier *
14380ee5cbfSDavid du Colombier * The new Plan 9 format uses strings of this form too,
14480ee5cbfSDavid du Colombier * since they're already there.
14580ee5cbfSDavid du Colombier */
14680ee5cbfSDavid du Colombier Cbuf*
Cputstring(Cdimg * cd,Cbuf * cp,Cbuf * cn,char * nm,char * p,int flags,int dowrite)14780ee5cbfSDavid du Colombier Cputstring(Cdimg *cd, Cbuf *cp, Cbuf *cn, char *nm, char *p, int flags, int dowrite)
14880ee5cbfSDavid du Colombier {
14980ee5cbfSDavid du Colombier char buf[256], *q;
15080ee5cbfSDavid du Colombier int free;
15180ee5cbfSDavid du Colombier
15280ee5cbfSDavid du Colombier for(; p[0] != '\0'; p = q) {
15380ee5cbfSDavid du Colombier cp = ensurespace(cd, 5+1, cp, cn, dowrite);
15480ee5cbfSDavid du Colombier cp->len -= 5+1;
15580ee5cbfSDavid du Colombier free = freespace(cp);
15680ee5cbfSDavid du Colombier assert(5+1 <= free && free < 256);
15780ee5cbfSDavid du Colombier
15880ee5cbfSDavid du Colombier strncpy(buf, p, free-5);
15980ee5cbfSDavid du Colombier buf[free-5] = '\0';
16080ee5cbfSDavid du Colombier q = p+strlen(buf);
16180ee5cbfSDavid du Colombier p = buf;
16280ee5cbfSDavid du Colombier
16380ee5cbfSDavid du Colombier ensurespace(cd, 5+strlen(p), cp, nil, dowrite); /* nil: better not use this. */
16480ee5cbfSDavid du Colombier Cputrripname(cd, nm, flags | (q[0] ? NMcontinue : 0), p, dowrite);
16580ee5cbfSDavid du Colombier }
16680ee5cbfSDavid du Colombier return cp;
16780ee5cbfSDavid du Colombier }
16880ee5cbfSDavid du Colombier
16980ee5cbfSDavid du Colombier /*
17080ee5cbfSDavid du Colombier * Write a Rock Ridge SUSP set of records for a directory entry.
17180ee5cbfSDavid du Colombier */
17280ee5cbfSDavid du Colombier int
Cputsysuse(Cdimg * cd,Direc * d,int dot,int dowrite,int initlen)17380ee5cbfSDavid du Colombier Cputsysuse(Cdimg *cd, Direc *d, int dot, int dowrite, int initlen)
17480ee5cbfSDavid du Colombier {
17580ee5cbfSDavid du Colombier char buf[256], buf0[256], *nextpath, *p, *path, *q;
17680ee5cbfSDavid du Colombier int flags, free, m, what;
177*73ee67a1SDavid du Colombier uvlong o;
17880ee5cbfSDavid du Colombier Cbuf cn, co, *cp;
17980ee5cbfSDavid du Colombier
18080ee5cbfSDavid du Colombier assert(cd != nil);
18180ee5cbfSDavid du Colombier assert((initlen&1) == 0);
18280ee5cbfSDavid du Colombier
18380ee5cbfSDavid du Colombier if(dot == DTroot)
18480ee5cbfSDavid du Colombier return 0;
18580ee5cbfSDavid du Colombier
18680ee5cbfSDavid du Colombier co.len = initlen;
18780ee5cbfSDavid du Colombier
18880ee5cbfSDavid du Colombier o = Cwoffset(cd);
18980ee5cbfSDavid du Colombier
19080ee5cbfSDavid du Colombier assert(dowrite==0 || Cwoffset(cd) == o+co.len-initlen);
19180ee5cbfSDavid du Colombier cp = &co;
19280ee5cbfSDavid du Colombier
19380ee5cbfSDavid du Colombier if (dot == DTrootdot) {
19480ee5cbfSDavid du Colombier m = CputsuspSP(cd, 0);
19580ee5cbfSDavid du Colombier cp = ensurespace(cd, m, cp, &cn, dowrite);
19680ee5cbfSDavid du Colombier CputsuspSP(cd, dowrite);
19780ee5cbfSDavid du Colombier
19880ee5cbfSDavid du Colombier m = CputsuspER(cd, 0);
19980ee5cbfSDavid du Colombier cp = ensurespace(cd, m, cp, &cn, dowrite);
20080ee5cbfSDavid du Colombier CputsuspER(cd, dowrite);
20180ee5cbfSDavid du Colombier }
20280ee5cbfSDavid du Colombier
20380ee5cbfSDavid du Colombier /*
20480ee5cbfSDavid du Colombier * In a perfect world, we'd be able to omit the NM
20580ee5cbfSDavid du Colombier * entries when our name was all lowercase and conformant,
20680ee5cbfSDavid du Colombier * but OpenBSD insists on uppercasing (really, not lowercasing)
20780ee5cbfSDavid du Colombier * the ISO9660 names.
20880ee5cbfSDavid du Colombier */
20980ee5cbfSDavid du Colombier what = RR_PX | RR_TF | RR_NM;
21080ee5cbfSDavid du Colombier if(d != nil && (d->mode & CHLINK))
21180ee5cbfSDavid du Colombier what |= RR_SL;
21280ee5cbfSDavid du Colombier
21380ee5cbfSDavid du Colombier m = CputsuspRR(cd, what, 0);
21480ee5cbfSDavid du Colombier cp = ensurespace(cd, m, cp, &cn, dowrite);
21580ee5cbfSDavid du Colombier CputsuspRR(cd, what, dowrite);
21680ee5cbfSDavid du Colombier
21780ee5cbfSDavid du Colombier if(what & RR_PX) {
21880ee5cbfSDavid du Colombier m = CputrripPX(cd, d, dot, 0);
21980ee5cbfSDavid du Colombier cp = ensurespace(cd, m, cp, &cn, dowrite);
22080ee5cbfSDavid du Colombier CputrripPX(cd, d, dot, dowrite);
22180ee5cbfSDavid du Colombier }
22280ee5cbfSDavid du Colombier
22380ee5cbfSDavid du Colombier if(what & RR_NM) {
22480ee5cbfSDavid du Colombier if(dot == DTiden)
22580ee5cbfSDavid du Colombier p = d->name;
22680ee5cbfSDavid du Colombier else if(dot == DTdotdot)
22780ee5cbfSDavid du Colombier p = "..";
22880ee5cbfSDavid du Colombier else
22980ee5cbfSDavid du Colombier p = ".";
23080ee5cbfSDavid du Colombier
23180ee5cbfSDavid du Colombier flags = suspdirflags(d, dot);
23280ee5cbfSDavid du Colombier assert(dowrite==0 || cp != &co || Cwoffset(cd) == o+co.len-initlen);
23380ee5cbfSDavid du Colombier cp = Cputstring(cd, cp, &cn, "NM", p, flags, dowrite);
23480ee5cbfSDavid du Colombier }
23580ee5cbfSDavid du Colombier
23680ee5cbfSDavid du Colombier /*
23780ee5cbfSDavid du Colombier * Put down the symbolic link. This is even more of a crock.
23880ee5cbfSDavid du Colombier * Not only are the individual elements potentially split,
23980ee5cbfSDavid du Colombier * but the whole path itself can be split across SL blocks.
24080ee5cbfSDavid du Colombier * To keep the code simple as possible (really), we write
24180ee5cbfSDavid du Colombier * only one element per SL block, wasting 6 bytes per element.
24280ee5cbfSDavid du Colombier */
24380ee5cbfSDavid du Colombier if(what & RR_SL) {
24480ee5cbfSDavid du Colombier for(path=d->symlink; path[0] != '\0'; path=nextpath) {
24580ee5cbfSDavid du Colombier /* break off one component */
24680ee5cbfSDavid du Colombier if((nextpath = strchr(path, '/')) == nil)
24780ee5cbfSDavid du Colombier nextpath = path+strlen(path);
24880ee5cbfSDavid du Colombier strncpy(buf0, path, nextpath-path);
24980ee5cbfSDavid du Colombier buf0[nextpath-path] = '\0';
25080ee5cbfSDavid du Colombier if(nextpath[0] == '/')
25180ee5cbfSDavid du Colombier nextpath++;
25280ee5cbfSDavid du Colombier p = buf0;
25380ee5cbfSDavid du Colombier
25480ee5cbfSDavid du Colombier /* write the name, perhaps broken into pieces */
25580ee5cbfSDavid du Colombier if(strcmp(p, "") == 0)
25680ee5cbfSDavid du Colombier flags = NMroot;
25780ee5cbfSDavid du Colombier else if(strcmp(p, ".") == 0)
25880ee5cbfSDavid du Colombier flags = NMcurrent;
25980ee5cbfSDavid du Colombier else if(strcmp(p, "..") == 0)
26080ee5cbfSDavid du Colombier flags = NMparent;
26180ee5cbfSDavid du Colombier else
26280ee5cbfSDavid du Colombier flags = 0;
26380ee5cbfSDavid du Colombier
26480ee5cbfSDavid du Colombier /* the do-while handles the empty string properly */
26580ee5cbfSDavid du Colombier do {
26680ee5cbfSDavid du Colombier /* must have room for at least 1 byte of name */
26780ee5cbfSDavid du Colombier cp = ensurespace(cd, 7+1, cp, &cn, dowrite);
26880ee5cbfSDavid du Colombier cp->len -= 7+1;
26980ee5cbfSDavid du Colombier free = freespace(cp);
27080ee5cbfSDavid du Colombier assert(7+1 <= free && free < 256);
27180ee5cbfSDavid du Colombier
27280ee5cbfSDavid du Colombier strncpy(buf, p, free-7);
27380ee5cbfSDavid du Colombier buf[free-7] = '\0';
27480ee5cbfSDavid du Colombier q = p+strlen(buf);
27580ee5cbfSDavid du Colombier p = buf;
27680ee5cbfSDavid du Colombier
27780ee5cbfSDavid du Colombier /* nil: better not need to expand */
27880ee5cbfSDavid du Colombier assert(7+strlen(p) <= free);
27980ee5cbfSDavid du Colombier ensurespace(cd, 7+strlen(p), cp, nil, dowrite);
28080ee5cbfSDavid du Colombier CputrripSL(cd, nextpath[0], flags | (q[0] ? NMcontinue : 0), p, dowrite);
28180ee5cbfSDavid du Colombier p = q;
28280ee5cbfSDavid du Colombier } while(p[0] != '\0');
28380ee5cbfSDavid du Colombier }
28480ee5cbfSDavid du Colombier }
28580ee5cbfSDavid du Colombier
28680ee5cbfSDavid du Colombier assert(dowrite==0 || cp != &co || Cwoffset(cd) == o+co.len-initlen);
28780ee5cbfSDavid du Colombier
28880ee5cbfSDavid du Colombier if(what & RR_TF) {
28980ee5cbfSDavid du Colombier m = CputrripTF(cd, d, TFcreation|TFmodify|TFaccess|TFattributes, 0);
29080ee5cbfSDavid du Colombier cp = ensurespace(cd, m, cp, &cn, dowrite);
29180ee5cbfSDavid du Colombier CputrripTF(cd, d, TFcreation|TFmodify|TFaccess|TFattributes, dowrite);
29280ee5cbfSDavid du Colombier }
29380ee5cbfSDavid du Colombier assert(dowrite==0 || cp != &co || Cwoffset(cd) == o+co.len-initlen);
29480ee5cbfSDavid du Colombier
29580ee5cbfSDavid du Colombier if(cp == &cn && dowrite) {
29680ee5cbfSDavid du Colombier /* seek out of continuation, but mark our place */
29780ee5cbfSDavid du Colombier cd->rrcontin = Cwoffset(cd);
29880ee5cbfSDavid du Colombier setcelen(cd, cn.ceoffset, cn.len);
29980ee5cbfSDavid du Colombier Cwseek(cd, o+co.len-initlen);
30080ee5cbfSDavid du Colombier }
30180ee5cbfSDavid du Colombier
30280ee5cbfSDavid du Colombier if(co.len & 1) {
30380ee5cbfSDavid du Colombier co.len++;
30480ee5cbfSDavid du Colombier if(dowrite)
30580ee5cbfSDavid du Colombier Cputc(cd, 0);
30680ee5cbfSDavid du Colombier }
30780ee5cbfSDavid du Colombier
30880ee5cbfSDavid du Colombier if(dowrite) {
30980ee5cbfSDavid du Colombier if(Cwoffset(cd) != o+co.len-initlen)
310*73ee67a1SDavid du Colombier fprint(2, "offset %llud o+co.len-initlen %llud\n",
311*73ee67a1SDavid du Colombier Cwoffset(cd), o+co.len-initlen);
31280ee5cbfSDavid du Colombier assert(Cwoffset(cd) == o+co.len-initlen);
31380ee5cbfSDavid du Colombier } else
31480ee5cbfSDavid du Colombier assert(Cwoffset(cd) == o);
31580ee5cbfSDavid du Colombier
31680ee5cbfSDavid du Colombier assert(co.len <= 255);
31780ee5cbfSDavid du Colombier return co.len - initlen;
31880ee5cbfSDavid du Colombier }
31980ee5cbfSDavid du Colombier
32080ee5cbfSDavid du Colombier static char SUSPrrip[10] = "RRIP_1991A";
32180ee5cbfSDavid du Colombier static char SUSPdesc[84] = "RRIP <more garbage here>";
32280ee5cbfSDavid du Colombier static char SUSPsrc[135] = "RRIP <more garbage here>";
32380ee5cbfSDavid du Colombier
32480ee5cbfSDavid du Colombier static ulong
CputsuspCE(Cdimg * cd,vlong offset)325*73ee67a1SDavid du Colombier CputsuspCE(Cdimg *cd, vlong offset)
32680ee5cbfSDavid du Colombier {
327*73ee67a1SDavid du Colombier vlong o, x;
32880ee5cbfSDavid du Colombier
329*73ee67a1SDavid du Colombier chat("writing SUSP CE record pointing to %ld, %ld\n",
330*73ee67a1SDavid du Colombier offset/Blocksize, offset%Blocksize);
33180ee5cbfSDavid du Colombier o = Cwoffset(cd);
33280ee5cbfSDavid du Colombier Cputc(cd, 'C');
33380ee5cbfSDavid du Colombier Cputc(cd, 'E');
33480ee5cbfSDavid du Colombier Cputc(cd, 28);
33580ee5cbfSDavid du Colombier Cputc(cd, 1);
33680ee5cbfSDavid du Colombier Cputn(cd, offset/Blocksize, 4);
33780ee5cbfSDavid du Colombier Cputn(cd, offset%Blocksize, 4);
33880ee5cbfSDavid du Colombier x = Cwoffset(cd);
33980ee5cbfSDavid du Colombier Cputn(cd, 0, 4);
34080ee5cbfSDavid du Colombier assert(Cwoffset(cd) == o+28);
34180ee5cbfSDavid du Colombier
34280ee5cbfSDavid du Colombier return x;
34380ee5cbfSDavid du Colombier }
34480ee5cbfSDavid du Colombier
34580ee5cbfSDavid du Colombier static int
CputsuspER(Cdimg * cd,int dowrite)34680ee5cbfSDavid du Colombier CputsuspER(Cdimg *cd, int dowrite)
34780ee5cbfSDavid du Colombier {
34880ee5cbfSDavid du Colombier assert(cd != nil);
34980ee5cbfSDavid du Colombier
35080ee5cbfSDavid du Colombier if(dowrite) {
35180ee5cbfSDavid du Colombier chat("writing SUSP ER record\n");
35280ee5cbfSDavid du Colombier Cputc(cd, 'E'); /* ER field marker */
35380ee5cbfSDavid du Colombier Cputc(cd, 'R');
35480ee5cbfSDavid du Colombier Cputc(cd, 26); /* Length */
35580ee5cbfSDavid du Colombier Cputc(cd, 1); /* Version */
35680ee5cbfSDavid du Colombier Cputc(cd, 10); /* LEN_ID */
35780ee5cbfSDavid du Colombier Cputc(cd, 4); /* LEN_DESC */
35880ee5cbfSDavid du Colombier Cputc(cd, 4); /* LEN_SRC */
35980ee5cbfSDavid du Colombier Cputc(cd, 1); /* EXT_VER */
36080ee5cbfSDavid du Colombier Cputs(cd, SUSPrrip, 10); /* EXT_ID */
36180ee5cbfSDavid du Colombier Cputs(cd, SUSPdesc, 4); /* EXT_DESC */
36280ee5cbfSDavid du Colombier Cputs(cd, SUSPsrc, 4); /* EXT_SRC */
36380ee5cbfSDavid du Colombier }
36480ee5cbfSDavid du Colombier return 8+10+4+4;
36580ee5cbfSDavid du Colombier }
36680ee5cbfSDavid du Colombier
36780ee5cbfSDavid du Colombier static int
CputsuspRR(Cdimg * cd,int what,int dowrite)36880ee5cbfSDavid du Colombier CputsuspRR(Cdimg *cd, int what, int dowrite)
36980ee5cbfSDavid du Colombier {
37080ee5cbfSDavid du Colombier assert(cd != nil);
37180ee5cbfSDavid du Colombier
37280ee5cbfSDavid du Colombier if(dowrite) {
37380ee5cbfSDavid du Colombier Cputc(cd, 'R'); /* RR field marker */
37480ee5cbfSDavid du Colombier Cputc(cd, 'R');
37580ee5cbfSDavid du Colombier Cputc(cd, 5); /* Length */
37680ee5cbfSDavid du Colombier Cputc(cd, 1); /* Version number */
37780ee5cbfSDavid du Colombier Cputc(cd, what); /* Flags */
37880ee5cbfSDavid du Colombier }
37980ee5cbfSDavid du Colombier return 5;
38080ee5cbfSDavid du Colombier }
38180ee5cbfSDavid du Colombier
38280ee5cbfSDavid du Colombier static int
CputsuspSP(Cdimg * cd,int dowrite)38380ee5cbfSDavid du Colombier CputsuspSP(Cdimg *cd, int dowrite)
38480ee5cbfSDavid du Colombier {
38580ee5cbfSDavid du Colombier assert(cd!=0);
38680ee5cbfSDavid du Colombier
38780ee5cbfSDavid du Colombier if(dowrite) {
38880ee5cbfSDavid du Colombier chat("writing SUSP SP record\n");
38980ee5cbfSDavid du Colombier Cputc(cd, 'S'); /* SP field marker */
39080ee5cbfSDavid du Colombier Cputc(cd, 'P');
39180ee5cbfSDavid du Colombier Cputc(cd, 7); /* Length */
39280ee5cbfSDavid du Colombier Cputc(cd, 1); /* Version */
39380ee5cbfSDavid du Colombier Cputc(cd, 0xBE); /* Magic */
39480ee5cbfSDavid du Colombier Cputc(cd, 0xEF);
39580ee5cbfSDavid du Colombier Cputc(cd, 0);
39680ee5cbfSDavid du Colombier }
39780ee5cbfSDavid du Colombier
39880ee5cbfSDavid du Colombier return 7;
39980ee5cbfSDavid du Colombier }
40080ee5cbfSDavid du Colombier
40180ee5cbfSDavid du Colombier #ifdef NOTUSED
40280ee5cbfSDavid du Colombier static int
CputsuspST(Cdimg * cd,int dowrite)40380ee5cbfSDavid du Colombier CputsuspST(Cdimg *cd, int dowrite)
40480ee5cbfSDavid du Colombier {
40580ee5cbfSDavid du Colombier assert(cd!=0);
40680ee5cbfSDavid du Colombier
40780ee5cbfSDavid du Colombier if(dowrite) {
40880ee5cbfSDavid du Colombier Cputc(cd, 'S'); /* ST field marker */
40980ee5cbfSDavid du Colombier Cputc(cd, 'T');
41080ee5cbfSDavid du Colombier Cputc(cd, 4); /* Length */
41180ee5cbfSDavid du Colombier Cputc(cd, 1); /* Version */
41280ee5cbfSDavid du Colombier }
41380ee5cbfSDavid du Colombier return 4;
41480ee5cbfSDavid du Colombier }
41580ee5cbfSDavid du Colombier #endif
41680ee5cbfSDavid du Colombier
41780ee5cbfSDavid du Colombier static ulong
suspdirflags(Direc * d,int dot)41880ee5cbfSDavid du Colombier suspdirflags(Direc *d, int dot)
41980ee5cbfSDavid du Colombier {
42080ee5cbfSDavid du Colombier uchar flags;
42180ee5cbfSDavid du Colombier
42280ee5cbfSDavid du Colombier USED(d);
42380ee5cbfSDavid du Colombier flags = 0;
42480ee5cbfSDavid du Colombier switch(dot) {
42580ee5cbfSDavid du Colombier default:
42680ee5cbfSDavid du Colombier assert(0);
42780ee5cbfSDavid du Colombier case DTdot:
42880ee5cbfSDavid du Colombier case DTrootdot:
42980ee5cbfSDavid du Colombier flags |= NMcurrent;
43080ee5cbfSDavid du Colombier break;
43180ee5cbfSDavid du Colombier case DTdotdot:
43280ee5cbfSDavid du Colombier flags |= NMparent;
43380ee5cbfSDavid du Colombier break;
43480ee5cbfSDavid du Colombier case DTroot:
43580ee5cbfSDavid du Colombier flags |= NMvolroot;
43680ee5cbfSDavid du Colombier break;
43780ee5cbfSDavid du Colombier case DTiden:
43880ee5cbfSDavid du Colombier break;
43980ee5cbfSDavid du Colombier }
44080ee5cbfSDavid du Colombier return flags;
44180ee5cbfSDavid du Colombier }
44280ee5cbfSDavid du Colombier
44380ee5cbfSDavid du Colombier static int
Cputrripname(Cdimg * cd,char * nm,int flags,char * name,int dowrite)44480ee5cbfSDavid du Colombier Cputrripname(Cdimg *cd, char *nm, int flags, char *name, int dowrite)
44580ee5cbfSDavid du Colombier {
44680ee5cbfSDavid du Colombier int l;
44780ee5cbfSDavid du Colombier
44880ee5cbfSDavid du Colombier l = strlen(name);
44980ee5cbfSDavid du Colombier if(dowrite) {
45080ee5cbfSDavid du Colombier Cputc(cd, nm[0]); /* NM field marker */
45180ee5cbfSDavid du Colombier Cputc(cd, nm[1]);
45280ee5cbfSDavid du Colombier Cputc(cd, l+5); /* Length */
45380ee5cbfSDavid du Colombier Cputc(cd, 1); /* Version */
45480ee5cbfSDavid du Colombier Cputc(cd, flags); /* Flags */
45580ee5cbfSDavid du Colombier Cputs(cd, name, l); /* Alternate name */
45680ee5cbfSDavid du Colombier }
45780ee5cbfSDavid du Colombier return 5+l;
45880ee5cbfSDavid du Colombier }
45980ee5cbfSDavid du Colombier
46080ee5cbfSDavid du Colombier static int
CputrripSL(Cdimg * cd,int contin,int flags,char * name,int dowrite)46180ee5cbfSDavid du Colombier CputrripSL(Cdimg *cd, int contin, int flags, char *name, int dowrite)
46280ee5cbfSDavid du Colombier {
46380ee5cbfSDavid du Colombier int l;
46480ee5cbfSDavid du Colombier
46580ee5cbfSDavid du Colombier l = strlen(name);
46680ee5cbfSDavid du Colombier if(dowrite) {
46780ee5cbfSDavid du Colombier Cputc(cd, 'S');
46880ee5cbfSDavid du Colombier Cputc(cd, 'L');
46980ee5cbfSDavid du Colombier Cputc(cd, l+7);
47080ee5cbfSDavid du Colombier Cputc(cd, 1);
47180ee5cbfSDavid du Colombier Cputc(cd, contin ? 1 : 0);
47280ee5cbfSDavid du Colombier Cputc(cd, flags);
47380ee5cbfSDavid du Colombier Cputc(cd, l);
47480ee5cbfSDavid du Colombier Cputs(cd, name, l);
47580ee5cbfSDavid du Colombier }
47680ee5cbfSDavid du Colombier return 7+l;
47780ee5cbfSDavid du Colombier }
47880ee5cbfSDavid du Colombier
47980ee5cbfSDavid du Colombier static int
CputrripPX(Cdimg * cd,Direc * d,int dot,int dowrite)48080ee5cbfSDavid du Colombier CputrripPX(Cdimg *cd, Direc *d, int dot, int dowrite)
48180ee5cbfSDavid du Colombier {
48280ee5cbfSDavid du Colombier assert(cd!=0);
48380ee5cbfSDavid du Colombier
48480ee5cbfSDavid du Colombier if(dowrite) {
48580ee5cbfSDavid du Colombier Cputc(cd, 'P'); /* PX field marker */
48680ee5cbfSDavid du Colombier Cputc(cd, 'X');
48780ee5cbfSDavid du Colombier Cputc(cd, 36); /* Length */
48880ee5cbfSDavid du Colombier Cputc(cd, 1); /* Version */
48980ee5cbfSDavid du Colombier
49080ee5cbfSDavid du Colombier Cputn(cd, mode(d, dot), 4); /* POSIX File mode */
49180ee5cbfSDavid du Colombier Cputn(cd, nlink(d), 4); /* POSIX st_nlink */
49280ee5cbfSDavid du Colombier Cputn(cd, d?d->uidno:0, 4); /* POSIX st_uid */
49380ee5cbfSDavid du Colombier Cputn(cd, d?d->gidno:0, 4); /* POSIX st_gid */
49480ee5cbfSDavid du Colombier }
49580ee5cbfSDavid du Colombier
49680ee5cbfSDavid du Colombier return 36;
49780ee5cbfSDavid du Colombier }
49880ee5cbfSDavid du Colombier
49980ee5cbfSDavid du Colombier static int
CputrripTF(Cdimg * cd,Direc * d,int type,int dowrite)50080ee5cbfSDavid du Colombier CputrripTF(Cdimg *cd, Direc *d, int type, int dowrite)
50180ee5cbfSDavid du Colombier {
50280ee5cbfSDavid du Colombier int i, length;
50380ee5cbfSDavid du Colombier
50480ee5cbfSDavid du Colombier assert(cd!=0);
50580ee5cbfSDavid du Colombier assert(!(type & TFlongform));
50680ee5cbfSDavid du Colombier
50780ee5cbfSDavid du Colombier length = 0;
50880ee5cbfSDavid du Colombier for(i=0; i<7; i++)
50980ee5cbfSDavid du Colombier if (type & (1<<i))
51080ee5cbfSDavid du Colombier length++;
51180ee5cbfSDavid du Colombier assert(length == 4);
51280ee5cbfSDavid du Colombier
51380ee5cbfSDavid du Colombier if(dowrite) {
51480ee5cbfSDavid du Colombier Cputc(cd, 'T'); /* TF field marker */
51580ee5cbfSDavid du Colombier Cputc(cd, 'F');
51680ee5cbfSDavid du Colombier Cputc(cd, 5+7*length); /* Length */
51780ee5cbfSDavid du Colombier Cputc(cd, 1); /* Version */
51880ee5cbfSDavid du Colombier Cputc(cd, type); /* Flags (types) */
51980ee5cbfSDavid du Colombier
52080ee5cbfSDavid du Colombier if (type & TFcreation)
52180ee5cbfSDavid du Colombier Cputdate(cd, d?d->ctime:0);
52280ee5cbfSDavid du Colombier if (type & TFmodify)
52380ee5cbfSDavid du Colombier Cputdate(cd, d?d->mtime:0);
52480ee5cbfSDavid du Colombier if (type & TFaccess)
52580ee5cbfSDavid du Colombier Cputdate(cd, d?d->atime:0);
52680ee5cbfSDavid du Colombier if (type & TFattributes)
52780ee5cbfSDavid du Colombier Cputdate(cd, d?d->ctime:0);
52880ee5cbfSDavid du Colombier
52980ee5cbfSDavid du Colombier // if (type & TFbackup)
53080ee5cbfSDavid du Colombier // Cputdate(cd, 0);
53180ee5cbfSDavid du Colombier // if (type & TFexpiration)
53280ee5cbfSDavid du Colombier // Cputdate(cd, 0);
53380ee5cbfSDavid du Colombier // if (type & TFeffective)
53480ee5cbfSDavid du Colombier // Cputdate(cd, 0);
53580ee5cbfSDavid du Colombier }
53680ee5cbfSDavid du Colombier return 5+7*length;
53780ee5cbfSDavid du Colombier }
53880ee5cbfSDavid du Colombier
53980ee5cbfSDavid du Colombier
54092f2054cSDavid du Colombier #define NONPXMODES (DMDIR | DMAPPEND | DMEXCL | DMMOUNT)
54180ee5cbfSDavid du Colombier #define POSIXMODEMASK (0177777)
54280ee5cbfSDavid du Colombier #ifndef S_IFMT
54380ee5cbfSDavid du Colombier #define S_IFMT (0170000)
54480ee5cbfSDavid du Colombier #endif
54580ee5cbfSDavid du Colombier #ifndef S_IFDIR
54680ee5cbfSDavid du Colombier #define S_IFDIR (0040000)
54780ee5cbfSDavid du Colombier #endif
54880ee5cbfSDavid du Colombier #ifndef S_IFREG
54980ee5cbfSDavid du Colombier #define S_IFREG (0100000)
55080ee5cbfSDavid du Colombier #endif
55180ee5cbfSDavid du Colombier #ifndef S_IFLNK
55280ee5cbfSDavid du Colombier #define S_IFLNK (0120000)
55380ee5cbfSDavid du Colombier #endif
55480ee5cbfSDavid du Colombier #undef ISTYPE
55580ee5cbfSDavid du Colombier #define ISTYPE(mode, mask) (((mode) & S_IFMT) == (mask))
55680ee5cbfSDavid du Colombier #ifndef S_ISDIR
55780ee5cbfSDavid du Colombier #define S_ISDIR(mode) ISTYPE(mode, S_IFDIR)
55880ee5cbfSDavid du Colombier #endif
55980ee5cbfSDavid du Colombier #ifndef S_ISREG
56080ee5cbfSDavid du Colombier #define S_ISREG(mode) ISTYPE(mode, S_IREG)
56180ee5cbfSDavid du Colombier #endif
56280ee5cbfSDavid du Colombier #ifndef S_ISLNK
56380ee5cbfSDavid du Colombier #define S_ISLNK(mode) ISTYPE(mode, S_ILNK)
56480ee5cbfSDavid du Colombier #endif
56580ee5cbfSDavid du Colombier
56680ee5cbfSDavid du Colombier
56780ee5cbfSDavid du Colombier static long
mode(Direc * d,int dot)56880ee5cbfSDavid du Colombier mode(Direc *d, int dot)
56980ee5cbfSDavid du Colombier {
57080ee5cbfSDavid du Colombier long mode;
57180ee5cbfSDavid du Colombier
57280ee5cbfSDavid du Colombier if (!d)
57380ee5cbfSDavid du Colombier return 0;
57480ee5cbfSDavid du Colombier
57580ee5cbfSDavid du Colombier if ((dot != DTroot) && (dot != DTrootdot)) {
57680ee5cbfSDavid du Colombier mode = (d->mode & ~(NONPXMODES));
5779a747e4fSDavid du Colombier if (d->mode & DMDIR)
57880ee5cbfSDavid du Colombier mode |= S_IFDIR;
57980ee5cbfSDavid du Colombier else if (d->mode & CHLINK)
58080ee5cbfSDavid du Colombier mode |= S_IFLNK;
58180ee5cbfSDavid du Colombier else
58280ee5cbfSDavid du Colombier mode |= S_IFREG;
58380ee5cbfSDavid du Colombier } else
58480ee5cbfSDavid du Colombier mode = S_IFDIR | (0755);
58580ee5cbfSDavid du Colombier
58680ee5cbfSDavid du Colombier mode &= POSIXMODEMASK;
58780ee5cbfSDavid du Colombier
58880ee5cbfSDavid du Colombier /* Botch: not all POSIX types supported yet */
58980ee5cbfSDavid du Colombier assert(mode & (S_IFDIR|S_IFREG));
59080ee5cbfSDavid du Colombier
59180ee5cbfSDavid du Colombier chat("writing PX record mode field %ulo with dot %d and name \"%s\"\n", mode, dot, d->name);
59280ee5cbfSDavid du Colombier
59380ee5cbfSDavid du Colombier return mode;
59480ee5cbfSDavid du Colombier }
59580ee5cbfSDavid du Colombier
59680ee5cbfSDavid du Colombier static long
nlink(Direc * d)59780ee5cbfSDavid du Colombier nlink(Direc *d) /* Trump up the nlink field for POSIX compliance */
59880ee5cbfSDavid du Colombier {
59980ee5cbfSDavid du Colombier int i;
60080ee5cbfSDavid du Colombier long n;
60180ee5cbfSDavid du Colombier
60280ee5cbfSDavid du Colombier if (!d)
60380ee5cbfSDavid du Colombier return 0;
60480ee5cbfSDavid du Colombier
60580ee5cbfSDavid du Colombier n = 1;
6069a747e4fSDavid du Colombier if (d->mode & DMDIR) /* One for "." and one more for ".." */
60780ee5cbfSDavid du Colombier n++;
60880ee5cbfSDavid du Colombier
60980ee5cbfSDavid du Colombier for(i=0; i<d->nchild; i++)
6109a747e4fSDavid du Colombier if (d->child[i].mode & DMDIR)
61180ee5cbfSDavid du Colombier n++;
61280ee5cbfSDavid du Colombier
61380ee5cbfSDavid du Colombier return n;
61480ee5cbfSDavid du Colombier }
61580ee5cbfSDavid du Colombier
616