]> git.lizzy.rs Git - plan9front.git/commitdiff
git/fs: use a better heuristic for permissions.
authorOri Bernstein <ori@eigenstate.org>
Tue, 22 Jun 2021 23:55:54 +0000 (23:55 +0000)
committerOri Bernstein <ori@eigenstate.org>
Tue, 22 Jun 2021 23:55:54 +0000 (23:55 +0000)
Since we now store /dist/plan9front in git, the
initial assumption that the owner of the repo
is the person touching it is not always true.

This change gives us a better heuristic for the
file permissions we should have in the files we
copy around, basing it off of the permissions of
the .git directory.

sys/man/4/gitfs
sys/src/cmd/git/fs.c
sys/src/cmd/git/pack.c

index 819435cecc830095e9aec7c171db5fa70edfd8d3..cd71e64306fd7743411c6e26b1774c78b09b2f8c 100644 (file)
@@ -74,6 +74,15 @@ hierarchy are the same as the date of the commit.
 .PP
 Trees are presented as directory listings, and blobs
 as files.
+The repository controls the user permissions.
+The group and world permissions are derived by masking
+the user permissions with the permissions of the
+.I .git
+directory.
+The user and group presented is the same as the user and
+group of the
+.I .git
+directory.
 
 .SH FILES
 .TP
@@ -100,11 +109,14 @@ The global configuration for git tools.
 
 .SH BUGS
 Symlinks are only partially supported.
-Symlinks are treated as regular files when reading.
-Modifying symlinks is unsupported.
+They will be followed when reading, but a commit that
+modifies a symlink is an error.
 
 .PP
-There is no way to inspect the raw objects. This is
-a feature that would be useful for debugging.
+For efficiency, git/fs only loads repo permissions at startup
+
+.PP
+There is no way to inspect the raw objects.
+Inspecting raw objects would be useful for debugging.
 
 
index f116f29737111d932ac9f0d41ba13ad345f53295..945a720f2362c1edce07c6c6bfa8ea2b2b2ecb57 100644 (file)
@@ -79,6 +79,7 @@ char *qroot[] = {
 
 char   gitdir[512];
 char   *username;
+char   *groupname;
 char   *mntpt = ".git/fs";
 char   **branches = nil;
 Cache  uqidcache[512];
@@ -164,7 +165,7 @@ obj2dir(Dir *d, Crumb *c, Object *o, char *name)
        d->mode = c->mode;
        d->name = estrdup9p(name);
        d->uid = estrdup9p(username);
-       d->gid = estrdup9p(username);
+       d->gid = estrdup9p(groupname);
        d->muid = estrdup9p(username);
        if(o->type == GBlob || o->type == GTag){
                d->qid.type = 0;
@@ -188,7 +189,7 @@ rootgen(int i, Dir *d, void *p)
        d->qid.type = strcmp(qroot[i], "ctl") == 0 ? 0 : QTDIR;
        d->qid.path = qpath(nil, i, i, Qroot);
        d->uid = estrdup9p(username);
-       d->gid = estrdup9p(username);
+       d->gid = estrdup9p(groupname);
        d->muid = estrdup9p(username);
        d->mtime = c->mtime;
        return 0;
@@ -210,7 +211,7 @@ branchgen(int i, Dir *d, void *p)
        d->qid.path = qpath(c, i, branchid(aux, aux->refpath), Qbranch | Internal);
        d->mode = 0555 | DMDIR;
        d->uid = estrdup9p(username);
-       d->gid = estrdup9p(username);
+       d->gid = estrdup9p(groupname);
        d->muid = estrdup9p(username);
        d->mtime = c->mtime;
        d->atime = c->mtime;
@@ -251,11 +252,10 @@ gtreegen(int i, Dir *d, void *p)
        d->qid.type = o->type == GTree ? QTDIR : 0;
        d->qid.path = qpath(c, i, o->id, aux->qdir);
        d->mode = m;
-       d->mode |= (o->type == GTree) ? 0755 : 0644;
        d->atime = c->mtime;
        d->mtime = c->mtime;
        d->uid = estrdup9p(username);
-       d->gid = estrdup9p(username);
+       d->gid = estrdup9p(groupname);
        d->muid = estrdup9p(username);
        d->name = estrdup9p(e->tree->ent[i].name);
        d->length = o->size;
@@ -271,7 +271,7 @@ gcommitgen(int i, Dir *d, void *p)
        c = crumb(p, 0);
        o = c->obj;
        d->uid = estrdup9p(username);
-       d->gid = estrdup9p(username);
+       d->gid = estrdup9p(groupname);
        d->muid = estrdup9p(username);
        d->mode = 0444;
        d->atime = o->commit->ctime;
@@ -490,7 +490,7 @@ objwalk1(Qid *q, Object *o, Crumb *p, Crumb *c, char *name, vlong qdir, Gitaux *
        }else if(o->type == GCommit){
                q->type = 0;
                c->mtime = o->commit->mtime;
-               c->mode = 0444;
+               c->mode = 0644;
                assert(qdir == Qcommit || qdir == Qobject || qdir == Qcommittree || qdir == Qhead);
                if(strcmp(name, "msg") == 0)
                        q->path = qpath(p, 0, o->id, Qcommitmsg);
@@ -804,7 +804,7 @@ gitstat(Req *r)
        aux = r->fid->aux;
        c = crumb(aux, 0);
        r->d.uid = estrdup9p(username);
-       r->d.gid = estrdup9p(username);
+       r->d.gid = estrdup9p(groupname);
        r->d.muid = estrdup9p(username);
        r->d.qid = r->fid->qid;
        r->d.mtime = c->mtime;
@@ -837,6 +837,8 @@ usage(void)
 void
 main(int argc, char **argv)
 {
+       Dir *d;
+
        gitinit();
        ARGBEGIN{
        case 'd':
@@ -852,7 +854,12 @@ main(int argc, char **argv)
        if(argc != 0)
                usage();
 
-       username = getuser();
+       if((d = dirstat(".git")) == nil)
+               sysfatal("dirstat .git: %r");
+       username = strdup(d->uid);
+       groupname = strdup(d->gid);
+       free(d);
+
        branches = emalloc(sizeof(char*));
        branches[0] = nil;
        postmountsrv(&gitsrv, nil, mntpt, MCREATE);
index 50077ba2771ce4167632dcab7754fdd3cc1d1b33..2ffcdec57e331ad9c49d2530387919099642e3a7 100644 (file)
@@ -70,6 +70,7 @@ int   cachemax = 4096;
 Packf  *packf;
 int    npackf;
 int    openpacks;
+int    gitdirmode = -1;
 
 static void
 clear(Object *o)
@@ -887,7 +888,7 @@ parsecommit(Object *o)
 static void
 parsetree(Object *o)
 {
-       int m, entsz, nent;
+       int m, a, entsz, nent;
        Dirent *t, *ent;
        char *p, *ep;
 
@@ -908,7 +909,15 @@ parsetree(Object *o)
                if(*p != ' ')
                        sysfatal("malformed tree %H: *p=(%d) %c\n", o->hash, *p, *p);
                p++;
-               t->mode = m & 0777;     
+               /*
+                * only the stored permissions for the user
+                * are relevant; git fills group and world
+                * bits with whatever -- so to serve with
+                * useful permissions, replicate the mode
+                * of the git repo dir.
+                */
+               a = (m & 0777)>>6;
+               t->mode = ((a<<6)|(a<<3)|a) & gitdirmode;
                t->ismod = 0;
                t->islink = 0;
                if(m == 0160000){
@@ -1048,7 +1057,14 @@ Object*
 readobject(Hash h)
 {
        Object *o;
+       Dir *d;
 
+       if(gitdirmode == -1){
+               if((d = dirstat(".git")) == nil)
+                       sysfatal("stat .git: %r");
+               gitdirmode = d->mode & 0777;
+               free(d);
+       }
        if((o = readidxobject(nil, h, 0)) == nil)
                return nil;
        parseobject(o);