typedef struct VacFs VacFs;
typedef struct VacDir VacDir;
typedef struct VacFile VacFile;
typedef struct VacDirEnum VacDirEnum;

#pragma incomplete VacFile
#pragma incomplete VacDirEnum

/*
* Mode bits
*/
enum
{
       ModeOtherExec = (1<<0),
       ModeOtherWrite = (1<<1),
       ModeOtherRead = (1<<2),
       ModeGroupExec = (1<<3),
       ModeGroupWrite = (1<<4),
       ModeGroupRead = (1<<5),
       ModeOwnerExec = (1<<6),
       ModeOwnerWrite = (1<<7),
       ModeOwnerRead = (1<<8),
       ModeSticky = (1<<9),
       ModeSetUid = (1<<10),
       ModeSetGid = (1<<11),
       ModeAppend = (1<<12),           /* append only file */
       ModeExclusive = (1<<13),        /* lock file - plan 9 */
       ModeLink = (1<<14),             /* sym link */
       ModeDir = (1<<15),              /* duplicate of DirEntry */
       ModeHidden = (1<<16),           /* MS-DOS */
       ModeSystem = (1<<17),           /* MS-DOS */
       ModeArchive = (1<<18),          /* MS-DOS */
       ModeTemporary = (1<<19),        /* MS-DOS */
       ModeSnapshot = (1<<20),         /* read only snapshot */
       ModeDevice = (1<<21),           /* Unix device */
       ModeNamedPipe = (1<<22) /* Unix named pipe */
};

enum
{
       MetaMagic = 0x5656fc79,
       MetaHeaderSize = 12,
       MetaIndexSize = 4,
       IndexEntrySize = 8,
       DirMagic = 0x1c4d9072
};

enum
{
       DirPlan9Entry = 1,      /* not valid in version >= 9 */
       DirNTEntry,             /* not valid in version >= 9 */
       DirQidSpaceEntry,
       DirGenEntry             /* not valid in version >= 9 */
};

struct VacDir
{
       char *elem;             /* path element */
       ulong entry;            /* entry in directory for data */
       ulong gen;              /* generation of data entry */
       ulong mentry;           /* entry in directory for meta */
       ulong mgen;             /* generation of meta entry */
       uvlong size;            /* size of file */
       uvlong qid;             /* unique file id */

       char *uid;              /* owner id */
       char *gid;              /* group id */
       char *mid;              /* last modified by */
       ulong mtime;            /* last modified time */
       ulong mcount;           /* number of modifications: can wrap! */
       ulong ctime;            /* directory entry last changed */
       ulong atime;            /* last time accessed */
       ulong mode;             /* various mode bits */

       /* plan 9 */
       int plan9;
       uvlong p9path;
       ulong p9version;

       /* sub space of qid */
       int qidspace;
       uvlong qidoffset;       /* qid offset */
       uvlong qidmax;          /* qid maximum */
};

struct VacFs
{
       char    name[128];
       uchar   score[VtScoreSize];
       VacFile *root;
       VtConn  *z;
       int             mode;
       int             bsize;
       uvlong  qid;
       VtCache *cache;
};

VacFs   *vacfsopen(VtConn *z, char *file, int mode, int ncache);
VacFs   *vacfsopenscore(VtConn *z, u8int *score, int mode, int ncache);
VacFs   *vacfscreate(VtConn *z, int bsize, int ncache);
void            vacfsclose(VacFs *fs);
int             vacfssync(VacFs *fs);
int             vacfssnapshot(VacFs *fs, char *src, char *dst);
int             vacfsgetscore(VacFs *fs, u8int *score);
int             vacfsgetmaxqid(VacFs*, uvlong*);
void            vacfsjumpqid(VacFs*, uvlong);

VacFile *vacfsgetroot(VacFs *fs);
VacFile *vacfileopen(VacFs *fs, char *path);
VacFile *vacfilecreate(VacFile *file, char *elem, ulong perm);
VacFile *vacfilewalk(VacFile *file, char *elem);
int             vacfileremove(VacFile *file);
int             vacfileread(VacFile *file, void *buf, int n, vlong offset);
int             vacfileblockscore(VacFile *file, u32int, u8int*);
int             vacfilewrite(VacFile *file, void *buf, int n, vlong offset);
uvlong  vacfilegetid(VacFile *file);
ulong   vacfilegetmcount(VacFile *file);
int             vacfileisdir(VacFile *file);
int             vacfileisroot(VacFile *file);
ulong   vacfilegetmode(VacFile *file);
int             vacfilegetsize(VacFile *file, uvlong *size);
int             vacfilegetdir(VacFile *file, VacDir *dir);
int             vacfilesetdir(VacFile *file, VacDir *dir);
VacFile *vacfilegetparent(VacFile *file);
int             vacfileflush(VacFile*, int);
VacFile *vacfileincref(VacFile*);
int             vacfiledecref(VacFile*);
int             vacfilesetsize(VacFile *f, uvlong size);

int             vacfilegetentries(VacFile *f, VtEntry *e, VtEntry *me);
int             vacfilesetentries(VacFile *f, VtEntry *e, VtEntry *me);

void            vdcleanup(VacDir *dir);
void            vdcopy(VacDir *dst, VacDir *src);
int             vacfilesetqidspace(VacFile*, u64int, u64int);
uvlong  vacfilegetqidoffset(VacFile*);

VacDirEnum      *vdeopen(VacFile*);
int                     vderead(VacDirEnum*, VacDir *);
void                    vdeclose(VacDirEnum*);
int     vdeunread(VacDirEnum*);

int     vacfiledsize(VacFile *f);
int     sha1matches(VacFile *f, ulong b, uchar *buf, int n);