19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <bio.h>
49a747e4fSDavid du Colombier #include <flate.h>
59a747e4fSDavid du Colombier #include <mp.h>
69a747e4fSDavid du Colombier #include <libsec.h>
79a747e4fSDavid du Colombier #include "paqfs.h"
89a747e4fSDavid du Colombier
99a747e4fSDavid du Colombier enum {
109a747e4fSDavid du Colombier OffsetSize = 4, /* size of block offset */
119a747e4fSDavid du Colombier };
129a747e4fSDavid du Colombier
139a747e4fSDavid du Colombier void paqfs(char *root, char *label);
149a747e4fSDavid du Colombier PaqDir *paqFile(char *name, Dir *dir);
159a747e4fSDavid du Colombier PaqDir *paqDir(char *name, Dir *dir);
169a747e4fSDavid du Colombier PaqDir *paqDirAlloc(Dir *d, ulong offset);
179a747e4fSDavid du Colombier void paqDirFree(PaqDir *pd);
189a747e4fSDavid du Colombier void writeHeader(char *label);
199a747e4fSDavid du Colombier void writeTrailer(ulong root);
209a747e4fSDavid du Colombier ulong writeBlock(uchar *buf, int type);
219a747e4fSDavid du Colombier void usage(void);
229a747e4fSDavid du Colombier void outWrite(void *buf, int n);
239a747e4fSDavid du Colombier int paqDirSize(PaqDir *dir);
249a747e4fSDavid du Colombier void putDir(uchar *p, PaqDir *dir);
259a747e4fSDavid du Colombier void putHeader(uchar *p, PaqHeader *h);
269a747e4fSDavid du Colombier void putBlock(uchar *p, PaqBlock *h);
279a747e4fSDavid du Colombier void putTrailer(uchar *p, PaqTrailer *t);
289a747e4fSDavid du Colombier void putl(uchar *p, ulong v);
299a747e4fSDavid du Colombier void puts(uchar *p, int x);
309a747e4fSDavid du Colombier uchar *putstr(uchar *p, char *s);
319a747e4fSDavid du Colombier void *emallocz(int size);
329a747e4fSDavid du Colombier void warn(char *fmt, ...);
339a747e4fSDavid du Colombier
349a747e4fSDavid du Colombier int uflag=0; /* uncompressed */
359a747e4fSDavid du Colombier long blocksize = 4*1024;
369a747e4fSDavid du Colombier
379a747e4fSDavid du Colombier Biobuf *out;
389a747e4fSDavid du Colombier DigestState *outdg;
399a747e4fSDavid du Colombier
409a747e4fSDavid du Colombier void
main(int argc,char * argv[])419a747e4fSDavid du Colombier main(int argc, char *argv[])
429a747e4fSDavid du Colombier {
439a747e4fSDavid du Colombier char *s, *ss;
449a747e4fSDavid du Colombier char *outfile = nil;
459a747e4fSDavid du Colombier char *label = nil;
469a747e4fSDavid du Colombier char *file;
479a747e4fSDavid du Colombier
489a747e4fSDavid du Colombier ARGBEGIN {
499a747e4fSDavid du Colombier case 'u':
509a747e4fSDavid du Colombier uflag=1;
519a747e4fSDavid du Colombier break;
529a747e4fSDavid du Colombier case 'o':
539a747e4fSDavid du Colombier outfile = ARGF();
549a747e4fSDavid du Colombier break;
559a747e4fSDavid du Colombier case 'l':
569a747e4fSDavid du Colombier label = ARGF();
579a747e4fSDavid du Colombier if(label == nil)
589a747e4fSDavid du Colombier usage();
599a747e4fSDavid du Colombier break;
609a747e4fSDavid du Colombier case 'b':
619a747e4fSDavid du Colombier s = ARGF();
629a747e4fSDavid du Colombier if(s) {
639a747e4fSDavid du Colombier blocksize = strtoul(s, &ss, 0);
649a747e4fSDavid du Colombier if(s == ss)
659a747e4fSDavid du Colombier usage();
669a747e4fSDavid du Colombier if(*ss == 'k')
679a747e4fSDavid du Colombier blocksize *= 1024;
689a747e4fSDavid du Colombier }
699a747e4fSDavid du Colombier if(blocksize < MinBlockSize)
709a747e4fSDavid du Colombier sysfatal("blocksize too small: must be at lease %d", MinBlockSize);
719a747e4fSDavid du Colombier if(blocksize > MaxBlockSize)
729a747e4fSDavid du Colombier sysfatal("blocksize too large: must be no greater than %d", MaxBlockSize);
739a747e4fSDavid du Colombier break;
749a747e4fSDavid du Colombier } ARGEND
759a747e4fSDavid du Colombier
769a747e4fSDavid du Colombier if(outfile == nil) {
779a747e4fSDavid du Colombier out = emallocz(sizeof(Biobuf));
789a747e4fSDavid du Colombier Binit(out, 1, OWRITE);
799a747e4fSDavid du Colombier } else {
809a747e4fSDavid du Colombier out = Bopen(outfile, OWRITE|OTRUNC);
819a747e4fSDavid du Colombier if(out == nil)
829a747e4fSDavid du Colombier sysfatal("could not create file: %s: %r", outfile);
839a747e4fSDavid du Colombier }
849a747e4fSDavid du Colombier
859a747e4fSDavid du Colombier deflateinit();
869a747e4fSDavid du Colombier
879a747e4fSDavid du Colombier file = argv[0];
889a747e4fSDavid du Colombier if(file == nil)
899a747e4fSDavid du Colombier file = ".";
909a747e4fSDavid du Colombier
919a747e4fSDavid du Colombier if(label == nil) {
929a747e4fSDavid du Colombier if(strrchr(file, '/'))
939a747e4fSDavid du Colombier label = strrchr(file, '/') + 1;
949a747e4fSDavid du Colombier else
959a747e4fSDavid du Colombier label = file;
969a747e4fSDavid du Colombier }
979a747e4fSDavid du Colombier
989a747e4fSDavid du Colombier paqfs(file, label);
999a747e4fSDavid du Colombier
1009a747e4fSDavid du Colombier Bterm(out);
1019a747e4fSDavid du Colombier
1029a747e4fSDavid du Colombier exits(0);
1039a747e4fSDavid du Colombier }
1049a747e4fSDavid du Colombier
1059a747e4fSDavid du Colombier void
usage(void)1069a747e4fSDavid du Colombier usage(void)
1079a747e4fSDavid du Colombier {
1089a747e4fSDavid du Colombier fprint(2, "usage: %s [-u] [-b blocksize] -o output [root]\n", argv0);
1099a747e4fSDavid du Colombier exits("usage");
1109a747e4fSDavid du Colombier }
1119a747e4fSDavid du Colombier
1129a747e4fSDavid du Colombier void
paqfs(char * root,char * label)1139a747e4fSDavid du Colombier paqfs(char *root, char *label)
1149a747e4fSDavid du Colombier {
1159a747e4fSDavid du Colombier Dir *dir;
1169a747e4fSDavid du Colombier PaqDir *pd;
1179a747e4fSDavid du Colombier ulong offset;
1189a747e4fSDavid du Colombier uchar *buf;
1199a747e4fSDavid du Colombier
1209a747e4fSDavid du Colombier dir = dirstat(root);
1219a747e4fSDavid du Colombier if(dir == nil)
1229a747e4fSDavid du Colombier sysfatal("could not stat root: %s: %r", root);
1239a747e4fSDavid du Colombier writeHeader(label);
1249a747e4fSDavid du Colombier if(dir->mode & DMDIR)
1259a747e4fSDavid du Colombier pd = paqDir(root, dir);
1269a747e4fSDavid du Colombier else
1279a747e4fSDavid du Colombier pd = paqFile(root, dir);
1289a747e4fSDavid du Colombier buf = emallocz(blocksize);
1299a747e4fSDavid du Colombier putDir(buf, pd);
1309a747e4fSDavid du Colombier offset = writeBlock(buf, DirBlock);
1319a747e4fSDavid du Colombier writeTrailer(offset);
1329a747e4fSDavid du Colombier paqDirFree(pd);
1339a747e4fSDavid du Colombier free(dir);
1349a747e4fSDavid du Colombier }
1359a747e4fSDavid du Colombier
1369a747e4fSDavid du Colombier
1379a747e4fSDavid du Colombier PaqDir *
paqFile(char * name,Dir * dir)1389a747e4fSDavid du Colombier paqFile(char *name, Dir *dir)
1399a747e4fSDavid du Colombier {
1409a747e4fSDavid du Colombier int fd, n, nn, nb;
141*fe853e23SDavid du Colombier vlong tot;
1429a747e4fSDavid du Colombier uchar *block, *pointer;
1439a747e4fSDavid du Colombier ulong offset;
1449a747e4fSDavid du Colombier
1459a747e4fSDavid du Colombier fd = open(name, OREAD);
1469a747e4fSDavid du Colombier if(fd < 0) {
1479a747e4fSDavid du Colombier warn("could not open file: %s: %r", name);
1489a747e4fSDavid du Colombier return nil;
1499a747e4fSDavid du Colombier }
1509a747e4fSDavid du Colombier
1519a747e4fSDavid du Colombier block = emallocz(blocksize);
1529a747e4fSDavid du Colombier pointer = emallocz(blocksize);
1539a747e4fSDavid du Colombier nb = 0;
1549a747e4fSDavid du Colombier n = 0;
155*fe853e23SDavid du Colombier tot = 0;
1569a747e4fSDavid du Colombier for(;;) {
1579a747e4fSDavid du Colombier nn = read(fd, block+n, blocksize-n);
1589a747e4fSDavid du Colombier if(nn < 0) {
1599a747e4fSDavid du Colombier warn("read failed: %s: %r", name);
1609a747e4fSDavid du Colombier goto Err;
1619a747e4fSDavid du Colombier }
162*fe853e23SDavid du Colombier tot += nn;
1639a747e4fSDavid du Colombier if(nn == 0) {
1649a747e4fSDavid du Colombier if(n == 0)
1659a747e4fSDavid du Colombier break;
1669a747e4fSDavid du Colombier /* pad out last block */
1679a747e4fSDavid du Colombier memset(block+n, 0, blocksize-n);
1689a747e4fSDavid du Colombier nn = blocksize - n;
1699a747e4fSDavid du Colombier }
1709a747e4fSDavid du Colombier n += nn;
1719a747e4fSDavid du Colombier if(n < blocksize)
1729a747e4fSDavid du Colombier continue;
1739a747e4fSDavid du Colombier if(nb >= blocksize/OffsetSize) {
1743ff48bf5SDavid du Colombier warn("file too big for blocksize: %s", name);
1759a747e4fSDavid du Colombier goto Err;
1769a747e4fSDavid du Colombier }
1779a747e4fSDavid du Colombier offset = writeBlock(block, DataBlock);
1789a747e4fSDavid du Colombier putl(pointer+nb*OffsetSize, offset);
1799a747e4fSDavid du Colombier nb++;
1809a747e4fSDavid du Colombier n = 0;
1819a747e4fSDavid du Colombier }
1829a747e4fSDavid du Colombier
1839a747e4fSDavid du Colombier offset = writeBlock(pointer, PointerBlock);
1849a747e4fSDavid du Colombier
1859a747e4fSDavid du Colombier close(fd);
1869a747e4fSDavid du Colombier free(pointer);
1879a747e4fSDavid du Colombier free(block);
188*fe853e23SDavid du Colombier dir->length = tot;
1899a747e4fSDavid du Colombier return paqDirAlloc(dir, offset);
1909a747e4fSDavid du Colombier Err:
1919a747e4fSDavid du Colombier close(fd);
1929a747e4fSDavid du Colombier free(pointer);
1939a747e4fSDavid du Colombier free(block);
1949a747e4fSDavid du Colombier return nil;
1959a747e4fSDavid du Colombier }
1969a747e4fSDavid du Colombier
1979a747e4fSDavid du Colombier PaqDir *
paqDir(char * name,Dir * dir)1989a747e4fSDavid du Colombier paqDir(char *name, Dir *dir)
1999a747e4fSDavid du Colombier {
2009a747e4fSDavid du Colombier Dir *dirs, *p;
2019a747e4fSDavid du Colombier PaqDir *pd;
2029a747e4fSDavid du Colombier int i, n, nb, fd, ndir;
2039a747e4fSDavid du Colombier uchar *block, *pointer;
2049a747e4fSDavid du Colombier char *nname;
2059a747e4fSDavid du Colombier ulong offset;
2069a747e4fSDavid du Colombier
2079a747e4fSDavid du Colombier fd = open(name, OREAD);
2089a747e4fSDavid du Colombier if(fd < 0) {
2099a747e4fSDavid du Colombier warn("could not open directory: %s: %r", name);
2109a747e4fSDavid du Colombier return nil;
2119a747e4fSDavid du Colombier }
2129a747e4fSDavid du Colombier
2139a747e4fSDavid du Colombier ndir = dirreadall(fd, &dirs);
2149a747e4fSDavid du Colombier close(fd);
2159a747e4fSDavid du Colombier
2169a747e4fSDavid du Colombier if(ndir < 0) {
2179a747e4fSDavid du Colombier warn("could not read directory: %s: %r", name);
2189a747e4fSDavid du Colombier return nil;
2199a747e4fSDavid du Colombier }
2209a747e4fSDavid du Colombier
2219a747e4fSDavid du Colombier block = emallocz(blocksize);
2229a747e4fSDavid du Colombier pointer = emallocz(blocksize);
2239a747e4fSDavid du Colombier nb = 0;
2249a747e4fSDavid du Colombier n = 0;
2259a747e4fSDavid du Colombier nname = nil;
2269a747e4fSDavid du Colombier pd = nil;
2279a747e4fSDavid du Colombier
2289a747e4fSDavid du Colombier for(i=0; i<ndir; i++) {
2299a747e4fSDavid du Colombier p = dirs + i;
2309a747e4fSDavid du Colombier free(nname);
2319a747e4fSDavid du Colombier nname = emallocz(strlen(name) + strlen(p->name) + 2);
2329a747e4fSDavid du Colombier sprint(nname, "%s/%s", name, p->name);
2339a747e4fSDavid du Colombier if(p->mode & DMDIR)
2349a747e4fSDavid du Colombier pd = paqDir(nname, p);
2359a747e4fSDavid du Colombier else
2369a747e4fSDavid du Colombier pd = paqFile(nname, p);
2379a747e4fSDavid du Colombier if(pd == nil)
2389a747e4fSDavid du Colombier continue;
2399a747e4fSDavid du Colombier
2409a747e4fSDavid du Colombier if(n+paqDirSize(pd) >= blocksize) {
2419a747e4fSDavid du Colombier
2429a747e4fSDavid du Colombier /* zero fill the block */
2439a747e4fSDavid du Colombier memset(block+n, 0, blocksize-n);
2449a747e4fSDavid du Colombier offset = writeBlock(block, DirBlock);
2459a747e4fSDavid du Colombier n = 0;
2469a747e4fSDavid du Colombier if(nb >= blocksize/OffsetSize) {
2479a747e4fSDavid du Colombier warn("directory too big for blocksize: %s", nname);
2489a747e4fSDavid du Colombier goto Err;
2499a747e4fSDavid du Colombier }
2509a747e4fSDavid du Colombier putl(pointer+nb*OffsetSize, offset);
2519a747e4fSDavid du Colombier nb++;
2529a747e4fSDavid du Colombier }
2539a747e4fSDavid du Colombier if(n+paqDirSize(pd) >= blocksize) {
2549a747e4fSDavid du Colombier warn("directory entry does not fit in a block: %s", nname);
2559a747e4fSDavid du Colombier paqDirFree(pd);
2569a747e4fSDavid du Colombier continue;
2579a747e4fSDavid du Colombier }
2589a747e4fSDavid du Colombier putDir(block+n, pd);
2599a747e4fSDavid du Colombier n += paqDirSize(pd);
2609a747e4fSDavid du Colombier paqDirFree(pd);
2619a747e4fSDavid du Colombier pd = nil;
2629a747e4fSDavid du Colombier }
2639a747e4fSDavid du Colombier
2649a747e4fSDavid du Colombier if(n > 0) {
2659a747e4fSDavid du Colombier /* zero fill the block */
2669a747e4fSDavid du Colombier memset(block+n, 0, blocksize-n);
2679a747e4fSDavid du Colombier offset = writeBlock(block, DirBlock);
2689a747e4fSDavid du Colombier if(nb >= blocksize/OffsetSize) {
2699a747e4fSDavid du Colombier warn("directory too big for blocksize: %s", nname);
2709a747e4fSDavid du Colombier goto Err;
2719a747e4fSDavid du Colombier }
2729a747e4fSDavid du Colombier putl(pointer+nb*OffsetSize, offset);
2739a747e4fSDavid du Colombier }
2749a747e4fSDavid du Colombier offset = writeBlock(pointer, PointerBlock);
2759a747e4fSDavid du Colombier
2769a747e4fSDavid du Colombier free(nname);
2779a747e4fSDavid du Colombier free(dirs);
2789a747e4fSDavid du Colombier paqDirFree(pd);
2799a747e4fSDavid du Colombier free(block);
2809a747e4fSDavid du Colombier free(pointer);
2819a747e4fSDavid du Colombier return paqDirAlloc(dir, offset);
2829a747e4fSDavid du Colombier Err:
2839a747e4fSDavid du Colombier free(nname);
2849a747e4fSDavid du Colombier free(dirs);
2859a747e4fSDavid du Colombier paqDirFree(pd);
2869a747e4fSDavid du Colombier free(block);
2879a747e4fSDavid du Colombier free(pointer);
2889a747e4fSDavid du Colombier return nil;
2899a747e4fSDavid du Colombier }
2909a747e4fSDavid du Colombier
2919a747e4fSDavid du Colombier PaqDir *
paqDirAlloc(Dir * dir,ulong offset)2929a747e4fSDavid du Colombier paqDirAlloc(Dir *dir, ulong offset)
2939a747e4fSDavid du Colombier {
2949a747e4fSDavid du Colombier PaqDir *pd;
2959a747e4fSDavid du Colombier static ulong qid = 1;
2969a747e4fSDavid du Colombier
2979a747e4fSDavid du Colombier pd = emallocz(sizeof(PaqDir));
2989a747e4fSDavid du Colombier
2999a747e4fSDavid du Colombier pd->name = strdup(dir->name);
3009a747e4fSDavid du Colombier pd->qid = qid++;
3019a747e4fSDavid du Colombier pd->mode = dir->mode & (DMDIR|DMAPPEND|0777);
3029a747e4fSDavid du Colombier pd->mtime = dir->mtime;
3039a747e4fSDavid du Colombier pd->length = dir->length;
3049a747e4fSDavid du Colombier pd->uid = strdup(dir->uid);
3059a747e4fSDavid du Colombier pd->gid = strdup(dir->gid);
3069a747e4fSDavid du Colombier pd->offset = offset;
3079a747e4fSDavid du Colombier
3089a747e4fSDavid du Colombier return pd;
3099a747e4fSDavid du Colombier }
3109a747e4fSDavid du Colombier
3119a747e4fSDavid du Colombier void
paqDirFree(PaqDir * pd)3129a747e4fSDavid du Colombier paqDirFree(PaqDir *pd)
3139a747e4fSDavid du Colombier {
3149a747e4fSDavid du Colombier if(pd == nil)
3159a747e4fSDavid du Colombier return;
3169a747e4fSDavid du Colombier free(pd->name);
3179a747e4fSDavid du Colombier free(pd->uid);
3189a747e4fSDavid du Colombier free(pd->gid);
3199a747e4fSDavid du Colombier free(pd);
3209a747e4fSDavid du Colombier }
3219a747e4fSDavid du Colombier
3229a747e4fSDavid du Colombier
3239a747e4fSDavid du Colombier void
writeHeader(char * label)3249a747e4fSDavid du Colombier writeHeader(char *label)
3259a747e4fSDavid du Colombier {
3269a747e4fSDavid du Colombier PaqHeader hdr;
3279a747e4fSDavid du Colombier uchar buf[HeaderSize];
3289a747e4fSDavid du Colombier
3299a747e4fSDavid du Colombier memset(&hdr, 0, sizeof(hdr));
3309a747e4fSDavid du Colombier hdr.magic = HeaderMagic;
3319a747e4fSDavid du Colombier hdr.version = Version;
3329a747e4fSDavid du Colombier hdr.blocksize = blocksize;
3339a747e4fSDavid du Colombier hdr.time = time(nil);
3349a747e4fSDavid du Colombier strncpy(hdr.label, label, sizeof(hdr.label));
3359a747e4fSDavid du Colombier hdr.label[sizeof(hdr.label)-1] = 0;
3369a747e4fSDavid du Colombier putHeader(buf, &hdr);
3379a747e4fSDavid du Colombier outWrite(buf, sizeof(buf));
3389a747e4fSDavid du Colombier }
3399a747e4fSDavid du Colombier
3409a747e4fSDavid du Colombier void
writeTrailer(ulong root)3419a747e4fSDavid du Colombier writeTrailer(ulong root)
3429a747e4fSDavid du Colombier {
3439a747e4fSDavid du Colombier PaqTrailer tlr;
3449a747e4fSDavid du Colombier uchar buf[TrailerSize];
3459a747e4fSDavid du Colombier
3469a747e4fSDavid du Colombier memset(&tlr, 0, sizeof(tlr));
3479a747e4fSDavid du Colombier tlr.magic = TrailerMagic;
3489a747e4fSDavid du Colombier tlr.root = root;
3499a747e4fSDavid du Colombier putTrailer(buf, &tlr);
3509a747e4fSDavid du Colombier outWrite(buf, sizeof(buf));
3519a747e4fSDavid du Colombier }
3529a747e4fSDavid du Colombier
3539a747e4fSDavid du Colombier ulong
writeBlock(uchar * b,int type)3549a747e4fSDavid du Colombier writeBlock(uchar *b, int type)
3559a747e4fSDavid du Colombier {
3569a747e4fSDavid du Colombier uchar *cb, *ob;
3579a747e4fSDavid du Colombier int n;
3589a747e4fSDavid du Colombier PaqBlock bh;
3599a747e4fSDavid du Colombier uchar buf[BlockSize];
3609a747e4fSDavid du Colombier ulong offset;
3619a747e4fSDavid du Colombier
3629a747e4fSDavid du Colombier offset = Boffset(out);
3639a747e4fSDavid du Colombier
3649a747e4fSDavid du Colombier bh.magic = BlockMagic;
3659a747e4fSDavid du Colombier bh.size = blocksize;
3669a747e4fSDavid du Colombier bh.type = type;
3679a747e4fSDavid du Colombier bh.encoding = NoEnc;
3689a747e4fSDavid du Colombier bh.adler32 = adler32(0, b, blocksize);
3699a747e4fSDavid du Colombier ob = b;
3709a747e4fSDavid du Colombier
3719a747e4fSDavid du Colombier if(!uflag) {
3729a747e4fSDavid du Colombier cb = emallocz(blocksize);
3739a747e4fSDavid du Colombier n = deflateblock(cb, blocksize, b, blocksize, 6, 0);
3749a747e4fSDavid du Colombier if(n > 0 && n < blocksize) {
3759a747e4fSDavid du Colombier bh.encoding = DeflateEnc;
3769a747e4fSDavid du Colombier bh.size = n;
3779a747e4fSDavid du Colombier ob = cb;
3789a747e4fSDavid du Colombier }
3799a747e4fSDavid du Colombier }
3809a747e4fSDavid du Colombier
3819a747e4fSDavid du Colombier putBlock(buf, &bh);
3829a747e4fSDavid du Colombier outWrite(buf, sizeof(buf));
3839a747e4fSDavid du Colombier outWrite(ob, bh.size);
3849a747e4fSDavid du Colombier
3859a747e4fSDavid du Colombier if(ob != b)
3869a747e4fSDavid du Colombier free(ob);
3879a747e4fSDavid du Colombier return offset;
3889a747e4fSDavid du Colombier }
3899a747e4fSDavid du Colombier
3909a747e4fSDavid du Colombier
3919a747e4fSDavid du Colombier void
outWrite(void * buf,int n)3929a747e4fSDavid du Colombier outWrite(void *buf, int n)
3939a747e4fSDavid du Colombier {
3949a747e4fSDavid du Colombier if(Bwrite(out, buf, n) < n)
3959a747e4fSDavid du Colombier sysfatal("write failed: %r");
3969a747e4fSDavid du Colombier outdg = sha1((uchar*)buf, n, nil, outdg);
3979a747e4fSDavid du Colombier }
3989a747e4fSDavid du Colombier
3999a747e4fSDavid du Colombier int
paqDirSize(PaqDir * d)4009a747e4fSDavid du Colombier paqDirSize(PaqDir *d)
4019a747e4fSDavid du Colombier {
4029a747e4fSDavid du Colombier return MinDirSize + strlen(d->name) + strlen(d->uid) + strlen(d->gid);
4039a747e4fSDavid du Colombier }
4049a747e4fSDavid du Colombier
4059a747e4fSDavid du Colombier void
putHeader(uchar * p,PaqHeader * h)4069a747e4fSDavid du Colombier putHeader(uchar *p, PaqHeader *h)
4079a747e4fSDavid du Colombier {
408*fe853e23SDavid du Colombier if(h->blocksize < 65536){
4099a747e4fSDavid du Colombier putl(p, h->magic);
4109a747e4fSDavid du Colombier puts(p+4, h->version);
4119a747e4fSDavid du Colombier puts(p+6, h->blocksize);
412*fe853e23SDavid du Colombier }else{
413*fe853e23SDavid du Colombier assert(h->magic == HeaderMagic);
414*fe853e23SDavid du Colombier puts(p, BigHeaderMagic);
415*fe853e23SDavid du Colombier puts(p+2, h->version);
416*fe853e23SDavid du Colombier putl(p+4, h->blocksize);
417*fe853e23SDavid du Colombier }
4189a747e4fSDavid du Colombier putl(p+8, h->time);
4199a747e4fSDavid du Colombier memmove(p+12, h->label, sizeof(h->label));
4209a747e4fSDavid du Colombier }
4219a747e4fSDavid du Colombier
4229a747e4fSDavid du Colombier void
putTrailer(uchar * p,PaqTrailer * h)4239a747e4fSDavid du Colombier putTrailer(uchar *p, PaqTrailer *h)
4249a747e4fSDavid du Colombier {
4259a747e4fSDavid du Colombier putl(p, h->magic);
4269a747e4fSDavid du Colombier putl(p+4, h->root);
4279a747e4fSDavid du Colombier outdg = sha1(p, 8, p+8, outdg);
4289a747e4fSDavid du Colombier }
4299a747e4fSDavid du Colombier
4309a747e4fSDavid du Colombier void
putBlock(uchar * p,PaqBlock * b)4319a747e4fSDavid du Colombier putBlock(uchar *p, PaqBlock *b)
4329a747e4fSDavid du Colombier {
433*fe853e23SDavid du Colombier if(b->size < 65536){
4349a747e4fSDavid du Colombier putl(p, b->magic);
4359a747e4fSDavid du Colombier puts(p+4, b->size);
436*fe853e23SDavid du Colombier }else{
437*fe853e23SDavid du Colombier assert(b->magic == BlockMagic);
438*fe853e23SDavid du Colombier puts(p, BigBlockMagic);
439*fe853e23SDavid du Colombier putl(p+2, b->size);
440*fe853e23SDavid du Colombier }
4419a747e4fSDavid du Colombier p[6] = b->type;
4429a747e4fSDavid du Colombier p[7] = b->encoding;
4439a747e4fSDavid du Colombier putl(p+8, b->adler32);
4449a747e4fSDavid du Colombier }
4459a747e4fSDavid du Colombier
4469a747e4fSDavid du Colombier void
putDir(uchar * p,PaqDir * d)4479a747e4fSDavid du Colombier putDir(uchar *p, PaqDir *d)
4489a747e4fSDavid du Colombier {
4499a747e4fSDavid du Colombier uchar *q;
4509a747e4fSDavid du Colombier
4519a747e4fSDavid du Colombier puts(p, paqDirSize(d));
4529a747e4fSDavid du Colombier putl(p+2, d->qid);
4539a747e4fSDavid du Colombier putl(p+6, d->mode);
4549a747e4fSDavid du Colombier putl(p+10, d->mtime);
4559a747e4fSDavid du Colombier putl(p+14, d->length);
4569a747e4fSDavid du Colombier putl(p+18, d->offset);
4579a747e4fSDavid du Colombier q = putstr(p+22, d->name);
4589a747e4fSDavid du Colombier q = putstr(q, d->uid);
4599a747e4fSDavid du Colombier q = putstr(q, d->gid);
4609a747e4fSDavid du Colombier assert(q-p == paqDirSize(d));
4619a747e4fSDavid du Colombier }
4629a747e4fSDavid du Colombier
4639a747e4fSDavid du Colombier void
putl(uchar * p,ulong v)4649a747e4fSDavid du Colombier putl(uchar *p, ulong v)
4659a747e4fSDavid du Colombier {
4669a747e4fSDavid du Colombier p[0] = v>>24;
4679a747e4fSDavid du Colombier p[1] = v>>16;
4689a747e4fSDavid du Colombier p[2] = v>>8;
4699a747e4fSDavid du Colombier p[3] = v;
4709a747e4fSDavid du Colombier }
4719a747e4fSDavid du Colombier
4729a747e4fSDavid du Colombier void
puts(uchar * p,int v)4739a747e4fSDavid du Colombier puts(uchar *p, int v)
4749a747e4fSDavid du Colombier {
4759a747e4fSDavid du Colombier assert(v < (1<<16));
4769a747e4fSDavid du Colombier p[0] = v>>8;
4779a747e4fSDavid du Colombier p[1] = v;
4789a747e4fSDavid du Colombier }
4799a747e4fSDavid du Colombier
4809a747e4fSDavid du Colombier uchar *
putstr(uchar * p,char * s)4819a747e4fSDavid du Colombier putstr(uchar *p, char *s)
4829a747e4fSDavid du Colombier {
4839a747e4fSDavid du Colombier int n = strlen(s);
4849a747e4fSDavid du Colombier puts(p, n+2);
4859a747e4fSDavid du Colombier memmove(p+2, s, n);
4869a747e4fSDavid du Colombier return p+2+n;
4879a747e4fSDavid du Colombier }
4889a747e4fSDavid du Colombier
4899a747e4fSDavid du Colombier
4909a747e4fSDavid du Colombier void *
emallocz(int size)4919a747e4fSDavid du Colombier emallocz(int size)
4929a747e4fSDavid du Colombier {
4939a747e4fSDavid du Colombier void *p;
4949a747e4fSDavid du Colombier
4959a747e4fSDavid du Colombier p = malloc(size);
4969a747e4fSDavid du Colombier if(p == nil)
4979a747e4fSDavid du Colombier sysfatal("malloc failed");
4989a747e4fSDavid du Colombier memset(p, 0, size);
4999a747e4fSDavid du Colombier return p;
5009a747e4fSDavid du Colombier }
5019a747e4fSDavid du Colombier
5029a747e4fSDavid du Colombier void
warn(char * fmt,...)5039a747e4fSDavid du Colombier warn(char *fmt, ...)
5049a747e4fSDavid du Colombier {
5059a747e4fSDavid du Colombier char buf[1024];
5069a747e4fSDavid du Colombier va_list arg;
5079a747e4fSDavid du Colombier
5089a747e4fSDavid du Colombier va_start(arg, fmt);
5099a747e4fSDavid du Colombier vseprint(buf, buf+sizeof(buf), fmt, arg);
5109a747e4fSDavid du Colombier va_end(arg);
5119a747e4fSDavid du Colombier fprint(2, "%s: %s\n", argv0, buf);
5129a747e4fSDavid du Colombier }
513