xref: /plan9/sys/src/cmd/tapefs/util.c (revision bbd061d49f2d27022e38642b8a1e5862b40931a7)
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <fcall.h>
5 #include <bio.h>
6 #include "tapefs.h"
7 
8 Idmap *
getpass(char * file)9 getpass(char *file)
10 {
11 	Biobuf *bp;
12 	char *cp;
13 	Idmap *up;
14 	int nid, maxid;
15 	char *line[4];
16 
17 	if ((bp = Bopen(file, OREAD)) == 0)
18 		error("Can't open passwd/group");
19 	up = emalloc(1*sizeof(Idmap));
20 	maxid = 1;
21 	nid = 0;
22 	while ((cp = Brdline(bp, '\n'))) {
23 		int nf;
24 		cp[Blinelen(bp)-1] = 0;
25 		nf = getfields(cp, line, 3, 0, ":\n");
26 		if (nf<3) {
27 			fprint(2, "bad format in %s\n", file);
28 			break;
29 		}
30 		if (nid>=maxid) {
31 			maxid *= 2;
32 			up = (Idmap *)erealloc(up, maxid*sizeof(Idmap));
33 		}
34 		up[nid].id = atoi(line[2]);
35 		up[nid].name = strdup(line[0]);
36 		nid++;
37 	}
38 	Bterm(bp);
39 	up[nid].name = 0;
40 	return up;
41 }
42 
43 char *
mapid(Idmap * up,int id)44 mapid(Idmap *up, int id)
45 {
46 	char buf[16];
47 
48 	if (up)
49 		while (up->name){
50 			if (up->id==id)
51 				return strdup(up->name);
52 			up++;
53 		}
54 	sprint(buf, "%d", id);
55 	return strdup(buf);
56 }
57 
58 Ram *
poppath(Fileinf fi,int new)59 poppath(Fileinf fi, int new)
60 {
61 	char *suffix, *origname;
62 	Ram *dir, *ent;
63 	Fileinf f;
64 
65 	if (*fi.name=='\0')
66 		return 0;
67 	origname = estrdup(fi.name);
68 	if (suffix=strrchr(fi.name, '/')){
69 		*suffix = 0;
70 		suffix++;
71 		if (*suffix=='\0'){
72 			fi.mode |= DMDIR;
73 			free(origname);
74 			return poppath(fi, 1);
75 		}
76 		/*
77 		 * create parent directory of suffix;
78 		 * may recurse, thus shortening fi.name even further.
79 		 */
80 		f = fi;
81 		f.size = 0;
82 		f.addr = 0;
83 		f.mode = 0555|DMDIR;
84 		dir = poppath(f, 0);
85 		if (dir==0)
86 			dir = ram;
87 	} else {
88 		suffix = fi.name;
89 		dir = ram;
90 		if (strcmp(suffix, ".")==0) {
91 			free(origname);
92 			return dir;
93 		}
94 	}
95 	ent = lookup(dir, suffix);
96 	fi.mode |= 0400;			/* at least user read */
97 	if (ent){
98 		if (((fi.mode&DMDIR)!=0) != ((ent->qid.type&QTDIR)!=0)){
99 			fprint(2,
100 		"%s file type changed; probably due to union dir.; ignoring\n",
101 				origname);
102 			free(origname);
103 			return ent;
104 		}
105 		if (new)  {
106 			ent->ndata = fi.size;
107 			ent->addr = fi.addr;
108 			ent->data = fi.data;
109 			ent->perm = fi.mode;
110 			ent->mtime = fi.mdate;
111 			ent->user = mapid(uidmap, fi.uid);
112 			ent->group = mapid(gidmap, fi.gid);
113 		}
114 	} else {
115 		fi.name = suffix;
116 		ent = popfile(dir, fi);
117 	}
118 	free(origname);
119 	return ent;
120 }
121 
122 Ram *
popfile(Ram * dir,Fileinf fi)123 popfile(Ram *dir, Fileinf fi)
124 {
125 	Ram *ent = (Ram *)emalloc(sizeof(Ram));
126 	if (*fi.name=='\0')
127 		return 0;
128 	ent->busy = 1;
129 	ent->open = 0;
130 	ent->parent = dir;
131 	ent->next = dir->child;
132 	dir->child = ent;
133 	ent->child = 0;
134 	ent->qid.path = ++path;
135 	ent->qid.vers = 0;
136 	if(fi.mode&DMDIR)
137 		ent->qid.type = QTDIR;
138 	else
139 		ent->qid.type = QTFILE;
140 	ent->perm = fi.mode;
141 	ent->name = estrdup(fi.name);
142 	ent->atime = ent->mtime = fi.mdate;
143 	ent->user = mapid(uidmap, fi.uid);
144 	ent->group = mapid(gidmap, fi.gid);
145 	ent->ndata = fi.size;
146 	ent->data = fi.data;
147 	ent->addr = fi.addr;
148 	ent->replete |= replete;
149 	return ent;
150 }
151 
152 Ram *
lookup(Ram * dir,char * name)153 lookup(Ram *dir, char *name)
154 {
155 	Ram *r;
156 
157 	if (dir==0)
158 		return 0;
159 	for (r=dir->child; r; r=r->next){
160 		if (r->busy==0 || strcmp(r->name, name)!=0)
161 			continue;
162 		return r;
163 	}
164 	return 0;
165 }
166