1 #include "u.h" 2 #include "../port/lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "../port/error.h" 7 #define DEVTAB 8 #include "devtab.h" 9 10 extern ulong kerndate; 11 12 int 13 devno(int c, int user) 14 { 15 Rune *s; 16 int i; 17 18 s = devchar; 19 i = 0; 20 while(*s){ 21 if(c == *s) 22 return i; 23 i++; 24 s++; 25 } 26 27 if(user) 28 return -1; 29 panic("devno %C 0x%ux", c, c); 30 return 0; 31 } 32 33 void 34 devdir(Chan *c, Qid qid, char *n, long length, char *user, long perm, Dir *db) 35 { 36 strcpy(db->name, n); 37 db->qid = qid; 38 db->type = devchar[c->type]; 39 db->dev = c->dev; 40 if(qid.path & CHDIR) 41 db->mode = CHDIR|perm; 42 else 43 db->mode = perm; 44 if(c->flag&CMSG) 45 db->mode |= CHMOUNT; 46 db->atime = seconds(); 47 db->mtime = kerndate; 48 db->hlength = 0; 49 db->length = length; 50 memmove(db->uid, user, NAMELEN); 51 memmove(db->gid, eve, NAMELEN); 52 } 53 54 int 55 devgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp) 56 { 57 if(tab==0 || i>=ntab) 58 return -1; 59 tab += i; 60 devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp); 61 return 1; 62 } 63 64 Chan * 65 devattach(int tc, char *spec) 66 { 67 Chan *c; 68 69 USED(spec); 70 c = newchan(); 71 c->qid = (Qid){CHDIR, 0}; 72 c->type = devno(tc, 0); 73 return c; 74 } 75 76 Chan * 77 devclone(Chan *c, Chan *nc) 78 { 79 if(c->flag & COPEN) 80 panic("clone of open file type %C\n", devchar[c->type]); 81 if(nc == 0) 82 nc = newchan(); 83 nc->type = c->type; 84 nc->dev = c->dev; 85 nc->mode = c->mode; 86 nc->qid = c->qid; 87 nc->offset = c->offset; 88 nc->flag = c->flag; 89 nc->mnt = c->mnt; 90 nc->mountid = c->mountid; 91 nc->aux = c->aux; 92 nc->mchan = c->mchan; 93 nc->mqid = c->mqid; 94 return nc; 95 } 96 97 int 98 devwalk(Chan *c, char *name, Dirtab *tab, int ntab, Devgen *gen) 99 { 100 long i; 101 Dir dir; 102 103 isdir(c); 104 if(name[0]=='.' && name[1]==0) 105 return 1; 106 for(i=0;; i++) 107 switch((*gen)(c, tab, ntab, i, &dir)){ 108 case -1: 109 strncpy(u->error, Enonexist, NAMELEN); 110 return 0; 111 case 0: 112 continue; 113 case 1: 114 if(strcmp(name, dir.name) == 0){ 115 c->qid = dir.qid; 116 return 1; 117 } 118 continue; 119 } 120 return 1; /* not reached */ 121 } 122 123 void 124 devstat(Chan *c, char *db, Dirtab *tab, int ntab, Devgen *gen) 125 { 126 int i; 127 Dir dir; 128 129 for(i=0;; i++) 130 switch((*gen)(c, tab, ntab, i, &dir)){ 131 case -1: 132 /* 133 * given a channel, we cannot derive the directory name 134 * that the channel was generated from since it was lost 135 * by namec. 136 */ 137 if(c->qid.path & CHDIR){ 138 devdir(c, c->qid, ".", 0L, eve, CHDIR|0775, &dir); 139 convD2M(&dir, db); 140 return; 141 } 142 print("%s %s: devstat %C %lux\n", u->p->text, u->p->user, 143 devchar[c->type], c->qid.path); 144 error(Enonexist); 145 case 0: 146 break; 147 case 1: 148 if(eqqid(c->qid, dir.qid)){ 149 if(c->flag&CMSG) 150 dir.mode |= CHMOUNT; 151 convD2M(&dir, db); 152 return; 153 } 154 break; 155 } 156 } 157 158 long 159 devdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen) 160 { 161 long k, m; 162 Dir dir; 163 164 k = c->offset/DIRLEN; 165 for(m=0; m<n; k++) 166 switch((*gen)(c, tab, ntab, k, &dir)){ 167 case -1: 168 return m; 169 170 case 0: 171 c->offset += DIRLEN; 172 break; 173 174 case 1: 175 convD2M(&dir, d); 176 m += DIRLEN; 177 d += DIRLEN; 178 break; 179 } 180 return m; 181 } 182 183 Chan * 184 devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen) 185 { 186 int i; 187 Dir dir; 188 ulong t, mode; 189 static int access[] = { 0400, 0200, 0600, 0100 }; 190 191 for(i=0;; i++) 192 switch((*gen)(c, tab, ntab, i, &dir)){ 193 case -1: 194 goto Return; 195 case 0: 196 break; 197 case 1: 198 if(eqqid(c->qid, dir.qid)) { 199 if(strcmp(u->p->user, dir.uid) == 0) /* User */ 200 mode = dir.mode; 201 else if(strcmp(u->p->user, eve) == 0) /* eve is group */ 202 mode = dir.mode<<3; 203 else 204 mode = dir.mode<<6; /* Other */ 205 206 t = access[omode&3]; 207 if((t & mode) == t) 208 goto Return; 209 error(Eperm); 210 } 211 break; 212 } 213 Return: 214 c->offset = 0; 215 if((c->qid.path&CHDIR) && omode!=OREAD) 216 error(Eperm); 217 c->mode = openmode(omode); 218 c->flag |= COPEN; 219 return c; 220 } 221