1 #include "headers.h" 2 3 static void 4 smblogprintattr(int cmd, ushort attr) 5 { 6 if (attr & SMB_ATTR_READ_ONLY) 7 smblogprint(cmd, " readonly"); 8 if (attr & SMB_ATTR_HIDDEN) 9 smblogprint(cmd, " hidden"); 10 if (attr & SMB_ATTR_SYSTEM) 11 smblogprint(cmd, " system"); 12 if (attr & SMB_ATTR_DIRECTORY) 13 smblogprint(cmd, " directory"); 14 if (attr & SMB_ATTR_ARCHIVE) 15 smblogprint(cmd, " archive"); 16 } 17 18 static SmbFile * 19 openfile(SmbSession *s, SmbTree *t, char *path, ushort mode, ushort attr, ushort ofun, ulong createoptions, uvlong createsize, 20 ushort *fidp, Dir **dp, ushort *actionp) 21 { 22 int p9mode; 23 int share; 24 Dir *d = nil; 25 int fd = -1; 26 ushort action; 27 SmbFile *f = nil; 28 SmbSharedFile *sf = nil; 29 char *fullpath = nil; 30 int diropen = 0; 31 32 p9mode = (mode >> SMB_OPEN_MODE_ACCESS_SHIFT) & SMB_OPEN_MODE_ACCESS_MASK; 33 share = (mode >> SMB_OPEN_MODE_SHARE_SHIFT) & SMB_OPEN_MODE_SHARE_MASK; 34 if (share == SMB_OPEN_MODE_SHARE_COMPATIBILITY) { 35 badshare: 36 smbseterror(s, ERRDOS, ERRbadshare); 37 goto done; 38 } 39 smbstringprint(&fullpath, "%s%s", t->serv->path, path); 40 d = dirstat(fullpath); 41 if (d) { 42 /* file exists */ 43 int ofunexist; 44 if (d->mode & DMDIR) { 45 if (createoptions & SMB_CO_FILE) { 46 smbseterror(s, ERRDOS, ERRnoaccess); 47 goto done; 48 } 49 } 50 else if (createoptions & SMB_CO_DIRECTORY) { 51 smbseterror(s, ERRDOS, ERRnoaccess); 52 goto done; 53 } 54 55 sf = smbsharedfileget(d, p9mode, &share); 56 if (sf == nil) 57 goto badshare; 58 action = 1; 59 ofunexist = (ofun >> SMB_OFUN_EXIST_SHIFT) & SMB_OFUN_EXIST_MASK; 60 if (ofunexist == SMB_OFUN_EXIST_FAIL) { 61 smbseterror(s, ERRDOS, ERRfilexists); 62 goto done; 63 } 64 else if (ofunexist == SMB_OFUN_EXIST_TRUNCATE) { 65 if ((d->mode & DMDIR) || (p9mode != OWRITE && p9mode != ORDWR)) { 66 smbseterror(s, ERRDOS, ERRbadaccess); 67 goto done; 68 } 69 p9mode |= OTRUNC; 70 action = 3; 71 } 72 else if (ofunexist != SMB_OFUN_EXIST_OPEN) { 73 smbseterror(s, ERRDOS, ERRbadaccess); 74 goto done; 75 } 76 if (d->mode & DMDIR) 77 diropen = 1; 78 else 79 fd = open(fullpath, p9mode); 80 } 81 else { 82 /* file does not exist */ 83 ulong p9attr; 84 action = 3; 85 if ((ofun & SMB_OFUN_NOEXIST_CREATE) == 0) { 86 smbseterror(s, ERRDOS, ERRbadfile); 87 goto done; 88 } 89 if (createsize != 0) { 90 smbseterror(s, ERRDOS, ERRunsup); 91 goto done; 92 } 93 //smblogprint(-1, "creating: attr 0x%.4ux co 0x%.8lux\n", attr, createoptions); 94 if (createoptions & SMB_CO_FILE) { 95 attr &= SMB_ATTR_DIRECTORY; 96 if (attr == 0) 97 attr = SMB_ATTR_NORMAL; 98 } 99 else if (createoptions & SMB_CO_DIRECTORY) { 100 attr &= ~SMB_ATTR_NORMAL; 101 attr |= SMB_ATTR_DIRECTORY; 102 } 103 //smblogprint(-1, "creating: before conversion attr 0x%.4ux\n", attr); 104 p9attr = smbdosattr2plan9mode(attr); 105 //smblogprint(-1, "creating: after conversion p9attr 0%.uo\n", p9attr); 106 fd = create(fullpath, p9mode, p9attr); 107 if (fd >= 0) { 108 d = dirfstat(fd); 109 sf = smbsharedfileget(d, p9mode, &share); 110 if (sf == nil) { 111 close(fd); 112 remove(path); 113 goto badshare; 114 } 115 } 116 } 117 if (!diropen && fd < 0) { 118 smbseterror(s, ERRSRV, ERRaccess); 119 goto done; 120 } 121 f = smbemalloc(sizeof(SmbFile)); 122 if (diropen) { 123 f->ioallowed = 0; 124 f->fd = -1; 125 } 126 else { 127 f->ioallowed = 1; 128 f->fd = fd; 129 } 130 f->name = smbestrdup(path); 131 f->sf = sf; 132 sf = nil; 133 f->share = share; 134 f->p9mode = p9mode; 135 f->t = t; 136 if (s->fidmap == nil) 137 s->fidmap = smbidmapnew(); 138 *fidp = smbidmapadd(s->fidmap, f); 139 smblogprintif(smbglobals.log.fids, "openfile: 0x%.4ux/0x%.4ux %s\n", t->id, *fidp, path); 140 if (actionp) 141 *actionp = action; 142 if (dp) { 143 *dp = d; 144 d = nil; 145 } 146 done: 147 if (sf) 148 smbsharedfileput(nil, sf, share); 149 free(d); 150 free(fullpath); 151 return f; 152 } 153 154 SmbProcessResult 155 smbcomopenandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b) 156 { 157 uchar andxcommand; 158 ushort andxoffset, flags, mode, sattr, attr; 159 ulong createtime; 160 ushort ofun; 161 ulong createsize, timeout; 162 char *path = nil; 163 ulong andxoffsetfixupoffset; 164 SmbProcessResult pr; 165 ushort action; 166 Dir *d = nil; 167 SmbFile *f; 168 SmbTree *t; 169 ushort fid; 170 171 if (!smbcheckwordcount("comopenandx", h, 15)) 172 return SmbProcessResultFormat; 173 174 andxcommand = *pdata++; 175 pdata++; 176 andxoffset = smbnhgets(pdata); pdata += 2; 177 flags = smbnhgets(pdata); pdata += 2; 178 mode = smbnhgets(pdata); pdata += 2; 179 sattr = smbnhgets(pdata); pdata += 2; 180 attr = smbnhgets(pdata); pdata += 2; 181 createtime = smbnhgetl(pdata); pdata += 4; 182 ofun = smbnhgets(pdata); pdata += 2; 183 createsize = smbnhgetl(pdata); pdata += 4; 184 timeout = smbnhgetl(pdata); pdata += 4; 185 pdata += 4; 186 USED(pdata); 187 if (!smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) { 188 pr = SmbProcessResultFormat; 189 goto done; 190 } 191 192 smbloglock(); 193 smblogprint(h->command, "flags 0x%.4ux", flags); 194 if (flags & SMB_OPEN_FLAGS_ADDITIONAL) 195 smblogprint(h->command, " additional"); 196 if (flags & SMB_OPEN_FLAGS_OPLOCK) 197 smblogprint(h->command, " oplock"); 198 if (flags & SMB_OPEN_FLAGS_OPBATCH) 199 smblogprint(h->command, " opbatch"); 200 smblogprint(h->command, "\n"); 201 smblogprint(h->command, "mode 0x%.4ux", mode); 202 switch ((mode >> SMB_OPEN_MODE_ACCESS_SHIFT) & SMB_OPEN_MODE_ACCESS_MASK) { 203 case OREAD: 204 smblogprint(h->command, " OREAD"); 205 break; 206 case OWRITE: 207 smblogprint(h->command, " OWRITE"); 208 break; 209 case ORDWR: 210 smblogprint(h->command, " ORDWR"); 211 break; 212 case OEXEC: 213 smblogprint(h->command, " OEXEC"); 214 break; 215 } 216 switch ((mode >> SMB_OPEN_MODE_SHARE_SHIFT) & SMB_OPEN_MODE_SHARE_MASK) { 217 case SMB_OPEN_MODE_SHARE_COMPATIBILITY: 218 smblogprint(h->command, " compatinility"); 219 break; 220 case SMB_OPEN_MODE_SHARE_EXCLUSIVE: 221 smblogprint(h->command, " exclusive"); 222 break; 223 case SMB_OPEN_MODE_SHARE_DENY_WRITE: 224 smblogprint(h->command, " deny write"); 225 break; 226 case SMB_OPEN_MODE_SHARE_DENY_READOREXEC: 227 smblogprint(h->command, " deny readorxec"); 228 break; 229 case SMB_OPEN_MODE_SHARE_DENY_NONE: 230 smblogprint(h->command, " deny none"); 231 break; 232 } 233 if (mode & SMB_OPEN_MODE_WRITE_THROUGH) 234 smblogprint(h->command, " write through"); 235 smblogprint(h->command, "\n"); 236 smblogprint(h->command, "sattr 0x%.4ux", sattr); 237 smblogprintattr(h->command, sattr); 238 smblogprint(h->command, "\n"); 239 smblogprint(h->command, "attr 0x%.4ux", attr); 240 smblogprintattr(h->command, attr); 241 smblogprint(h->command, "\n"); 242 smblogprint(h->command, "createtime 0x%.8lux\n", createtime); 243 smblogprint(h->command, "ofun 0x%.4ux", ofun); 244 if (ofun & SMB_OFUN_NOEXIST_CREATE) 245 smblogprint(h->command, " noexistscreate"); 246 else 247 smblogprint(h->command, " noexistfail"); 248 switch ((ofun >> SMB_OFUN_EXIST_SHIFT) & SMB_OFUN_EXIST_MASK) { 249 case SMB_OFUN_EXIST_FAIL: 250 smblogprint(h->command, " existfail"); 251 break; 252 case SMB_OFUN_EXIST_OPEN: 253 smblogprint(h->command, " existopen"); 254 break; 255 case SMB_OFUN_EXIST_TRUNCATE: 256 smblogprint(h->command, " existtruncate"); 257 break; 258 } 259 smblogprint(h->command, "\n"); 260 smblogprint(h->command, "createsize 0x%.8lux\n", createsize); 261 smblogprint(h->command, "timeout 0x%.8lux\n", timeout); 262 smblogprint(h->command, "path %s\n", path); 263 smblogunlock(); 264 265 t = smbidmapfind(s->tidmap, h->tid); 266 if (t == nil) { 267 smbseterror(s, ERRSRV, ERRinvtid); 268 goto errordone; 269 } 270 271 f = openfile(s, t, path, mode, attr, ofun, 0, createsize, &fid, &d, &action); 272 if (f == nil) { 273 pr = SmbProcessResultError; 274 goto done; 275 } 276 h->wordcount = 15; 277 if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixupoffset) 278 || !smbbufferputs(s->response, fid) 279 || !smbbufferputs(s->response, smbplan9mode2dosattr(d->mode)) 280 || !smbbufferputl(s->response, smbplan9time2utime(d->mtime, s->tzoff)) 281 || !smbbufferputl(s->response, smbplan9length2size32(d->length)) 282 || !smbbufferputs(s->response, smbplan9mode2dosattr(d->mode)) // probbaly bogus 283 || !smbbufferputs(s->response, 0) // all files are files 284 || !smbbufferputs(s->response, 0) // pipe state 285 || !smbbufferputs(s->response, action) 286 || !smbbufferputl(s->response, 0) // fileID 287 || !smbbufferputs(s->response, 0) 288 || !smbbufferputs(s->response, 0)) { // bytecount 0 289 smbfileclose(s, f); 290 pr = SmbProcessResultMisc; 291 goto done; 292 } 293 if (andxcommand != SMB_COM_NO_ANDX_COMMAND) 294 pr = smbchaincommand(s, h, andxoffsetfixupoffset, andxcommand, andxoffset, b); 295 else 296 pr = SmbProcessResultReply; 297 goto done; 298 errordone: 299 pr = SmbProcessResultError; 300 done: 301 free(path); 302 free(d); 303 return pr; 304 } 305 306 SmbProcessResult 307 smbcomopen(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b) 308 { 309 uchar fmt; 310 char *path; 311 ushort mode, attr; 312 SmbTree *t; 313 ushort fid; 314 Dir *d = nil; 315 SmbFile *f; 316 SmbProcessResult pr; 317 318 if (!smbcheckwordcount("comopen", h, 2)) 319 return SmbProcessResultFormat; 320 mode = smbnhgets(pdata); 321 attr = smbnhgets(pdata + 2); 322 if (!smbbuffergetb(b, &fmt) 323 || fmt != 4 324 || !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) { 325 pr = SmbProcessResultFormat; 326 goto done; 327 } 328 t = smbidmapfind(s->tidmap, h->tid); 329 if (t == nil) { 330 smbseterror(s, ERRSRV, ERRinvtid); 331 error: 332 pr = SmbProcessResultError; 333 goto done; 334 } 335 f = openfile(s, t, path, mode, attr, 336 SMB_OFUN_EXIST_OPEN << SMB_OFUN_EXIST_SHIFT, 337 0, 0, &fid, &d, nil); 338 if (f == nil) 339 goto error; 340 h->wordcount = 7; 341 if (!smbbufferputheader(s->response, h, &s->peerinfo) 342 || !smbbufferputs(s->response, fid) 343 || !smbbufferputs(s->response, smbplan9mode2dosattr(d->mode)) 344 || !smbbufferputl(s->response, smbplan9time2utime(d->mtime, s->tzoff)) 345 || !smbbufferputl(s->response, smbplan9length2size32(d->length)) 346 || !smbbufferputs(s->response, 2) // lies - this should be the actual access allowed 347 || !smbbufferputs(s->response, 0)) 348 pr = SmbProcessResultMisc; 349 else 350 pr = SmbProcessResultReply; 351 done: 352 free(path); 353 free(d); 354 return pr; 355 } 356 357 typedef struct SmbSblut { 358 char *s; 359 ulong mask; 360 } SmbSblut; 361 362 static SmbSblut dasblut[] = { 363 { "SMB_DA_SPECIFIC_READ_DATA", SMB_DA_SPECIFIC_READ_DATA }, 364 { "SMB_DA_SPECIFIC_WRITE_DATA", SMB_DA_SPECIFIC_WRITE_DATA }, 365 { "SMB_DA_SPECIFIC_APPEND_DATA", SMB_DA_SPECIFIC_APPEND_DATA }, 366 { "SMB_DA_SPECIFIC_READ_EA", SMB_DA_SPECIFIC_READ_EA }, 367 { "SMB_DA_SPECIFIC_WRITE_EA", SMB_DA_SPECIFIC_WRITE_EA }, 368 { "SMB_DA_SPECIFIC_EXECUTE", SMB_DA_SPECIFIC_EXECUTE }, 369 { "SMB_DA_SPECIFIC_DELETE_CHILD", SMB_DA_SPECIFIC_DELETE_CHILD }, 370 { "SMB_DA_SPECIFIC_READ_ATTRIBUTES", SMB_DA_SPECIFIC_READ_ATTRIBUTES }, 371 { "SMB_DA_SPECIFIC_WRITE_ATTRIBUTES", SMB_DA_SPECIFIC_WRITE_ATTRIBUTES }, 372 { "SMB_DA_STANDARD_DELETE_ACCESS", SMB_DA_STANDARD_DELETE_ACCESS }, 373 { "SMB_DA_STANDARD_READ_CONTROL_ACCESS", SMB_DA_STANDARD_READ_CONTROL_ACCESS }, 374 { "SMB_DA_STANDARD_WRITE_DAC_ACCESS", SMB_DA_STANDARD_WRITE_DAC_ACCESS }, 375 { "SMB_DA_STANDARD_WRITE_OWNER_ACCESS", SMB_DA_STANDARD_WRITE_OWNER_ACCESS }, 376 { "SMB_DA_STANDARD_SYNCHRONIZE_ACCESS", SMB_DA_STANDARD_SYNCHRONIZE_ACCESS }, 377 { "SMB_DA_GENERIC_ALL_ACCESS", SMB_DA_GENERIC_ALL_ACCESS }, 378 { "SMB_DA_GENERIC_EXECUTE_ACCESS", SMB_DA_GENERIC_EXECUTE_ACCESS }, 379 { "SMB_DA_GENERIC_WRITE_ACCESS", SMB_DA_GENERIC_WRITE_ACCESS }, 380 { "SMB_DA_GENERIC_READ_ACCESS", SMB_DA_GENERIC_READ_ACCESS }, 381 { 0 } 382 }; 383 384 static SmbSblut efasblut[] = { 385 { "SMB_ATTR_READ_ONLY", SMB_ATTR_READ_ONLY }, 386 { "SMB_ATTR_HIDDEN", SMB_ATTR_HIDDEN }, 387 { "SMB_ATTR_SYSTEM", SMB_ATTR_SYSTEM }, 388 { "SMB_ATTR_DIRECTORY", SMB_ATTR_DIRECTORY }, 389 { "SMB_ATTR_ARCHIVE", SMB_ATTR_ARCHIVE }, 390 { "SMB_ATTR_NORMAL", SMB_ATTR_NORMAL }, 391 { "SMB_ATTR_COMPRESSED", SMB_ATTR_COMPRESSED }, 392 { "SMB_ATTR_TEMPORARY", SMB_ATTR_TEMPORARY }, 393 { "SMB_ATTR_WRITETHROUGH", SMB_ATTR_WRITETHROUGH }, 394 { "SMB_ATTR_NO_BUFFERING", SMB_ATTR_NO_BUFFERING }, 395 { "SMB_ATTR_RANDOM_ACCESS", SMB_ATTR_RANDOM_ACCESS }, 396 { 0 } 397 }; 398 399 static SmbSblut sasblut[] = { 400 { "SMB_SA_SHARE_READ", SMB_SA_SHARE_READ }, 401 { "SMB_SA_SHARE_WRITE", SMB_SA_SHARE_WRITE }, 402 { "SMB_SA_SHARE_DELETE", SMB_SA_SHARE_DELETE }, 403 { "SMB_SA_NO_SHARE", SMB_SA_NO_SHARE }, 404 { 0 } 405 }; 406 407 static SmbSblut cosblut[] = { 408 { "SMB_CO_DIRECTORY", SMB_CO_DIRECTORY }, 409 { "SMB_CO_WRITETHROUGH", SMB_CO_WRITETHROUGH }, 410 { "SMB_CO_SEQUENTIAL_ONLY", SMB_CO_SEQUENTIAL_ONLY }, 411 { "SMB_CO_FILE", SMB_CO_FILE }, 412 { "SMB_CO_NO_EA_KNOWLEDGE", SMB_CO_NO_EA_KNOWLEDGE }, 413 { "SMB_CO_EIGHT_DOT_THREE_ONLY", SMB_CO_EIGHT_DOT_THREE_ONLY }, 414 { "SMB_CO_RANDOM_ACCESS", SMB_CO_RANDOM_ACCESS }, 415 { "SMB_CO_DELETE_ON_CLOSE", SMB_CO_DELETE_ON_CLOSE }, 416 { 0 } 417 }; 418 419 static SmbSlut cdslut[] = { 420 { "SMB_CD_SUPERCEDE", SMB_CD_SUPERCEDE }, 421 { "SMB_CD_OPEN", SMB_CD_OPEN }, 422 { "SMB_CD_CREATE", SMB_CD_CREATE }, 423 { "SMB_CD_OPEN_IF", SMB_CD_OPEN_IF }, 424 { "SMB_CD_OVERWRITE", SMB_CD_OVERWRITE }, 425 { "SMB_CD_OVERWRITE_IF", SMB_CD_OVERWRITE_IF }, 426 { 0 } 427 }; 428 429 static void 430 smbsblutlogprint(uchar cmd, SmbSblut *sblut, ulong mask) 431 { 432 while (sblut->s) { 433 if (mask && (sblut->mask & mask) || (mask == 0 && sblut->mask == 0)) 434 smblogprint(cmd, " %s", sblut->s); 435 sblut++; 436 } 437 } 438 439 SmbProcessResult 440 smbcomntcreateandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b) 441 { 442 uchar andxcommand; 443 ushort andxoffset; 444 char *path = nil; 445 SmbProcessResult pr; 446 ulong namelength; 447 ulong flags; 448 ulong rootdirectoryfid, desiredaccess; 449 uvlong allocationsize; 450 ulong extfileattributes, shareaccess, createdisposition, createoptions, impersonationlevel; 451 uchar securityflags; 452 int p9mode; 453 int sharemode; 454 ushort mode; 455 SmbTree *t; 456 ushort ofun; 457 SmbFile *f; 458 ushort fid; 459 Dir *d = nil; 460 ushort action; 461 uvlong mtime; 462 ulong andxoffsetfixup; 463 464 if (!smbcheckwordcount("comntcreateandx", h, 24)) 465 return SmbProcessResultFormat; 466 467 andxcommand = *pdata++; 468 pdata++; 469 andxoffset = smbnhgets(pdata); pdata += 2; 470 pdata++; 471 namelength = smbnhgets(pdata); pdata += 2; 472 flags = smbnhgetl(pdata); pdata += 4; 473 rootdirectoryfid = smbnhgetl(pdata); pdata += 4; 474 desiredaccess = smbnhgetl(pdata); pdata += 4; 475 allocationsize = smbnhgetv(pdata); pdata += 8; 476 extfileattributes = smbnhgetl(pdata); pdata += 4; 477 shareaccess = smbnhgetl(pdata); pdata += 4; 478 createdisposition = smbnhgetl(pdata); pdata += 4; 479 createoptions = smbnhgetl(pdata); pdata += 4; 480 impersonationlevel = smbnhgetl(pdata); pdata += 4; 481 securityflags = *pdata++; 482 USED(pdata); 483 484 if (!smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) { 485 pr = SmbProcessResultFormat; 486 goto done; 487 } 488 489 smblogprint(h->command, "namelength %d\n", namelength); 490 smblogprint(h->command, "flags 0x%.8lux\n", flags); 491 smblogprint(h->command, "rootdirectoryfid %lud\n", rootdirectoryfid); 492 smblogprint(h->command, "desiredaccess 0x%.8lux", desiredaccess); 493 smbsblutlogprint(h->command, dasblut, desiredaccess); 494 smblogprint(h->command, "\n"); 495 smblogprint(h->command, "allocationsize %llud\n", allocationsize); 496 smblogprint(h->command, "extfileattributes 0x%.8lux", extfileattributes); 497 smbsblutlogprint(h->command, efasblut, extfileattributes); 498 smblogprint(h->command, "\n"); 499 smblogprint(h->command, "shareaccess 0x%.8lux", shareaccess); 500 smbsblutlogprint(h->command, sasblut, shareaccess); 501 smblogprint(h->command, "\n"); 502 smblogprint(h->command, "createdisposition 0x%.8lux %s\n", 503 createdisposition, smbrevslut(cdslut, createdisposition)); 504 smblogprint(h->command, "createoptions 0x%.8lux", createoptions); 505 smbsblutlogprint(h->command, cosblut, createoptions); 506 smblogprint(h->command, "\n"); 507 smblogprint(h->command, "impersonationlevel 0x%.8lux\n", impersonationlevel); 508 smblogprint(h->command, "securityflags 0x%.2ux\n", securityflags); 509 smblogprint(h->command, "path %s\n", path); 510 511 if (rootdirectoryfid != 0) { 512 smblogprint(-1, "smbcomntcreateandx: fid relative not implemented\n"); 513 goto unimp; 514 } 515 516 if (desiredaccess & SMB_DA_GENERIC_MASK) { 517 smblogprint(-1, "smbcomntcreateandx: generic bits in desiredaccess not implemented\n"); 518 goto unimp; 519 } 520 521 if (desiredaccess & SMB_DA_SPECIFIC_READ_DATA) 522 if (desiredaccess & (SMB_DA_SPECIFIC_WRITE_DATA | SMB_DA_SPECIFIC_APPEND_DATA)) 523 p9mode = ORDWR; 524 else 525 p9mode = OREAD; 526 else if (desiredaccess & (SMB_DA_SPECIFIC_WRITE_DATA | SMB_DA_SPECIFIC_APPEND_DATA)) 527 p9mode = ORDWR; 528 else 529 p9mode = OREAD; 530 531 if (shareaccess == SMB_SA_NO_SHARE) 532 sharemode = SMB_OPEN_MODE_SHARE_EXCLUSIVE; 533 else if (shareaccess & (SMB_SA_SHARE_READ | SMB_SA_SHARE_WRITE) == 534 (SMB_SA_SHARE_READ | SMB_SA_SHARE_WRITE)) 535 sharemode = SMB_OPEN_MODE_SHARE_DENY_NONE; 536 else if (shareaccess & SMB_SA_SHARE_READ) 537 sharemode = SMB_OPEN_MODE_SHARE_DENY_WRITE; 538 else if (shareaccess & SMB_SA_SHARE_WRITE) 539 sharemode = SMB_OPEN_MODE_SHARE_DENY_READOREXEC; 540 else 541 sharemode = SMB_OPEN_MODE_SHARE_DENY_NONE; 542 543 mode = (sharemode << SMB_OPEN_MODE_SHARE_SHIFT) | (p9mode << SMB_OPEN_MODE_ACCESS_SHIFT); 544 545 switch (createdisposition) { 546 default: 547 smblogprint(-1, "smbcomntcreateandx: createdisposition 0x%.8lux not implemented\n", createdisposition); 548 goto unimp; 549 case SMB_CD_OPEN: 550 ofun = SMB_OFUN_EXIST_OPEN; 551 break; 552 case SMB_CD_CREATE: 553 ofun = SMB_OFUN_EXIST_FAIL | SMB_OFUN_NOEXIST_CREATE; 554 break; 555 case SMB_CD_OPEN_IF: 556 ofun = SMB_OFUN_EXIST_OPEN | SMB_OFUN_NOEXIST_CREATE; 557 break; 558 case SMB_CD_OVERWRITE: 559 ofun = SMB_OFUN_EXIST_TRUNCATE; 560 break; 561 case SMB_CD_OVERWRITE_IF: 562 ofun = SMB_OFUN_EXIST_TRUNCATE | SMB_OFUN_NOEXIST_CREATE; 563 break; 564 } 565 566 t = smbidmapfind(s->tidmap, h->tid); 567 if (t == nil) { 568 smbseterror(s, ERRSRV, ERRinvtid); 569 pr = SmbProcessResultError; 570 goto done; 571 } 572 573 f = openfile(s, t, path, mode, extfileattributes, ofun, createoptions, allocationsize, &fid, &d, &action); 574 575 if (f == nil) { 576 pr = SmbProcessResultError; 577 goto done; 578 } 579 580 h->wordcount = 42; 581 mtime = smbplan9time2time(d->mtime); 582 if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup) 583 || !smbbufferputb(s->response, 0) // oplocks? pah 584 || !smbbufferputs(s->response, fid) 585 || !smbbufferputl(s->response, action) 586 || !smbbufferputv(s->response, mtime) 587 || !smbbufferputv(s->response, smbplan9time2time(d->atime)) 588 || !smbbufferputv(s->response, mtime) 589 || !smbbufferputv(s->response, mtime) 590 || !smbbufferputl(s->response, smbplan9mode2dosattr(d->mode)) 591 || !smbbufferputv(s->response, smbl2roundupvlong(d->length, smbglobals.l2allocationsize)) 592 || !smbbufferputv(s->response, d->length) 593 || !smbbufferputbytes(s->response, nil, 4) 594 || !smbbufferputb(s->response, (d->qid.type & QTDIR) != 0) 595 || !smbbufferputbytes(s->response, nil, 8) 596 || !smbbufferputs(s->response, 0)) { 597 pr = SmbProcessResultMisc; 598 goto done; 599 } 600 601 if (andxcommand != SMB_COM_NO_ANDX_COMMAND) 602 pr = smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b); 603 else 604 pr = SmbProcessResultReply; 605 606 goto done; 607 608 unimp: 609 pr = SmbProcessResultUnimp; 610 611 done: 612 free(path); 613 free(d); 614 615 return pr; 616 } 617 618