1 #include <u.h> 2 #include <libc.h> 3 #include <fcall.h> 4 #include <thread.h> 5 #include <9p.h> 6 #include "dat.h" 7 #include "fns.h" 8 9 #define thdr r->ifcall 10 #define rhdr r->ofcall 11 12 extern int errno; 13 14 static void 15 response(Req *r) 16 { 17 char *err; 18 19 if (errno) { 20 err = xerrstr(errno); 21 chat("%s\n", err); 22 respond(r, err); 23 } else { 24 chat("OK\n"); 25 respond(r, nil); 26 } 27 } 28 29 static void 30 rattach(Req *r) 31 { 32 Xfs *xf; 33 Xfile *root; 34 35 chat("attach(fid=%d,uname=\"%s\",aname=\"%s\",afid=\"%d\")...", 36 thdr.fid, thdr.uname, thdr.aname, thdr.afid); 37 38 errno = 0; 39 root = xfile(r->fid, Clean); 40 if(!root){ 41 errno = Enomem; 42 goto error; 43 } 44 root->xf = xf = getxfs(thdr.aname); 45 if(!xf) 46 goto error; 47 48 /* now attach root inode */ 49 if( get_inode(root, EXT2_ROOT_INODE) < 0 ) 50 goto error; 51 52 r->fid->qid.type = QTDIR; 53 r->fid->qid.vers = 0; 54 root->xf->rootqid = r->fid->qid; 55 root->pinbr = EXT2_ROOT_INODE; 56 root->root = 1; 57 rhdr.qid = r->fid->qid; 58 59 error: 60 response(r); 61 } 62 static char * 63 rclone(Fid *fid, Fid *newfid) 64 { 65 Xfile *of = xfile(fid, Asis); 66 Xfile *nf = xfile(newfid, Clean); 67 68 chat("clone(fid=%d,newfid=%d)...", fid->fid, newfid->fid); 69 errno = 0; 70 if(!of) 71 errno = Eio; 72 else if(!nf) 73 errno = Enomem; 74 else{ 75 Xfile *next = nf->next; 76 *nf = *of; 77 nf->next = next; 78 nf->fid = newfid->fid; 79 nf->root = 0; 80 } 81 chat("%s\n", errno? xerrstr(errno) : "OK"); 82 return errno ? xerrstr(errno) : 0; 83 } 84 static char * 85 rwalk1(Fid *fid, char *name, Qid *qid) 86 { 87 Xfile *f=xfile(fid, Asis); 88 int nr, sinbr = 0; 89 90 chat("walk1(fid=%d,name=\"%s\")...", fid->fid, name); 91 errno = 0; 92 if( !f ){ 93 chat("no xfile..."); 94 goto error; 95 } 96 if( !(fid->qid.type & QTDIR) ){ 97 chat("qid.type=0x%x...", fid->qid.type); 98 goto error; 99 } 100 sinbr = f->pinbr; 101 if( name == 0 || name[0] == 0 || !strcmp(name, ".") ){ 102 *qid = fid->qid; 103 goto ok; 104 }else if( !strcmp(name, "..") ){ 105 if( fid->qid.path == f->xf->rootqid.path ){ 106 chat("walkup from root..."); 107 *qid = fid->qid; 108 goto ok; 109 } 110 if( get_inode(f, f->pinbr) < 0 ) 111 goto error; 112 if( f->pinbr == EXT2_ROOT_INODE ){ 113 *qid = f->xf->rootqid; 114 f->pinbr = EXT2_ROOT_INODE; 115 } else { 116 *qid = (Qid){f->pinbr,0,QTDIR}; 117 f->inbr = f->pinbr; 118 if( (nr = get_file(f, "..")) < 0 ) 119 goto error; 120 f->pinbr = nr; 121 } 122 }else{ 123 f->pinbr = f->inbr; 124 if( (nr = get_file(f, name)) < 0 ) 125 goto error; 126 if( get_inode(f, nr) < 0 ) 127 goto error; 128 *qid = (Qid){nr,0,0}; 129 if( nr == EXT2_ROOT_INODE ) 130 *qid = f->xf->rootqid; 131 else if( S_ISDIR(getmode(f)) ) 132 qid->type = QTDIR; 133 /*strcpy(f->name, thdr.name);*/ 134 } 135 ok: 136 chat("OK\n"); 137 return 0; 138 error: 139 f->pinbr = sinbr; 140 chat("%s\n", xerrstr(Enonexist)); 141 return xerrstr(Enonexist); 142 } 143 static void 144 rstat(Req *r) 145 { 146 Xfile *f=xfile(r->fid, Asis); 147 148 chat("stat(fid=%d)...", thdr.fid); 149 errno = 0; 150 if( !f ) 151 errno = Eio; 152 else{ 153 dostat(r->fid->qid, f, &r->d); 154 } 155 response(r); 156 } 157 static void 158 rwstat(Req *r) 159 { 160 Xfile *f=xfile(r->fid, Asis); 161 162 chat("wstat(fid=%d)...", thdr.fid); 163 errno = 0; 164 if( !f ) 165 errno = Eio; 166 else 167 dowstat(f, &r->d); 168 response(r); 169 } 170 static void 171 rread(Req *r) 172 { 173 Xfile *f; 174 int nr; 175 176 chat("read(fid=%d,offset=%lld,count=%d)...", 177 thdr.fid, thdr.offset, thdr.count); 178 errno = 0; 179 if ( !(f=xfile(r->fid, Asis)) ) 180 goto error; 181 if( r->fid->qid.type & QTDIR ){ 182 nr = readdir(f, r->rbuf, thdr.offset, thdr.count); 183 }else 184 nr = readfile(f, r->rbuf, thdr.offset, thdr.count); 185 186 if(nr >= 0){ 187 rhdr.count = nr; 188 chat("rcnt=%d...OK\n", nr); 189 respond(r, nil); 190 return; 191 } 192 error: 193 errno = Eio; 194 response(r); 195 } 196 static void 197 rwrite(Req *r) 198 { 199 Xfile *f; int nr; 200 201 chat("write(fid=%d,offset=%lld,count=%d)...", 202 thdr.fid, thdr.offset, thdr.count); 203 204 errno = 0; 205 if (!(f=xfile(r->fid, Asis)) ){ 206 errno = Eio; 207 goto error; 208 } 209 if( !S_ISREG(getmode(f)) ){ 210 errno = Elink; 211 goto error; 212 } 213 nr = writefile(f, thdr.data, thdr.offset, thdr.count); 214 if(nr >= 0){ 215 rhdr.count = nr; 216 chat("rcnt=%d...OK\n", nr); 217 respond(r, nil); 218 return; 219 } 220 errno = Eio; 221 error: 222 response(r); 223 } 224 static void 225 destroyfid(Fid *fid) 226 { 227 chat("destroy(fid=%d)\n", fid->fid); 228 xfile(fid, Clunk); 229 /*syncbuf(xf);*/ 230 } 231 static void 232 ropen(Req *r) 233 { 234 Xfile *f; 235 236 chat("open(fid=%d,mode=%d)...", thdr.fid, thdr.mode); 237 238 errno = 0; 239 f = xfile(r->fid, Asis); 240 if( !f ){ 241 errno = Eio; 242 goto error; 243 } 244 245 if(thdr.mode & OTRUNC){ 246 if( !S_ISREG(getmode(f)) ){ 247 errno = Eperm; 248 goto error; 249 } 250 if(truncfile(f) < 0){ 251 goto error; 252 } 253 } 254 chat("f->qid=0x%8.8lux...", r->fid->qid.path); 255 rhdr.qid = r->fid->qid; 256 error: 257 response(r); 258 } 259 static void 260 rcreate(Req *r) 261 { 262 Xfile *f; 263 int inr, perm; 264 265 chat("create(fid=%d,name=\"%s\",perm=%uo,mode=%d)...", 266 thdr.fid, thdr.name, thdr.perm, thdr.mode); 267 268 errno = 0; 269 if(strcmp(thdr.name, ".") == 0 || strcmp(thdr.name, "..") == 0){ 270 errno = Eperm; 271 goto error; 272 } 273 f = xfile(r->fid, Asis); 274 if( !f ){ 275 errno = Eio; 276 goto error; 277 } 278 if( strlen(thdr.name) > EXT2_NAME_LEN ){ 279 chat("name too long ..."); 280 errno = Elongname; 281 goto error; 282 } 283 284 /* create */ 285 errno = 0; 286 if( thdr.perm & DMDIR ){ 287 perm = (thdr.perm & ~0777) | 288 (getmode(f) & thdr.perm & 0777); 289 perm |= S_IFDIR; 290 inr = create_dir(f, thdr.name, perm); 291 }else{ 292 perm = (thdr.perm & (~0777|0111)) | 293 (getmode(f) & thdr.perm & 0666); 294 perm |= S_IFREG; 295 inr = create_file(f, thdr.name, perm); 296 297 } 298 if( inr < 0 ) 299 goto error; 300 301 /* fill with new inode */ 302 f->pinbr = f->inbr; 303 if( get_inode(f, inr) < 0 ){ 304 errno = Eio; 305 goto error; 306 } 307 r->fid->qid = (Qid){inr, 0, 0}; 308 if( S_ISDIR(getmode(f)) ) 309 r->fid->qid.type |= QTDIR; 310 chat("f->qid=0x%8.8lux...", r->fid->qid.path); 311 rhdr.qid = r->fid->qid; 312 error: 313 response(r); 314 } 315 static void 316 rremove(Req *r) 317 { 318 Xfile *f=xfile(r->fid, Asis); 319 320 chat("remove(fid=%d) ...", thdr.fid); 321 322 errno = 0; 323 if(!f){ 324 errno = Eio; 325 goto error; 326 } 327 328 /* check permission here !!!!*/ 329 330 unlink(f); 331 332 error: 333 response(r); 334 } 335 336 Srv ext2srv = { 337 .destroyfid = destroyfid, 338 .attach = rattach, 339 .stat = rstat, 340 .wstat = rwstat, 341 .clone = rclone, 342 .walk1 = rwalk1, 343 .open = ropen, 344 .read = rread, 345 .write = rwrite, 346 .create = rcreate, 347 .remove = rremove, 348 }; 349