ref: 45426d65b7b9f83a0adaf30acbec47611438f93c
parent: 22a4ca0f360a36a4a0927844e4d41e0845614826
author: Ori Bernstein <ori@eigenstate.org>
date: Fri Feb 7 18:25:16 EST 2020
add support for symlinks.
--- a/fs.c
+++ b/fs.c
@@ -84,6 +84,8 @@
Cache uqidcache[512];
vlong nextqid = Qmax;
+static char* gitwalk1(Fid *fid, char *name, Qid *q);
+
vlong
qpath(Crumb *p, int idx, vlong id, vlong t)
{
@@ -411,8 +413,29 @@
respond(r, nil);
}
+static char*
+walklink(Fid *fid, char *_path, int npath, Qid *q)
+{
+ char *p, *e, *err, *path;
+
+ err = nil;
+ path = emalloc(npath + 1);
+ memcpy(path, _path, npath);
+ cleanname(path);
+ for(p = path; *p; p = e){
+ e = p + strcspn(p, "/");
+ if(*e == '/')
+ *e++ = '\0';
+ err = gitwalk1(fid, p, q);
+ if(err != nil)
+ break;
+ }
+ free(path);
+ return err;
+}
+
static char *
-objwalk1(Qid *q, Object *o, Crumb *p, Crumb *c, char *name, vlong qdir)
+objwalk1(Fid *fid, Qid *q, Object *o, Crumb *p, Crumb *c, char *name, vlong qdir)
{
Object *w;
char *e;
@@ -432,6 +455,8 @@
w = modrefobj(&o->tree->ent[i]);
if(!w)
die("could not read object for %s: %r", name);
+ if(o->tree->ent[i].mode == 0)
+ return walklink(fid, w->data, w->size, q);
q->type = (w->type == GTree) ? QTDIR : 0;
q->path = qpath(c, i, w->id, qdir);
c->mode = o->tree->ent[i].mode;
@@ -577,7 +602,7 @@
break;
case Qobject:
if(c->obj){
- e = objwalk1(q, o->obj, o, c, name, Qobject);
+ e = objwalk1(fid, q, o->obj, o, c, name, Qobject);
}else{
if(hparse(&h, name) == -1)
return "invalid object name";
@@ -590,13 +615,13 @@
}
break;
case Qhead:
- e = objwalk1(q, o->obj, o, c, name, Qhead);
+ e = objwalk1(fid, q, o->obj, o, c, name, Qhead);
break;
case Qcommit:
- e = objwalk1(q, o->obj, o, c, name, Qcommit);
+ e = objwalk1(fid, q, o->obj, o, c, name, Qcommit);
break;
case Qcommittree:
- e = objwalk1(q, o->obj, o, c, name, Qcommittree);
+ e = objwalk1(fid, q, o->obj, o, c, name, Qcommittree);
break;
case Qcommitparent:
case Qcommitmsg:
--- a/save.c
+++ b/save.c
@@ -27,13 +27,14 @@
int
gitmode(int m)
{
- int b;
-
- if((m & 0111) || (m & DMDIR))
- b = 0755;
- else
- b = 0644;
- return b | ((m & DMDIR) ? 0040000 : 0100000);
+ if(m & DMDIR) /* directory */
+ return 0040755;
+ else if(m & 0111) /* executable */
+ return 0100755;
+ else if(m != 0) /* regular */
+ return 0100644;
+ else /* symlink */
+ return 0120000;
}
int
@@ -167,6 +168,8 @@
if((d->mode & DMDIR) != 0)
sysfatal("not file: %s", path);
+ if(*mode == 0)
+ sysfatal("symlinks may not be modified: %s", path);
*mode = d->mode;
nh = snprint(h, sizeof(h), "%T %lld", GBlob, d->length) + 1;
if((f = open(path, OREAD)) == -1)