plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

mntgen.c (3755B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <fcall.h>
      4 #include <thread.h>
      5 #include <9p.h>
      6 #include <mp.h>
      7 #include <libsec.h>
      8 
      9 static void
     10 usage(void)
     11 {
     12 	fprint(2, "mntgen [-s srvname] [mtpt]\n");
     13 	threadexits("usage");
     14 }
     15 
     16 ulong time0;
     17 
     18 typedef struct Tab Tab;
     19 struct Tab
     20 {
     21 	char *name;
     22 	vlong qid;
     23 	ulong time;
     24 	int ref;
     25 };
     26 
     27 Tab *tab;
     28 int ntab;
     29 int mtab;
     30 
     31 static Tab*
     32 findtab(vlong path)
     33 {
     34 	int i;
     35 
     36 	for(i=0; i<ntab; i++)
     37 		if(tab[i].qid == path)
     38 			return &tab[i];
     39 	return nil;
     40 }
     41 
     42 static vlong
     43 hash(char *name)
     44 {
     45 	vlong digest[MD5dlen / sizeof(vlong) + 1];
     46 	md5((uchar *)name, strlen(name), (uchar *)digest, nil);
     47 	return digest[0] & ((1ULL<<48)-1);
     48 }
     49 
     50 static void
     51 fsopen(Req *r)
     52 {
     53 	if(r->ifcall.mode != OREAD)
     54 		respond(r, "permission denied");
     55 	else
     56 		respond(r, nil);
     57 }
     58 
     59 static int
     60 dirgen(int i, Dir *d, void* v)
     61 {
     62 	USED(v);
     63 
     64 	if(i >= ntab)
     65 		return -1;
     66 	memset(d, 0, sizeof *d);
     67 	d->qid.type = QTDIR;
     68 	d->uid = estrdup9p("sys");
     69 	d->gid = estrdup9p("sys");
     70 	d->mode = DMDIR|0555;
     71 	d->length = 0;
     72 	if(i == -1){
     73 		d->name = estrdup9p("/");
     74 		d->atime = d->mtime = time0;
     75 	}else{
     76 		d->qid.path = tab[i].qid;
     77 		d->name = estrdup9p(tab[i].name);
     78 		d->atime = d->mtime = tab[i].time;
     79 	}
     80 	return 0;
     81 }
     82 
     83 static void
     84 fsread(Req *r)
     85 {
     86 	if(r->fid->qid.path == 0)
     87 		dirread9p(r, dirgen, nil);
     88 	else
     89 		r->ofcall.count = 0;
     90 	respond(r, nil);
     91 }
     92 
     93 static void
     94 fsstat(Req *r)
     95 {
     96 	Tab *t;
     97 	vlong qid;
     98 
     99 	qid = r->fid->qid.path;
    100 	if(qid == 0)
    101 		dirgen(-1, &r->d, nil);
    102 	else{
    103 		if((t = findtab(qid)) == nil){
    104 			respond(r, "path not found ( ??? )");
    105 			return;
    106 		}
    107 		dirgen(t-tab, &r->d, nil);
    108 	}
    109 	respond(r, nil);
    110 }
    111 
    112 static char*
    113 fswalk1(Fid *fid, char *name, void* v)
    114 {
    115 	int i;
    116 	Tab *t;
    117 	vlong h;
    118 
    119 	USED(v);
    120 
    121 	if(fid->qid.path != 0){
    122 		/* nothing in child directory */
    123 		if(strcmp(name, "..") == 0){
    124 			if((t = findtab(fid->qid.path)) != nil)
    125 				t->ref--;
    126 			fid->qid.path = 0;
    127 			return nil;
    128 		}
    129 		return "path not found";
    130 	}
    131 	/* root */
    132 	if(strcmp(name, "..") == 0)
    133 		return nil;
    134 	for(i=0; i<ntab; i++)
    135 		if(strcmp(tab[i].name, name) == 0){
    136 			tab[i].ref++;
    137 			fid->qid.path = tab[i].qid;
    138 			return nil;
    139 		}
    140 	h = hash(name);
    141 	if(findtab(h) != nil)
    142 		return "hash collision";
    143 
    144 	/* create it */
    145 	if(ntab == mtab){
    146 		if(mtab == 0)
    147 			mtab = 16;
    148 		else
    149 			mtab *= 2;
    150 		tab = erealloc9p(tab, sizeof(tab[0])*mtab);
    151 	}
    152 	tab[ntab].qid = h;
    153 	fid->qid.path = tab[ntab].qid;
    154 	tab[ntab].name = estrdup9p(name);
    155 	tab[ntab].time = time(0);
    156 	tab[ntab].ref = 1;
    157 	ntab++;
    158 
    159 	return nil;
    160 }
    161 
    162 static char*
    163 fsclone(Fid *fid, Fid* v, void* w)
    164 {
    165 	USED(v);
    166 	USED(w);
    167 
    168 	Tab *t;
    169 
    170 	if((t = findtab(fid->qid.path)) != nil)
    171 		t->ref++;
    172 	return nil;
    173 }
    174 
    175 static void
    176 fswalk(Req *r)
    177 {
    178 	walkandclone(r, fswalk1, fsclone, nil);
    179 }
    180 
    181 static void
    182 fsclunk(Fid *fid)
    183 {
    184 	Tab *t;
    185 	vlong qid;
    186 
    187 	qid = fid->qid.path;
    188 	if(qid == 0)
    189 		return;
    190 	if((t = findtab(qid)) == nil){
    191 		fprint(2, "warning: cannot find %llux\n", qid);
    192 		return;
    193 	}
    194 	if(--t->ref == 0){
    195 		free(t->name);
    196 		tab[t-tab] = tab[--ntab];
    197 	}else if(t->ref < 0)
    198 		fprint(2, "warning: negative ref count for %s\n", t->name);
    199 }
    200 
    201 static void
    202 fsattach(Req *r)
    203 {
    204 	char *spec;
    205 
    206 	spec = r->ifcall.aname;
    207 	if(spec && spec[0]){
    208 		respond(r, "invalid attach specifier");
    209 		return;
    210 	}
    211 	
    212 	r->ofcall.qid = (Qid){0, 0, QTDIR};
    213 	r->fid->qid = r->ofcall.qid;
    214 	respond(r, nil);
    215 }
    216 
    217 Srv fs=
    218 {
    219 .attach=	fsattach,
    220 .open=	fsopen,
    221 .read=	fsread,
    222 .stat=	fsstat,
    223 .walk=	fswalk,
    224 .destroyfid=	fsclunk
    225 };
    226 
    227 int
    228 threadmaybackground(void)
    229 {
    230 	return 1;
    231 }
    232 
    233 void
    234 threadmain(int argc, char *argv[])
    235 {
    236 	char *service;
    237 
    238 	time0 = time(0);
    239 	service = nil;
    240 	ARGBEGIN{
    241 	case 'D':
    242 		chatty9p++;
    243 		break;
    244 	case 's':
    245 		service = EARGF(usage());
    246 		break;
    247 	default:
    248 		usage();
    249 	}ARGEND
    250 
    251 	if(argc > 1)
    252 		usage();
    253 	threadpostmountsrv(&fs, service, argc ? argv[0] : "/n", MAFTER);
    254 	threadexits(nil);
    255 }
    256