2005-01-14 18:46:35 +00:00
|
|
|
#include <u.h>
|
2004-03-21 04:33:13 +00:00
|
|
|
#include <sys/stat.h>
|
2004-03-15 01:56:49 +00:00
|
|
|
#include "stdinc.h"
|
|
|
|
|
#include "vac.h"
|
|
|
|
|
#include "dat.h"
|
|
|
|
|
#include "fns.h"
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-21 04:33:13 +00:00
|
|
|
int mainstacksize = 128*1024;
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
typedef struct Sink Sink;
|
|
|
|
|
typedef struct MetaSink MetaSink;
|
|
|
|
|
typedef struct DirSink DirSink;
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
struct Sink {
|
|
|
|
|
VtConn *z;
|
|
|
|
|
VtEntry dir;
|
|
|
|
|
uchar *buf;
|
|
|
|
|
uchar *pbuf[VtPointerDepth+1];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct DirSink {
|
|
|
|
|
Sink *sink;
|
|
|
|
|
MetaSink *msink;
|
|
|
|
|
ulong nentry;
|
|
|
|
|
uchar *buf;
|
|
|
|
|
uchar *p; /* current pointer */
|
|
|
|
|
uchar *ep; /* end pointer */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct MetaSink {
|
|
|
|
|
Sink *sink;
|
|
|
|
|
uchar *buf;
|
|
|
|
|
int maxindex;
|
|
|
|
|
int nindex;
|
|
|
|
|
uchar *rp; /* start of current record */
|
|
|
|
|
uchar *p; /* current pointer */
|
|
|
|
|
uchar *ep; /* end pointer */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void usage(void);
|
|
|
|
|
static int strpcmp(const void*, const void*);
|
|
|
|
|
static void warn(char *fmt, ...);
|
|
|
|
|
static void cleanup(void);
|
|
|
|
|
static u64int unittoull(char *s);
|
|
|
|
|
static void vac(VtConn *z, char *argv[]);
|
|
|
|
|
static void vacfile(DirSink *dsink, char *lname, char *sname, VacFile*);
|
|
|
|
|
static void vacstdin(DirSink *dsink, char *name, VacFile *vf);
|
|
|
|
|
static void vacdata(DirSink *dsink, int fd, char *lname, VacFile*, Dir*);
|
|
|
|
|
static void vacdir(DirSink *dsink, int fd, char *lname, char *sname, VacFile*);
|
|
|
|
|
static int vacmerge(DirSink *dsink, char *lname, char *sname);
|
2005-09-13 02:00:06 +00:00
|
|
|
static int vacspecial(DirSink *dsink, Dir *dir, char *lname, char *sname, VacFile *vf);
|
2004-03-15 01:56:49 +00:00
|
|
|
Sink *sinkalloc(VtConn *z, int psize, int dsize);
|
|
|
|
|
void sinkwrite(Sink *k, uchar *data, int n);
|
|
|
|
|
void sinkwritescore(Sink *k, uchar *score, int n);
|
|
|
|
|
void sinkclose(Sink *k);
|
|
|
|
|
void sinkfree(Sink *k);
|
|
|
|
|
|
|
|
|
|
DirSink *dirsinkalloc(VtConn *z, int psize, int dsize);
|
|
|
|
|
void dirsinkwrite(DirSink *k, VtEntry*);
|
|
|
|
|
void dirsinkwritesink(DirSink *k, Sink*);
|
|
|
|
|
int dirsinkwritefile(DirSink *k, VacFile *vf);
|
|
|
|
|
void dirsinkclose(DirSink *k);
|
|
|
|
|
void dirsinkfree(DirSink *k);
|
|
|
|
|
|
|
|
|
|
MetaSink *metasinkalloc(VtConn *z, int psize, int dsize);
|
|
|
|
|
void metasinkputc(MetaSink *k, int c);
|
|
|
|
|
void metasinkputstring(MetaSink *k, char *s);
|
|
|
|
|
void metasinkputuint32(MetaSink *k, ulong x);
|
|
|
|
|
void metasinkputuint64(MetaSink *k, uvlong x);
|
|
|
|
|
void metasinkwrite(MetaSink *k, uchar *data, int n);
|
|
|
|
|
void metasinkwritedir(MetaSink *ms, VacDir *vd);
|
|
|
|
|
void metasinkeor(MetaSink *k);
|
|
|
|
|
void metasinkclose(MetaSink *k);
|
|
|
|
|
void metasinkfree(MetaSink *k);
|
|
|
|
|
void plan9tovacdir(VacDir*, Dir*, ulong entry, uvlong qid);
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
Version = 8,
|
|
|
|
|
BlockSize = 8*1024,
|
|
|
|
|
MaxExclude = 1000,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct {
|
|
|
|
|
ulong file;
|
|
|
|
|
ulong sfile;
|
|
|
|
|
ulong data;
|
|
|
|
|
ulong sdata;
|
|
|
|
|
ulong skip;
|
|
|
|
|
ulong meta;
|
|
|
|
|
} stats;
|
|
|
|
|
|
|
|
|
|
int bsize = BlockSize;
|
|
|
|
|
int maxbsize;
|
|
|
|
|
char *oname, *dfile;
|
|
|
|
|
int verbose;
|
|
|
|
|
uvlong fileid = 1;
|
|
|
|
|
int qdiff;
|
|
|
|
|
char *exclude[MaxExclude];
|
|
|
|
|
int nexclude;
|
|
|
|
|
int nowrite;
|
|
|
|
|
int merge;
|
|
|
|
|
char *isi;
|
|
|
|
|
|
|
|
|
|
static void
|
2003-11-23 17:55:34 +00:00
|
|
|
usage(void)
|
|
|
|
|
{
|
2004-03-15 01:56:49 +00:00
|
|
|
fprint(2, "usage: %s [-amqsv] [-h host] [-d vacfile] [-b blocksize] [-i name] [-e exclude] [-f vacfile] file ... \n", argv0);
|
2005-01-17 21:29:00 +00:00
|
|
|
threadexitsall("usage");
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
threadmain(int argc, char *argv[])
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
2004-03-15 01:56:49 +00:00
|
|
|
VtConn *z;
|
|
|
|
|
char *p;
|
|
|
|
|
char *host = nil;
|
|
|
|
|
int statsflag = 0;
|
|
|
|
|
|
|
|
|
|
atexit(cleanup);
|
|
|
|
|
|
2003-11-23 17:55:34 +00:00
|
|
|
ARGBEGIN{
|
|
|
|
|
default:
|
|
|
|
|
usage();
|
|
|
|
|
case 'b':
|
2004-03-15 01:56:49 +00:00
|
|
|
p = ARGF();
|
|
|
|
|
if(p == 0)
|
|
|
|
|
usage();
|
|
|
|
|
bsize = unittoull(p);
|
|
|
|
|
if(bsize == ~0)
|
|
|
|
|
usage();
|
|
|
|
|
break;
|
|
|
|
|
case 'd':
|
|
|
|
|
dfile = ARGF();
|
|
|
|
|
if(dfile == nil)
|
|
|
|
|
usage();
|
|
|
|
|
break;
|
|
|
|
|
case 'e':
|
|
|
|
|
if(nexclude >= MaxExclude)
|
|
|
|
|
sysfatal("too many exclusions\n");
|
|
|
|
|
exclude[nexclude] = ARGF();
|
|
|
|
|
if(exclude[nexclude] == nil)
|
|
|
|
|
usage();
|
|
|
|
|
nexclude++;
|
|
|
|
|
break;
|
|
|
|
|
case 'f':
|
|
|
|
|
oname = ARGF();
|
|
|
|
|
if(oname == 0)
|
|
|
|
|
usage();
|
2003-11-23 17:55:34 +00:00
|
|
|
break;
|
|
|
|
|
case 'h':
|
2004-03-15 01:56:49 +00:00
|
|
|
host = ARGF();
|
|
|
|
|
if(host == nil)
|
|
|
|
|
usage();
|
|
|
|
|
break;
|
|
|
|
|
case 'i':
|
|
|
|
|
isi = ARGF();
|
|
|
|
|
if(isi == nil)
|
|
|
|
|
usage();
|
|
|
|
|
break;
|
|
|
|
|
case 'n':
|
|
|
|
|
nowrite++;
|
|
|
|
|
break;
|
|
|
|
|
case 'm':
|
|
|
|
|
merge++;
|
|
|
|
|
break;
|
|
|
|
|
case 'q':
|
|
|
|
|
qdiff++;
|
2003-11-23 17:55:34 +00:00
|
|
|
break;
|
2004-03-15 01:56:49 +00:00
|
|
|
case 's':
|
|
|
|
|
statsflag++;
|
|
|
|
|
break;
|
|
|
|
|
case 'v':
|
|
|
|
|
verbose++;
|
|
|
|
|
break;
|
|
|
|
|
}ARGEND;
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-21 04:33:13 +00:00
|
|
|
if(argc == 0)
|
|
|
|
|
usage();
|
|
|
|
|
|
2003-11-23 17:55:34 +00:00
|
|
|
if(bsize < 512)
|
|
|
|
|
bsize = 512;
|
|
|
|
|
if(bsize > VtMaxLumpSize)
|
|
|
|
|
bsize = VtMaxLumpSize;
|
|
|
|
|
maxbsize = bsize;
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
fmtinstall('V', vtscorefmt);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
z = vtdial(host);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(z == nil)
|
2004-03-15 01:56:49 +00:00
|
|
|
sysfatal("could not connect to server: %r");
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
if(vtconnect(z) < 0)
|
|
|
|
|
sysfatal("vtconnect: %r");
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
qsort(exclude, nexclude, sizeof(char*), strpcmp);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
vac(z, argv);
|
2004-03-15 01:56:49 +00:00
|
|
|
|
|
|
|
|
if(vtsync(z) < 0)
|
2004-12-27 21:05:39 +00:00
|
|
|
fprint(2, "warning: could not ask server to flush pending writes: %r\n");
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
if(statsflag)
|
2003-11-23 17:55:34 +00:00
|
|
|
fprint(2, "files %ld:%ld data %ld:%ld:%ld meta %ld\n", stats.file, stats.sfile,
|
|
|
|
|
stats.data, stats.skip, stats.sdata, stats.meta);
|
|
|
|
|
//packetStats();
|
2004-03-15 01:56:49 +00:00
|
|
|
vthangup(z);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
threadexitsall(0);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
2004-03-15 01:56:49 +00:00
|
|
|
strpcmp(const void *p0, const void *p1)
|
|
|
|
|
{
|
|
|
|
|
return strcmp(*(char**)p0, *(char**)p1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
vacwrite(VtConn *z, uchar score[VtScoreSize], int type, uchar *buf, int n)
|
|
|
|
|
{
|
|
|
|
|
assert(n > 0);
|
|
|
|
|
if(nowrite){
|
|
|
|
|
sha1(buf, n, score, nil);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return vtwrite(z, score, type, buf, n);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char*
|
|
|
|
|
lastelem(char *oname)
|
|
|
|
|
{
|
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
|
|
if(oname == nil)
|
|
|
|
|
abort();
|
|
|
|
|
if((p = strrchr(oname, '/')) == nil)
|
|
|
|
|
return oname;
|
|
|
|
|
return p+1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
vac(VtConn *z, char *argv[])
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
DirSink *dsink, *ds;
|
|
|
|
|
MetaSink *ms;
|
|
|
|
|
VtRoot root;
|
|
|
|
|
uchar score[VtScoreSize], buf[VtRootSize];
|
|
|
|
|
char cwd[2048];
|
2004-03-15 01:56:49 +00:00
|
|
|
int cd;
|
2003-11-23 17:55:34 +00:00
|
|
|
char *cp2, *cp;
|
2004-03-15 01:56:49 +00:00
|
|
|
VacFs *fs;
|
2003-11-23 17:55:34 +00:00
|
|
|
VacFile *vff;
|
|
|
|
|
int fd;
|
|
|
|
|
Dir *dir;
|
|
|
|
|
VacDir vd;
|
|
|
|
|
|
|
|
|
|
if(getwd(cwd, sizeof(cwd)) == 0)
|
|
|
|
|
sysfatal("can't find current directory: %r\n");
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
dsink = dirsinkalloc(z, bsize, bsize);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
fs = nil;
|
|
|
|
|
if(dfile != nil) {
|
2004-03-15 01:56:49 +00:00
|
|
|
fs = vacfsopen(z, dfile, VtOREAD, 1000);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(fs == nil)
|
2004-03-15 01:56:49 +00:00
|
|
|
fprint(2, "could not open diff: %s: %r\n", dfile);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(oname != nil) {
|
|
|
|
|
fd = create(oname, OWRITE, 0666);
|
|
|
|
|
if(fd < 0)
|
|
|
|
|
sysfatal("could not create file: %s: %r", oname);
|
|
|
|
|
} else
|
|
|
|
|
fd = 1;
|
|
|
|
|
|
|
|
|
|
dir = dirfstat(fd);
|
|
|
|
|
if(dir == nil)
|
|
|
|
|
sysfatal("dirfstat failed: %r");
|
2004-03-15 01:56:49 +00:00
|
|
|
if(oname)
|
|
|
|
|
dir->name = lastelem(oname);
|
|
|
|
|
else
|
|
|
|
|
dir->name = "stdin";
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
for(; *argv; argv++) {
|
|
|
|
|
cp2 = *argv;
|
|
|
|
|
cd = 0;
|
|
|
|
|
for (cp = *argv; *cp; cp++)
|
|
|
|
|
if (*cp == '/')
|
|
|
|
|
cp2 = cp;
|
|
|
|
|
if (cp2 != *argv) {
|
|
|
|
|
*cp2 = '\0';
|
|
|
|
|
chdir(*argv);
|
|
|
|
|
*cp2 = '/';
|
|
|
|
|
cp2++;
|
|
|
|
|
cd = 1;
|
|
|
|
|
}
|
|
|
|
|
vff = nil;
|
|
|
|
|
if(fs)
|
2004-03-15 01:56:49 +00:00
|
|
|
vff = vacfileopen(fs, cp2);
|
|
|
|
|
vacfile(dsink, argv[0], cp2, vff);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(vff)
|
2004-03-15 01:56:49 +00:00
|
|
|
vacfiledecref(vff);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(cd && chdir(cwd) < 0)
|
|
|
|
|
sysfatal("can't cd back to %s: %r\n", cwd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(isi) {
|
|
|
|
|
vff = nil;
|
|
|
|
|
if(fs)
|
2004-03-15 01:56:49 +00:00
|
|
|
vff = vacfileopen(fs, isi);
|
|
|
|
|
vacstdin(dsink, isi, vff);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(vff)
|
2004-03-15 01:56:49 +00:00
|
|
|
vacfiledecref(vff);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
dirsinkclose(dsink);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
/* build meta information for the root */
|
2004-03-15 01:56:49 +00:00
|
|
|
ms = metasinkalloc(z, bsize, bsize);
|
2003-11-23 17:55:34 +00:00
|
|
|
/* fake into a directory */
|
2005-07-24 20:15:44 +00:00
|
|
|
dir->mode = DMDIR|0555;
|
2003-11-23 17:55:34 +00:00
|
|
|
dir->qid.type |= QTDIR;
|
2004-03-15 01:56:49 +00:00
|
|
|
plan9tovacdir(&vd, dir, 0, fileid++);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(strcmp(vd.elem, "/") == 0){
|
2004-03-15 01:56:49 +00:00
|
|
|
vtfree(vd.elem);
|
|
|
|
|
vd.elem = vtstrdup("root");
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkwritedir(ms, &vd);
|
|
|
|
|
vdcleanup(&vd);
|
|
|
|
|
metasinkclose(ms);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
ds = dirsinkalloc(z, bsize, bsize);
|
|
|
|
|
dirsinkwritesink(ds, dsink->sink);
|
|
|
|
|
dirsinkwritesink(ds, dsink->msink->sink);
|
|
|
|
|
dirsinkwritesink(ds, ms->sink);
|
|
|
|
|
dirsinkclose(ds);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
memset(&root, 0, sizeof(root));
|
|
|
|
|
strncpy(root.name, dir->name, sizeof(root.name));
|
|
|
|
|
root.name[sizeof(root.name)-1] = 0;
|
|
|
|
|
free(dir);
|
|
|
|
|
sprint(root.type, "vac");
|
|
|
|
|
memmove(root.score, ds->sink->dir.score, VtScoreSize);
|
2004-03-15 01:56:49 +00:00
|
|
|
root.blocksize = maxbsize;
|
2003-11-23 17:55:34 +00:00
|
|
|
if(fs != nil)
|
2004-03-15 01:56:49 +00:00
|
|
|
vacfsgetscore(fs, root.prev);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkfree(ms);
|
|
|
|
|
dirsinkfree(ds);
|
|
|
|
|
dirsinkfree(dsink);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(fs != nil)
|
2004-03-15 01:56:49 +00:00
|
|
|
vacfsclose(fs);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
vtrootpack(&root, buf);
|
|
|
|
|
if(vacwrite(z, score, VtRootType, buf, VtRootSize) < 0)
|
|
|
|
|
sysfatal("vacWrite failed: %r");
|
|
|
|
|
|
|
|
|
|
fprint(fd, "vac:%V\n", score);
|
|
|
|
|
|
2003-11-23 17:55:34 +00:00
|
|
|
/* avoid remove at cleanup */
|
|
|
|
|
oname = nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
2004-03-15 01:56:49 +00:00
|
|
|
isexcluded(char *name)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
int bot, top, i, x;
|
|
|
|
|
|
|
|
|
|
bot = 0;
|
|
|
|
|
top = nexclude;
|
|
|
|
|
while(bot < top) {
|
|
|
|
|
i = (bot+top)>>1;
|
|
|
|
|
x = strcmp(exclude[i], name);
|
|
|
|
|
if(x == 0)
|
|
|
|
|
return 1;
|
|
|
|
|
if(x < 0)
|
|
|
|
|
bot = i + 1;
|
|
|
|
|
else /* x > 0 */
|
|
|
|
|
top = i;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2004-03-15 01:56:49 +00:00
|
|
|
vacfile(DirSink *dsink, char *lname, char *sname, VacFile *vf)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
int fd;
|
|
|
|
|
Dir *dir;
|
|
|
|
|
VacDir vd;
|
|
|
|
|
ulong entry;
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
if(isexcluded(lname)) {
|
2003-11-23 17:55:34 +00:00
|
|
|
warn("excluding: %s", lname);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
if(merge && vacmerge(dsink, lname, sname) >= 0)
|
2003-11-23 17:55:34 +00:00
|
|
|
return;
|
|
|
|
|
|
2005-02-08 20:27:10 +00:00
|
|
|
if((dir = dirstat(sname)) == nil){
|
|
|
|
|
warn("could not stat file %s: %r", lname);
|
2005-02-11 20:32:41 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2005-09-13 02:00:06 +00:00
|
|
|
if(dir->mode&(DMSYMLINK|DMDEVICE|DMNAMEDPIPE)){
|
|
|
|
|
vacspecial(dsink, dir, lname, sname, vf);
|
|
|
|
|
free(dir);
|
|
|
|
|
return;
|
|
|
|
|
}else if(dir->mode&DMSOCKET){
|
2005-02-08 20:27:10 +00:00
|
|
|
free(dir);
|
2004-03-21 04:33:13 +00:00
|
|
|
return;
|
2005-02-08 20:27:10 +00:00
|
|
|
}
|
|
|
|
|
free(dir);
|
|
|
|
|
|
2003-11-23 17:55:34 +00:00
|
|
|
fd = open(sname, OREAD);
|
|
|
|
|
if(fd < 0) {
|
2004-03-15 01:56:49 +00:00
|
|
|
warn("could not open file: %s: %r", lname);
|
2003-11-23 17:55:34 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(verbose)
|
|
|
|
|
fprint(2, "%s\n", lname);
|
|
|
|
|
|
|
|
|
|
dir = dirfstat(fd);
|
|
|
|
|
if(dir == nil) {
|
|
|
|
|
warn("can't stat %s: %r", lname);
|
|
|
|
|
close(fd);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2004-03-15 01:56:49 +00:00
|
|
|
dir->name = lastelem(sname);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
entry = dsink->nentry;
|
|
|
|
|
|
|
|
|
|
if(dir->mode & DMDIR)
|
2004-03-15 01:56:49 +00:00
|
|
|
vacdir(dsink, fd, lname, sname, vf);
|
2003-11-23 17:55:34 +00:00
|
|
|
else
|
2004-03-15 01:56:49 +00:00
|
|
|
vacdata(dsink, fd, lname, vf, dir);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
plan9tovacdir(&vd, dir, entry, fileid++);
|
|
|
|
|
metasinkwritedir(dsink->msink, &vd);
|
|
|
|
|
vdcleanup(&vd);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
free(dir);
|
|
|
|
|
close(fd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2004-03-15 01:56:49 +00:00
|
|
|
vacstdin(DirSink *dsink, char *name, VacFile *vf)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
Dir *dir;
|
|
|
|
|
VacDir vd;
|
|
|
|
|
ulong entry;
|
|
|
|
|
|
|
|
|
|
if(verbose)
|
|
|
|
|
fprint(2, "%s\n", "<stdio>");
|
|
|
|
|
|
|
|
|
|
dir = dirfstat(0);
|
|
|
|
|
if(dir == nil) {
|
|
|
|
|
warn("can't stat <stdio>: %r");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2004-03-15 01:56:49 +00:00
|
|
|
dir->name = "stdin";
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
entry = dsink->nentry;
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
vacdata(dsink, 0, "<stdin>", vf, dir);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
plan9tovacdir(&vd, dir, entry, fileid++);
|
|
|
|
|
vd.elem = vtstrdup(name);
|
|
|
|
|
metasinkwritedir(dsink->msink, &vd);
|
|
|
|
|
vdcleanup(&vd);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
free(dir);
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
static int
|
|
|
|
|
sha1check(u8int *score, uchar *buf, int n)
|
|
|
|
|
{
|
2005-03-15 20:27:59 +00:00
|
|
|
uchar score2[VtScoreSize];
|
2004-03-15 01:56:49 +00:00
|
|
|
|
2005-02-18 18:28:00 +00:00
|
|
|
sha1(buf, n, score2, nil);
|
2004-03-15 01:56:49 +00:00
|
|
|
if(memcmp(score, score2, VtScoreSize) == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-23 17:55:34 +00:00
|
|
|
static ulong
|
2004-03-15 01:56:49 +00:00
|
|
|
vacdataskip(Sink *sink, VacFile *vf, int fd, ulong blocks, uchar *buf, char *lname)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
int n;
|
|
|
|
|
ulong i;
|
|
|
|
|
uchar score[VtScoreSize];
|
|
|
|
|
|
|
|
|
|
/* skip blocks for append only files */
|
|
|
|
|
if(seek(fd, (blocks-1)*bsize, 0) != (blocks-1)*bsize) {
|
|
|
|
|
warn("error seeking: %s", lname);
|
|
|
|
|
goto Err;
|
|
|
|
|
}
|
2004-03-15 01:56:49 +00:00
|
|
|
n = readn(fd, buf, bsize);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(n < bsize) {
|
|
|
|
|
warn("error checking append only file: %s", lname);
|
|
|
|
|
goto Err;
|
|
|
|
|
}
|
2004-03-15 01:56:49 +00:00
|
|
|
if(vacfileblockscore(vf, blocks-1, score)<0 || sha1check(score, buf, n)<0) {
|
2003-11-23 17:55:34 +00:00
|
|
|
warn("last block of append file did not match: %s", lname);
|
|
|
|
|
goto Err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(i=0; i<blocks; i++) {
|
2004-03-15 01:56:49 +00:00
|
|
|
if(vacfileblockscore(vf, i, score) < 0) {
|
2003-11-23 17:55:34 +00:00
|
|
|
warn("could not get score: %s: %lud", lname, i);
|
|
|
|
|
seek(fd, i*bsize, 0);
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
stats.skip++;
|
2004-03-15 01:56:49 +00:00
|
|
|
sinkwritescore(sink, score, bsize);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return i;
|
|
|
|
|
Err:
|
|
|
|
|
seek(fd, 0, 0);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2004-03-15 01:56:49 +00:00
|
|
|
vacdata(DirSink *dsink, int fd, char *lname, VacFile *vf, Dir *dir)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
uchar *buf;
|
|
|
|
|
Sink *sink;
|
|
|
|
|
int n;
|
|
|
|
|
uchar score[VtScoreSize];
|
|
|
|
|
ulong block, same;
|
|
|
|
|
VacDir vd;
|
|
|
|
|
ulong vfblocks;
|
|
|
|
|
|
|
|
|
|
vfblocks = 0;
|
|
|
|
|
if(vf != nil && qdiff) {
|
2004-03-15 01:56:49 +00:00
|
|
|
vacfilegetdir(vf, &vd);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(vd.mtime == dir->mtime)
|
|
|
|
|
if(vd.size == dir->length)
|
|
|
|
|
if(!vd.plan9 || /* vd.p9path == dir->qid.path && */ vd.p9version == dir->qid.vers)
|
2004-03-15 01:56:49 +00:00
|
|
|
if(dirsinkwritefile(dsink, vf)) {
|
2003-11-23 17:55:34 +00:00
|
|
|
stats.sfile++;
|
2004-03-15 01:56:49 +00:00
|
|
|
vdcleanup(&vd);
|
2003-11-23 17:55:34 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* look for an append only file */
|
|
|
|
|
if((dir->mode&DMAPPEND) != 0)
|
|
|
|
|
if(vd.size < dir->length)
|
|
|
|
|
if(vd.plan9)
|
|
|
|
|
if(vd.p9path == dir->qid.path)
|
|
|
|
|
vfblocks = vd.size/bsize;
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
vdcleanup(&vd);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
stats.file++;
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
buf = vtmalloc(bsize);
|
|
|
|
|
sink = sinkalloc(dsink->sink->z, bsize, bsize);
|
2003-11-23 17:55:34 +00:00
|
|
|
block = 0;
|
|
|
|
|
same = stats.sdata+stats.skip;
|
|
|
|
|
|
|
|
|
|
if(vfblocks > 1)
|
2004-03-15 01:56:49 +00:00
|
|
|
block += vacdataskip(sink, vf, fd, vfblocks, buf, lname);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
if(0) fprint(2, "vacData: %s: %ld\n", lname, block);
|
|
|
|
|
for(;;) {
|
2004-03-15 01:56:49 +00:00
|
|
|
n = readn(fd, buf, bsize);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(0 && n < 0)
|
2004-03-15 01:56:49 +00:00
|
|
|
warn("file truncated due to read error: %s: %r", lname);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(n <= 0)
|
|
|
|
|
break;
|
2005-02-18 18:28:00 +00:00
|
|
|
if(vf != nil && vacfileblockscore(vf, block, score)>=0 && sha1check(score, buf, n)>=0) {
|
2003-11-23 17:55:34 +00:00
|
|
|
stats.sdata++;
|
2004-03-15 01:56:49 +00:00
|
|
|
sinkwritescore(sink, score, n);
|
2003-11-23 17:55:34 +00:00
|
|
|
} else
|
2004-03-15 01:56:49 +00:00
|
|
|
sinkwrite(sink, buf, n);
|
2003-11-23 17:55:34 +00:00
|
|
|
block++;
|
|
|
|
|
}
|
|
|
|
|
same = stats.sdata+stats.skip - same;
|
|
|
|
|
|
|
|
|
|
if(same && (dir->mode&DMAPPEND) != 0)
|
|
|
|
|
if(0)fprint(2, "%s: total %lud same %lud:%lud diff %lud\n",
|
|
|
|
|
lname, block, same, vfblocks, block-same);
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
sinkclose(sink);
|
|
|
|
|
dirsinkwritesink(dsink, sink);
|
|
|
|
|
sinkfree(sink);
|
2003-11-23 17:55:34 +00:00
|
|
|
free(buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2004-03-15 01:56:49 +00:00
|
|
|
vacdir(DirSink *dsink, int fd, char *lname, char *sname, VacFile *vf)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
Dir *dirs;
|
|
|
|
|
char *ln, *sn;
|
|
|
|
|
int i, nd;
|
|
|
|
|
DirSink *ds;
|
|
|
|
|
VacFile *vvf;
|
|
|
|
|
char *name;
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
ds = dirsinkalloc(dsink->sink->z, bsize, bsize);
|
2003-11-23 17:55:34 +00:00
|
|
|
while((nd = dirread(fd, &dirs)) > 0){
|
|
|
|
|
for(i = 0; i < nd; i++){
|
|
|
|
|
name = dirs[i].name;
|
|
|
|
|
/* check for bad file names */
|
|
|
|
|
if(name[0] == 0 || strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
|
|
|
|
|
continue;
|
2004-03-15 01:56:49 +00:00
|
|
|
ln = vtmalloc(strlen(lname) + strlen(name) + 2);
|
|
|
|
|
sn = vtmalloc(strlen(sname) + strlen(name) + 2);
|
2005-12-29 21:59:54 +00:00
|
|
|
strcpy(ln, lname);
|
|
|
|
|
strcat(ln, "/");
|
|
|
|
|
strcat(ln, name);
|
|
|
|
|
strcpy(sn, sname);
|
|
|
|
|
strcat(sn, "/");
|
|
|
|
|
strcat(sn, name);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(vf != nil)
|
2004-03-15 01:56:49 +00:00
|
|
|
vvf = vacfilewalk(vf, name);
|
2003-11-23 17:55:34 +00:00
|
|
|
else
|
|
|
|
|
vvf = nil;
|
2004-03-15 01:56:49 +00:00
|
|
|
vacfile(ds, ln, sn, vvf);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(vvf != nil)
|
2004-03-15 01:56:49 +00:00
|
|
|
vacfiledecref(vvf);
|
|
|
|
|
vtfree(ln);
|
|
|
|
|
vtfree(sn);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
free(dirs);
|
|
|
|
|
}
|
2004-03-15 01:56:49 +00:00
|
|
|
dirsinkclose(ds);
|
|
|
|
|
dirsinkwritesink(dsink, ds->sink);
|
|
|
|
|
dirsinkwritesink(dsink, ds->msink->sink);
|
|
|
|
|
dirsinkfree(ds);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
2004-03-15 01:56:49 +00:00
|
|
|
vacmergefile(DirSink *dsink, VacFile *vf, VacDir *dir, uvlong offset, uvlong *max)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
uchar buf[VtEntrySize];
|
|
|
|
|
VtEntry dd, md;
|
|
|
|
|
int e;
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
if(vacfileread(vf, buf, VtEntrySize, (uvlong)dir->entry*VtEntrySize) != VtEntrySize) {
|
2003-11-23 17:55:34 +00:00
|
|
|
warn("could not read venti dir entry: %s\n", dir->elem);
|
2004-03-15 01:56:49 +00:00
|
|
|
return -1;
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
2004-03-15 01:56:49 +00:00
|
|
|
vtentryunpack(&dd, buf, 0);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
if(dir->mode & ModeDir) {
|
|
|
|
|
e = dir->mentry;
|
|
|
|
|
if(e == 0)
|
|
|
|
|
e = dir->entry + 1;
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
if(vacfileread(vf, buf, VtEntrySize, e*VtEntrySize) != VtEntrySize) {
|
2003-11-23 17:55:34 +00:00
|
|
|
warn("could not read venti dir entry: %s\n", dir->elem);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2004-03-15 01:56:49 +00:00
|
|
|
vtentryunpack(&md, buf, 0);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* max might incorrect in some old dumps */
|
|
|
|
|
if(dir->qid >= *max) {
|
|
|
|
|
warn("qid out of range: %s", dir->elem);
|
|
|
|
|
*max = dir->qid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dir->qid += offset;
|
|
|
|
|
dir->entry = dsink->nentry;
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
if(dir->qidspace) {
|
|
|
|
|
dir->qidoffset += offset;
|
2003-11-23 17:55:34 +00:00
|
|
|
} else {
|
2004-03-15 01:56:49 +00:00
|
|
|
dir->qidspace = 1;
|
|
|
|
|
dir->qidoffset = offset;
|
|
|
|
|
dir->qidmax = *max;
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
dirsinkwrite(dsink, &dd);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(dir->mode & ModeDir)
|
2004-03-15 01:56:49 +00:00
|
|
|
dirsinkwrite(dsink, &md);
|
|
|
|
|
metasinkwritedir(dsink->msink, dir);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
return 0;
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
2004-03-15 01:56:49 +00:00
|
|
|
vacmerge(DirSink *dsink, char *lname, char *sname)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
char *p;
|
2004-03-15 01:56:49 +00:00
|
|
|
VacFs *fs;
|
2003-11-23 17:55:34 +00:00
|
|
|
VacFile *vf;
|
|
|
|
|
VacDirEnum *d;
|
|
|
|
|
VacDir dir;
|
|
|
|
|
uvlong max;
|
|
|
|
|
|
2005-02-21 04:28:34 +00:00
|
|
|
if((p=strrchr(sname, '.')) == nil || strcmp(p, ".vac") != 0)
|
2005-02-20 22:51:24 +00:00
|
|
|
return -1;
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
d = nil;
|
2004-03-15 01:56:49 +00:00
|
|
|
fs = vacfsopen(dsink->sink->z, sname, VtOREAD, 100);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(fs == nil)
|
2004-03-15 01:56:49 +00:00
|
|
|
return -1;
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
vf = vacfileopen(fs, "/");
|
2003-11-23 17:55:34 +00:00
|
|
|
if(vf == nil)
|
|
|
|
|
goto Done;
|
2004-03-15 01:56:49 +00:00
|
|
|
max = vacfilegetid(vf);
|
|
|
|
|
d = vdeopen(vf);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(d == nil)
|
|
|
|
|
goto Done;
|
|
|
|
|
|
|
|
|
|
if(verbose)
|
|
|
|
|
fprint(2, "merging: %s\n", lname);
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
if(maxbsize < fs->bsize)
|
|
|
|
|
maxbsize = fs->bsize;
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
for(;;) {
|
2004-03-15 01:56:49 +00:00
|
|
|
if(vderead(d, &dir) < 1)
|
2003-11-23 17:55:34 +00:00
|
|
|
break;
|
2004-03-15 01:56:49 +00:00
|
|
|
vacmergefile(dsink, vf, &dir, fileid, &max);
|
|
|
|
|
vdcleanup(&dir);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
fileid += max;
|
|
|
|
|
|
|
|
|
|
Done:
|
|
|
|
|
if(d != nil)
|
2004-03-15 01:56:49 +00:00
|
|
|
vdeclose(d);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(vf != nil)
|
2004-03-15 01:56:49 +00:00
|
|
|
vacfiledecref(vf);
|
|
|
|
|
vacfsclose(fs);
|
|
|
|
|
return 0;
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
2005-09-13 02:00:06 +00:00
|
|
|
static int
|
|
|
|
|
vacspecial(DirSink *dsink, Dir* dir, char *lname, char *sname, VacFile *vf)
|
|
|
|
|
{
|
|
|
|
|
char *btmp, *buf;
|
|
|
|
|
int buflen, dtype, major, minor, n;
|
|
|
|
|
ulong entry;
|
|
|
|
|
Sink *sink;
|
|
|
|
|
VacDir vd;
|
|
|
|
|
|
|
|
|
|
n = 0;
|
|
|
|
|
buflen = 128;
|
|
|
|
|
buf = malloc(buflen);
|
|
|
|
|
if(buf == nil)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
if(verbose)
|
|
|
|
|
fprint(2, "%s\n", lname);
|
|
|
|
|
|
|
|
|
|
dir->name = lastelem(sname);
|
|
|
|
|
|
|
|
|
|
if(dir->mode & DMSYMLINK){
|
|
|
|
|
while((n = readlink(sname, buf, buflen)) == buflen){
|
|
|
|
|
buflen *= 2;
|
|
|
|
|
btmp = vtrealloc(buf, buflen);
|
|
|
|
|
if(btmp == nil){
|
|
|
|
|
free(buf);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
buf = btmp;
|
|
|
|
|
}
|
|
|
|
|
dir->mode &= ~DMDIR;
|
|
|
|
|
dir->mode |= DMSYMLINK;
|
|
|
|
|
}else if(dir->mode & DMDEVICE){
|
|
|
|
|
dtype = (dir->qid.path >> 16) & 0xFF;
|
|
|
|
|
minor = dir->qid.path & 0xff;
|
|
|
|
|
major = (dir->qid.path >> 8) & 0xFF;
|
|
|
|
|
n = snprint(buf, buflen, "%c %d %d", dtype, major, minor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
entry = dsink->nentry;
|
|
|
|
|
|
|
|
|
|
sink = sinkalloc(dsink->sink->z, bsize, bsize);
|
2005-09-13 03:58:31 +00:00
|
|
|
sinkwrite(sink, (uchar*)buf, n);
|
2005-09-13 02:00:06 +00:00
|
|
|
sinkclose(sink);
|
|
|
|
|
dirsinkwritesink(dsink, sink);
|
|
|
|
|
sinkfree(sink);
|
|
|
|
|
free(buf);
|
|
|
|
|
|
|
|
|
|
dir->name = lastelem(sname);
|
|
|
|
|
dir->length = n;
|
|
|
|
|
plan9tovacdir(&vd, dir, entry, fileid++);
|
|
|
|
|
metasinkwritedir(dsink->msink, &vd);
|
|
|
|
|
vdcleanup(&vd);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-11-23 17:55:34 +00:00
|
|
|
Sink *
|
2004-03-15 01:56:49 +00:00
|
|
|
sinkalloc(VtConn *z, int psize, int dsize)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
Sink *k;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if(psize < 512 || psize > VtMaxLumpSize)
|
2004-03-15 01:56:49 +00:00
|
|
|
sysfatal("sinkalloc: bad psize");
|
2003-11-23 17:55:34 +00:00
|
|
|
if(dsize < 512 || dsize > VtMaxLumpSize)
|
2004-03-15 01:56:49 +00:00
|
|
|
sysfatal("sinkalloc: bad psize");
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
psize = VtScoreSize*(psize/VtScoreSize);
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
k = vtmallocz(sizeof(Sink));
|
2003-11-23 17:55:34 +00:00
|
|
|
k->z = z;
|
|
|
|
|
k->dir.flags = VtEntryActive;
|
|
|
|
|
k->dir.psize = psize;
|
|
|
|
|
k->dir.dsize = dsize;
|
2004-03-15 01:56:49 +00:00
|
|
|
k->buf = vtmallocz(VtPointerDepth*k->dir.psize + VtScoreSize);
|
2003-11-23 17:55:34 +00:00
|
|
|
for(i=0; i<=VtPointerDepth; i++)
|
|
|
|
|
k->pbuf[i] = k->buf + i*k->dir.psize;
|
|
|
|
|
return k;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
sinkwritescore(Sink *k, uchar score[VtScoreSize], int n)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
uchar *p;
|
|
|
|
|
VtEntry *d;
|
|
|
|
|
|
|
|
|
|
memmove(k->pbuf[0], score, VtScoreSize);
|
|
|
|
|
|
|
|
|
|
d = &k->dir;
|
|
|
|
|
|
|
|
|
|
for(i=0; i<VtPointerDepth; i++) {
|
|
|
|
|
k->pbuf[i] += VtScoreSize;
|
|
|
|
|
if(k->pbuf[i] < k->buf + d->psize*(i+1))
|
|
|
|
|
break;
|
|
|
|
|
if(i == VtPointerDepth-1)
|
2004-03-15 01:56:49 +00:00
|
|
|
sysfatal("file too big");
|
2003-11-23 17:55:34 +00:00
|
|
|
p = k->buf+i*d->psize;
|
|
|
|
|
stats.meta++;
|
2004-03-15 01:56:49 +00:00
|
|
|
if(vacwrite(k->z, k->pbuf[i+1], VtDataType+1+i, p, d->psize) < 0)
|
|
|
|
|
sysfatal("vacwrite failed: %r");
|
2003-11-23 17:55:34 +00:00
|
|
|
k->pbuf[i] = p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* round size up to multiple of dsize */
|
|
|
|
|
d->size = d->dsize * ((d->size + d->dsize-1)/d->dsize);
|
|
|
|
|
|
|
|
|
|
d->size += n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
sinkwrite(Sink *k, uchar *p, int n)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
int type;
|
|
|
|
|
uchar score[VtScoreSize];
|
|
|
|
|
|
2005-09-13 02:00:06 +00:00
|
|
|
if(n == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2003-11-23 17:55:34 +00:00
|
|
|
if(n > k->dir.dsize)
|
2004-03-15 01:56:49 +00:00
|
|
|
sysfatal("sinkWrite: size too big");
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
if((k->dir.type&~VtTypeDepthMask) == VtDirType){
|
2003-11-23 17:55:34 +00:00
|
|
|
type = VtDirType;
|
|
|
|
|
stats.meta++;
|
|
|
|
|
} else {
|
|
|
|
|
type = VtDataType;
|
|
|
|
|
stats.data++;
|
|
|
|
|
}
|
2004-03-15 01:56:49 +00:00
|
|
|
if(vacwrite(k->z, score, type, p, n) < 0)
|
|
|
|
|
sysfatal("vacWrite failed: %r");
|
2003-11-23 17:55:34 +00:00
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
sinkwritescore(k, score, n);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
2004-03-15 01:56:49 +00:00
|
|
|
sizetodepth(uvlong s, int psize, int dsize)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
int np;
|
|
|
|
|
int d;
|
|
|
|
|
|
|
|
|
|
/* determine pointer depth */
|
|
|
|
|
np = psize/VtScoreSize;
|
|
|
|
|
s = (s + dsize - 1)/dsize;
|
|
|
|
|
for(d = 0; s > 1; d++)
|
|
|
|
|
s = (s + np - 1)/np;
|
|
|
|
|
return d;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
sinkclose(Sink *k)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
2004-03-15 01:56:49 +00:00
|
|
|
int i, n, base;
|
2003-11-23 17:55:34 +00:00
|
|
|
uchar *p;
|
|
|
|
|
VtEntry *kd;
|
|
|
|
|
|
|
|
|
|
kd = &k->dir;
|
|
|
|
|
|
|
|
|
|
/* empty */
|
|
|
|
|
if(kd->size == 0) {
|
2004-03-15 01:56:49 +00:00
|
|
|
memmove(kd->score, vtzeroscore, VtScoreSize);
|
2003-11-23 17:55:34 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(n=VtPointerDepth-1; n>0; n--)
|
|
|
|
|
if(k->pbuf[n] > k->buf + kd->psize*n)
|
|
|
|
|
break;
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
base = kd->type&~VtTypeDepthMask;
|
|
|
|
|
kd->type = base + sizetodepth(kd->size, kd->psize, kd->dsize);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
/* skip full part of tree */
|
|
|
|
|
for(i=0; i<n && k->pbuf[i] == k->buf + kd->psize*i; i++)
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* is the tree completely full */
|
|
|
|
|
if(i == n && k->pbuf[n] == k->buf + kd->psize*n + VtScoreSize) {
|
|
|
|
|
memmove(kd->score, k->pbuf[n] - VtScoreSize, VtScoreSize);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
n++;
|
|
|
|
|
|
|
|
|
|
/* clean up the edge */
|
|
|
|
|
for(; i<n; i++) {
|
|
|
|
|
p = k->buf+i*kd->psize;
|
|
|
|
|
stats.meta++;
|
2004-03-15 01:56:49 +00:00
|
|
|
if(vacwrite(k->z, k->pbuf[i+1], base+1+i, p, k->pbuf[i]-p) < 0)
|
|
|
|
|
sysfatal("vacWrite failed: %r");
|
2003-11-23 17:55:34 +00:00
|
|
|
k->pbuf[i+1] += VtScoreSize;
|
|
|
|
|
}
|
|
|
|
|
memmove(kd->score, k->pbuf[i] - VtScoreSize, VtScoreSize);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
sinkfree(Sink *k)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
2004-03-15 01:56:49 +00:00
|
|
|
vtfree(k->buf);
|
|
|
|
|
vtfree(k);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DirSink *
|
2004-03-15 01:56:49 +00:00
|
|
|
dirsinkalloc(VtConn *z, int psize, int dsize)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
DirSink *k;
|
|
|
|
|
int ds;
|
|
|
|
|
|
|
|
|
|
ds = VtEntrySize*(dsize/VtEntrySize);
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
k = vtmallocz(sizeof(DirSink));
|
|
|
|
|
k->sink = sinkalloc(z, psize, ds);
|
|
|
|
|
k->sink->dir.type = VtDirType;
|
|
|
|
|
k->msink = metasinkalloc(z, psize, dsize);
|
|
|
|
|
k->buf = vtmalloc(ds);
|
2003-11-23 17:55:34 +00:00
|
|
|
k->p = k->buf;
|
|
|
|
|
k->ep = k->buf + ds;
|
|
|
|
|
return k;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
dirsinkwrite(DirSink *k, VtEntry *dir)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
if(k->p + VtEntrySize > k->ep) {
|
2004-03-15 01:56:49 +00:00
|
|
|
sinkwrite(k->sink, k->buf, k->p - k->buf);
|
2003-11-23 17:55:34 +00:00
|
|
|
k->p = k->buf;
|
|
|
|
|
}
|
2004-03-15 01:56:49 +00:00
|
|
|
vtentrypack(dir, k->p, 0);
|
2003-11-23 17:55:34 +00:00
|
|
|
k->nentry++;
|
|
|
|
|
k->p += VtEntrySize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
dirsinkwritesink(DirSink *k, Sink *sink)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
2004-03-15 01:56:49 +00:00
|
|
|
dirsinkwrite(k, &sink->dir);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2004-03-15 01:56:49 +00:00
|
|
|
dirsinkwritefile(DirSink *k, VacFile *vf)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
VtEntry dir;
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
if(vacfilegetvtentry(vf, &dir) < 0)
|
|
|
|
|
return -1;
|
|
|
|
|
dirsinkwrite(k, &dir);
|
|
|
|
|
return 0;
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
dirsinkclose(DirSink *k)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkclose(k->msink);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(k->p != k->buf)
|
2004-03-15 01:56:49 +00:00
|
|
|
sinkwrite(k->sink, k->buf, k->p - k->buf);
|
|
|
|
|
sinkclose(k->sink);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
dirsinkfree(DirSink *k)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
2004-03-15 01:56:49 +00:00
|
|
|
sinkfree(k->sink);
|
|
|
|
|
metasinkfree(k->msink);
|
|
|
|
|
vtfree(k->buf);
|
|
|
|
|
vtfree(k);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
MetaSink*
|
|
|
|
|
metasinkalloc(VtConn *z, int psize, int dsize)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
MetaSink *k;
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
k = vtmallocz(sizeof(MetaSink));
|
|
|
|
|
k->sink = sinkalloc(z, psize, dsize);
|
|
|
|
|
k->buf = vtmalloc(dsize);
|
2003-11-23 17:55:34 +00:00
|
|
|
k->maxindex = dsize/100; /* 100 byte entries seems reasonable */
|
|
|
|
|
if(k->maxindex < 1)
|
|
|
|
|
k->maxindex = 1;
|
|
|
|
|
k->rp = k->p = k->buf + MetaHeaderSize + k->maxindex*MetaIndexSize;
|
|
|
|
|
k->ep = k->buf + dsize;
|
|
|
|
|
return k;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* hack to get base to compare routine - not reentrant */
|
2004-03-15 01:56:49 +00:00
|
|
|
uchar *blockbase;
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
int
|
2004-03-15 01:56:49 +00:00
|
|
|
dircmp(const void *p0, const void *p1)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
uchar *q0, *q1;
|
|
|
|
|
int n0, n1, r;
|
|
|
|
|
|
|
|
|
|
/* name is first element of entry */
|
2004-03-15 01:56:49 +00:00
|
|
|
q0 = (uchar*)p0;
|
|
|
|
|
q0 = blockbase + (q0[0]<<8) + q0[1];
|
2003-11-23 17:55:34 +00:00
|
|
|
n0 = (q0[6]<<8) + q0[7];
|
|
|
|
|
q0 += 8;
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
q1 = (uchar*)p1;
|
|
|
|
|
q1 = blockbase + (q1[0]<<8) + q1[1];
|
2003-11-23 17:55:34 +00:00
|
|
|
n1 = (q1[6]<<8) + q1[7];
|
|
|
|
|
q1 += 8;
|
|
|
|
|
|
|
|
|
|
if(n0 == n1)
|
|
|
|
|
return memcmp(q0, q1, n0);
|
|
|
|
|
else if (n0 < n1) {
|
|
|
|
|
r = memcmp(q0, q1, n0);
|
|
|
|
|
return (r==0)?1:r;
|
|
|
|
|
} else {
|
|
|
|
|
r = memcmp(q0, q1, n1);
|
|
|
|
|
return (r==0)?-1:r;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkflush(MetaSink *k)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
uchar *p;
|
|
|
|
|
int n;
|
|
|
|
|
MetaBlock mb;
|
|
|
|
|
|
|
|
|
|
if(k->nindex == 0)
|
|
|
|
|
return;
|
|
|
|
|
assert(k->nindex <= k->maxindex);
|
|
|
|
|
|
|
|
|
|
p = k->buf;
|
|
|
|
|
n = k->rp - p;
|
|
|
|
|
|
|
|
|
|
mb.size = n;
|
|
|
|
|
mb.free = 0;
|
|
|
|
|
mb.nindex = k->nindex;
|
|
|
|
|
mb.maxindex = k->maxindex;
|
|
|
|
|
mb.buf = p;
|
2004-03-15 01:56:49 +00:00
|
|
|
mbpack(&mb);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
p += MetaHeaderSize;
|
|
|
|
|
|
|
|
|
|
/* XXX this is not reentrant! */
|
2004-03-15 01:56:49 +00:00
|
|
|
blockbase = k->buf;
|
|
|
|
|
qsort(p, k->nindex, MetaIndexSize, dircmp);
|
2003-11-23 17:55:34 +00:00
|
|
|
p += k->nindex*MetaIndexSize;
|
|
|
|
|
|
|
|
|
|
memset(p, 0, (k->maxindex-k->nindex)*MetaIndexSize);
|
|
|
|
|
p += (k->maxindex-k->nindex)*MetaIndexSize;
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
sinkwrite(k->sink, k->buf, n);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
/* move down partial entry */
|
|
|
|
|
n = k->p - k->rp;
|
|
|
|
|
memmove(p, k->rp, n);
|
|
|
|
|
k->rp = p;
|
|
|
|
|
k->p = p + n;
|
|
|
|
|
k->nindex = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkputc(MetaSink *k, int c)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
if(k->p+1 > k->ep)
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkflush(k);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(k->p+1 > k->ep)
|
2004-03-15 01:56:49 +00:00
|
|
|
sysfatal("directory entry too large");
|
2003-11-23 17:55:34 +00:00
|
|
|
k->p[0] = c;
|
|
|
|
|
k->p++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkputstring(MetaSink *k, char *s)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
int n = strlen(s);
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkputc(k, n>>8);
|
|
|
|
|
metasinkputc(k, n);
|
|
|
|
|
metasinkwrite(k, (uchar*)s, n);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkputuint32(MetaSink *k, ulong x)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkputc(k, x>>24);
|
|
|
|
|
metasinkputc(k, x>>16);
|
|
|
|
|
metasinkputc(k, x>>8);
|
|
|
|
|
metasinkputc(k, x);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkputuint64(MetaSink *k, uvlong x)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkputuint32(k, x>>32);
|
|
|
|
|
metasinkputuint32(k, x);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkwrite(MetaSink *k, uchar *data, int n)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
if(k->p + n > k->ep)
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkflush(k);
|
2003-11-23 17:55:34 +00:00
|
|
|
if(k->p + n > k->ep)
|
2004-03-15 01:56:49 +00:00
|
|
|
sysfatal("directory entry too large");
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
memmove(k->p, data, n);
|
|
|
|
|
k->p += n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkwritedir(MetaSink *ms, VacDir *dir)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkputuint32(ms, DirMagic);
|
|
|
|
|
metasinkputc(ms, Version>>8);
|
|
|
|
|
metasinkputc(ms, Version);
|
|
|
|
|
metasinkputstring(ms, dir->elem);
|
|
|
|
|
metasinkputuint32(ms, dir->entry);
|
|
|
|
|
metasinkputuint64(ms, dir->qid);
|
|
|
|
|
metasinkputstring(ms, dir->uid);
|
|
|
|
|
metasinkputstring(ms, dir->gid);
|
|
|
|
|
metasinkputstring(ms, dir->mid);
|
|
|
|
|
metasinkputuint32(ms, dir->mtime);
|
|
|
|
|
metasinkputuint32(ms, dir->mcount);
|
|
|
|
|
metasinkputuint32(ms, dir->ctime);
|
|
|
|
|
metasinkputuint32(ms, dir->atime);
|
|
|
|
|
metasinkputuint32(ms, dir->mode);
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
if(dir->plan9) {
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkputc(ms, DirPlan9Entry); /* plan9 extra info */
|
|
|
|
|
metasinkputc(ms, 0); /* plan9 extra size */
|
|
|
|
|
metasinkputc(ms, 12); /* plan9 extra size */
|
|
|
|
|
metasinkputuint64(ms, dir->p9path);
|
|
|
|
|
metasinkputuint32(ms, dir->p9version);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
if(dir->qidspace != 0) {
|
|
|
|
|
metasinkputc(ms, DirQidSpaceEntry);
|
|
|
|
|
metasinkputc(ms, 0);
|
|
|
|
|
metasinkputc(ms, 16);
|
|
|
|
|
metasinkputuint64(ms, dir->qidoffset);
|
|
|
|
|
metasinkputuint64(ms, dir->qidmax);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(dir->gen != 0) {
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkputc(ms, DirGenEntry);
|
|
|
|
|
metasinkputc(ms, 0);
|
|
|
|
|
metasinkputc(ms, 4);
|
|
|
|
|
metasinkputuint32(ms, dir->gen);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkeor(ms);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
plan9tovacdir(VacDir *vd, Dir *dir, ulong entry, uvlong qid)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
memset(vd, 0, sizeof(VacDir));
|
|
|
|
|
|
2004-03-15 01:56:49 +00:00
|
|
|
vd->elem = vtstrdup(dir->name);
|
2003-11-23 17:55:34 +00:00
|
|
|
vd->entry = entry;
|
|
|
|
|
vd->qid = qid;
|
2004-03-15 01:56:49 +00:00
|
|
|
vd->uid = vtstrdup(dir->uid);
|
|
|
|
|
vd->gid = vtstrdup(dir->gid);
|
|
|
|
|
vd->mid = vtstrdup(dir->muid);
|
2003-11-23 17:55:34 +00:00
|
|
|
vd->mtime = dir->mtime;
|
|
|
|
|
vd->mcount = 0;
|
|
|
|
|
vd->ctime = dir->mtime; /* ctime: not available on plan 9 */
|
|
|
|
|
vd->atime = dir->atime;
|
|
|
|
|
|
|
|
|
|
vd->mode = dir->mode & 0777;
|
|
|
|
|
if(dir->mode & DMDIR)
|
|
|
|
|
vd->mode |= ModeDir;
|
|
|
|
|
if(dir->mode & DMAPPEND)
|
|
|
|
|
vd->mode |= ModeAppend;
|
|
|
|
|
if(dir->mode & DMEXCL)
|
|
|
|
|
vd->mode |= ModeExclusive;
|
2005-09-13 02:00:06 +00:00
|
|
|
if(dir->mode & DMDEVICE)
|
|
|
|
|
vd->mode |= ModeDevice;
|
|
|
|
|
if(dir->mode & DMNAMEDPIPE)
|
|
|
|
|
vd->mode |= ModeNamedPipe;
|
|
|
|
|
if(dir->mode & DMSYMLINK)
|
|
|
|
|
vd->mode |= ModeLink;
|
2003-11-23 17:55:34 +00:00
|
|
|
|
|
|
|
|
vd->plan9 = 1;
|
|
|
|
|
vd->p9path = dir->qid.path;
|
|
|
|
|
vd->p9version = dir->qid.vers;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkeor(MetaSink *k)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
|
|
|
|
uchar *p;
|
|
|
|
|
int o, n;
|
|
|
|
|
|
|
|
|
|
p = k->buf + MetaHeaderSize;
|
|
|
|
|
p += k->nindex * MetaIndexSize;
|
|
|
|
|
o = k->rp-k->buf; /* offset from start of block */
|
|
|
|
|
n = k->p-k->rp; /* size of entry */
|
|
|
|
|
p[0] = o >> 8;
|
|
|
|
|
p[1] = o;
|
|
|
|
|
p[2] = n >> 8;
|
|
|
|
|
p[3] = n;
|
|
|
|
|
k->rp = k->p;
|
|
|
|
|
k->nindex++;
|
|
|
|
|
if(k->nindex == k->maxindex)
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkflush(k);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkclose(MetaSink *k)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkflush(k);
|
|
|
|
|
sinkclose(k->sink);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-03-15 01:56:49 +00:00
|
|
|
metasinkfree(MetaSink *k)
|
2003-11-23 17:55:34 +00:00
|
|
|
{
|
2004-03-15 01:56:49 +00:00
|
|
|
sinkfree(k->sink);
|
|
|
|
|
vtfree(k->buf);
|
|
|
|
|
vtfree(k);
|
2003-11-23 17:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
warn(char *fmt, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list arg;
|
|
|
|
|
|
|
|
|
|
va_start(arg, fmt);
|
|
|
|
|
fprint(2, "%s: ", argv0);
|
|
|
|
|
vfprint(2, fmt, arg);
|
|
|
|
|
fprint(2, "\n");
|
|
|
|
|
va_end(arg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
cleanup(void)
|
|
|
|
|
{
|
|
|
|
|
if(oname != nil)
|
|
|
|
|
remove(oname);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define TWID64 ((u64int)~(u64int)0)
|
|
|
|
|
|
|
|
|
|
static u64int
|
|
|
|
|
unittoull(char *s)
|
|
|
|
|
{
|
|
|
|
|
char *es;
|
|
|
|
|
u64int n;
|
|
|
|
|
|
|
|
|
|
if(s == nil)
|
|
|
|
|
return TWID64;
|
|
|
|
|
n = strtoul(s, &es, 0);
|
|
|
|
|
if(*es == 'k' || *es == 'K'){
|
|
|
|
|
n *= 1024;
|
|
|
|
|
es++;
|
|
|
|
|
}else if(*es == 'm' || *es == 'M'){
|
|
|
|
|
n *= 1024*1024;
|
|
|
|
|
es++;
|
|
|
|
|
}else if(*es == 'g' || *es == 'G'){
|
|
|
|
|
n *= 1024*1024*1024;
|
|
|
|
|
es++;
|
|
|
|
|
}
|
|
|
|
|
if(*es != '\0')
|
|
|
|
|
return TWID64;
|
|
|
|
|
return n;
|
|
|
|
|
}
|