33 */ 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/kernel.h> 37#include <sys/malloc.h> 38#include <sys/proc.h> 39#include <sys/lock.h> 40#include <sys/vnode.h> 41#include <sys/mbuf.h> 42#include <sys/mount.h> 43 44#ifdef USE_MD5_HASH 45#include <sys/md5.h> 46#endif 47 48#include <netsmb/smb.h> 49#include <netsmb/smb_subr.h> 50#include <netsmb/smb_rq.h> 51#include <netsmb/smb_conn.h> 52 53#include <fs/smbfs/smbfs.h> 54#include <fs/smbfs/smbfs_node.h> 55#include <fs/smbfs/smbfs_subr.h> 56 57/* 58 * Lack of inode numbers leads us to the problem of generating them. 59 * Partially this problem can be solved by having a dir/file cache 60 * with inode numbers generated from the incremented by one counter. 61 * However this way will require too much kernel memory, gives all 62 * sorts of locking and consistency problems, not to mentinon counter overflows. 63 * So, I'm decided to use a hash function to generate pseudo random (and unique) 64 * inode numbers. 65 */ 66static long 67smbfs_getino(struct smbnode *dnp, const char *name, int nmlen) 68{ 69#ifdef USE_MD5_HASH 70 MD5_CTX md5; 71 u_int32_t state[4]; 72 long ino; 73 int i; 74 75 MD5Init(&md5); 76 MD5Update(&md5, name, nmlen); 77 MD5Final((u_char *)state, &md5); 78 for (i = 0, ino = 0; i < 4; i++) 79 ino += state[i]; 80 return dnp->n_ino + ino; 81#endif 82 u_int32_t ino; 83 84 ino = dnp->n_ino + smbfs_hash(name, nmlen); 85 if (ino <= 2) 86 ino += 3; 87 return ino; 88} 89 90static int 91smbfs_smb_lockandx(struct smbnode *np, int op, u_int32_t pid, off_t start, off_t end, 92 struct smb_cred *scred) 93{ 94 struct smb_share *ssp = np->n_mount->sm_share; 95 struct smb_rq rq, *rqp = &rq; 96 struct mbchain *mbp; 97 u_char ltype = 0; 98 int error; 99 100 if (op == SMB_LOCK_SHARED) 101 ltype |= SMB_LOCKING_ANDX_SHARED_LOCK; 102 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scred); 103 if (error) 104 return error; 105 smb_rq_getrequest(rqp, &mbp); 106 smb_rq_wstart(rqp); 107 mb_put_uint8(mbp, 0xff); /* secondary command */ 108 mb_put_uint8(mbp, 0); /* MBZ */ 109 mb_put_uint16le(mbp, 0); 110 mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 111 mb_put_uint8(mbp, ltype); /* locktype */ 112 mb_put_uint8(mbp, 0); /* oplocklevel - 0 seems is NO_OPLOCK */ 113 mb_put_uint32le(mbp, 0); /* timeout - break immediately */ 114 mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 1 : 0); 115 mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 0 : 1); 116 smb_rq_wend(rqp); 117 smb_rq_bstart(rqp); 118 mb_put_uint16le(mbp, pid); 119 mb_put_uint32le(mbp, start); 120 mb_put_uint32le(mbp, end - start); 121 smb_rq_bend(rqp); 122 error = smb_rq_simple(rqp); 123 smb_rq_done(rqp); 124 return error; 125} 126 127int 128smbfs_smb_lock(struct smbnode *np, int op, caddr_t id, 129 off_t start, off_t end, struct smb_cred *scred) 130{ 131 struct smb_share *ssp = np->n_mount->sm_share; 132 133 if (SMB_DIALECT(SSTOVC(ssp)) < SMB_DIALECT_LANMAN1_0) 134 /* 135 * TODO: use LOCK_BYTE_RANGE here. 136 */ 137 return EINVAL; 138 else 139 return smbfs_smb_lockandx(np, op, (uintptr_t)id, start, end, scred); 140} 141 142static int 143smbfs_smb_qpathinfo(struct smbnode *np, struct smbfattr *fap, 144 struct smb_cred *scred, short infolevel) 145{ 146 struct smb_share *ssp = np->n_mount->sm_share; 147 struct smb_vc *vcp = SSTOVC(ssp); 148 struct smb_t2rq *t2p; 149 int error, svtz, timesok = 1; 150 struct mbchain *mbp; 151 struct mdchain *mdp; 152 u_int16_t date, time, wattr; 153 int64_t lint; 154 u_int32_t size, dattr; 155 156 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_PATH_INFORMATION, 157 scred, &t2p); 158 if (error) 159 return error; 160 mbp = &t2p->t2_tparam; 161 mb_init(mbp); 162 if (!infolevel) { 163 if (SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12) 164 infolevel = SMB_QUERY_FILE_STANDARD; 165 else 166 infolevel = SMB_QUERY_FILE_BASIC_INFO; 167 } 168 mb_put_uint16le(mbp, infolevel); 169 mb_put_uint32le(mbp, 0); 170 /* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */ 171 error = smbfs_fullpath(mbp, vcp, np, NULL, 0); 172 if (error) { 173 smb_t2_done(t2p); 174 return error; 175 } 176 t2p->t2_maxpcount = 2; 177 t2p->t2_maxdcount = vcp->vc_txmax; 178 error = smb_t2_request(t2p); 179 if (error) { 180 smb_t2_done(t2p); 181 if (infolevel == SMB_QUERY_FILE_STANDARD || error != EINVAL) 182 return error; 183 return smbfs_smb_qpathinfo(np, fap, scred, 184 SMB_QUERY_FILE_STANDARD); 185 } 186 mdp = &t2p->t2_rdata; 187 svtz = vcp->vc_sopt.sv_tz; 188 switch (infolevel) { 189 case SMB_QUERY_FILE_STANDARD: 190 timesok = 0; 191 md_get_uint16le(mdp, NULL); 192 md_get_uint16le(mdp, NULL); /* creation time */ 193 md_get_uint16le(mdp, &date); 194 md_get_uint16le(mdp, &time); /* access time */ 195 if (date || time) { 196 timesok++; 197 smb_dos2unixtime(date, time, 0, svtz, &fap->fa_atime); 198 } 199 md_get_uint16le(mdp, &date); 200 md_get_uint16le(mdp, &time); /* modify time */ 201 if (date || time) { 202 timesok++; 203 smb_dos2unixtime(date, time, 0, svtz, &fap->fa_mtime); 204 } 205 md_get_uint32le(mdp, &size); 206 fap->fa_size = size; 207 md_get_uint32(mdp, NULL); /* allocation size */ 208 md_get_uint16le(mdp, &wattr); 209 fap->fa_attr = wattr; 210 break; 211 case SMB_QUERY_FILE_BASIC_INFO: 212 timesok = 0; 213 md_get_int64(mdp, NULL); /* creation time */ 214 md_get_int64le(mdp, &lint); 215 if (lint) { 216 timesok++; 217 smb_time_NT2local(lint, svtz, &fap->fa_atime); 218 } 219 md_get_int64le(mdp, &lint); 220 if (lint) { 221 timesok++; 222 smb_time_NT2local(lint, svtz, &fap->fa_mtime); 223 } 224 md_get_int64le(mdp, &lint); 225 if (lint) { 226 timesok++; 227 smb_time_NT2local(lint, svtz, &fap->fa_ctime); 228 } 229 md_get_uint32le(mdp, &dattr); 230 fap->fa_attr = dattr; 231 md_get_uint32(mdp, NULL); 232 /* XXX could use ALL_INFO to get size */ 233 break; 234 default: 235 SMBERROR("unexpected info level %d\n", infolevel); 236 error = EINVAL; 237 } 238 smb_t2_done(t2p); 239 /* 240 * if all times are zero (observed with FAT on NT4SP6) 241 * then fall back to older info level 242 */ 243 if (!timesok) { 244 if (infolevel != SMB_QUERY_FILE_STANDARD) 245 return smbfs_smb_qpathinfo(np, fap, scred, 246 SMB_QUERY_FILE_STANDARD); 247 error = EINVAL; 248 } 249 return error; 250} 251 252int 253smbfs_smb_statfs2(struct smb_share *ssp, struct statfs *sbp, 254 struct smb_cred *scred) 255{ 256 struct smb_t2rq *t2p; 257 struct mbchain *mbp; 258 struct mdchain *mdp; 259 u_int16_t bsize; 260 u_int32_t units, bpu, funits; 261 int error; 262 263 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION, 264 scred, &t2p); 265 if (error) 266 return error; 267 mbp = &t2p->t2_tparam; 268 mb_init(mbp); 269 mb_put_uint16le(mbp, SMB_INFO_ALLOCATION); 270 t2p->t2_maxpcount = 4; 271 t2p->t2_maxdcount = 4 * 4 + 2; 272 error = smb_t2_request(t2p); 273 if (error) { 274 smb_t2_done(t2p); 275 return error; 276 } 277 mdp = &t2p->t2_rdata; 278 md_get_uint32(mdp, NULL); /* fs id */ 279 md_get_uint32le(mdp, &bpu); 280 md_get_uint32le(mdp, &units); 281 md_get_uint32le(mdp, &funits); 282 md_get_uint16le(mdp, &bsize); 283 sbp->f_bsize = bpu * bsize; /* fundamental filesystem block size */ 284 sbp->f_blocks= units; /* total data blocks in filesystem */ 285 sbp->f_bfree = funits; /* free blocks in fs */ 286 sbp->f_bavail= funits; /* free blocks avail to non-superuser */ 287 sbp->f_files = 0xffff; /* total file nodes in filesystem */ 288 sbp->f_ffree = 0xffff; /* free file nodes in fs */ 289 smb_t2_done(t2p); 290 return 0; 291} 292 293int 294smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp, 295 struct smb_cred *scred) 296{ 297 struct smb_rq rq, *rqp = &rq; 298 struct mdchain *mdp; 299 u_int16_t units, bpu, bsize, funits; 300 int error; 301 302 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION_DISK, scred); 303 if (error) 304 return error; 305 smb_rq_wstart(rqp); 306 smb_rq_wend(rqp); 307 smb_rq_bstart(rqp); 308 smb_rq_bend(rqp); 309 error = smb_rq_simple(rqp); 310 if (error) { 311 smb_rq_done(rqp); 312 return error; 313 } 314 smb_rq_getreply(rqp, &mdp); 315 md_get_uint16le(mdp, &units); 316 md_get_uint16le(mdp, &bpu); 317 md_get_uint16le(mdp, &bsize); 318 md_get_uint16le(mdp, &funits); 319 sbp->f_bsize = bpu * bsize; /* fundamental filesystem block size */ 320 sbp->f_blocks= units; /* total data blocks in filesystem */ 321 sbp->f_bfree = funits; /* free blocks in fs */ 322 sbp->f_bavail= funits; /* free blocks avail to non-superuser */ 323 sbp->f_files = 0xffff; /* total file nodes in filesystem */ 324 sbp->f_ffree = 0xffff; /* free file nodes in fs */ 325 smb_rq_done(rqp); 326 return 0; 327} 328 329static int 330smbfs_smb_seteof(struct smbnode *np, int64_t newsize, struct smb_cred *scred) 331{ 332 struct smb_t2rq *t2p; 333 struct smb_share *ssp = np->n_mount->sm_share; 334 struct mbchain *mbp; 335 int error; 336 337 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION, 338 scred, &t2p); 339 if (error) 340 return error; 341 mbp = &t2p->t2_tparam; 342 mb_init(mbp); 343 mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 344 mb_put_uint16le(mbp, SMB_SET_FILE_END_OF_FILE_INFO); 345 mb_put_uint32le(mbp, 0); 346 mbp = &t2p->t2_tdata; 347 mb_init(mbp); 348 mb_put_int64le(mbp, newsize); 349 mb_put_uint32le(mbp, 0); /* padding */ 350 mb_put_uint16le(mbp, 0); 351 t2p->t2_maxpcount = 2; 352 t2p->t2_maxdcount = 0; 353 error = smb_t2_request(t2p); 354 smb_t2_done(t2p); 355 return error; 356} 357 358static int 359smb_smb_flush(struct smbnode *np, struct smb_cred *scred) 360{ 361 struct smb_share *ssp = np->n_mount->sm_share; 362 struct smb_rq rq, *rqp = &rq; 363 struct mbchain *mbp; 364 int error; 365 366 if (np->n_opencount <= 0 || !SMBTOV(np) || SMBTOV(np)->v_type != VREG) 367 return 0; /* not a regular open file */ 368 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_FLUSH, scred); 369 if (error) 370 return (error); 371 smb_rq_getrequest(rqp, &mbp); 372 smb_rq_wstart(rqp); 373 mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 374 smb_rq_wend(rqp); 375 smb_rq_bstart(rqp); 376 smb_rq_bend(rqp); 377 error = smb_rq_simple(rqp); 378 smb_rq_done(rqp); 379 if (!error) 380 np->n_flag &= ~NFLUSHWIRE; 381 return (error); 382} 383 384int 385smbfs_smb_flush(struct smbnode *np, struct smb_cred *scred) 386{ 387 if (np->n_flag & NFLUSHWIRE) 388 return (smb_smb_flush(np, scred)); 389 return (0); 390} 391 392int 393smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred) 394{ 395 struct smb_share *ssp = np->n_mount->sm_share; 396 struct smb_rq rq, *rqp = &rq; 397 struct mbchain *mbp; 398 int error; 399 400 if (!smbfs_smb_seteof(np, (int64_t) newsize, scred)) { 401 np->n_flag |= NFLUSHWIRE; 402 return (0); 403 } 404 405 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_WRITE, scred); 406 if (error) 407 return error; 408 smb_rq_getrequest(rqp, &mbp); 409 smb_rq_wstart(rqp); 410 mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 411 mb_put_uint16le(mbp, 0); 412 mb_put_uint32le(mbp, newsize); 413 mb_put_uint16le(mbp, 0); 414 smb_rq_wend(rqp); 415 smb_rq_bstart(rqp); 416 mb_put_uint8(mbp, SMB_DT_DATA); 417 mb_put_uint16le(mbp, 0); 418 smb_rq_bend(rqp); 419 error = smb_rq_simple(rqp); 420 smb_rq_done(rqp); 421 return error; 422} 423 424int 425smbfs_smb_query_info(struct smbnode *np, const char *name, int len, 426 struct smbfattr *fap, struct smb_cred *scred) 427{ 428 struct smb_rq rq, *rqp = &rq; 429 struct smb_share *ssp = np->n_mount->sm_share; 430 struct mbchain *mbp; 431 struct mdchain *mdp; 432 u_int8_t wc; 433 int error; 434 u_int16_t wattr; 435 u_int32_t lint; 436 437 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION, scred); 438 if (error) 439 return error; 440 smb_rq_getrequest(rqp, &mbp); 441 smb_rq_wstart(rqp); 442 smb_rq_wend(rqp); 443 smb_rq_bstart(rqp); 444 mb_put_uint8(mbp, SMB_DT_ASCII); 445 do { 446 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, len); 447 if (error) 448 break; 449 smb_rq_bend(rqp); 450 error = smb_rq_simple(rqp); 451 if (error) 452 break; 453 smb_rq_getreply(rqp, &mdp); 454 if (md_get_uint8(mdp, &wc) != 0 || wc != 10) { 455 error = EBADRPC; 456 break; 457 } 458 md_get_uint16le(mdp, &wattr); 459 fap->fa_attr = wattr; 460 /* 461 * Be careful using the time returned here, as 462 * with FAT on NT4SP6, at least, the time returned is low 463 * 32 bits of 100s of nanoseconds (since 1601) so it rolls 464 * over about every seven minutes! 465 */ 466 md_get_uint32le(mdp, &lint); /* specs: secs since 1970 */ 467 if (lint) /* avoid bogus zero returns */ 468 smb_time_server2local(lint, SSTOVC(ssp)->vc_sopt.sv_tz, 469 &fap->fa_mtime); 470 md_get_uint32le(mdp, &lint); 471 fap->fa_size = lint; 472 } while(0); 473 smb_rq_done(rqp); 474 return error; 475} 476 477/* 478 * Set DOS file attributes. mtime should be NULL for dialects above lm10 479 */ 480int 481smbfs_smb_setpattr(struct smbnode *np, u_int16_t attr, struct timespec *mtime, 482 struct smb_cred *scred) 483{ 484 struct smb_rq rq, *rqp = &rq; 485 struct smb_share *ssp = np->n_mount->sm_share; 486 struct mbchain *mbp; 487 u_long time; 488 int error, svtz; 489 490 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION, scred); 491 if (error) 492 return error; 493 svtz = SSTOVC(ssp)->vc_sopt.sv_tz; 494 smb_rq_getrequest(rqp, &mbp); 495 smb_rq_wstart(rqp); 496 mb_put_uint16le(mbp, attr); 497 if (mtime) { 498 smb_time_local2server(mtime, svtz, &time); 499 } else 500 time = 0; 501 mb_put_uint32le(mbp, time); /* mtime */ 502 mb_put_mem(mbp, NULL, 5 * 2, MB_MZERO); 503 smb_rq_wend(rqp); 504 smb_rq_bstart(rqp); 505 mb_put_uint8(mbp, SMB_DT_ASCII); 506 do { 507 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0); 508 if (error) 509 break; 510 mb_put_uint8(mbp, SMB_DT_ASCII); 511 mb_put_uint8(mbp, 0); 512 smb_rq_bend(rqp); 513 error = smb_rq_simple(rqp); 514 SMBERROR("%d\n", error); 515 if (error) 516 break; 517 } while(0); 518 smb_rq_done(rqp); 519 return error; 520} 521 522/* 523 * Note, win95 doesn't support this call. 524 */ 525int 526smbfs_smb_setptime2(struct smbnode *np, struct timespec *mtime, 527 struct timespec *atime, int attr, struct smb_cred *scred) 528{ 529 struct smb_t2rq *t2p; 530 struct smb_share *ssp = np->n_mount->sm_share; 531 struct smb_vc *vcp = SSTOVC(ssp); 532 struct mbchain *mbp; 533 u_int16_t date, time; 534 int error, tzoff; 535 536 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_PATH_INFORMATION, 537 scred, &t2p); 538 if (error) 539 return error; 540 mbp = &t2p->t2_tparam; 541 mb_init(mbp); 542 mb_put_uint16le(mbp, SMB_INFO_STANDARD); 543 mb_put_uint32le(mbp, 0); /* MBZ */ 544 /* mb_put_uint8(mbp, SMB_DT_ASCII); specs incorrect */ 545 error = smbfs_fullpath(mbp, vcp, np, NULL, 0); 546 if (error) { 547 smb_t2_done(t2p); 548 return error; 549 } 550 tzoff = vcp->vc_sopt.sv_tz; 551 mbp = &t2p->t2_tdata; 552 mb_init(mbp); 553 mb_put_uint32le(mbp, 0); /* creation time */ 554 if (atime) 555 smb_time_unix2dos(atime, tzoff, &date, &time, NULL); 556 else 557 time = date = 0; 558 mb_put_uint16le(mbp, date); 559 mb_put_uint16le(mbp, time); 560 if (mtime) 561 smb_time_unix2dos(mtime, tzoff, &date, &time, NULL); 562 else 563 time = date = 0; 564 mb_put_uint16le(mbp, date); 565 mb_put_uint16le(mbp, time); 566 mb_put_uint32le(mbp, 0); /* file size */ 567 mb_put_uint32le(mbp, 0); /* allocation unit size */ 568 mb_put_uint16le(mbp, attr); /* DOS attr */ 569 mb_put_uint32le(mbp, 0); /* EA size */ 570 t2p->t2_maxpcount = 5 * 2; 571 t2p->t2_maxdcount = vcp->vc_txmax; 572 error = smb_t2_request(t2p); 573 smb_t2_done(t2p); 574 return error; 575} 576 577/* 578 * NT level. Specially for win9x 579 */ 580int 581smbfs_smb_setpattrNT(struct smbnode *np, u_short attr, struct timespec *mtime, 582 struct timespec *atime, struct smb_cred *scred) 583{ 584 struct smb_t2rq *t2p; 585 struct smb_share *ssp = np->n_mount->sm_share; 586 struct smb_vc *vcp = SSTOVC(ssp); 587 struct mbchain *mbp; 588 int64_t tm; 589 int error, tzoff; 590 591 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_PATH_INFORMATION, 592 scred, &t2p); 593 if (error) 594 return error; 595 mbp = &t2p->t2_tparam; 596 mb_init(mbp); 597 mb_put_uint16le(mbp, SMB_SET_FILE_BASIC_INFO); 598 mb_put_uint32le(mbp, 0); /* MBZ */ 599 /* mb_put_uint8(mbp, SMB_DT_ASCII); specs incorrect */ 600 error = smbfs_fullpath(mbp, vcp, np, NULL, 0); 601 if (error) { 602 smb_t2_done(t2p); 603 return error; 604 } 605 tzoff = vcp->vc_sopt.sv_tz; 606 mbp = &t2p->t2_tdata; 607 mb_init(mbp); 608 mb_put_int64le(mbp, 0); /* creation time */ 609 if (atime) { 610 smb_time_local2NT(atime, tzoff, &tm); 611 } else 612 tm = 0; 613 mb_put_int64le(mbp, tm); 614 if (mtime) { 615 smb_time_local2NT(mtime, tzoff, &tm); 616 } else 617 tm = 0; 618 mb_put_int64le(mbp, tm); 619 mb_put_int64le(mbp, tm); /* change time */ 620 mb_put_uint32le(mbp, attr); /* attr */ 621 t2p->t2_maxpcount = 24; 622 t2p->t2_maxdcount = 56; 623 error = smb_t2_request(t2p); 624 smb_t2_done(t2p); 625 return error; 626} 627 628/* 629 * Set file atime and mtime. Doesn't supported by core dialect. 630 */ 631int 632smbfs_smb_setftime(struct smbnode *np, struct timespec *mtime, 633 struct timespec *atime, struct smb_cred *scred) 634{ 635 struct smb_rq rq, *rqp = &rq; 636 struct smb_share *ssp = np->n_mount->sm_share; 637 struct mbchain *mbp; 638 u_int16_t date, time; 639 int error, tzoff; 640 641 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION2, scred); 642 if (error) 643 return error; 644 tzoff = SSTOVC(ssp)->vc_sopt.sv_tz; 645 smb_rq_getrequest(rqp, &mbp); 646 smb_rq_wstart(rqp); 647 mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 648 mb_put_uint32le(mbp, 0); /* creation time */ 649 650 if (atime) 651 smb_time_unix2dos(atime, tzoff, &date, &time, NULL); 652 else 653 time = date = 0; 654 mb_put_uint16le(mbp, date); 655 mb_put_uint16le(mbp, time); 656 if (mtime) 657 smb_time_unix2dos(mtime, tzoff, &date, &time, NULL); 658 else 659 time = date = 0; 660 mb_put_uint16le(mbp, date); 661 mb_put_uint16le(mbp, time); 662 smb_rq_wend(rqp); 663 smb_rq_bstart(rqp); 664 smb_rq_bend(rqp); 665 error = smb_rq_simple(rqp); 666 SMBSDEBUG("%d\n", error); 667 smb_rq_done(rqp); 668 return error; 669} 670 671/* 672 * Set DOS file attributes. 673 * Looks like this call can be used only if CAP_NT_SMBS bit is on. 674 */ 675int 676smbfs_smb_setfattrNT(struct smbnode *np, u_int16_t attr, struct timespec *mtime, 677 struct timespec *atime, struct smb_cred *scred) 678{ 679 struct smb_t2rq *t2p; 680 struct smb_share *ssp = np->n_mount->sm_share; 681 struct mbchain *mbp; 682 int64_t tm; 683 int error, svtz; 684 685 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION, 686 scred, &t2p); 687 if (error) 688 return error; 689 svtz = SSTOVC(ssp)->vc_sopt.sv_tz; 690 mbp = &t2p->t2_tparam; 691 mb_init(mbp); 692 mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 693 mb_put_uint16le(mbp, SMB_SET_FILE_BASIC_INFO); 694 mb_put_uint32le(mbp, 0); 695 mbp = &t2p->t2_tdata; 696 mb_init(mbp); 697 mb_put_int64le(mbp, 0); /* creation time */ 698 if (atime) { 699 smb_time_local2NT(atime, svtz, &tm); 700 } else 701 tm = 0; 702 mb_put_int64le(mbp, tm); 703 if (mtime) { 704 smb_time_local2NT(mtime, svtz, &tm); 705 } else 706 tm = 0; 707 mb_put_int64le(mbp, tm); 708 mb_put_int64le(mbp, tm); /* change time */ 709 mb_put_uint16le(mbp, attr); 710 mb_put_uint32le(mbp, 0); /* padding */ 711 mb_put_uint16le(mbp, 0); 712 t2p->t2_maxpcount = 2; 713 t2p->t2_maxdcount = 0; 714 error = smb_t2_request(t2p); 715 smb_t2_done(t2p); 716 return error; 717} 718 719 720int 721smbfs_smb_open(struct smbnode *np, int accmode, struct smb_cred *scred) 722{ 723 struct smb_rq rq, *rqp = &rq; 724 struct smb_share *ssp = np->n_mount->sm_share; 725 struct mbchain *mbp; 726 struct mdchain *mdp; 727 u_int8_t wc; 728 u_int16_t fid, wattr, grantedmode; 729 int error; 730 731 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN, scred); 732 if (error) 733 return error; 734 smb_rq_getrequest(rqp, &mbp); 735 smb_rq_wstart(rqp); 736 mb_put_uint16le(mbp, accmode); 737 mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN); 738 smb_rq_wend(rqp); 739 smb_rq_bstart(rqp); 740 mb_put_uint8(mbp, SMB_DT_ASCII); 741 do { 742 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0); 743 if (error) 744 break; 745 smb_rq_bend(rqp); 746 error = smb_rq_simple(rqp); 747 if (error) 748 break; 749 smb_rq_getreply(rqp, &mdp); 750 if (md_get_uint8(mdp, &wc) != 0 || wc != 7) { 751 error = EBADRPC; 752 break; 753 } 754 md_get_uint16(mdp, &fid); 755 md_get_uint16le(mdp, &wattr); 756 md_get_uint32(mdp, NULL); /* mtime */ 757 md_get_uint32(mdp, NULL); /* fsize */ 758 md_get_uint16le(mdp, &grantedmode); 759 /* 760 * TODO: refresh attributes from this reply 761 */ 762 } while(0); 763 smb_rq_done(rqp); 764 if (error) 765 return error; 766 np->n_fid = fid; 767 np->n_rwstate = grantedmode; 768 return 0; 769} 770 771 772int 773smbfs_smb_close(struct smb_share *ssp, u_int16_t fid, struct timespec *mtime, 774 struct smb_cred *scred) 775{ 776 struct smb_rq rq, *rqp = &rq; 777 struct mbchain *mbp; 778 u_long time; 779 int error; 780 781 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scred); 782 if (error) 783 return error; 784 smb_rq_getrequest(rqp, &mbp); 785 smb_rq_wstart(rqp); 786 mb_put_mem(mbp, (caddr_t)&fid, sizeof(fid), MB_MSYSTEM); 787 if (mtime) { 788 smb_time_local2server(mtime, SSTOVC(ssp)->vc_sopt.sv_tz, &time); 789 } else 790 time = 0; 791 mb_put_uint32le(mbp, time); 792 smb_rq_wend(rqp); 793 smb_rq_bstart(rqp); 794 smb_rq_bend(rqp); 795 error = smb_rq_simple(rqp); 796 smb_rq_done(rqp); 797 return error; 798} 799 800int 801smbfs_smb_create(struct smbnode *dnp, const char *name, int nmlen, 802 struct smb_cred *scred) 803{ 804 struct smb_rq rq, *rqp = &rq; 805 struct smb_share *ssp = dnp->n_mount->sm_share; 806 struct mbchain *mbp; 807 struct mdchain *mdp; 808 struct timespec ctime; 809 u_int8_t wc; 810 u_int16_t fid; 811 u_long tm; 812 int error; 813 814 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE, scred); 815 if (error) 816 return error; 817 smb_rq_getrequest(rqp, &mbp); 818 smb_rq_wstart(rqp); 819 mb_put_uint16le(mbp, SMB_FA_ARCHIVE); /* attributes */ 820 nanotime(&ctime); 821 smb_time_local2server(&ctime, SSTOVC(ssp)->vc_sopt.sv_tz, &tm); 822 mb_put_uint32le(mbp, tm); 823 smb_rq_wend(rqp); 824 smb_rq_bstart(rqp); 825 mb_put_uint8(mbp, SMB_DT_ASCII); 826 error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, nmlen); 827 if (!error) { 828 smb_rq_bend(rqp); 829 error = smb_rq_simple(rqp); 830 if (!error) { 831 smb_rq_getreply(rqp, &mdp); 832 md_get_uint8(mdp, &wc); 833 if (wc == 1) 834 md_get_uint16(mdp, &fid); 835 else 836 error = EBADRPC; 837 } 838 } 839 smb_rq_done(rqp); 840 if (error) 841 return error; 842 smbfs_smb_close(ssp, fid, &ctime, scred); 843 return error; 844} 845 846int 847smbfs_smb_delete(struct smbnode *np, struct smb_cred *scred) 848{ 849 struct smb_rq rq, *rqp = &rq; 850 struct smb_share *ssp = np->n_mount->sm_share; 851 struct mbchain *mbp; 852 int error; 853 854 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE, scred); 855 if (error) 856 return error; 857 smb_rq_getrequest(rqp, &mbp); 858 smb_rq_wstart(rqp); 859 mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN); 860 smb_rq_wend(rqp); 861 smb_rq_bstart(rqp); 862 mb_put_uint8(mbp, SMB_DT_ASCII); 863 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0); 864 if (!error) { 865 smb_rq_bend(rqp); 866 error = smb_rq_simple(rqp); 867 } 868 smb_rq_done(rqp); 869 return error; 870} 871 872int 873smbfs_smb_rename(struct smbnode *src, struct smbnode *tdnp, 874 const char *tname, int tnmlen, struct smb_cred *scred) 875{ 876 struct smb_rq rq, *rqp = &rq; 877 struct smb_share *ssp = src->n_mount->sm_share; 878 struct mbchain *mbp; 879 int error; 880 881 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_RENAME, scred); 882 if (error) 883 return error; 884 smb_rq_getrequest(rqp, &mbp); 885 smb_rq_wstart(rqp); 886 mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN); 887 smb_rq_wend(rqp); 888 smb_rq_bstart(rqp); 889 mb_put_uint8(mbp, SMB_DT_ASCII); 890 do { 891 error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, 0); 892 if (error) 893 break; 894 mb_put_uint8(mbp, SMB_DT_ASCII); 895 error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, tnmlen); 896 if (error) 897 break; 898 smb_rq_bend(rqp); 899 error = smb_rq_simple(rqp); 900 } while(0); 901 smb_rq_done(rqp); 902 return error; 903} 904 905int 906smbfs_smb_move(struct smbnode *src, struct smbnode *tdnp, 907 const char *tname, int tnmlen, u_int16_t flags, struct smb_cred *scred) 908{ 909 struct smb_rq rq, *rqp = &rq; 910 struct smb_share *ssp = src->n_mount->sm_share; 911 struct mbchain *mbp; 912 int error; 913 914 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_MOVE, scred); 915 if (error) 916 return error; 917 smb_rq_getrequest(rqp, &mbp); 918 smb_rq_wstart(rqp); 919 mb_put_uint16le(mbp, SMB_TID_UNKNOWN); 920 mb_put_uint16le(mbp, 0x20); /* delete target file */ 921 mb_put_uint16le(mbp, flags); 922 smb_rq_wend(rqp); 923 smb_rq_bstart(rqp); 924 mb_put_uint8(mbp, SMB_DT_ASCII); 925 do { 926 error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, 0); 927 if (error) 928 break; 929 mb_put_uint8(mbp, SMB_DT_ASCII); 930 error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, tnmlen); 931 if (error) 932 break; 933 smb_rq_bend(rqp); 934 error = smb_rq_simple(rqp); 935 } while(0); 936 smb_rq_done(rqp); 937 return error; 938} 939 940int 941smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int len, 942 struct smb_cred *scred) 943{ 944 struct smb_rq rq, *rqp = &rq; 945 struct smb_share *ssp = dnp->n_mount->sm_share; 946 struct mbchain *mbp; 947 int error; 948 949 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE_DIRECTORY, scred); 950 if (error) 951 return error; 952 smb_rq_getrequest(rqp, &mbp); 953 smb_rq_wstart(rqp); 954 smb_rq_wend(rqp); 955 smb_rq_bstart(rqp); 956 mb_put_uint8(mbp, SMB_DT_ASCII); 957 error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, len); 958 if (!error) { 959 smb_rq_bend(rqp); 960 error = smb_rq_simple(rqp); 961 } 962 smb_rq_done(rqp); 963 return error; 964} 965 966int 967smbfs_smb_rmdir(struct smbnode *np, struct smb_cred *scred) 968{ 969 struct smb_rq rq, *rqp = &rq; 970 struct smb_share *ssp = np->n_mount->sm_share; 971 struct mbchain *mbp; 972 int error; 973 974 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE_DIRECTORY, scred); 975 if (error) 976 return error; 977 smb_rq_getrequest(rqp, &mbp); 978 smb_rq_wstart(rqp); 979 smb_rq_wend(rqp); 980 smb_rq_bstart(rqp); 981 mb_put_uint8(mbp, SMB_DT_ASCII); 982 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0); 983 if (!error) { 984 smb_rq_bend(rqp); 985 error = smb_rq_simple(rqp); 986 } 987 smb_rq_done(rqp); 988 return error; 989} 990 991static int 992smbfs_smb_search(struct smbfs_fctx *ctx) 993{ 994 struct smb_vc *vcp = SSTOVC(ctx->f_ssp); 995 struct smb_rq *rqp; 996 struct mbchain *mbp; 997 struct mdchain *mdp; 998 u_int8_t wc, bt; 999 u_int16_t ec, dlen, bc; 1000 int maxent, error, iseof = 0; 1001 1002 maxent = min(ctx->f_left, (vcp->vc_txmax - SMB_HDRLEN - 3) / SMB_DENTRYLEN); 1003 if (ctx->f_rq) { 1004 smb_rq_done(ctx->f_rq); 1005 ctx->f_rq = NULL; 1006 } 1007 error = smb_rq_alloc(SSTOCP(ctx->f_ssp), SMB_COM_SEARCH, ctx->f_scred, &rqp); 1008 if (error) 1009 return error; 1010 ctx->f_rq = rqp; 1011 smb_rq_getrequest(rqp, &mbp); 1012 smb_rq_wstart(rqp); 1013 mb_put_uint16le(mbp, maxent); /* max entries to return */ 1014 mb_put_uint16le(mbp, ctx->f_attrmask); 1015 smb_rq_wend(rqp); 1016 smb_rq_bstart(rqp); 1017 mb_put_uint8(mbp, SMB_DT_ASCII); /* buffer format */ 1018 if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 1019 error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard, ctx->f_wclen); 1020 if (error) 1021 return error; 1022 mb_put_uint8(mbp, SMB_DT_VARIABLE); 1023 mb_put_uint16le(mbp, 0); /* context length */ 1024 ctx->f_flags &= ~SMBFS_RDD_FINDFIRST; 1025 } else { 1026 mb_put_uint8(mbp, 0); /* file name length */ 1027 mb_put_uint8(mbp, SMB_DT_VARIABLE); 1028 mb_put_uint16le(mbp, SMB_SKEYLEN); 1029 mb_put_mem(mbp, ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM); 1030 } 1031 smb_rq_bend(rqp); 1032 error = smb_rq_simple(rqp); 1033 if (error) { 1034 if (rqp->sr_errclass == ERRDOS && rqp->sr_serror == ERRnofiles) { 1035 error = 0; 1036 iseof = 1; 1037 ctx->f_flags |= SMBFS_RDD_EOF; 1038 } else 1039 return error; 1040 } 1041 smb_rq_getreply(rqp, &mdp); 1042 md_get_uint8(mdp, &wc); 1043 if (wc != 1) 1044 return iseof ? ENOENT : EBADRPC; 1045 md_get_uint16le(mdp, &ec); 1046 if (ec == 0) 1047 return ENOENT; 1048 ctx->f_ecnt = ec; 1049 md_get_uint16le(mdp, &bc); 1050 if (bc < 3) 1051 return EBADRPC; 1052 bc -= 3; 1053 md_get_uint8(mdp, &bt); 1054 if (bt != SMB_DT_VARIABLE) 1055 return EBADRPC; 1056 md_get_uint16le(mdp, &dlen); 1057 if (dlen != bc || dlen % SMB_DENTRYLEN != 0) 1058 return EBADRPC; 1059 return 0; 1060} 1061 1062static int 1063smbfs_findopenLM1(struct smbfs_fctx *ctx, struct smbnode *dnp, 1064 const char *wildcard, int wclen, int attr, struct smb_cred *scred) 1065{ 1066 ctx->f_attrmask = attr; 1067 if (wildcard) { 1068 if (wclen == 1 && wildcard[0] == '*') { 1069 ctx->f_wildcard = "*.*"; 1070 ctx->f_wclen = 3; 1071 } else { 1072 ctx->f_wildcard = wildcard; 1073 ctx->f_wclen = wclen; 1074 } 1075 } else { 1076 ctx->f_wildcard = NULL; 1077 ctx->f_wclen = 0; 1078 } 1079 ctx->f_name = ctx->f_fname; 1080 return 0; 1081} 1082 1083static int 1084smbfs_findnextLM1(struct smbfs_fctx *ctx, int limit) 1085{ 1086 struct mdchain *mbp; 1087 struct smb_rq *rqp; 1088 char *cp; 1089 u_int8_t battr; 1090 u_int16_t date, time; 1091 u_int32_t size; 1092 int error; 1093 1094 if (ctx->f_ecnt == 0) { 1095 if (ctx->f_flags & SMBFS_RDD_EOF) 1096 return ENOENT; 1097 ctx->f_left = ctx->f_limit = limit; 1098 error = smbfs_smb_search(ctx); 1099 if (error) 1100 return error; 1101 } 1102 rqp = ctx->f_rq; 1103 smb_rq_getreply(rqp, &mbp); 1104 md_get_mem(mbp, ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM); 1105 md_get_uint8(mbp, &battr); 1106 md_get_uint16le(mbp, &time); 1107 md_get_uint16le(mbp, &date); 1108 md_get_uint32le(mbp, &size); 1109 cp = ctx->f_name; 1110 md_get_mem(mbp, cp, sizeof(ctx->f_fname), MB_MSYSTEM); 1111 cp[sizeof(ctx->f_fname) - 1] = 0; 1112 cp += strlen(cp) - 1; 1113 while (*cp == ' ' && cp >= ctx->f_name) 1114 *cp-- = 0; 1115 ctx->f_attr.fa_attr = battr; 1116 smb_dos2unixtime(date, time, 0, rqp->sr_vc->vc_sopt.sv_tz, 1117 &ctx->f_attr.fa_mtime); 1118 ctx->f_attr.fa_size = size; 1119 ctx->f_nmlen = strlen(ctx->f_name); 1120 ctx->f_ecnt--; 1121 ctx->f_left--; 1122 return 0; 1123} 1124 1125static int 1126smbfs_findcloseLM1(struct smbfs_fctx *ctx) 1127{ 1128 if (ctx->f_rq) 1129 smb_rq_done(ctx->f_rq); 1130 return 0; 1131} 1132 1133/* 1134 * TRANS2_FIND_FIRST2/NEXT2, used for NT LM12 dialect 1135 */ 1136static int 1137smbfs_smb_trans2find2(struct smbfs_fctx *ctx) 1138{ 1139 struct smb_t2rq *t2p; 1140 struct smb_vc *vcp = SSTOVC(ctx->f_ssp); 1141 struct mbchain *mbp; 1142 struct mdchain *mdp; 1143 u_int16_t tw, flags; 1144 int error; 1145 1146 if (ctx->f_t2) { 1147 smb_t2_done(ctx->f_t2); 1148 ctx->f_t2 = NULL; 1149 } 1150 ctx->f_flags &= ~SMBFS_RDD_GOTRNAME; 1151 flags = 8 | 2; /* <resume> | <close if EOS> */ 1152 if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) { 1153 flags |= 1; /* close search after this request */ 1154 ctx->f_flags |= SMBFS_RDD_NOCLOSE; 1155 } 1156 if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 1157 error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_FIRST2, 1158 ctx->f_scred, &t2p); 1159 if (error) 1160 return error; 1161 ctx->f_t2 = t2p; 1162 mbp = &t2p->t2_tparam; 1163 mb_init(mbp); 1164 mb_put_uint16le(mbp, ctx->f_attrmask); 1165 mb_put_uint16le(mbp, ctx->f_limit); 1166 mb_put_uint16le(mbp, flags); 1167 mb_put_uint16le(mbp, ctx->f_infolevel); 1168 mb_put_uint32le(mbp, 0); 1169 error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard, ctx->f_wclen); 1170 if (error) 1171 return error; 1172 } else { 1173 error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_NEXT2, 1174 ctx->f_scred, &t2p); 1175 if (error) 1176 return error; 1177 ctx->f_t2 = t2p; 1178 mbp = &t2p->t2_tparam; 1179 mb_init(mbp); 1180 mb_put_mem(mbp, (caddr_t)&ctx->f_Sid, 2, MB_MSYSTEM); 1181 mb_put_uint16le(mbp, ctx->f_limit); 1182 mb_put_uint16le(mbp, ctx->f_infolevel); 1183 mb_put_uint32le(mbp, 0); /* resume key */ 1184 mb_put_uint16le(mbp, flags); 1185 if (ctx->f_rname) 1186 mb_put_mem(mbp, ctx->f_rname, strlen(ctx->f_rname) + 1, MB_MSYSTEM); 1187 else 1188 mb_put_uint8(mbp, 0); /* resume file name */ 1189#if 0 1190 struct timeval tv; 1191 tv.tv_sec = 0; 1192 tv.tv_usec = 200 * 1000; /* 200ms */ 1193 if (vcp->vc_flags & SMBC_WIN95) { 1194 /* 1195 * some implementations suggests to sleep here 1196 * for 200ms, due to the bug in the Win95. 1197 * I've didn't notice any problem, but put code 1198 * for it. 1199 */ 1200 tsleep(&flags, PVFS, "fix95", tvtohz(&tv)); 1201 } 1202#endif 1203 } 1204 t2p->t2_maxpcount = 5 * 2; 1205 t2p->t2_maxdcount = vcp->vc_txmax; 1206 error = smb_t2_request(t2p); 1207 if (error) 1208 return error; 1209 mdp = &t2p->t2_rparam; 1210 if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 1211 if ((error = md_get_uint16(mdp, &ctx->f_Sid)) != 0) 1212 return error; 1213 ctx->f_flags &= ~SMBFS_RDD_FINDFIRST; 1214 } 1215 if ((error = md_get_uint16le(mdp, &tw)) != 0) 1216 return error; 1217 ctx->f_ecnt = tw; 1218 if ((error = md_get_uint16le(mdp, &tw)) != 0) 1219 return error; 1220 if (tw) 1221 ctx->f_flags |= SMBFS_RDD_EOF | SMBFS_RDD_NOCLOSE; 1222 if ((error = md_get_uint16le(mdp, &tw)) != 0) 1223 return error; 1224 if ((error = md_get_uint16le(mdp, &tw)) != 0) 1225 return error; 1226 if (ctx->f_ecnt == 0) 1227 return ENOENT; 1228 ctx->f_rnameofs = tw; 1229 mdp = &t2p->t2_rdata; 1230 if (mdp->md_top == NULL) { 1231 printf("bug: ecnt = %d, but data is NULL (please report)\n", ctx->f_ecnt); 1232 return ENOENT; 1233 } 1234 if (mdp->md_top->m_len == 0) { 1235 printf("bug: ecnt = %d, but m_len = 0 and m_next = %p (please report)\n", ctx->f_ecnt,mbp->mb_top->m_next); 1236 return ENOENT; 1237 } 1238 ctx->f_eofs = 0; 1239 return 0; 1240} 1241 1242static int 1243smbfs_smb_findclose2(struct smbfs_fctx *ctx) 1244{ 1245 struct smb_rq rq, *rqp = &rq; 1246 struct mbchain *mbp; 1247 int error; 1248 1249 error = smb_rq_init(rqp, SSTOCP(ctx->f_ssp), SMB_COM_FIND_CLOSE2, ctx->f_scred); 1250 if (error) 1251 return error; 1252 smb_rq_getrequest(rqp, &mbp); 1253 smb_rq_wstart(rqp); 1254 mb_put_mem(mbp, (caddr_t)&ctx->f_Sid, 2, MB_MSYSTEM); 1255 smb_rq_wend(rqp); 1256 smb_rq_bstart(rqp); 1257 smb_rq_bend(rqp); 1258 error = smb_rq_simple(rqp); 1259 smb_rq_done(rqp); 1260 return error; 1261} 1262 1263static int 1264smbfs_findopenLM2(struct smbfs_fctx *ctx, struct smbnode *dnp, 1265 const char *wildcard, int wclen, int attr, struct smb_cred *scred) 1266{
| 33 */ 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/kernel.h> 37#include <sys/malloc.h> 38#include <sys/proc.h> 39#include <sys/lock.h> 40#include <sys/vnode.h> 41#include <sys/mbuf.h> 42#include <sys/mount.h> 43 44#ifdef USE_MD5_HASH 45#include <sys/md5.h> 46#endif 47 48#include <netsmb/smb.h> 49#include <netsmb/smb_subr.h> 50#include <netsmb/smb_rq.h> 51#include <netsmb/smb_conn.h> 52 53#include <fs/smbfs/smbfs.h> 54#include <fs/smbfs/smbfs_node.h> 55#include <fs/smbfs/smbfs_subr.h> 56 57/* 58 * Lack of inode numbers leads us to the problem of generating them. 59 * Partially this problem can be solved by having a dir/file cache 60 * with inode numbers generated from the incremented by one counter. 61 * However this way will require too much kernel memory, gives all 62 * sorts of locking and consistency problems, not to mentinon counter overflows. 63 * So, I'm decided to use a hash function to generate pseudo random (and unique) 64 * inode numbers. 65 */ 66static long 67smbfs_getino(struct smbnode *dnp, const char *name, int nmlen) 68{ 69#ifdef USE_MD5_HASH 70 MD5_CTX md5; 71 u_int32_t state[4]; 72 long ino; 73 int i; 74 75 MD5Init(&md5); 76 MD5Update(&md5, name, nmlen); 77 MD5Final((u_char *)state, &md5); 78 for (i = 0, ino = 0; i < 4; i++) 79 ino += state[i]; 80 return dnp->n_ino + ino; 81#endif 82 u_int32_t ino; 83 84 ino = dnp->n_ino + smbfs_hash(name, nmlen); 85 if (ino <= 2) 86 ino += 3; 87 return ino; 88} 89 90static int 91smbfs_smb_lockandx(struct smbnode *np, int op, u_int32_t pid, off_t start, off_t end, 92 struct smb_cred *scred) 93{ 94 struct smb_share *ssp = np->n_mount->sm_share; 95 struct smb_rq rq, *rqp = &rq; 96 struct mbchain *mbp; 97 u_char ltype = 0; 98 int error; 99 100 if (op == SMB_LOCK_SHARED) 101 ltype |= SMB_LOCKING_ANDX_SHARED_LOCK; 102 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scred); 103 if (error) 104 return error; 105 smb_rq_getrequest(rqp, &mbp); 106 smb_rq_wstart(rqp); 107 mb_put_uint8(mbp, 0xff); /* secondary command */ 108 mb_put_uint8(mbp, 0); /* MBZ */ 109 mb_put_uint16le(mbp, 0); 110 mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 111 mb_put_uint8(mbp, ltype); /* locktype */ 112 mb_put_uint8(mbp, 0); /* oplocklevel - 0 seems is NO_OPLOCK */ 113 mb_put_uint32le(mbp, 0); /* timeout - break immediately */ 114 mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 1 : 0); 115 mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 0 : 1); 116 smb_rq_wend(rqp); 117 smb_rq_bstart(rqp); 118 mb_put_uint16le(mbp, pid); 119 mb_put_uint32le(mbp, start); 120 mb_put_uint32le(mbp, end - start); 121 smb_rq_bend(rqp); 122 error = smb_rq_simple(rqp); 123 smb_rq_done(rqp); 124 return error; 125} 126 127int 128smbfs_smb_lock(struct smbnode *np, int op, caddr_t id, 129 off_t start, off_t end, struct smb_cred *scred) 130{ 131 struct smb_share *ssp = np->n_mount->sm_share; 132 133 if (SMB_DIALECT(SSTOVC(ssp)) < SMB_DIALECT_LANMAN1_0) 134 /* 135 * TODO: use LOCK_BYTE_RANGE here. 136 */ 137 return EINVAL; 138 else 139 return smbfs_smb_lockandx(np, op, (uintptr_t)id, start, end, scred); 140} 141 142static int 143smbfs_smb_qpathinfo(struct smbnode *np, struct smbfattr *fap, 144 struct smb_cred *scred, short infolevel) 145{ 146 struct smb_share *ssp = np->n_mount->sm_share; 147 struct smb_vc *vcp = SSTOVC(ssp); 148 struct smb_t2rq *t2p; 149 int error, svtz, timesok = 1; 150 struct mbchain *mbp; 151 struct mdchain *mdp; 152 u_int16_t date, time, wattr; 153 int64_t lint; 154 u_int32_t size, dattr; 155 156 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_PATH_INFORMATION, 157 scred, &t2p); 158 if (error) 159 return error; 160 mbp = &t2p->t2_tparam; 161 mb_init(mbp); 162 if (!infolevel) { 163 if (SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12) 164 infolevel = SMB_QUERY_FILE_STANDARD; 165 else 166 infolevel = SMB_QUERY_FILE_BASIC_INFO; 167 } 168 mb_put_uint16le(mbp, infolevel); 169 mb_put_uint32le(mbp, 0); 170 /* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */ 171 error = smbfs_fullpath(mbp, vcp, np, NULL, 0); 172 if (error) { 173 smb_t2_done(t2p); 174 return error; 175 } 176 t2p->t2_maxpcount = 2; 177 t2p->t2_maxdcount = vcp->vc_txmax; 178 error = smb_t2_request(t2p); 179 if (error) { 180 smb_t2_done(t2p); 181 if (infolevel == SMB_QUERY_FILE_STANDARD || error != EINVAL) 182 return error; 183 return smbfs_smb_qpathinfo(np, fap, scred, 184 SMB_QUERY_FILE_STANDARD); 185 } 186 mdp = &t2p->t2_rdata; 187 svtz = vcp->vc_sopt.sv_tz; 188 switch (infolevel) { 189 case SMB_QUERY_FILE_STANDARD: 190 timesok = 0; 191 md_get_uint16le(mdp, NULL); 192 md_get_uint16le(mdp, NULL); /* creation time */ 193 md_get_uint16le(mdp, &date); 194 md_get_uint16le(mdp, &time); /* access time */ 195 if (date || time) { 196 timesok++; 197 smb_dos2unixtime(date, time, 0, svtz, &fap->fa_atime); 198 } 199 md_get_uint16le(mdp, &date); 200 md_get_uint16le(mdp, &time); /* modify time */ 201 if (date || time) { 202 timesok++; 203 smb_dos2unixtime(date, time, 0, svtz, &fap->fa_mtime); 204 } 205 md_get_uint32le(mdp, &size); 206 fap->fa_size = size; 207 md_get_uint32(mdp, NULL); /* allocation size */ 208 md_get_uint16le(mdp, &wattr); 209 fap->fa_attr = wattr; 210 break; 211 case SMB_QUERY_FILE_BASIC_INFO: 212 timesok = 0; 213 md_get_int64(mdp, NULL); /* creation time */ 214 md_get_int64le(mdp, &lint); 215 if (lint) { 216 timesok++; 217 smb_time_NT2local(lint, svtz, &fap->fa_atime); 218 } 219 md_get_int64le(mdp, &lint); 220 if (lint) { 221 timesok++; 222 smb_time_NT2local(lint, svtz, &fap->fa_mtime); 223 } 224 md_get_int64le(mdp, &lint); 225 if (lint) { 226 timesok++; 227 smb_time_NT2local(lint, svtz, &fap->fa_ctime); 228 } 229 md_get_uint32le(mdp, &dattr); 230 fap->fa_attr = dattr; 231 md_get_uint32(mdp, NULL); 232 /* XXX could use ALL_INFO to get size */ 233 break; 234 default: 235 SMBERROR("unexpected info level %d\n", infolevel); 236 error = EINVAL; 237 } 238 smb_t2_done(t2p); 239 /* 240 * if all times are zero (observed with FAT on NT4SP6) 241 * then fall back to older info level 242 */ 243 if (!timesok) { 244 if (infolevel != SMB_QUERY_FILE_STANDARD) 245 return smbfs_smb_qpathinfo(np, fap, scred, 246 SMB_QUERY_FILE_STANDARD); 247 error = EINVAL; 248 } 249 return error; 250} 251 252int 253smbfs_smb_statfs2(struct smb_share *ssp, struct statfs *sbp, 254 struct smb_cred *scred) 255{ 256 struct smb_t2rq *t2p; 257 struct mbchain *mbp; 258 struct mdchain *mdp; 259 u_int16_t bsize; 260 u_int32_t units, bpu, funits; 261 int error; 262 263 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION, 264 scred, &t2p); 265 if (error) 266 return error; 267 mbp = &t2p->t2_tparam; 268 mb_init(mbp); 269 mb_put_uint16le(mbp, SMB_INFO_ALLOCATION); 270 t2p->t2_maxpcount = 4; 271 t2p->t2_maxdcount = 4 * 4 + 2; 272 error = smb_t2_request(t2p); 273 if (error) { 274 smb_t2_done(t2p); 275 return error; 276 } 277 mdp = &t2p->t2_rdata; 278 md_get_uint32(mdp, NULL); /* fs id */ 279 md_get_uint32le(mdp, &bpu); 280 md_get_uint32le(mdp, &units); 281 md_get_uint32le(mdp, &funits); 282 md_get_uint16le(mdp, &bsize); 283 sbp->f_bsize = bpu * bsize; /* fundamental filesystem block size */ 284 sbp->f_blocks= units; /* total data blocks in filesystem */ 285 sbp->f_bfree = funits; /* free blocks in fs */ 286 sbp->f_bavail= funits; /* free blocks avail to non-superuser */ 287 sbp->f_files = 0xffff; /* total file nodes in filesystem */ 288 sbp->f_ffree = 0xffff; /* free file nodes in fs */ 289 smb_t2_done(t2p); 290 return 0; 291} 292 293int 294smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp, 295 struct smb_cred *scred) 296{ 297 struct smb_rq rq, *rqp = &rq; 298 struct mdchain *mdp; 299 u_int16_t units, bpu, bsize, funits; 300 int error; 301 302 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION_DISK, scred); 303 if (error) 304 return error; 305 smb_rq_wstart(rqp); 306 smb_rq_wend(rqp); 307 smb_rq_bstart(rqp); 308 smb_rq_bend(rqp); 309 error = smb_rq_simple(rqp); 310 if (error) { 311 smb_rq_done(rqp); 312 return error; 313 } 314 smb_rq_getreply(rqp, &mdp); 315 md_get_uint16le(mdp, &units); 316 md_get_uint16le(mdp, &bpu); 317 md_get_uint16le(mdp, &bsize); 318 md_get_uint16le(mdp, &funits); 319 sbp->f_bsize = bpu * bsize; /* fundamental filesystem block size */ 320 sbp->f_blocks= units; /* total data blocks in filesystem */ 321 sbp->f_bfree = funits; /* free blocks in fs */ 322 sbp->f_bavail= funits; /* free blocks avail to non-superuser */ 323 sbp->f_files = 0xffff; /* total file nodes in filesystem */ 324 sbp->f_ffree = 0xffff; /* free file nodes in fs */ 325 smb_rq_done(rqp); 326 return 0; 327} 328 329static int 330smbfs_smb_seteof(struct smbnode *np, int64_t newsize, struct smb_cred *scred) 331{ 332 struct smb_t2rq *t2p; 333 struct smb_share *ssp = np->n_mount->sm_share; 334 struct mbchain *mbp; 335 int error; 336 337 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION, 338 scred, &t2p); 339 if (error) 340 return error; 341 mbp = &t2p->t2_tparam; 342 mb_init(mbp); 343 mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 344 mb_put_uint16le(mbp, SMB_SET_FILE_END_OF_FILE_INFO); 345 mb_put_uint32le(mbp, 0); 346 mbp = &t2p->t2_tdata; 347 mb_init(mbp); 348 mb_put_int64le(mbp, newsize); 349 mb_put_uint32le(mbp, 0); /* padding */ 350 mb_put_uint16le(mbp, 0); 351 t2p->t2_maxpcount = 2; 352 t2p->t2_maxdcount = 0; 353 error = smb_t2_request(t2p); 354 smb_t2_done(t2p); 355 return error; 356} 357 358static int 359smb_smb_flush(struct smbnode *np, struct smb_cred *scred) 360{ 361 struct smb_share *ssp = np->n_mount->sm_share; 362 struct smb_rq rq, *rqp = &rq; 363 struct mbchain *mbp; 364 int error; 365 366 if (np->n_opencount <= 0 || !SMBTOV(np) || SMBTOV(np)->v_type != VREG) 367 return 0; /* not a regular open file */ 368 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_FLUSH, scred); 369 if (error) 370 return (error); 371 smb_rq_getrequest(rqp, &mbp); 372 smb_rq_wstart(rqp); 373 mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 374 smb_rq_wend(rqp); 375 smb_rq_bstart(rqp); 376 smb_rq_bend(rqp); 377 error = smb_rq_simple(rqp); 378 smb_rq_done(rqp); 379 if (!error) 380 np->n_flag &= ~NFLUSHWIRE; 381 return (error); 382} 383 384int 385smbfs_smb_flush(struct smbnode *np, struct smb_cred *scred) 386{ 387 if (np->n_flag & NFLUSHWIRE) 388 return (smb_smb_flush(np, scred)); 389 return (0); 390} 391 392int 393smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred) 394{ 395 struct smb_share *ssp = np->n_mount->sm_share; 396 struct smb_rq rq, *rqp = &rq; 397 struct mbchain *mbp; 398 int error; 399 400 if (!smbfs_smb_seteof(np, (int64_t) newsize, scred)) { 401 np->n_flag |= NFLUSHWIRE; 402 return (0); 403 } 404 405 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_WRITE, scred); 406 if (error) 407 return error; 408 smb_rq_getrequest(rqp, &mbp); 409 smb_rq_wstart(rqp); 410 mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 411 mb_put_uint16le(mbp, 0); 412 mb_put_uint32le(mbp, newsize); 413 mb_put_uint16le(mbp, 0); 414 smb_rq_wend(rqp); 415 smb_rq_bstart(rqp); 416 mb_put_uint8(mbp, SMB_DT_DATA); 417 mb_put_uint16le(mbp, 0); 418 smb_rq_bend(rqp); 419 error = smb_rq_simple(rqp); 420 smb_rq_done(rqp); 421 return error; 422} 423 424int 425smbfs_smb_query_info(struct smbnode *np, const char *name, int len, 426 struct smbfattr *fap, struct smb_cred *scred) 427{ 428 struct smb_rq rq, *rqp = &rq; 429 struct smb_share *ssp = np->n_mount->sm_share; 430 struct mbchain *mbp; 431 struct mdchain *mdp; 432 u_int8_t wc; 433 int error; 434 u_int16_t wattr; 435 u_int32_t lint; 436 437 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION, scred); 438 if (error) 439 return error; 440 smb_rq_getrequest(rqp, &mbp); 441 smb_rq_wstart(rqp); 442 smb_rq_wend(rqp); 443 smb_rq_bstart(rqp); 444 mb_put_uint8(mbp, SMB_DT_ASCII); 445 do { 446 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, len); 447 if (error) 448 break; 449 smb_rq_bend(rqp); 450 error = smb_rq_simple(rqp); 451 if (error) 452 break; 453 smb_rq_getreply(rqp, &mdp); 454 if (md_get_uint8(mdp, &wc) != 0 || wc != 10) { 455 error = EBADRPC; 456 break; 457 } 458 md_get_uint16le(mdp, &wattr); 459 fap->fa_attr = wattr; 460 /* 461 * Be careful using the time returned here, as 462 * with FAT on NT4SP6, at least, the time returned is low 463 * 32 bits of 100s of nanoseconds (since 1601) so it rolls 464 * over about every seven minutes! 465 */ 466 md_get_uint32le(mdp, &lint); /* specs: secs since 1970 */ 467 if (lint) /* avoid bogus zero returns */ 468 smb_time_server2local(lint, SSTOVC(ssp)->vc_sopt.sv_tz, 469 &fap->fa_mtime); 470 md_get_uint32le(mdp, &lint); 471 fap->fa_size = lint; 472 } while(0); 473 smb_rq_done(rqp); 474 return error; 475} 476 477/* 478 * Set DOS file attributes. mtime should be NULL for dialects above lm10 479 */ 480int 481smbfs_smb_setpattr(struct smbnode *np, u_int16_t attr, struct timespec *mtime, 482 struct smb_cred *scred) 483{ 484 struct smb_rq rq, *rqp = &rq; 485 struct smb_share *ssp = np->n_mount->sm_share; 486 struct mbchain *mbp; 487 u_long time; 488 int error, svtz; 489 490 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION, scred); 491 if (error) 492 return error; 493 svtz = SSTOVC(ssp)->vc_sopt.sv_tz; 494 smb_rq_getrequest(rqp, &mbp); 495 smb_rq_wstart(rqp); 496 mb_put_uint16le(mbp, attr); 497 if (mtime) { 498 smb_time_local2server(mtime, svtz, &time); 499 } else 500 time = 0; 501 mb_put_uint32le(mbp, time); /* mtime */ 502 mb_put_mem(mbp, NULL, 5 * 2, MB_MZERO); 503 smb_rq_wend(rqp); 504 smb_rq_bstart(rqp); 505 mb_put_uint8(mbp, SMB_DT_ASCII); 506 do { 507 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0); 508 if (error) 509 break; 510 mb_put_uint8(mbp, SMB_DT_ASCII); 511 mb_put_uint8(mbp, 0); 512 smb_rq_bend(rqp); 513 error = smb_rq_simple(rqp); 514 SMBERROR("%d\n", error); 515 if (error) 516 break; 517 } while(0); 518 smb_rq_done(rqp); 519 return error; 520} 521 522/* 523 * Note, win95 doesn't support this call. 524 */ 525int 526smbfs_smb_setptime2(struct smbnode *np, struct timespec *mtime, 527 struct timespec *atime, int attr, struct smb_cred *scred) 528{ 529 struct smb_t2rq *t2p; 530 struct smb_share *ssp = np->n_mount->sm_share; 531 struct smb_vc *vcp = SSTOVC(ssp); 532 struct mbchain *mbp; 533 u_int16_t date, time; 534 int error, tzoff; 535 536 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_PATH_INFORMATION, 537 scred, &t2p); 538 if (error) 539 return error; 540 mbp = &t2p->t2_tparam; 541 mb_init(mbp); 542 mb_put_uint16le(mbp, SMB_INFO_STANDARD); 543 mb_put_uint32le(mbp, 0); /* MBZ */ 544 /* mb_put_uint8(mbp, SMB_DT_ASCII); specs incorrect */ 545 error = smbfs_fullpath(mbp, vcp, np, NULL, 0); 546 if (error) { 547 smb_t2_done(t2p); 548 return error; 549 } 550 tzoff = vcp->vc_sopt.sv_tz; 551 mbp = &t2p->t2_tdata; 552 mb_init(mbp); 553 mb_put_uint32le(mbp, 0); /* creation time */ 554 if (atime) 555 smb_time_unix2dos(atime, tzoff, &date, &time, NULL); 556 else 557 time = date = 0; 558 mb_put_uint16le(mbp, date); 559 mb_put_uint16le(mbp, time); 560 if (mtime) 561 smb_time_unix2dos(mtime, tzoff, &date, &time, NULL); 562 else 563 time = date = 0; 564 mb_put_uint16le(mbp, date); 565 mb_put_uint16le(mbp, time); 566 mb_put_uint32le(mbp, 0); /* file size */ 567 mb_put_uint32le(mbp, 0); /* allocation unit size */ 568 mb_put_uint16le(mbp, attr); /* DOS attr */ 569 mb_put_uint32le(mbp, 0); /* EA size */ 570 t2p->t2_maxpcount = 5 * 2; 571 t2p->t2_maxdcount = vcp->vc_txmax; 572 error = smb_t2_request(t2p); 573 smb_t2_done(t2p); 574 return error; 575} 576 577/* 578 * NT level. Specially for win9x 579 */ 580int 581smbfs_smb_setpattrNT(struct smbnode *np, u_short attr, struct timespec *mtime, 582 struct timespec *atime, struct smb_cred *scred) 583{ 584 struct smb_t2rq *t2p; 585 struct smb_share *ssp = np->n_mount->sm_share; 586 struct smb_vc *vcp = SSTOVC(ssp); 587 struct mbchain *mbp; 588 int64_t tm; 589 int error, tzoff; 590 591 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_PATH_INFORMATION, 592 scred, &t2p); 593 if (error) 594 return error; 595 mbp = &t2p->t2_tparam; 596 mb_init(mbp); 597 mb_put_uint16le(mbp, SMB_SET_FILE_BASIC_INFO); 598 mb_put_uint32le(mbp, 0); /* MBZ */ 599 /* mb_put_uint8(mbp, SMB_DT_ASCII); specs incorrect */ 600 error = smbfs_fullpath(mbp, vcp, np, NULL, 0); 601 if (error) { 602 smb_t2_done(t2p); 603 return error; 604 } 605 tzoff = vcp->vc_sopt.sv_tz; 606 mbp = &t2p->t2_tdata; 607 mb_init(mbp); 608 mb_put_int64le(mbp, 0); /* creation time */ 609 if (atime) { 610 smb_time_local2NT(atime, tzoff, &tm); 611 } else 612 tm = 0; 613 mb_put_int64le(mbp, tm); 614 if (mtime) { 615 smb_time_local2NT(mtime, tzoff, &tm); 616 } else 617 tm = 0; 618 mb_put_int64le(mbp, tm); 619 mb_put_int64le(mbp, tm); /* change time */ 620 mb_put_uint32le(mbp, attr); /* attr */ 621 t2p->t2_maxpcount = 24; 622 t2p->t2_maxdcount = 56; 623 error = smb_t2_request(t2p); 624 smb_t2_done(t2p); 625 return error; 626} 627 628/* 629 * Set file atime and mtime. Doesn't supported by core dialect. 630 */ 631int 632smbfs_smb_setftime(struct smbnode *np, struct timespec *mtime, 633 struct timespec *atime, struct smb_cred *scred) 634{ 635 struct smb_rq rq, *rqp = &rq; 636 struct smb_share *ssp = np->n_mount->sm_share; 637 struct mbchain *mbp; 638 u_int16_t date, time; 639 int error, tzoff; 640 641 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION2, scred); 642 if (error) 643 return error; 644 tzoff = SSTOVC(ssp)->vc_sopt.sv_tz; 645 smb_rq_getrequest(rqp, &mbp); 646 smb_rq_wstart(rqp); 647 mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 648 mb_put_uint32le(mbp, 0); /* creation time */ 649 650 if (atime) 651 smb_time_unix2dos(atime, tzoff, &date, &time, NULL); 652 else 653 time = date = 0; 654 mb_put_uint16le(mbp, date); 655 mb_put_uint16le(mbp, time); 656 if (mtime) 657 smb_time_unix2dos(mtime, tzoff, &date, &time, NULL); 658 else 659 time = date = 0; 660 mb_put_uint16le(mbp, date); 661 mb_put_uint16le(mbp, time); 662 smb_rq_wend(rqp); 663 smb_rq_bstart(rqp); 664 smb_rq_bend(rqp); 665 error = smb_rq_simple(rqp); 666 SMBSDEBUG("%d\n", error); 667 smb_rq_done(rqp); 668 return error; 669} 670 671/* 672 * Set DOS file attributes. 673 * Looks like this call can be used only if CAP_NT_SMBS bit is on. 674 */ 675int 676smbfs_smb_setfattrNT(struct smbnode *np, u_int16_t attr, struct timespec *mtime, 677 struct timespec *atime, struct smb_cred *scred) 678{ 679 struct smb_t2rq *t2p; 680 struct smb_share *ssp = np->n_mount->sm_share; 681 struct mbchain *mbp; 682 int64_t tm; 683 int error, svtz; 684 685 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION, 686 scred, &t2p); 687 if (error) 688 return error; 689 svtz = SSTOVC(ssp)->vc_sopt.sv_tz; 690 mbp = &t2p->t2_tparam; 691 mb_init(mbp); 692 mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 693 mb_put_uint16le(mbp, SMB_SET_FILE_BASIC_INFO); 694 mb_put_uint32le(mbp, 0); 695 mbp = &t2p->t2_tdata; 696 mb_init(mbp); 697 mb_put_int64le(mbp, 0); /* creation time */ 698 if (atime) { 699 smb_time_local2NT(atime, svtz, &tm); 700 } else 701 tm = 0; 702 mb_put_int64le(mbp, tm); 703 if (mtime) { 704 smb_time_local2NT(mtime, svtz, &tm); 705 } else 706 tm = 0; 707 mb_put_int64le(mbp, tm); 708 mb_put_int64le(mbp, tm); /* change time */ 709 mb_put_uint16le(mbp, attr); 710 mb_put_uint32le(mbp, 0); /* padding */ 711 mb_put_uint16le(mbp, 0); 712 t2p->t2_maxpcount = 2; 713 t2p->t2_maxdcount = 0; 714 error = smb_t2_request(t2p); 715 smb_t2_done(t2p); 716 return error; 717} 718 719 720int 721smbfs_smb_open(struct smbnode *np, int accmode, struct smb_cred *scred) 722{ 723 struct smb_rq rq, *rqp = &rq; 724 struct smb_share *ssp = np->n_mount->sm_share; 725 struct mbchain *mbp; 726 struct mdchain *mdp; 727 u_int8_t wc; 728 u_int16_t fid, wattr, grantedmode; 729 int error; 730 731 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN, scred); 732 if (error) 733 return error; 734 smb_rq_getrequest(rqp, &mbp); 735 smb_rq_wstart(rqp); 736 mb_put_uint16le(mbp, accmode); 737 mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN); 738 smb_rq_wend(rqp); 739 smb_rq_bstart(rqp); 740 mb_put_uint8(mbp, SMB_DT_ASCII); 741 do { 742 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0); 743 if (error) 744 break; 745 smb_rq_bend(rqp); 746 error = smb_rq_simple(rqp); 747 if (error) 748 break; 749 smb_rq_getreply(rqp, &mdp); 750 if (md_get_uint8(mdp, &wc) != 0 || wc != 7) { 751 error = EBADRPC; 752 break; 753 } 754 md_get_uint16(mdp, &fid); 755 md_get_uint16le(mdp, &wattr); 756 md_get_uint32(mdp, NULL); /* mtime */ 757 md_get_uint32(mdp, NULL); /* fsize */ 758 md_get_uint16le(mdp, &grantedmode); 759 /* 760 * TODO: refresh attributes from this reply 761 */ 762 } while(0); 763 smb_rq_done(rqp); 764 if (error) 765 return error; 766 np->n_fid = fid; 767 np->n_rwstate = grantedmode; 768 return 0; 769} 770 771 772int 773smbfs_smb_close(struct smb_share *ssp, u_int16_t fid, struct timespec *mtime, 774 struct smb_cred *scred) 775{ 776 struct smb_rq rq, *rqp = &rq; 777 struct mbchain *mbp; 778 u_long time; 779 int error; 780 781 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scred); 782 if (error) 783 return error; 784 smb_rq_getrequest(rqp, &mbp); 785 smb_rq_wstart(rqp); 786 mb_put_mem(mbp, (caddr_t)&fid, sizeof(fid), MB_MSYSTEM); 787 if (mtime) { 788 smb_time_local2server(mtime, SSTOVC(ssp)->vc_sopt.sv_tz, &time); 789 } else 790 time = 0; 791 mb_put_uint32le(mbp, time); 792 smb_rq_wend(rqp); 793 smb_rq_bstart(rqp); 794 smb_rq_bend(rqp); 795 error = smb_rq_simple(rqp); 796 smb_rq_done(rqp); 797 return error; 798} 799 800int 801smbfs_smb_create(struct smbnode *dnp, const char *name, int nmlen, 802 struct smb_cred *scred) 803{ 804 struct smb_rq rq, *rqp = &rq; 805 struct smb_share *ssp = dnp->n_mount->sm_share; 806 struct mbchain *mbp; 807 struct mdchain *mdp; 808 struct timespec ctime; 809 u_int8_t wc; 810 u_int16_t fid; 811 u_long tm; 812 int error; 813 814 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE, scred); 815 if (error) 816 return error; 817 smb_rq_getrequest(rqp, &mbp); 818 smb_rq_wstart(rqp); 819 mb_put_uint16le(mbp, SMB_FA_ARCHIVE); /* attributes */ 820 nanotime(&ctime); 821 smb_time_local2server(&ctime, SSTOVC(ssp)->vc_sopt.sv_tz, &tm); 822 mb_put_uint32le(mbp, tm); 823 smb_rq_wend(rqp); 824 smb_rq_bstart(rqp); 825 mb_put_uint8(mbp, SMB_DT_ASCII); 826 error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, nmlen); 827 if (!error) { 828 smb_rq_bend(rqp); 829 error = smb_rq_simple(rqp); 830 if (!error) { 831 smb_rq_getreply(rqp, &mdp); 832 md_get_uint8(mdp, &wc); 833 if (wc == 1) 834 md_get_uint16(mdp, &fid); 835 else 836 error = EBADRPC; 837 } 838 } 839 smb_rq_done(rqp); 840 if (error) 841 return error; 842 smbfs_smb_close(ssp, fid, &ctime, scred); 843 return error; 844} 845 846int 847smbfs_smb_delete(struct smbnode *np, struct smb_cred *scred) 848{ 849 struct smb_rq rq, *rqp = &rq; 850 struct smb_share *ssp = np->n_mount->sm_share; 851 struct mbchain *mbp; 852 int error; 853 854 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE, scred); 855 if (error) 856 return error; 857 smb_rq_getrequest(rqp, &mbp); 858 smb_rq_wstart(rqp); 859 mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN); 860 smb_rq_wend(rqp); 861 smb_rq_bstart(rqp); 862 mb_put_uint8(mbp, SMB_DT_ASCII); 863 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0); 864 if (!error) { 865 smb_rq_bend(rqp); 866 error = smb_rq_simple(rqp); 867 } 868 smb_rq_done(rqp); 869 return error; 870} 871 872int 873smbfs_smb_rename(struct smbnode *src, struct smbnode *tdnp, 874 const char *tname, int tnmlen, struct smb_cred *scred) 875{ 876 struct smb_rq rq, *rqp = &rq; 877 struct smb_share *ssp = src->n_mount->sm_share; 878 struct mbchain *mbp; 879 int error; 880 881 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_RENAME, scred); 882 if (error) 883 return error; 884 smb_rq_getrequest(rqp, &mbp); 885 smb_rq_wstart(rqp); 886 mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN); 887 smb_rq_wend(rqp); 888 smb_rq_bstart(rqp); 889 mb_put_uint8(mbp, SMB_DT_ASCII); 890 do { 891 error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, 0); 892 if (error) 893 break; 894 mb_put_uint8(mbp, SMB_DT_ASCII); 895 error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, tnmlen); 896 if (error) 897 break; 898 smb_rq_bend(rqp); 899 error = smb_rq_simple(rqp); 900 } while(0); 901 smb_rq_done(rqp); 902 return error; 903} 904 905int 906smbfs_smb_move(struct smbnode *src, struct smbnode *tdnp, 907 const char *tname, int tnmlen, u_int16_t flags, struct smb_cred *scred) 908{ 909 struct smb_rq rq, *rqp = &rq; 910 struct smb_share *ssp = src->n_mount->sm_share; 911 struct mbchain *mbp; 912 int error; 913 914 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_MOVE, scred); 915 if (error) 916 return error; 917 smb_rq_getrequest(rqp, &mbp); 918 smb_rq_wstart(rqp); 919 mb_put_uint16le(mbp, SMB_TID_UNKNOWN); 920 mb_put_uint16le(mbp, 0x20); /* delete target file */ 921 mb_put_uint16le(mbp, flags); 922 smb_rq_wend(rqp); 923 smb_rq_bstart(rqp); 924 mb_put_uint8(mbp, SMB_DT_ASCII); 925 do { 926 error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, 0); 927 if (error) 928 break; 929 mb_put_uint8(mbp, SMB_DT_ASCII); 930 error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, tnmlen); 931 if (error) 932 break; 933 smb_rq_bend(rqp); 934 error = smb_rq_simple(rqp); 935 } while(0); 936 smb_rq_done(rqp); 937 return error; 938} 939 940int 941smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int len, 942 struct smb_cred *scred) 943{ 944 struct smb_rq rq, *rqp = &rq; 945 struct smb_share *ssp = dnp->n_mount->sm_share; 946 struct mbchain *mbp; 947 int error; 948 949 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE_DIRECTORY, scred); 950 if (error) 951 return error; 952 smb_rq_getrequest(rqp, &mbp); 953 smb_rq_wstart(rqp); 954 smb_rq_wend(rqp); 955 smb_rq_bstart(rqp); 956 mb_put_uint8(mbp, SMB_DT_ASCII); 957 error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, len); 958 if (!error) { 959 smb_rq_bend(rqp); 960 error = smb_rq_simple(rqp); 961 } 962 smb_rq_done(rqp); 963 return error; 964} 965 966int 967smbfs_smb_rmdir(struct smbnode *np, struct smb_cred *scred) 968{ 969 struct smb_rq rq, *rqp = &rq; 970 struct smb_share *ssp = np->n_mount->sm_share; 971 struct mbchain *mbp; 972 int error; 973 974 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE_DIRECTORY, scred); 975 if (error) 976 return error; 977 smb_rq_getrequest(rqp, &mbp); 978 smb_rq_wstart(rqp); 979 smb_rq_wend(rqp); 980 smb_rq_bstart(rqp); 981 mb_put_uint8(mbp, SMB_DT_ASCII); 982 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0); 983 if (!error) { 984 smb_rq_bend(rqp); 985 error = smb_rq_simple(rqp); 986 } 987 smb_rq_done(rqp); 988 return error; 989} 990 991static int 992smbfs_smb_search(struct smbfs_fctx *ctx) 993{ 994 struct smb_vc *vcp = SSTOVC(ctx->f_ssp); 995 struct smb_rq *rqp; 996 struct mbchain *mbp; 997 struct mdchain *mdp; 998 u_int8_t wc, bt; 999 u_int16_t ec, dlen, bc; 1000 int maxent, error, iseof = 0; 1001 1002 maxent = min(ctx->f_left, (vcp->vc_txmax - SMB_HDRLEN - 3) / SMB_DENTRYLEN); 1003 if (ctx->f_rq) { 1004 smb_rq_done(ctx->f_rq); 1005 ctx->f_rq = NULL; 1006 } 1007 error = smb_rq_alloc(SSTOCP(ctx->f_ssp), SMB_COM_SEARCH, ctx->f_scred, &rqp); 1008 if (error) 1009 return error; 1010 ctx->f_rq = rqp; 1011 smb_rq_getrequest(rqp, &mbp); 1012 smb_rq_wstart(rqp); 1013 mb_put_uint16le(mbp, maxent); /* max entries to return */ 1014 mb_put_uint16le(mbp, ctx->f_attrmask); 1015 smb_rq_wend(rqp); 1016 smb_rq_bstart(rqp); 1017 mb_put_uint8(mbp, SMB_DT_ASCII); /* buffer format */ 1018 if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 1019 error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard, ctx->f_wclen); 1020 if (error) 1021 return error; 1022 mb_put_uint8(mbp, SMB_DT_VARIABLE); 1023 mb_put_uint16le(mbp, 0); /* context length */ 1024 ctx->f_flags &= ~SMBFS_RDD_FINDFIRST; 1025 } else { 1026 mb_put_uint8(mbp, 0); /* file name length */ 1027 mb_put_uint8(mbp, SMB_DT_VARIABLE); 1028 mb_put_uint16le(mbp, SMB_SKEYLEN); 1029 mb_put_mem(mbp, ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM); 1030 } 1031 smb_rq_bend(rqp); 1032 error = smb_rq_simple(rqp); 1033 if (error) { 1034 if (rqp->sr_errclass == ERRDOS && rqp->sr_serror == ERRnofiles) { 1035 error = 0; 1036 iseof = 1; 1037 ctx->f_flags |= SMBFS_RDD_EOF; 1038 } else 1039 return error; 1040 } 1041 smb_rq_getreply(rqp, &mdp); 1042 md_get_uint8(mdp, &wc); 1043 if (wc != 1) 1044 return iseof ? ENOENT : EBADRPC; 1045 md_get_uint16le(mdp, &ec); 1046 if (ec == 0) 1047 return ENOENT; 1048 ctx->f_ecnt = ec; 1049 md_get_uint16le(mdp, &bc); 1050 if (bc < 3) 1051 return EBADRPC; 1052 bc -= 3; 1053 md_get_uint8(mdp, &bt); 1054 if (bt != SMB_DT_VARIABLE) 1055 return EBADRPC; 1056 md_get_uint16le(mdp, &dlen); 1057 if (dlen != bc || dlen % SMB_DENTRYLEN != 0) 1058 return EBADRPC; 1059 return 0; 1060} 1061 1062static int 1063smbfs_findopenLM1(struct smbfs_fctx *ctx, struct smbnode *dnp, 1064 const char *wildcard, int wclen, int attr, struct smb_cred *scred) 1065{ 1066 ctx->f_attrmask = attr; 1067 if (wildcard) { 1068 if (wclen == 1 && wildcard[0] == '*') { 1069 ctx->f_wildcard = "*.*"; 1070 ctx->f_wclen = 3; 1071 } else { 1072 ctx->f_wildcard = wildcard; 1073 ctx->f_wclen = wclen; 1074 } 1075 } else { 1076 ctx->f_wildcard = NULL; 1077 ctx->f_wclen = 0; 1078 } 1079 ctx->f_name = ctx->f_fname; 1080 return 0; 1081} 1082 1083static int 1084smbfs_findnextLM1(struct smbfs_fctx *ctx, int limit) 1085{ 1086 struct mdchain *mbp; 1087 struct smb_rq *rqp; 1088 char *cp; 1089 u_int8_t battr; 1090 u_int16_t date, time; 1091 u_int32_t size; 1092 int error; 1093 1094 if (ctx->f_ecnt == 0) { 1095 if (ctx->f_flags & SMBFS_RDD_EOF) 1096 return ENOENT; 1097 ctx->f_left = ctx->f_limit = limit; 1098 error = smbfs_smb_search(ctx); 1099 if (error) 1100 return error; 1101 } 1102 rqp = ctx->f_rq; 1103 smb_rq_getreply(rqp, &mbp); 1104 md_get_mem(mbp, ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM); 1105 md_get_uint8(mbp, &battr); 1106 md_get_uint16le(mbp, &time); 1107 md_get_uint16le(mbp, &date); 1108 md_get_uint32le(mbp, &size); 1109 cp = ctx->f_name; 1110 md_get_mem(mbp, cp, sizeof(ctx->f_fname), MB_MSYSTEM); 1111 cp[sizeof(ctx->f_fname) - 1] = 0; 1112 cp += strlen(cp) - 1; 1113 while (*cp == ' ' && cp >= ctx->f_name) 1114 *cp-- = 0; 1115 ctx->f_attr.fa_attr = battr; 1116 smb_dos2unixtime(date, time, 0, rqp->sr_vc->vc_sopt.sv_tz, 1117 &ctx->f_attr.fa_mtime); 1118 ctx->f_attr.fa_size = size; 1119 ctx->f_nmlen = strlen(ctx->f_name); 1120 ctx->f_ecnt--; 1121 ctx->f_left--; 1122 return 0; 1123} 1124 1125static int 1126smbfs_findcloseLM1(struct smbfs_fctx *ctx) 1127{ 1128 if (ctx->f_rq) 1129 smb_rq_done(ctx->f_rq); 1130 return 0; 1131} 1132 1133/* 1134 * TRANS2_FIND_FIRST2/NEXT2, used for NT LM12 dialect 1135 */ 1136static int 1137smbfs_smb_trans2find2(struct smbfs_fctx *ctx) 1138{ 1139 struct smb_t2rq *t2p; 1140 struct smb_vc *vcp = SSTOVC(ctx->f_ssp); 1141 struct mbchain *mbp; 1142 struct mdchain *mdp; 1143 u_int16_t tw, flags; 1144 int error; 1145 1146 if (ctx->f_t2) { 1147 smb_t2_done(ctx->f_t2); 1148 ctx->f_t2 = NULL; 1149 } 1150 ctx->f_flags &= ~SMBFS_RDD_GOTRNAME; 1151 flags = 8 | 2; /* <resume> | <close if EOS> */ 1152 if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) { 1153 flags |= 1; /* close search after this request */ 1154 ctx->f_flags |= SMBFS_RDD_NOCLOSE; 1155 } 1156 if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 1157 error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_FIRST2, 1158 ctx->f_scred, &t2p); 1159 if (error) 1160 return error; 1161 ctx->f_t2 = t2p; 1162 mbp = &t2p->t2_tparam; 1163 mb_init(mbp); 1164 mb_put_uint16le(mbp, ctx->f_attrmask); 1165 mb_put_uint16le(mbp, ctx->f_limit); 1166 mb_put_uint16le(mbp, flags); 1167 mb_put_uint16le(mbp, ctx->f_infolevel); 1168 mb_put_uint32le(mbp, 0); 1169 error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard, ctx->f_wclen); 1170 if (error) 1171 return error; 1172 } else { 1173 error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_NEXT2, 1174 ctx->f_scred, &t2p); 1175 if (error) 1176 return error; 1177 ctx->f_t2 = t2p; 1178 mbp = &t2p->t2_tparam; 1179 mb_init(mbp); 1180 mb_put_mem(mbp, (caddr_t)&ctx->f_Sid, 2, MB_MSYSTEM); 1181 mb_put_uint16le(mbp, ctx->f_limit); 1182 mb_put_uint16le(mbp, ctx->f_infolevel); 1183 mb_put_uint32le(mbp, 0); /* resume key */ 1184 mb_put_uint16le(mbp, flags); 1185 if (ctx->f_rname) 1186 mb_put_mem(mbp, ctx->f_rname, strlen(ctx->f_rname) + 1, MB_MSYSTEM); 1187 else 1188 mb_put_uint8(mbp, 0); /* resume file name */ 1189#if 0 1190 struct timeval tv; 1191 tv.tv_sec = 0; 1192 tv.tv_usec = 200 * 1000; /* 200ms */ 1193 if (vcp->vc_flags & SMBC_WIN95) { 1194 /* 1195 * some implementations suggests to sleep here 1196 * for 200ms, due to the bug in the Win95. 1197 * I've didn't notice any problem, but put code 1198 * for it. 1199 */ 1200 tsleep(&flags, PVFS, "fix95", tvtohz(&tv)); 1201 } 1202#endif 1203 } 1204 t2p->t2_maxpcount = 5 * 2; 1205 t2p->t2_maxdcount = vcp->vc_txmax; 1206 error = smb_t2_request(t2p); 1207 if (error) 1208 return error; 1209 mdp = &t2p->t2_rparam; 1210 if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 1211 if ((error = md_get_uint16(mdp, &ctx->f_Sid)) != 0) 1212 return error; 1213 ctx->f_flags &= ~SMBFS_RDD_FINDFIRST; 1214 } 1215 if ((error = md_get_uint16le(mdp, &tw)) != 0) 1216 return error; 1217 ctx->f_ecnt = tw; 1218 if ((error = md_get_uint16le(mdp, &tw)) != 0) 1219 return error; 1220 if (tw) 1221 ctx->f_flags |= SMBFS_RDD_EOF | SMBFS_RDD_NOCLOSE; 1222 if ((error = md_get_uint16le(mdp, &tw)) != 0) 1223 return error; 1224 if ((error = md_get_uint16le(mdp, &tw)) != 0) 1225 return error; 1226 if (ctx->f_ecnt == 0) 1227 return ENOENT; 1228 ctx->f_rnameofs = tw; 1229 mdp = &t2p->t2_rdata; 1230 if (mdp->md_top == NULL) { 1231 printf("bug: ecnt = %d, but data is NULL (please report)\n", ctx->f_ecnt); 1232 return ENOENT; 1233 } 1234 if (mdp->md_top->m_len == 0) { 1235 printf("bug: ecnt = %d, but m_len = 0 and m_next = %p (please report)\n", ctx->f_ecnt,mbp->mb_top->m_next); 1236 return ENOENT; 1237 } 1238 ctx->f_eofs = 0; 1239 return 0; 1240} 1241 1242static int 1243smbfs_smb_findclose2(struct smbfs_fctx *ctx) 1244{ 1245 struct smb_rq rq, *rqp = &rq; 1246 struct mbchain *mbp; 1247 int error; 1248 1249 error = smb_rq_init(rqp, SSTOCP(ctx->f_ssp), SMB_COM_FIND_CLOSE2, ctx->f_scred); 1250 if (error) 1251 return error; 1252 smb_rq_getrequest(rqp, &mbp); 1253 smb_rq_wstart(rqp); 1254 mb_put_mem(mbp, (caddr_t)&ctx->f_Sid, 2, MB_MSYSTEM); 1255 smb_rq_wend(rqp); 1256 smb_rq_bstart(rqp); 1257 smb_rq_bend(rqp); 1258 error = smb_rq_simple(rqp); 1259 smb_rq_done(rqp); 1260 return error; 1261} 1262 1263static int 1264smbfs_findopenLM2(struct smbfs_fctx *ctx, struct smbnode *dnp, 1265 const char *wildcard, int wclen, int attr, struct smb_cred *scred) 1266{
|