#include <u.h>#include <libc.h>#include <bio.h>#include <error.h>#include <b.h>#include <avl.h>#include "repl.h" intdbcmp(Avl* l, Avl* r){ Dbent* ldb = (Dbent*)l; Dbent* rdb = (Dbent*)r; return strcmp(ldb->fname, rdb->fname);} Dbent*readdbent(Biobufhdr* bp){ char* ln; Dbent* dp; char* p; char* e; while (ln = Brdstr(bp, '\n', 1)){ dp = emalloc(sizeof(Dbent)); memset(dp, 0, sizeof(Dbent)); dp->fname = ln; p = strchr(ln, ' '); if (p == nil) goto bad; *p++ = 0; dp->hist = p; p = strchr(p, ' '); if (p == nil) goto bad; *p++ = 0; dp->uid = p; p = strchr(p, ' '); if (p == nil) goto bad; *p++ = 0; dp->gid = p; p = strchr(p, ' '); if (p == nil) goto bad; *p++ = 0; dp->mode = strtoul(p, &e, 16); p = e++; dp->mtime = strtoul(p, &e, 16); p = e++; dp->length = strtoll(p,&e, 10); p = e; if (p && *p == ' ') dp->vers = strtoul(p+1, nil, 10); else dp->vers = ~0; dp->fname= estrdup(dp->fname); dp->hist = estrdup(dp->hist); dp->hlen = strlen(dp->hist); dp->uid = estrdup(dp->uid); dp->gid = estrdup(dp->gid); free(ln); return dp; bad: warn("malformed db entry for %s", dp->fname); free(ln); free(dp); } return nil;} voidinsertdb(Db* db, Dbent* dp){ Dbent* old; insertavl(db->tree, (Avl*)dp, (Avl**)&old); if (old) free(old);} Db*readdb(Biobufhdr* bp){ Db* db; Dbent* dp; char* ln; ln = Brdstr(bp, '\n', 1); if (ln == nil) return nil; db = emalloc(sizeof(Db)); memset(db, 0, sizeof(Db)); db->id = ln[0]; if (strstr(ln, "replica")) // old format db->mtime=0UL; else db->mtime = strtoul(ln+2, nil, 16); free(ln); db->tree = mkavltree(dbcmp); while(dp = readdbent(bp)) insertdb(db, dp); return db;} Db*newdb(char id){ Db* db; db = emalloc(sizeof(Db)); memset(db, 0, sizeof(Db)); db->id = id; db->tree = mkavltree(dbcmp); db->mtime = time(nil); return db;} Db*readdbfile(char* file){ Db* db; Biobuf* bin; Dir* d; d = dirstat(file); if (d != nil){ if (d->qid.type&QTDIR) error("dbfile is a directory."); free(d); } bin = Bopen(file, OREAD); if (bin == nil) error("can't open %s: %r", file); db = readdb(bin); /* We'll keep the db locked until the caller process * * Bterm(bin); */ return db;} voidwritedb(Biobufhdr* bp, Db* db){ Avlwalk*w; Dbent* dp; Bprint(bp, "%c %08ulx repl db:\n", db->id, db->mtime); w = avlwalk(db->tree); while(dp = (Dbent*)avlnext(w)){ if (Bprint(bp, "%s %s %s %s %08ulx %08ulx %lld %uld\n", dp->fname, dp->hist, dp->uid, dp->gid, dp->mode, dp->mtime, dp->length, dp->vers) < 0) sysfatal("writedb"); } endwalk(w);} voidwritedbfile(char* file, Db* db){ Biobuf* bout; Dir* dp; Dir d; bout = Bopen(file,OWRITE|OTRUNC); if (bout == nil) error("can't open %s: %r", file); writedb(bout, db); if (Bterm(bout) < 0) error("closing %s: %r", file); dp = dirstat(file); if (dp != nil){ if (!(dp->mode&DMEXCL)){ nulldir(&d); d.mode = dp->mode|DMEXCL; dirwstat(file, &d); } free(dp); }} voidrename(char* to, char* frompath){ Dir d; char* p; remove(to); p = strrchr(to, '/'); if (p != nil) to = p + 1; nulldir(&d); d.name = to; if (dirwstat(frompath, &d) < 0) error("can't rename %s: %r", frompath);}
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <error.h>
#include <b.h>
#include <avl.h>
#include "repl.h"
int
dbcmp(Avl* l, Avl* r)
{
Dbent* ldb = (Dbent*)l;
Dbent* rdb = (Dbent*)r;
return strcmp(ldb->fname, rdb->fname);
}
Dbent*
readdbent(Biobufhdr* bp)
{
char* ln;
Dbent* dp;
char* p;
char* e;
while (ln = Brdstr(bp, '\n', 1)){
dp = emalloc(sizeof(Dbent));
memset(dp, 0, sizeof(Dbent));
dp->fname = ln;
p = strchr(ln, ' ');
if (p == nil)
goto bad;
*p++ = 0;
dp->hist = p;
p = strchr(p, ' ');
if (p == nil)
goto bad;
*p++ = 0;
dp->uid = p;
p = strchr(p, ' ');
if (p == nil)
goto bad;
*p++ = 0;
dp->gid = p;
p = strchr(p, ' ');
if (p == nil)
goto bad;
*p++ = 0;
dp->mode = strtoul(p, &e, 16);
p = e++;
dp->mtime = strtoul(p, &e, 16);
p = e++;
dp->length = strtoll(p,&e, 10);
p = e;
if (p && *p == ' ')
dp->vers = strtoul(p+1, nil, 10);
else
dp->vers = ~0;
dp->fname= estrdup(dp->fname);
dp->hist = estrdup(dp->hist);
dp->hlen = strlen(dp->hist);
dp->uid = estrdup(dp->uid);
dp->gid = estrdup(dp->gid);
free(ln);
return dp;
bad:
warn("malformed db entry for %s", dp->fname);
free(ln);
free(dp);
}
return nil;
}
void
insertdb(Db* db, Dbent* dp)
{
Dbent* old;
insertavl(db->tree, (Avl*)dp, (Avl**)&old);
if (old)
free(old);
}
Db*
readdb(Biobufhdr* bp)
{
Db* db;
Dbent* dp;
char* ln;
ln = Brdstr(bp, '\n', 1);
if (ln == nil)
return nil;
db = emalloc(sizeof(Db));
memset(db, 0, sizeof(Db));
db->id = ln[0];
if (strstr(ln, "replica")) // old format
db->mtime=0UL;
else
db->mtime = strtoul(ln+2, nil, 16);
free(ln);
db->tree = mkavltree(dbcmp);
while(dp = readdbent(bp))
insertdb(db, dp);
return db;
}
Db*
newdb(char id)
{
Db* db;
db = emalloc(sizeof(Db));
memset(db, 0, sizeof(Db));
db->id = id;
db->tree = mkavltree(dbcmp);
db->mtime = time(nil);
return db;
}
Db*
readdbfile(char* file)
{
Db* db;
Biobuf* bin;
Dir* d;
d = dirstat(file);
if (d != nil){
if (d->qid.type&QTDIR)
error("dbfile is a directory.");
free(d);
}
bin = Bopen(file, OREAD);
if (bin == nil)
error("can't open %s: %r", file);
db = readdb(bin);
/* We'll keep the db locked until the caller process
*
* Bterm(bin);
*/
return db;
}
void
writedb(Biobufhdr* bp, Db* db)
{
Avlwalk*w;
Dbent* dp;
Bprint(bp, "%c %08ulx repl db:\n", db->id, db->mtime);
w = avlwalk(db->tree);
while(dp = (Dbent*)avlnext(w)){
if (Bprint(bp, "%s %s %s %s %08ulx %08ulx %lld %uld\n",
dp->fname, dp->hist,
dp->uid, dp->gid, dp->mode, dp->mtime, dp->length,
dp->vers) < 0)
sysfatal("writedb");
}
endwalk(w);
}
void
writedbfile(char* file, Db* db)
{
Biobuf* bout;
Dir* dp;
Dir d;
bout = Bopen(file,OWRITE|OTRUNC);
if (bout == nil)
error("can't open %s: %r", file);
writedb(bout, db);
if (Bterm(bout) < 0)
error("closing %s: %r", file);
dp = dirstat(file);
if (dp != nil){
if (!(dp->mode&DMEXCL)){
nulldir(&d);
d.mode = dp->mode|DMEXCL;
dirwstat(file, &d);
}
free(dp);
}
}
void
rename(char* to, char* frompath)
{
Dir d;
char* p;
remove(to);
p = strrchr(to, '/');
if (p != nil)
to = p + 1;
nulldir(&d);
d.name = to;
if (dirwstat(frompath, &d) < 0)
error("can't rename %s: %r", frompath);
}