PageRenderTime 59ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c

https://bitbucket.org/osunix/osunix-gate
C | 2831 lines | 2119 code | 255 blank | 457 comment | 371 complexity | 3b8c9685fb05652d92bc904bc48edff4 MD5 | raw file
Possible License(s): BSD-3-Clause-No-Nuclear-License-2014, MPL-2.0-no-copyleft-exception, BSD-3-Clause, BSD-2-Clause, LGPL-3.0, 0BSD, GPL-2.0, LGPL-2.0, AGPL-1.0, AGPL-3.0, GPL-3.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (c) 2000-2001 Boris Popov
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. All advertising materials mentioning features or use of this software
  14. * must display the following acknowledgement:
  15. * This product includes software developed by Boris Popov.
  16. * 4. Neither the name of the author nor the names of any co-contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * $Id: smbfs_smb.c,v 1.73.38.1 2005/05/27 02:35:28 lindak Exp $
  33. */
  34. /*
  35. * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
  36. * Use is subject to license terms.
  37. */
  38. #include <sys/param.h>
  39. #include <sys/systm.h>
  40. #include <sys/time.h>
  41. #include <sys/vnode.h>
  42. #include <sys/sunddi.h>
  43. #include <sys/cmn_err.h>
  44. #include <netsmb/smb_osdep.h>
  45. #include <netsmb/smb.h>
  46. #include <netsmb/smb_conn.h>
  47. #include <netsmb/smb_subr.h>
  48. #include <netsmb/smb_rq.h>
  49. #include <smbfs/smbfs.h>
  50. #include <smbfs/smbfs_node.h>
  51. #include <smbfs/smbfs_subr.h>
  52. /*
  53. * Jan 1 1980 as 64 bit NT time.
  54. * (tenths of microseconds since 1601)
  55. */
  56. const uint64_t NT1980 = 11960035200ULL*10000000ULL;
  57. /*
  58. * Local functions.
  59. * Not static, to aid debugging.
  60. */
  61. int smbfs_smb_query_info(struct smbnode *np, const char *name, int nmlen,
  62. struct smbfattr *fap, struct smb_cred *scrp);
  63. int smbfs_smb_trans2_query(struct smbnode *np, struct smbfattr *fap,
  64. struct smb_cred *scrp, uint16_t infolevel);
  65. int smbfs_smb_statfsLM1(struct smb_share *ssp,
  66. statvfs64_t *sbp, struct smb_cred *scrp);
  67. int smbfs_smb_statfsLM2(struct smb_share *ssp,
  68. statvfs64_t *sbp, struct smb_cred *scrp);
  69. int smbfs_smb_setfattrNT(struct smbnode *np, int fid,
  70. uint32_t attr, struct timespec *mtime, struct timespec *atime,
  71. struct smb_cred *scrp);
  72. int smbfs_smb_setftime1(struct smbnode *np, uint16_t fid,
  73. struct timespec *mtime, struct timespec *atime,
  74. struct smb_cred *scrp);
  75. int smbfs_smb_setpattr1(struct smbnode *np,
  76. const char *name, int len, uint32_t attr,
  77. struct timespec *mtime, struct smb_cred *scrp);
  78. /*
  79. * Todo: locking over-the-wire
  80. */
  81. #ifdef APPLE
  82. static int
  83. smbfs_smb_lockandx(struct smbnode *np, int op, uint32_t pid,
  84. offset_t start, uint64_t len, int largelock,
  85. struct smb_cred *scrp, uint32_t timeout)
  86. {
  87. struct smb_share *ssp = np->n_mount->smi_share;
  88. struct smb_rq rq, *rqp = &rq;
  89. struct mbchain *mbp;
  90. uint8_t ltype = 0;
  91. int error;
  92. /* Shared lock for n_fid use below. */
  93. ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
  94. /* After reconnect, n_fid is invalid */
  95. if (np->n_vcgenid != ssp->ss_vcgenid)
  96. return (ESTALE);
  97. if (op == SMB_LOCK_SHARED)
  98. ltype |= SMB_LOCKING_ANDX_SHARED_LOCK;
  99. /* XXX: if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)? */
  100. if (largelock)
  101. ltype |= SMB_LOCKING_ANDX_LARGE_FILES;
  102. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scrp);
  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_uint16le(mbp, np->n_fid);
  111. mb_put_uint8(mbp, ltype); /* locktype */
  112. mb_put_uint8(mbp, 0); /* oplocklevel - 0 seems is NO_OPLOCK */
  113. mb_put_uint32le(mbp, timeout); /* 0 nowait, -1 infinite wait */
  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. if (!largelock) {
  120. mb_put_uint32le(mbp, start);
  121. mb_put_uint32le(mbp, len);
  122. } else {
  123. mb_put_uint16le(mbp, 0); /* pad */
  124. mb_put_uint32le(mbp, start >> 32); /* OffsetHigh */
  125. mb_put_uint32le(mbp, start & 0xffffffff); /* OffsetLow */
  126. mb_put_uint32le(mbp, len >> 32); /* LengthHigh */
  127. mb_put_uint32le(mbp, len & 0xffffffff); /* LengthLow */
  128. }
  129. smb_rq_bend(rqp);
  130. /*
  131. * Don't want to risk missing a successful
  132. * unlock send or lock response, or we could
  133. * lose track of an outstanding lock.
  134. */
  135. if (op == SMB_LOCK_RELEASE)
  136. rqp->sr_flags |= SMBR_NOINTR_SEND;
  137. else
  138. rqp->sr_flags |= SMBR_NOINTR_RECV;
  139. error = smb_rq_simple(rqp);
  140. smb_rq_done(rqp);
  141. return (error);
  142. }
  143. int
  144. smbfs_smb_lock(struct smbnode *np, int op, caddr_t id,
  145. offset_t start, uint64_t len, int largelock,
  146. struct smb_cred *scrp, uint32_t timeout)
  147. {
  148. struct smb_share *ssp = np->n_mount->smi_share;
  149. if (SMB_DIALECT(SSTOVC(ssp)) < SMB_DIALECT_LANMAN1_0)
  150. /*
  151. * TODO: use LOCK_BYTE_RANGE here.
  152. */
  153. return (EINVAL);
  154. /*
  155. * XXX: compute largelock via:
  156. * (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)?
  157. */
  158. return (smbfs_smb_lockandx(np, op, (uint32_t)id, start, len,
  159. largelock, scrp, timeout));
  160. }
  161. #endif /* APPLE */
  162. /*
  163. * Helper for smbfs_getattr
  164. * Something like nfs_getattr_otw
  165. */
  166. int
  167. smbfs_smb_getfattr(
  168. struct smbnode *np,
  169. struct smbfattr *fap,
  170. struct smb_cred *scrp)
  171. {
  172. int error;
  173. /*
  174. * This lock is necessary for FID-based calls.
  175. * Lock may be writer (via open) or reader.
  176. */
  177. ASSERT(np->r_lkserlock.count != 0);
  178. /*
  179. * Extended attribute directory or file.
  180. */
  181. if (np->n_flag & N_XATTR) {
  182. error = smbfs_xa_getfattr(np, fap, scrp);
  183. return (error);
  184. }
  185. error = smbfs_smb_trans2_query(np, fap, scrp, 0);
  186. if (error != EINVAL)
  187. return (error);
  188. /* fallback */
  189. error = smbfs_smb_query_info(np, NULL, 0, fap, scrp);
  190. return (error);
  191. }
  192. /*
  193. * Common function for QueryFileInfo, QueryPathInfo.
  194. */
  195. int
  196. smbfs_smb_trans2_query(struct smbnode *np, struct smbfattr *fap,
  197. struct smb_cred *scrp, uint16_t infolevel)
  198. {
  199. struct smb_share *ssp = np->n_mount->smi_share;
  200. struct smb_vc *vcp = SSTOVC(ssp);
  201. struct smb_t2rq *t2p;
  202. int error, svtz, timesok = 1;
  203. struct mbchain *mbp;
  204. struct mdchain *mdp;
  205. uint16_t cmd, date, time, wattr;
  206. uint64_t llongint, lsize;
  207. uint32_t size, dattr;
  208. /*
  209. * Shared lock for n_fid use below.
  210. * See smbfs_smb_getfattr()
  211. */
  212. ASSERT(np->r_lkserlock.count != 0);
  213. /*
  214. * If we have a valid open FID, use it.
  215. */
  216. if ((np->n_fidrefs > 0) &&
  217. (np->n_fid != SMB_FID_UNUSED) &&
  218. (np->n_vcgenid == ssp->ss_vcgenid))
  219. cmd = SMB_TRANS2_QUERY_FILE_INFORMATION;
  220. else
  221. cmd = SMB_TRANS2_QUERY_PATH_INFORMATION;
  222. top:
  223. error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p);
  224. if (error)
  225. return (error);
  226. mbp = &t2p->t2_tparam;
  227. mb_init(mbp);
  228. if (!infolevel) {
  229. if (SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12)
  230. infolevel = SMB_QFILEINFO_STANDARD;
  231. else
  232. infolevel = SMB_QFILEINFO_ALL_INFO;
  233. }
  234. if (cmd == SMB_TRANS2_QUERY_FILE_INFORMATION)
  235. mb_put_uint16le(mbp, np->n_fid);
  236. mb_put_uint16le(mbp, infolevel);
  237. if (cmd == SMB_TRANS2_QUERY_PATH_INFORMATION) {
  238. mb_put_uint32le(mbp, 0);
  239. /* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */
  240. error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\');
  241. if (error) {
  242. smb_t2_done(t2p);
  243. return (error);
  244. }
  245. }
  246. t2p->t2_maxpcount = 2;
  247. t2p->t2_maxdcount = vcp->vc_txmax;
  248. error = smb_t2_request(t2p);
  249. if (error) {
  250. smb_t2_done(t2p);
  251. /* Invalid info level? Try fallback. */
  252. if (error == EINVAL &&
  253. infolevel == SMB_QFILEINFO_ALL_INFO) {
  254. infolevel = SMB_QFILEINFO_STANDARD;
  255. goto top;
  256. }
  257. return (error);
  258. }
  259. mdp = &t2p->t2_rdata;
  260. svtz = vcp->vc_sopt.sv_tz;
  261. switch (infolevel) {
  262. case SMB_QFILEINFO_STANDARD:
  263. md_get_uint16le(mdp, &date);
  264. md_get_uint16le(mdp, &time); /* creation time */
  265. smb_dos2unixtime(date, time, 0, svtz, &fap->fa_createtime);
  266. md_get_uint16le(mdp, &date);
  267. md_get_uint16le(mdp, &time); /* access time */
  268. smb_dos2unixtime(date, time, 0, svtz, &fap->fa_atime);
  269. md_get_uint16le(mdp, &date);
  270. md_get_uint16le(mdp, &time); /* modify time */
  271. smb_dos2unixtime(date, time, 0, svtz, &fap->fa_mtime);
  272. md_get_uint32le(mdp, &size); /* EOF position */
  273. fap->fa_size = size;
  274. md_get_uint32le(mdp, &size); /* allocation size */
  275. fap->fa_allocsz = size;
  276. error = md_get_uint16le(mdp, &wattr);
  277. fap->fa_attr = wattr;
  278. timesok = 1;
  279. break;
  280. case SMB_QFILEINFO_ALL_INFO:
  281. timesok = 0;
  282. /* creation time */
  283. md_get_uint64le(mdp, &llongint);
  284. if (llongint)
  285. timesok++;
  286. smb_time_NT2local(llongint, &fap->fa_createtime);
  287. /* last access time */
  288. md_get_uint64le(mdp, &llongint);
  289. if (llongint)
  290. timesok++;
  291. smb_time_NT2local(llongint, &fap->fa_atime);
  292. /* last write time */
  293. md_get_uint64le(mdp, &llongint);
  294. if (llongint)
  295. timesok++;
  296. smb_time_NT2local(llongint, &fap->fa_mtime);
  297. /* last change time */
  298. md_get_uint64le(mdp, &llongint);
  299. if (llongint)
  300. timesok++;
  301. smb_time_NT2local(llongint, &fap->fa_ctime);
  302. /* attributes */
  303. md_get_uint32le(mdp, &dattr);
  304. fap->fa_attr = dattr;
  305. /*
  306. * 4-Byte alignment - discard
  307. * Specs don't talk about this.
  308. */
  309. md_get_uint32le(mdp, NULL);
  310. /* allocation size */
  311. md_get_uint64le(mdp, &lsize);
  312. fap->fa_allocsz = lsize;
  313. /* File size */
  314. error = md_get_uint64le(mdp, &lsize);
  315. fap->fa_size = lsize;
  316. break;
  317. default:
  318. SMBVDEBUG("unexpected info level %d\n", infolevel);
  319. error = EINVAL;
  320. }
  321. smb_t2_done(t2p);
  322. /*
  323. * if all times are zero (observed with FAT on NT4SP6)
  324. * then fall back to older info level
  325. */
  326. if (!timesok) {
  327. if (infolevel == SMB_QFILEINFO_ALL_INFO) {
  328. infolevel = SMB_QFILEINFO_STANDARD;
  329. goto top;
  330. }
  331. error = EINVAL;
  332. }
  333. return (error);
  334. }
  335. /*
  336. * Support functions for _qstreaminfo
  337. * Moved to smbfs_xattr.c
  338. */
  339. int
  340. smbfs_smb_qfsattr(struct smb_share *ssp, struct smb_fs_attr_info *fsa,
  341. struct smb_cred *scrp)
  342. {
  343. struct smb_t2rq *t2p;
  344. struct mbchain *mbp;
  345. struct mdchain *mdp;
  346. int error;
  347. uint32_t nlen;
  348. error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION,
  349. scrp, &t2p);
  350. if (error)
  351. return (error);
  352. mbp = &t2p->t2_tparam;
  353. mb_init(mbp);
  354. mb_put_uint16le(mbp, SMB_QFS_ATTRIBUTE_INFO);
  355. t2p->t2_maxpcount = 4;
  356. t2p->t2_maxdcount = 4 * 3 + 512;
  357. error = smb_t2_request(t2p);
  358. if (error)
  359. goto out;
  360. mdp = &t2p->t2_rdata;
  361. md_get_uint32le(mdp, &fsa->fsa_aflags);
  362. md_get_uint32le(mdp, &fsa->fsa_maxname);
  363. error = md_get_uint32le(mdp, &nlen); /* fs name length */
  364. if (error)
  365. goto out;
  366. /*
  367. * Get the FS type name.
  368. */
  369. bzero(fsa->fsa_tname, FSTYPSZ);
  370. if (SMB_UNICODE_STRINGS(SSTOVC(ssp))) {
  371. uint16_t tmpbuf[FSTYPSZ];
  372. size_t tmplen, outlen;
  373. if (nlen > sizeof (tmpbuf))
  374. nlen = sizeof (tmpbuf);
  375. error = md_get_mem(mdp, tmpbuf, nlen, MB_MSYSTEM);
  376. tmplen = nlen / 2; /* UCS-2 chars */
  377. outlen = FSTYPSZ - 1;
  378. (void) uconv_u16tou8(tmpbuf, &tmplen,
  379. (uchar_t *)fsa->fsa_tname, &outlen,
  380. UCONV_IN_LITTLE_ENDIAN);
  381. } else {
  382. if (nlen > (FSTYPSZ - 1))
  383. nlen = FSTYPSZ - 1;
  384. error = md_get_mem(mdp, fsa->fsa_tname, nlen, MB_MSYSTEM);
  385. }
  386. /*
  387. * If fs_name starts with FAT, we can't set dates before 1980
  388. */
  389. if (0 == strncmp(fsa->fsa_tname, "FAT", 3)) {
  390. SMB_SS_LOCK(ssp);
  391. ssp->ss_flags |= SMBS_FST_FAT;
  392. SMB_SS_UNLOCK(ssp);
  393. }
  394. out:
  395. smb_t2_done(t2p);
  396. return (0);
  397. }
  398. int
  399. smbfs_smb_statfs(struct smb_share *ssp, statvfs64_t *sbp,
  400. struct smb_cred *scp)
  401. {
  402. int error;
  403. if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0)
  404. error = smbfs_smb_statfsLM2(ssp, sbp, scp);
  405. else
  406. error = smbfs_smb_statfsLM1(ssp, sbp, scp);
  407. return (error);
  408. }
  409. int
  410. smbfs_smb_statfsLM2(struct smb_share *ssp, statvfs64_t *sbp,
  411. struct smb_cred *scrp)
  412. {
  413. struct smb_t2rq *t2p;
  414. struct mbchain *mbp;
  415. struct mdchain *mdp;
  416. uint16_t bsize;
  417. uint32_t units, bpu, funits;
  418. uint64_t s, t, f;
  419. int error;
  420. error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION,
  421. scrp, &t2p);
  422. if (error)
  423. return (error);
  424. mbp = &t2p->t2_tparam;
  425. mb_init(mbp);
  426. mb_put_uint16le(mbp, SMB_QFS_ALLOCATION);
  427. t2p->t2_maxpcount = 4;
  428. t2p->t2_maxdcount = 4 * 4 + 2;
  429. error = smb_t2_request(t2p);
  430. if (error)
  431. goto out;
  432. mdp = &t2p->t2_rdata;
  433. md_get_uint32le(mdp, NULL); /* fs id */
  434. md_get_uint32le(mdp, &bpu);
  435. md_get_uint32le(mdp, &units);
  436. md_get_uint32le(mdp, &funits);
  437. error = md_get_uint16le(mdp, &bsize);
  438. if (error)
  439. goto out;
  440. s = bsize;
  441. s *= bpu;
  442. t = units;
  443. f = funits;
  444. /*
  445. * Don't allow over-large blocksizes as they determine
  446. * Finder List-view size granularities. On the other
  447. * hand, we mustn't let the block count overflow the
  448. * 31 bits available.
  449. */
  450. while (s > 16 * 1024) {
  451. if (t > LONG_MAX)
  452. break;
  453. s /= 2;
  454. t *= 2;
  455. f *= 2;
  456. }
  457. while (t > LONG_MAX) {
  458. t /= 2;
  459. f /= 2;
  460. s *= 2;
  461. }
  462. sbp->f_bsize = (ulong_t)s; /* file system block size */
  463. sbp->f_blocks = t; /* total data blocks in file system */
  464. sbp->f_bfree = f; /* free blocks in fs */
  465. sbp->f_bavail = f; /* free blocks avail to non-superuser */
  466. sbp->f_files = (-1); /* total file nodes in file system */
  467. sbp->f_ffree = (-1); /* free file nodes in fs */
  468. out:
  469. smb_t2_done(t2p);
  470. return (0);
  471. }
  472. int
  473. smbfs_smb_statfsLM1(struct smb_share *ssp, statvfs64_t *sbp,
  474. struct smb_cred *scrp)
  475. {
  476. struct smb_rq rq, *rqp = &rq;
  477. struct mdchain *mdp;
  478. uint16_t units, bpu, bsize, funits;
  479. uint64_t s, t, f;
  480. int error;
  481. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION_DISK,
  482. scrp);
  483. if (error)
  484. return (error);
  485. smb_rq_wstart(rqp);
  486. smb_rq_wend(rqp);
  487. smb_rq_bstart(rqp);
  488. smb_rq_bend(rqp);
  489. error = smb_rq_simple(rqp);
  490. if (error)
  491. goto out;
  492. smb_rq_getreply(rqp, &mdp);
  493. md_get_uint16le(mdp, &units);
  494. md_get_uint16le(mdp, &bpu);
  495. md_get_uint16le(mdp, &bsize);
  496. error = md_get_uint16le(mdp, &funits);
  497. if (error)
  498. goto out;
  499. s = bsize;
  500. s *= bpu;
  501. t = units;
  502. f = funits;
  503. /*
  504. * Don't allow over-large blocksizes as they determine
  505. * Finder List-view size granularities. On the other
  506. * hand, we mustn't let the block count overflow the
  507. * 31 bits available.
  508. */
  509. while (s > 16 * 1024) {
  510. if (t > LONG_MAX)
  511. break;
  512. s /= 2;
  513. t *= 2;
  514. f *= 2;
  515. }
  516. while (t > LONG_MAX) {
  517. t /= 2;
  518. f /= 2;
  519. s *= 2;
  520. }
  521. sbp->f_bsize = (ulong_t)s; /* file system block size */
  522. sbp->f_blocks = t; /* total data blocks in file system */
  523. sbp->f_bfree = f; /* free blocks in fs */
  524. sbp->f_bavail = f; /* free blocks avail to non-superuser */
  525. sbp->f_files = (-1); /* total file nodes in file system */
  526. sbp->f_ffree = (-1); /* free file nodes in fs */
  527. out:
  528. smb_rq_done(rqp);
  529. return (0);
  530. }
  531. int
  532. smbfs_smb_seteof(struct smb_share *ssp, uint16_t fid, uint64_t newsize,
  533. struct smb_cred *scrp)
  534. {
  535. struct smb_t2rq *t2p;
  536. struct smb_vc *vcp = SSTOVC(ssp);
  537. struct mbchain *mbp;
  538. int error;
  539. error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION,
  540. scrp, &t2p);
  541. if (error)
  542. return (error);
  543. mbp = &t2p->t2_tparam;
  544. mb_init(mbp);
  545. mb_put_uint16le(mbp, fid);
  546. if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
  547. mb_put_uint16le(mbp, SMB_SFILEINFO_END_OF_FILE_INFORMATION);
  548. else
  549. mb_put_uint16le(mbp, SMB_SFILEINFO_END_OF_FILE_INFO);
  550. mb_put_uint16le(mbp, 0); /* pad */
  551. mbp = &t2p->t2_tdata;
  552. mb_init(mbp);
  553. mb_put_uint64le(mbp, newsize);
  554. t2p->t2_maxpcount = 2;
  555. t2p->t2_maxdcount = 0;
  556. error = smb_t2_request(t2p);
  557. smb_t2_done(t2p);
  558. return (error);
  559. }
  560. /*ARGSUSED*/
  561. int
  562. smbfs_smb_t2rename(struct smbnode *np, struct smbnode *tdnp,
  563. const char *tname, int tnmlen, struct smb_cred *scrp, int overwrite)
  564. {
  565. struct smb_t2rq *t2p;
  566. struct smb_share *ssp = np->n_mount->smi_share;
  567. struct smb_vc *vcp = SSTOVC(ssp);
  568. struct mbchain *mbp;
  569. int32_t *ucslenp;
  570. int error, cerror;
  571. uint16_t fid = 0;
  572. /* Shared lock for n_fid use below. */
  573. ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
  574. /* After reconnect, n_fid is invalid */
  575. if (np->n_vcgenid != ssp->ss_vcgenid)
  576. return (ESTALE);
  577. if (!(vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU))
  578. return (ENOTSUP);
  579. error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION,
  580. scrp, &t2p);
  581. if (error)
  582. return (error);
  583. if (tdnp) {
  584. error = smbfs_smb_tmpopen(tdnp, SA_RIGHT_FILE_READ_DATA, scrp,
  585. &fid);
  586. if (error)
  587. goto exit;
  588. }
  589. mbp = &t2p->t2_tparam;
  590. mb_init(mbp);
  591. mb_put_uint16le(mbp, np->n_fid);
  592. mb_put_uint16le(mbp, SMB_SFILEINFO_RENAME_INFORMATION);
  593. mb_put_uint16le(mbp, 0); /* reserved, nowadays */
  594. mbp = &t2p->t2_tdata;
  595. mb_init(mbp);
  596. mb_put_uint32le(mbp, overwrite);
  597. mb_put_uint16le(mbp, fid); /* base for tname */
  598. mb_put_uint16le(mbp, 0); /* part of a 32bit fid? */
  599. ucslenp = (int32_t *)mb_reserve(mbp, sizeof (int32_t));
  600. mbp->mb_count = 0;
  601. error = smb_put_dstring(mbp, vcp, tname, SMB_CS_NONE);
  602. if (error)
  603. goto exit;
  604. mbp->mb_count--; /* don't count the null */
  605. *ucslenp = htolel(mbp->mb_count);
  606. t2p->t2_maxpcount = 2;
  607. t2p->t2_maxdcount = 0;
  608. error = smb_t2_request(t2p);
  609. exit:
  610. if (fid) {
  611. cerror = smbfs_smb_tmpclose(tdnp, fid, scrp);
  612. if (cerror)
  613. SMBVDEBUG("error %d closing %s\n",
  614. cerror, tdnp->n_rpath);
  615. }
  616. smb_t2_done(t2p);
  617. return (error);
  618. }
  619. int
  620. smbfs_smb_flush(struct smbnode *np, struct smb_cred *scrp)
  621. {
  622. struct smb_share *ssp = np->n_mount->smi_share;
  623. struct smb_rq rq, *rqp = &rq;
  624. struct mbchain *mbp;
  625. int error;
  626. /* Shared lock for n_fid use below. */
  627. ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
  628. if (!(np->n_flag & NFLUSHWIRE))
  629. return (0);
  630. if (np->n_fidrefs == 0)
  631. return (0); /* not open */
  632. /* After reconnect, n_fid is invalid */
  633. if (np->n_vcgenid != ssp->ss_vcgenid)
  634. return (ESTALE);
  635. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_FLUSH, scrp);
  636. if (error)
  637. return (error);
  638. smb_rq_getrequest(rqp, &mbp);
  639. smb_rq_wstart(rqp);
  640. mb_put_uint16le(mbp, np->n_fid);
  641. smb_rq_wend(rqp);
  642. smb_rq_bstart(rqp);
  643. smb_rq_bend(rqp);
  644. error = smb_rq_simple(rqp);
  645. smb_rq_done(rqp);
  646. if (!error) {
  647. mutex_enter(&np->r_statelock);
  648. np->n_flag &= ~NFLUSHWIRE;
  649. mutex_exit(&np->r_statelock);
  650. }
  651. return (error);
  652. }
  653. int
  654. smbfs_smb_setfsize(struct smbnode *np, uint16_t fid, uint64_t newsize,
  655. struct smb_cred *scrp)
  656. {
  657. struct smb_share *ssp = np->n_mount->smi_share;
  658. struct smb_rq rq, *rqp = &rq;
  659. struct mbchain *mbp;
  660. int error;
  661. if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
  662. /*
  663. * This call knows about 64-bit offsets.
  664. */
  665. error = smbfs_smb_seteof(ssp, fid, newsize, scrp);
  666. if (!error) {
  667. mutex_enter(&np->r_statelock);
  668. np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
  669. mutex_exit(&np->r_statelock);
  670. return (0);
  671. }
  672. }
  673. /*
  674. * OK, so fallback to SMB_COM_WRITE, but note:
  675. * it only supports 32-bit file offsets.
  676. */
  677. if (newsize > UINT32_MAX)
  678. return (EFBIG);
  679. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_WRITE, scrp);
  680. if (error)
  681. return (error);
  682. smb_rq_getrequest(rqp, &mbp);
  683. smb_rq_wstart(rqp);
  684. mb_put_uint16le(mbp, fid);
  685. mb_put_uint16le(mbp, 0);
  686. mb_put_uint32le(mbp, newsize);
  687. mb_put_uint16le(mbp, 0);
  688. smb_rq_wend(rqp);
  689. smb_rq_bstart(rqp);
  690. mb_put_uint8(mbp, SMB_DT_DATA);
  691. mb_put_uint16le(mbp, 0);
  692. smb_rq_bend(rqp);
  693. error = smb_rq_simple(rqp);
  694. smb_rq_done(rqp);
  695. mutex_enter(&np->r_statelock);
  696. np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
  697. mutex_exit(&np->r_statelock);
  698. return (error);
  699. }
  700. /*
  701. * Old method for getting file attributes.
  702. */
  703. int
  704. smbfs_smb_query_info(struct smbnode *np, const char *name, int nmlen,
  705. struct smbfattr *fap, struct smb_cred *scrp)
  706. {
  707. struct smb_rq rq, *rqp = &rq;
  708. struct smb_share *ssp = np->n_mount->smi_share;
  709. struct mbchain *mbp;
  710. struct mdchain *mdp;
  711. uint8_t wc;
  712. int error;
  713. uint16_t wattr;
  714. uint32_t longint;
  715. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION, scrp);
  716. if (error)
  717. return (error);
  718. smb_rq_getrequest(rqp, &mbp);
  719. smb_rq_wstart(rqp);
  720. smb_rq_wend(rqp);
  721. smb_rq_bstart(rqp);
  722. mb_put_uint8(mbp, SMB_DT_ASCII);
  723. error = smbfs_fullpath(mbp, SSTOVC(ssp), np,
  724. name, &nmlen, '\\');
  725. if (error)
  726. goto out;
  727. smb_rq_bend(rqp);
  728. error = smb_rq_simple(rqp);
  729. if (error)
  730. goto out;
  731. smb_rq_getreply(rqp, &mdp);
  732. error = md_get_uint8(mdp, &wc);
  733. if (error)
  734. goto out;
  735. if (wc != 10) {
  736. error = EBADRPC;
  737. goto out;
  738. }
  739. md_get_uint16le(mdp, &wattr);
  740. fap->fa_attr = wattr;
  741. /*
  742. * Be careful using the time returned here, as
  743. * with FAT on NT4SP6, at least, the time returned is low
  744. * 32 bits of 100s of nanoseconds (since 1601) so it rolls
  745. * over about every seven minutes!
  746. */
  747. md_get_uint32le(mdp, &longint); /* specs: secs since 1970 */
  748. smb_time_server2local(longint,
  749. SSTOVC(ssp)->vc_sopt.sv_tz, &fap->fa_mtime);
  750. error = md_get_uint32le(mdp, &longint);
  751. fap->fa_size = longint;
  752. out:
  753. smb_rq_done(rqp);
  754. return (error);
  755. }
  756. /*
  757. * Set DOS file attributes. mtime should be NULL for dialects above lm10
  758. */
  759. int
  760. smbfs_smb_setpattr1(struct smbnode *np, const char *name, int len,
  761. uint32_t attr, struct timespec *mtime,
  762. struct smb_cred *scrp)
  763. {
  764. struct smb_rq rq, *rqp = &rq;
  765. struct smb_share *ssp = np->n_mount->smi_share;
  766. struct mbchain *mbp;
  767. long time;
  768. int error, svtz;
  769. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION, scrp);
  770. if (error)
  771. return (error);
  772. svtz = SSTOVC(ssp)->vc_sopt.sv_tz;
  773. smb_rq_getrequest(rqp, &mbp);
  774. smb_rq_wstart(rqp);
  775. mb_put_uint16le(mbp, (uint16_t)attr);
  776. if (mtime) {
  777. smb_time_local2server(mtime, svtz, &time);
  778. } else
  779. time = 0;
  780. mb_put_uint32le(mbp, time); /* mtime */
  781. mb_put_mem(mbp, NULL, 5 * 2, MB_MZERO);
  782. smb_rq_wend(rqp);
  783. smb_rq_bstart(rqp);
  784. mb_put_uint8(mbp, SMB_DT_ASCII);
  785. error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, &len, '\\');
  786. if (error)
  787. goto out;
  788. mb_put_uint8(mbp, SMB_DT_ASCII);
  789. if (SMB_UNICODE_STRINGS(SSTOVC(ssp))) {
  790. mb_put_padbyte(mbp);
  791. mb_put_uint8(mbp, 0); /* 1st byte NULL Unicode char */
  792. }
  793. mb_put_uint8(mbp, 0);
  794. smb_rq_bend(rqp);
  795. error = smb_rq_simple(rqp);
  796. out:
  797. smb_rq_done(rqp);
  798. return (error);
  799. }
  800. int
  801. smbfs_smb_hideit(struct smbnode *np, const char *name, int len,
  802. struct smb_cred *scrp)
  803. {
  804. struct smbfattr fa;
  805. int error;
  806. uint32_t attr;
  807. error = smbfs_smb_query_info(np, name, len, &fa, scrp);
  808. attr = fa.fa_attr;
  809. if (!error && !(attr & SMB_FA_HIDDEN)) {
  810. attr |= SMB_FA_HIDDEN;
  811. error = smbfs_smb_setpattr1(np, name, len, attr, NULL, scrp);
  812. }
  813. return (error);
  814. }
  815. int
  816. smbfs_smb_unhideit(struct smbnode *np, const char *name, int len,
  817. struct smb_cred *scrp)
  818. {
  819. struct smbfattr fa;
  820. uint32_t attr;
  821. int error;
  822. error = smbfs_smb_query_info(np, name, len, &fa, scrp);
  823. attr = fa.fa_attr;
  824. if (!error && (attr & SMB_FA_HIDDEN)) {
  825. attr &= ~SMB_FA_HIDDEN;
  826. error = smbfs_smb_setpattr1(np, name, len, attr, NULL, scrp);
  827. }
  828. return (error);
  829. }
  830. /*
  831. * Set file attributes (optionally: DOS attr, atime, mtime)
  832. * either by open FID or by path name (FID == -1).
  833. */
  834. int
  835. smbfs_smb_setfattr(
  836. struct smbnode *np,
  837. int fid,
  838. uint32_t attr,
  839. struct timespec *mtime,
  840. struct timespec *atime,
  841. struct smb_cred *scrp)
  842. {
  843. struct smb_share *ssp = np->n_mount->smi_share;
  844. struct smb_vc *vcp = SSTOVC(ssp);
  845. int error;
  846. /*
  847. * Normally can use the trans2 call.
  848. */
  849. if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
  850. error = smbfs_smb_setfattrNT(np, fid,
  851. attr, mtime, atime, scrp);
  852. return (error);
  853. }
  854. /*
  855. * Fall-back for older protocols.
  856. */
  857. if (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN1_0) {
  858. error = smbfs_smb_setftime1(np, fid,
  859. mtime, atime, scrp);
  860. return (error);
  861. }
  862. error = smbfs_smb_setpattr1(np, NULL, 0,
  863. attr, mtime, scrp);
  864. return (error);
  865. }
  866. /*
  867. * Set file atime and mtime. Isn't supported by core dialect.
  868. */
  869. int
  870. smbfs_smb_setftime1(
  871. struct smbnode *np,
  872. uint16_t fid,
  873. struct timespec *mtime,
  874. struct timespec *atime,
  875. struct smb_cred *scrp)
  876. {
  877. struct smb_rq rq, *rqp = &rq;
  878. struct smb_share *ssp = np->n_mount->smi_share;
  879. struct mbchain *mbp;
  880. uint16_t date, time;
  881. int error, tzoff;
  882. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION2, scrp);
  883. if (error)
  884. return (error);
  885. tzoff = SSTOVC(ssp)->vc_sopt.sv_tz;
  886. smb_rq_getrequest(rqp, &mbp);
  887. smb_rq_wstart(rqp);
  888. mb_put_uint16le(mbp, fid);
  889. mb_put_uint32le(mbp, 0); /* creation time */
  890. if (atime)
  891. smb_time_unix2dos(atime, tzoff, &date, &time, NULL);
  892. else
  893. time = date = 0;
  894. mb_put_uint16le(mbp, date);
  895. mb_put_uint16le(mbp, time);
  896. if (mtime)
  897. smb_time_unix2dos(mtime, tzoff, &date, &time, NULL);
  898. else
  899. time = date = 0;
  900. mb_put_uint16le(mbp, date);
  901. mb_put_uint16le(mbp, time);
  902. smb_rq_wend(rqp);
  903. smb_rq_bstart(rqp);
  904. smb_rq_bend(rqp);
  905. error = smb_rq_simple(rqp);
  906. SMBVDEBUG("%d\n", error);
  907. smb_rq_done(rqp);
  908. return (error);
  909. }
  910. /*
  911. * Set DOS file attributes, either via open FID or by path name.
  912. * Looks like this call can be used only if CAP_NT_SMBS bit is on.
  913. *
  914. * When setting via path (fid == -1):
  915. * *BASIC_INFO works with Samba, but Win2K servers say it is an
  916. * invalid information level on a SET_PATH_INFO. Note Win2K does
  917. * support *BASIC_INFO on a SET_FILE_INFO, and they support the
  918. * equivalent *BASIC_INFORMATION on SET_PATH_INFO. Go figure.
  919. */
  920. int
  921. smbfs_smb_setfattrNT(
  922. struct smbnode *np,
  923. int fid, /* if fid == -1, set by path */
  924. uint32_t attr,
  925. struct timespec *mtime,
  926. struct timespec *atime,
  927. struct smb_cred *scrp)
  928. {
  929. struct smb_t2rq *t2p;
  930. struct smb_share *ssp = np->n_mount->smi_share;
  931. struct smb_vc *vcp = SSTOVC(ssp);
  932. struct mbchain *mbp;
  933. uint64_t tm;
  934. int error;
  935. uint16_t cmd, level;
  936. if (fid == -1) {
  937. cmd = SMB_TRANS2_SET_PATH_INFORMATION;
  938. } else {
  939. if (fid > UINT16_MAX)
  940. return (EINVAL);
  941. cmd = SMB_TRANS2_SET_FILE_INFORMATION;
  942. }
  943. if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
  944. level = SMB_SFILEINFO_BASIC_INFORMATION;
  945. else
  946. level = SMB_SFILEINFO_BASIC_INFO;
  947. error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p);
  948. if (error)
  949. return (error);
  950. mbp = &t2p->t2_tparam;
  951. mb_init(mbp);
  952. if (cmd == SMB_TRANS2_SET_FILE_INFORMATION)
  953. mb_put_uint16le(mbp, fid);
  954. mb_put_uint16le(mbp, level);
  955. mb_put_uint32le(mbp, 0); /* MBZ */
  956. if (cmd == SMB_TRANS2_SET_PATH_INFORMATION) {
  957. error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\');
  958. if (error != 0)
  959. goto out;
  960. }
  961. /* FAT file systems don't support dates earlier than 1980. */
  962. mbp = &t2p->t2_tdata;
  963. mb_init(mbp);
  964. mb_put_uint64le(mbp, 0); /* creation time */
  965. if (atime) {
  966. smb_time_local2NT(atime, &tm);
  967. if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) &&
  968. tm < NT1980)
  969. tm = NT1980;
  970. } else
  971. tm = 0;
  972. mb_put_uint64le(mbp, tm); /* access time */
  973. if (mtime) {
  974. smb_time_local2NT(mtime, &tm);
  975. if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) &&
  976. tm < NT1980)
  977. tm = NT1980;
  978. } else
  979. tm = 0;
  980. mb_put_uint64le(mbp, tm); /* last write time */
  981. mb_put_uint64le(mbp, 0); /* ctime (no change) */
  982. mb_put_uint32le(mbp, attr);
  983. mb_put_uint32le(mbp, 0); /* padding */
  984. t2p->t2_maxpcount = 2;
  985. t2p->t2_maxdcount = 0;
  986. error = smb_t2_request(t2p);
  987. out:
  988. smb_t2_done(t2p);
  989. return (error);
  990. }
  991. /*
  992. * Modern create/open of file or directory.
  993. *
  994. * If disp is ..._DISP_OPEN, or ...DISP_OPEN_IF, or...
  995. * then this is an open attempt, and:
  996. * If xattr then name is the stream to be opened at np,
  997. * Else np should be opened.
  998. * ...we won't touch *fidp,
  999. * ...we will set or clear *attrcacheupdated.
  1000. * Else this is a creation attempt, and:
  1001. * If xattr then name is the stream to create at np,
  1002. * Else name is the thing to create under directory np.
  1003. * ...we will return *fidp,
  1004. * ...we won't touch *attrcacheupdated.
  1005. *
  1006. * Note, We use: disp = ...OPEN_IF, ...OVERWRITE_IF, etc.
  1007. * now too, which may or may not create a new object.
  1008. */
  1009. int
  1010. smbfs_smb_ntcreatex(
  1011. struct smbnode *np,
  1012. const char *name,
  1013. int nmlen,
  1014. int xattr, /* is named stream? */
  1015. uint32_t req_acc, /* requested access */
  1016. uint32_t efa, /* ext. file attrs (DOS attr +) */
  1017. uint32_t share_acc,
  1018. uint32_t disp, /* open disposition */
  1019. uint32_t createopt, /* NTCREATEX_OPTIONS_ */
  1020. struct smb_cred *scrp,
  1021. uint16_t *fidp,
  1022. uint32_t *cr_act_p, /* create action */
  1023. struct smbfattr *fap) /* optional */
  1024. {
  1025. struct smb_rq rq, *rqp = &rq;
  1026. struct smb_share *ssp = np->n_mount->smi_share;
  1027. struct smb_vc *vcp = SSTOVC(ssp);
  1028. struct mbchain *mbp;
  1029. struct mdchain *mdp;
  1030. struct smbfattr fa;
  1031. uint8_t wc;
  1032. uint32_t longint, createact;
  1033. uint64_t llongint;
  1034. int error;
  1035. uint16_t fid, *namelenp;
  1036. bzero(&fa, sizeof (fa));
  1037. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_NT_CREATE_ANDX, scrp);
  1038. if (error)
  1039. return (error);
  1040. smb_rq_getrequest(rqp, &mbp);
  1041. smb_rq_wstart(rqp);
  1042. mb_put_uint8(mbp, 0xff); /* secondary command */
  1043. mb_put_uint8(mbp, 0); /* MBZ */
  1044. mb_put_uint16le(mbp, 0); /* offset to next command (none) */
  1045. mb_put_uint8(mbp, 0); /* MBZ */
  1046. namelenp = (uint16_t *)mb_reserve(mbp, sizeof (uint16_t));
  1047. /*
  1048. * XP to a W2K Server does not use NTCREATEX_FLAGS_OPEN_DIRECTORY
  1049. * for creating nor for opening a directory. Samba ignores the bit.
  1050. */
  1051. mb_put_uint32le(mbp, 0); /* NTCREATEX_FLAGS_* */
  1052. mb_put_uint32le(mbp, 0); /* FID - basis for path if not root */
  1053. mb_put_uint32le(mbp, req_acc);
  1054. mb_put_uint64le(mbp, 0); /* "initial allocation size" */
  1055. mb_put_uint32le(mbp, efa);
  1056. mb_put_uint32le(mbp, share_acc);
  1057. mb_put_uint32le(mbp, disp);
  1058. mb_put_uint32le(mbp, createopt);
  1059. mb_put_uint32le(mbp, NTCREATEX_IMPERSONATION_IMPERSONATION); /* (?) */
  1060. mb_put_uint8(mbp, 0); /* security flags (?) */
  1061. smb_rq_wend(rqp);
  1062. smb_rq_bstart(rqp);
  1063. if (name == NULL)
  1064. nmlen = 0;
  1065. error = smbfs_fullpath(mbp, vcp, np, name, &nmlen,
  1066. xattr ? ':' : '\\');
  1067. if (error)
  1068. goto done;
  1069. *namelenp = htoles(nmlen); /* includes null */
  1070. smb_rq_bend(rqp);
  1071. /*
  1072. * Don't want to risk missing a successful
  1073. * open response, or we could "leak" FIDs.
  1074. */
  1075. rqp->sr_flags |= SMBR_NOINTR_RECV;
  1076. error = smb_rq_simple_timed(rqp, smb_timo_open);
  1077. if (error)
  1078. goto done;
  1079. smb_rq_getreply(rqp, &mdp);
  1080. /*
  1081. * spec says 26 for word count, but 34 words are defined
  1082. * and observed from win2000
  1083. */
  1084. error = md_get_uint8(mdp, &wc);
  1085. if (error)
  1086. goto done;
  1087. if (wc != 26 && wc != 34 && wc != 42) {
  1088. error = EBADRPC;
  1089. goto done;
  1090. }
  1091. md_get_uint8(mdp, NULL); /* secondary cmd */
  1092. md_get_uint8(mdp, NULL); /* mbz */
  1093. md_get_uint16le(mdp, NULL); /* andxoffset */
  1094. md_get_uint8(mdp, NULL); /* oplock lvl granted */
  1095. md_get_uint16le(mdp, &fid); /* file ID */
  1096. md_get_uint32le(mdp, &createact); /* create_action */
  1097. md_get_uint64le(mdp, &llongint); /* creation time */
  1098. smb_time_NT2local(llongint, &fa.fa_createtime);
  1099. md_get_uint64le(mdp, &llongint); /* access time */
  1100. smb_time_NT2local(llongint, &fa.fa_atime);
  1101. md_get_uint64le(mdp, &llongint); /* write time */
  1102. smb_time_NT2local(llongint, &fa.fa_mtime);
  1103. md_get_uint64le(mdp, &llongint); /* change time */
  1104. smb_time_NT2local(llongint, &fa.fa_ctime);
  1105. md_get_uint32le(mdp, &longint); /* attributes */
  1106. fa.fa_attr = longint;
  1107. md_get_uint64le(mdp, &llongint); /* allocation size */
  1108. fa.fa_allocsz = llongint;
  1109. md_get_uint64le(mdp, &llongint); /* EOF position */
  1110. fa.fa_size = llongint;
  1111. error = md_get_uint16le(mdp, NULL); /* file type */
  1112. /* other stuff we don't care about */
  1113. done:
  1114. smb_rq_done(rqp);
  1115. if (error)
  1116. return (error);
  1117. if (fidp)
  1118. *fidp = fid;
  1119. if (cr_act_p)
  1120. *cr_act_p = createact;
  1121. if (fap)
  1122. *fap = fa; /* struct copy */
  1123. return (0);
  1124. }
  1125. static uint32_t
  1126. smb_mode2rights(int mode)
  1127. {
  1128. mode = mode & SMB_AM_OPENMODE;
  1129. uint32_t rights =
  1130. STD_RIGHT_SYNCHRONIZE_ACCESS |
  1131. STD_RIGHT_READ_CONTROL_ACCESS;
  1132. if ((mode == SMB_AM_OPENREAD) ||
  1133. (mode == SMB_AM_OPENRW)) {
  1134. rights |=
  1135. SA_RIGHT_FILE_READ_ATTRIBUTES |
  1136. SA_RIGHT_FILE_READ_DATA;
  1137. }
  1138. if ((mode == SMB_AM_OPENWRITE) ||
  1139. (mode == SMB_AM_OPENRW)) {
  1140. rights |=
  1141. SA_RIGHT_FILE_WRITE_ATTRIBUTES |
  1142. SA_RIGHT_FILE_APPEND_DATA |
  1143. SA_RIGHT_FILE_WRITE_DATA;
  1144. }
  1145. if (mode == SMB_AM_OPENEXEC) {
  1146. rights |=
  1147. SA_RIGHT_FILE_READ_ATTRIBUTES |
  1148. SA_RIGHT_FILE_EXECUTE;
  1149. }
  1150. return (rights);
  1151. }
  1152. static int
  1153. smb_rights2mode(uint32_t rights)
  1154. {
  1155. int accmode = SMB_AM_OPENEXEC; /* our fallback */
  1156. if (rights & (SA_RIGHT_FILE_APPEND_DATA | SA_RIGHT_FILE_DELETE_CHILD |
  1157. SA_RIGHT_FILE_WRITE_EA | SA_RIGHT_FILE_WRITE_ATTRIBUTES |
  1158. SA_RIGHT_FILE_WRITE_DATA | STD_RIGHT_WRITE_OWNER_ACCESS |
  1159. STD_RIGHT_DELETE_ACCESS | STD_RIGHT_WRITE_DAC_ACCESS))
  1160. accmode = SMB_AM_OPENWRITE;
  1161. if (rights & (SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_READ_ATTRIBUTES |
  1162. SA_RIGHT_FILE_READ_EA | STD_RIGHT_READ_CONTROL_ACCESS))
  1163. accmode = (accmode == SMB_AM_OPENEXEC) ? SMB_AM_OPENREAD
  1164. : SMB_AM_OPENRW;
  1165. return (accmode);
  1166. }
  1167. static int
  1168. smbfs_smb_oldopen(
  1169. struct smbnode *np,
  1170. const char *name,
  1171. int nmlen,
  1172. int xattr,
  1173. int accmode,
  1174. struct smb_cred *scrp,
  1175. uint16_t *fidp,
  1176. uint16_t *granted_mode_p,
  1177. smbfattr_t *fap)
  1178. {
  1179. struct smb_rq rq, *rqp = &rq;
  1180. struct smb_share *ssp = np->n_mount->smi_share;
  1181. struct smb_vc *vcp = SSTOVC(ssp);
  1182. struct mbchain *mbp;
  1183. struct mdchain *mdp;
  1184. struct smbfattr fa;
  1185. uint8_t wc;
  1186. uint16_t wattr;
  1187. uint32_t longint;
  1188. int error;
  1189. bzero(&fa, sizeof (fa));
  1190. /*
  1191. * XXX: move to callers...
  1192. *
  1193. * Use DENYNONE to give unixy semantics of permitting
  1194. * everything not forbidden by permissions. Ie denial
  1195. * is up to server with clients/openers needing to use
  1196. * advisory locks for further control.
  1197. */
  1198. accmode |= SMB_SM_DENYNONE;
  1199. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN, scrp);
  1200. if (error)
  1201. return (error);
  1202. smb_rq_getrequest(rqp, &mbp);
  1203. smb_rq_wstart(rqp);
  1204. mb_put_uint16le(mbp, accmode);
  1205. mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_RDONLY |
  1206. SMB_FA_DIR);
  1207. smb_rq_wend(rqp);
  1208. smb_rq_bstart(rqp);
  1209. mb_put_uint8(mbp, SMB_DT_ASCII);
  1210. error = smbfs_fullpath(mbp, vcp, np, name, &nmlen,
  1211. xattr ? ':' : '\\');
  1212. if (error)
  1213. goto done;
  1214. smb_rq_bend(rqp);
  1215. /*
  1216. * Don't want to risk missing a successful
  1217. * open response, or we could "leak" FIDs.
  1218. */
  1219. rqp->sr_flags |= SMBR_NOINTR_RECV;
  1220. error = smb_rq_simple_timed(rqp, smb_timo_open);
  1221. if (error)
  1222. goto done;
  1223. smb_rq_getreply(rqp, &mdp);
  1224. /*
  1225. * 8/2002 a DAVE server returned wc of 15 so we ignore that.
  1226. * (the actual packet length and data was correct)
  1227. */
  1228. error = md_get_uint8(mdp, &wc);
  1229. if (error)
  1230. goto done;
  1231. if (wc != 7 && wc != 15) {
  1232. error = EBADRPC;
  1233. goto done;
  1234. }
  1235. md_get_uint16le(mdp, fidp);
  1236. md_get_uint16le(mdp, &wattr);
  1237. fa.fa_attr = wattr;
  1238. /*
  1239. * Be careful using the time returned here, as
  1240. * with FAT on NT4SP6, at least, the time returned is low
  1241. * 32 bits of 100s of nanoseconds (since 1601) so it rolls
  1242. * over about every seven minutes!
  1243. */
  1244. md_get_uint32le(mdp, &longint); /* specs: secs since 1970 */
  1245. smb_time_server2local(longint, vcp->vc_sopt.sv_tz, &fa.fa_mtime);
  1246. md_get_uint32le(mdp, &longint);
  1247. fa.fa_size = longint;
  1248. error = md_get_uint16le(mdp, granted_mode_p);
  1249. done:
  1250. smb_rq_done(rqp);
  1251. if (error)
  1252. return (error);
  1253. if (fap)
  1254. *fap = fa; /* struct copy */
  1255. return (0);
  1256. }
  1257. int
  1258. smbfs_smb_tmpopen(struct smbnode *np, uint32_t rights, struct smb_cred *scrp,
  1259. uint16_t *fidp)
  1260. {
  1261. struct smb_share *ssp = np->n_mount->smi_share;
  1262. struct smb_vc *vcp = SSTOVC(ssp);
  1263. int accmode, error;
  1264. /* Shared lock for n_fid use below. */
  1265. ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
  1266. /* Can we re-use n_fid? or must we open anew? */
  1267. mutex_enter(&np->r_statelock);
  1268. if (np->n_fidrefs > 0 &&
  1269. np->n_vcgenid == ssp->ss_vcgenid &&
  1270. (rights & np->n_rights) == rights) {
  1271. np->n_fidrefs++;
  1272. *fidp = np->n_fid;
  1273. mutex_exit(&np->r_statelock);
  1274. return (0);
  1275. }
  1276. mutex_exit(&np->r_statelock);
  1277. /* re-open an existing file. */
  1278. if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
  1279. error = smbfs_smb_ntcreatex(np,
  1280. NULL, 0, 0, /* name nmlen xattr */
  1281. rights, SMB_EFA_NORMAL,
  1282. NTCREATEX_SHARE_ACCESS_ALL,
  1283. NTCREATEX_DISP_OPEN,
  1284. 0, /* create options */
  1285. scrp, fidp,
  1286. NULL, NULL); /* cr_act_p fa_p */
  1287. return (error);
  1288. }
  1289. accmode = smb_rights2mode(rights);
  1290. error = smbfs_smb_oldopen(np,
  1291. NULL, 0, 0, /* name nmlen xattr */
  1292. accmode, scrp,
  1293. fidp,
  1294. NULL, /* granted mode p */
  1295. NULL); /* fa p */
  1296. return (error);
  1297. }
  1298. int
  1299. smbfs_smb_tmpclose(struct smbnode *np, uint16_t fid, struct smb_cred *scrp)
  1300. {
  1301. struct smb_share *ssp = np->n_mount->smi_share;
  1302. int error = 0;
  1303. uint16_t oldfid = SMB_FID_UNUSED;
  1304. /* Shared lock for n_fid use below. */
  1305. ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
  1306. mutex_enter(&np->r_statelock);
  1307. if (fid == np->n_fid) {
  1308. ASSERT(np->n_fidrefs > 0);
  1309. if (--np->n_fidrefs == 0) {
  1310. /*
  1311. * Don't expect to find the last reference
  1312. * here in tmpclose. Hard to deal with as
  1313. * we don't have r_lkserlock exclusive.
  1314. * Will close oldfid below.
  1315. */
  1316. oldfid = np->n_fid;
  1317. np->n_fid = SMB_FID_UNUSED;
  1318. }
  1319. } else {
  1320. /* Will close the passed fid. */
  1321. oldfid = fid;
  1322. }
  1323. mutex_exit(&np->r_statelock);
  1324. if (oldfid != SMB_FID_UNUSED)
  1325. error = smbfs_smb_close(ssp, oldfid, NULL, scrp);
  1326. return (error);
  1327. }
  1328. int
  1329. smbfs_smb_open(
  1330. struct smbnode *np,
  1331. const char *name,
  1332. int nmlen,
  1333. int xattr,
  1334. uint32_t rights,
  1335. struct smb_cred *scrp,
  1336. uint16_t *fidp,
  1337. uint32_t *rightsp,
  1338. smbfattr_t *fap)
  1339. {
  1340. struct smb_share *ssp = np->n_mount->smi_share;
  1341. struct smb_vc *vcp = SSTOVC(ssp);
  1342. int accmode, error;
  1343. uint16_t grantedmode;
  1344. /* open an existing file */
  1345. if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
  1346. error = smbfs_smb_ntcreatex(np,
  1347. name, nmlen, xattr,
  1348. rights, SMB_EFA_NORMAL,
  1349. NTCREATEX_SHARE_ACCESS_ALL,
  1350. NTCREATEX_DISP_OPEN,
  1351. 0, /* create options */
  1352. scrp, fidp,
  1353. NULL, fap); /* cr_act_p fa_p */
  1354. if (error != 0)
  1355. return (error);
  1356. *rightsp = rights;
  1357. return (0);
  1358. }
  1359. accmode = smb_rights2mode(rights);
  1360. error = smbfs_smb_oldopen(np,
  1361. name, nmlen, xattr, accmode, scrp,
  1362. fidp, &grantedmode, fap);
  1363. if (error != 0)
  1364. return (error);
  1365. *rightsp = smb_mode2rights(grantedmode);
  1366. (void) smbfs_smb_getfattr(np, fap, scrp);
  1367. return (0);
  1368. }
  1369. int
  1370. smbfs_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime,
  1371. struct smb_cred *scrp)
  1372. {
  1373. struct smb_rq rq, *rqp = &rq;
  1374. struct mbchain *mbp;
  1375. long time;
  1376. int error;
  1377. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scrp);
  1378. if (error)
  1379. return (error);
  1380. smb_rq_getrequest(rqp, &mbp);
  1381. smb_rq_wstart(rqp);
  1382. mb_put_uint16le(mbp, fid);
  1383. if (mtime) {
  1384. int sv_tz = SSTOVC(ssp)->vc_sopt.sv_tz;
  1385. smb_time_local2server(mtime, sv_tz, &time);
  1386. } else
  1387. time = 0;
  1388. mb_put_uint32le(mbp, time);
  1389. smb_rq_wend(rqp);
  1390. smb_rq_bstart(rqp);
  1391. smb_rq_bend(rqp);
  1392. /*
  1393. * We don't really care about the result here, but we
  1394. * do need to make sure we send this out, or we could
  1395. * "leak" open file handles on interrupt or timeout.
  1396. * The NOINTR_SEND flag makes this request immune to
  1397. * interrupt or timeout until the send is done.
  1398. */
  1399. rqp->sr_flags |= SMBR_NOINTR_SEND;
  1400. error = smb_rq_simple(rqp);
  1401. smb_rq_done(rqp);
  1402. /*
  1403. * ENOTCONN isn't interesting - if the connection is closed,
  1404. * so are all our FIDs - and EIO is also not interesting,
  1405. * as it means a forced unmount was done. (was ENXIO)
  1406. * Also ETIME, which means we sent the request but gave up
  1407. * waiting before the response came back.
  1408. *
  1409. * Don't clog up the system log with warnings about these
  1410. * uninteresting failures on closes.
  1411. */
  1412. switch (error) {
  1413. case ENOTCONN:
  1414. case ENXIO:
  1415. case EIO:
  1416. case ETIME:
  1417. error = 0;
  1418. }
  1419. return (error);
  1420. }
  1421. static int
  1422. smbfs_smb_oldcreate(struct smbnode *dnp, const char *name, int nmlen,
  1423. int xattr, struct smb_cred *scrp, uint16_t *fidp)
  1424. {
  1425. struct smb_rq rq, *rqp = &rq;
  1426. struct smb_share *ssp = dnp->n_mount->smi_share;
  1427. struct mbchain *mbp;
  1428. struct mdchain *mdp;
  1429. struct timespec ctime;
  1430. uint8_t wc;
  1431. long tm;
  1432. int error;
  1433. uint16_t attr = SMB_FA_ARCHIVE;
  1434. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE, scrp);
  1435. if (error)
  1436. return (error);
  1437. smb_rq_getrequest(rqp, &mbp);
  1438. smb_rq_wstart(rqp);
  1439. if (name && *name == '.')
  1440. attr |= SMB_FA_HIDDEN;
  1441. mb_put_uint16le(mbp, attr); /* attributes */
  1442. gethrestime(&ctime);
  1443. smb_time_local2server(&ctime, SSTOVC(ssp)->vc_sopt.sv_tz, &tm);
  1444. mb_put_uint32le(mbp, tm);
  1445. smb_rq_wend(rqp);
  1446. smb_rq_bstart(rqp);
  1447. mb_put_uint8(mbp, SMB_DT_ASCII);
  1448. error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, &nmlen,
  1449. xattr ? ':' : '\\');
  1450. if (error)
  1451. goto out;
  1452. smb_rq_bend(rqp);
  1453. /*
  1454. * Don't want to risk missing a successful
  1455. * open response, or we could "leak" FIDs.
  1456. */
  1457. rqp->sr_flags |= SMBR_NOINTR_RECV;
  1458. error = smb_rq_simple_timed(rqp, smb_timo_open);
  1459. if (error)
  1460. goto out;
  1461. smb_rq_getreply(rqp, &mdp);
  1462. md_get_uint8(mdp, &wc);
  1463. if (wc != 1) {
  1464. error = EBADRPC;
  1465. goto out;
  1466. }
  1467. error = md_get_uint16le(mdp, fidp);
  1468. out:
  1469. smb_rq_done(rqp);
  1470. return (error);
  1471. }
  1472. int
  1473. smbfs_smb_create(
  1474. struct smbnode *dnp,
  1475. const char *name,
  1476. int nmlen,
  1477. int xattr,
  1478. uint32_t disp,
  1479. struct smb_cred *scrp,
  1480. uint16_t *fidp)
  1481. {
  1482. struct smb_share *ssp = dnp->n_mount->smi_share;
  1483. struct smb_vc *vcp = SSTOVC(ssp);
  1484. uint32_t efa, rights;
  1485. int error;
  1486. /*
  1487. * At present the only access we might need is to WRITE data,
  1488. * and that only if we are creating a "symlink". When/if the
  1489. * access needed gets more complex it should made a parameter
  1490. * and be set upstream.
  1491. */
  1492. if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
  1493. rights = SA_RIGHT_FILE_WRITE_DATA;
  1494. efa = SMB_EFA_NORMAL;
  1495. if (!xattr && name && *name == '.')
  1496. efa = SMB_EFA_HIDDEN;
  1497. error = smbfs_smb_ntcreatex(dnp,
  1498. name, nmlen, xattr, rights, efa,
  1499. NTCREATEX_SHARE_ACCESS_ALL,
  1500. disp, /* != NTCREATEX_DISP_OPEN */
  1501. NTCREATEX_OPTIONS_NON_DIRECTORY_FILE,
  1502. scrp, fidp, NULL, NULL); /* cr_act_p fa_p */
  1503. return (error);
  1504. }
  1505. error = smbfs_smb_oldcreate(dnp, name, nmlen, xattr, scrp, fidp);
  1506. return (error);
  1507. }
  1508. int
  1509. smbfs_smb_delete(struct smbnode *np, struct smb_cred *scrp, const char *name,
  1510. int nmlen, int xattr)
  1511. {
  1512. struct smb_rq rq, *rqp = &rq;
  1513. struct smb_share *ssp = np->n_mount->smi_share;
  1514. struct mbchain *mbp;
  1515. int error;
  1516. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE, scrp);
  1517. if (error)
  1518. return (error);
  1519. smb_rq_getrequest(rqp, &mbp);
  1520. smb_rq_wstart(rqp);
  1521. mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN);
  1522. smb_rq_wend(rqp);
  1523. smb_rq_bstart(rqp);
  1524. mb_put_uint8(mbp, SMB_DT_ASCII);
  1525. error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, &nmlen,
  1526. xattr ? ':' : '\\');
  1527. if (!error) {
  1528. smb_rq_bend(rqp);
  1529. error = smb_rq_simple(rqp);
  1530. }
  1531. smb_rq_done(rqp);
  1532. return (error);
  1533. }
  1534. int
  1535. smbfs_smb_rename(struct smbnode *src, struct smbnode *tdnp,
  1536. const char *tname, int tnmlen, struct smb_cred *scrp)
  1537. {
  1538. struct smb_rq rq, *rqp = &rq;
  1539. struct smb_share *ssp = src->n_mount->smi_share;
  1540. struct mbchain *mbp;
  1541. int error;
  1542. uint16_t fa;
  1543. char sep;
  1544. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_RENAME, scrp);
  1545. if (error)
  1546. return (error);
  1547. smb_rq_getrequest(rqp, &mbp);
  1548. smb_rq_wstart(rqp);
  1549. /* freebsd bug: Let directories be renamed - Win98 requires DIR bit */
  1550. fa = (SMBTOV(src)->v_type == VDIR) ? SMB_FA_DIR : 0;
  1551. fa |= SMB_FA_SYSTEM | SMB_FA_HIDDEN;
  1552. mb_put_uint16le(mbp, fa);
  1553. smb_rq_wend(rqp);
  1554. smb_rq_bstart(rqp);
  1555. /*
  1556. * When we're not adding any component name, the
  1557. * passed sep is ignored, so just pass sep=0.
  1558. */
  1559. mb_put_uint8(mbp, SMB_DT_ASCII);
  1560. error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, NULL, 0);
  1561. if (error)
  1562. goto out;
  1563. /*
  1564. * After XATTR directories, separator is ":"
  1565. */
  1566. sep = (src->n_flag & N_XATTR) ? ':' : '\\';
  1567. mb_put_uint8(mbp, SMB_DT_ASCII);
  1568. error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, &tnmlen, sep);
  1569. if (error)
  1570. goto out;
  1571. smb_rq_bend(rqp);
  1572. error = smb_rq_simple(rqp);
  1573. out:
  1574. smb_rq_done(rqp);
  1575. return (error);
  1576. }
  1577. int
  1578. smbfs_smb_move(struct smbnode *src, struct smbnode *tdnp,
  1579. const char *tname, int tnmlen, uint16_t flags, struct smb_cred *scrp)
  1580. {
  1581. struct smb_rq rq, *rqp = &rq;
  1582. struct smb_share *ssp = src->n_mount->smi_share;
  1583. struct mbchain *mbp;
  1584. int error;
  1585. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_MOVE, scrp);
  1586. if (error)
  1587. return (error);
  1588. smb_rq_getrequest(rqp, &mbp);
  1589. smb_rq_wstart(rqp);
  1590. mb_put_uint16le(mbp, SMB_TID_UNKNOWN);
  1591. mb_put_uint16le(mbp, 0x20); /* delete target file */
  1592. mb_put_uint16le(mbp, flags);
  1593. smb_rq_wend(rqp);
  1594. smb_rq_bstart(rqp);
  1595. mb_put_uint8(mbp, SMB_DT_ASCII);
  1596. error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, NULL, '\\');
  1597. if (error)
  1598. goto out;
  1599. mb_put_uint8(mbp, SMB_DT_ASCII);
  1600. error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, &tnmlen, '\\');
  1601. if (error)
  1602. goto out;
  1603. smb_rq_bend(rqp);
  1604. error = smb_rq_simple(rqp);
  1605. out:
  1606. smb_rq_done(rqp);
  1607. return (error);
  1608. }
  1609. static int
  1610. smbfs_smb_oldmkdir(struct smbnode *dnp, const char *name, int len,
  1611. struct smb_cred *scrp)
  1612. {
  1613. struct smb_rq rq, *rqp = &rq;
  1614. struct smb_share *ssp = dnp->n_mount->smi_share;
  1615. struct mbchain *mbp;
  1616. int error;
  1617. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE_DIRECTORY, scrp);
  1618. if (error)
  1619. return (error);
  1620. smb_rq_getrequest(rqp, &mbp);
  1621. smb_rq_wstart(rqp);
  1622. smb_rq_wend(rqp);
  1623. smb_rq_bstart(rqp);
  1624. mb_put_uint8(mbp, SMB_DT_ASCII);
  1625. error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, &len, '\\');
  1626. if (!error) {
  1627. smb_rq_bend(rqp);
  1628. error = smb_rq_simple(rqp);
  1629. }
  1630. smb_rq_done(rqp);
  1631. return (error);
  1632. }
  1633. int
  1634. smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int nmlen,
  1635. struct smb_cred *scrp)
  1636. {
  1637. struct smb_share *ssp = dnp->n_mount->smi_share;
  1638. struct smb_vc *vcp = SSTOVC(ssp);
  1639. uint32_t rights;
  1640. uint16_t fid;
  1641. int error;
  1642. /*
  1643. * We ask for SA_RIGHT_FILE_READ_DATA not because we need it, but
  1644. * just to be asking for something. The rights==0 case could
  1645. * easily be broken on some old or unusual servers.
  1646. */
  1647. if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
  1648. rights = SA_RIGHT_FILE_READ_DATA;
  1649. error = smbfs_smb_ntcreatex(dnp,
  1650. name, nmlen, 0, /* xattr */
  1651. rights, SMB_EFA_DIRECTORY,
  1652. NTCREATEX_SHARE_ACCESS_ALL,
  1653. NTCREATEX_DISP_CREATE,
  1654. NTCREATEX_OPTIONS_DIRECTORY,
  1655. scrp, &fid, NULL, NULL); /* cr_act_p fa_p */
  1656. if (error)
  1657. return (error);
  1658. (void) smbfs_smb_close(ssp, fid, NULL, scrp);
  1659. return (0);
  1660. }
  1661. error = smbfs_smb_oldmkdir(dnp, name, nmlen, scrp);
  1662. return (error);
  1663. }
  1664. int
  1665. smbfs_smb_rmdir(struct smbnode *np, struct smb_cred *scrp)
  1666. {
  1667. struct smb_rq rq, *rqp = &rq;
  1668. struct smb_share *ssp = np->n_mount->smi_share;
  1669. struct mbchain *mbp;
  1670. int error;
  1671. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE_DIRECTORY, scrp);
  1672. if (error)
  1673. return (error);
  1674. smb_rq_getrequest(rqp, &mbp);
  1675. smb_rq_wstart(rqp);
  1676. smb_rq_wend(rqp);
  1677. smb_rq_bstart(rqp);
  1678. mb_put_uint8(mbp, SMB_DT_ASCII);
  1679. error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, NULL, '\\');
  1680. if (!error) {
  1681. smb_rq_bend(rqp);
  1682. error = smb_rq_simple(rqp);
  1683. }
  1684. smb_rq_done(rqp);
  1685. return (error);
  1686. }
  1687. static int
  1688. smbfs_smb_search(struct smbfs_fctx *ctx)
  1689. {
  1690. struct smb_vc *vcp = SSTOVC(ctx->f_ssp);
  1691. struct smb_rq *rqp;
  1692. struct mbchain *mbp;
  1693. struct mdchain *mdp;
  1694. uint8_t wc, bt;
  1695. uint16_t ec, dlen, bc;
  1696. int len, maxent, error, iseof = 0;
  1697. maxent = min(ctx->f_left,
  1698. (vcp->vc_txmax - SMB_HDRLEN - 2*2) / SMB_DENTRYLEN);
  1699. if (ctx->f_rq) {
  1700. smb_rq_done(ctx->f_rq);
  1701. ctx->f_rq = NULL;
  1702. }
  1703. error = smb_rq_alloc(SSTOCP(ctx->f_ssp), SMB_COM_SEARCH,
  1704. ctx->f_scred, &rqp);
  1705. if (error)
  1706. return (error);
  1707. ctx->f_rq = rqp;
  1708. smb_rq_getrequest(rqp, &mbp);
  1709. smb_rq_wstart(rqp);
  1710. mb_put_uint16le(mbp, maxent); /* max entries to return */
  1711. mb_put_uint16le(mbp, ctx->f_attrmask);
  1712. smb_rq_wend(rqp);
  1713. smb_rq_bstart(rqp);
  1714. mb_put_uint8(mbp, SMB_DT_ASCII); /* buffer format */
  1715. if (ctx->f_flags & SMBFS_RDD_FINDFIRST) {
  1716. len = ctx->f_wclen;
  1717. error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard,
  1718. &len, '\\');
  1719. if (error)
  1720. return (error);
  1721. mb_put_uint8(mbp, SMB_DT_VARIABLE);
  1722. mb_put_uint16le(mbp, 0); /* context length */
  1723. ctx->f_flags &= ~SMBFS_RDD_FINDFIRST;
  1724. } else {
  1725. if (SMB_UNICODE_STRINGS(vcp)) {
  1726. mb_put_padbyte(mbp);
  1727. mb_put_uint8(mbp, 0);
  1728. }
  1729. mb_put_uint8(mbp, 0);
  1730. mb_put_uint8(mbp, SMB_DT_VARIABLE);
  1731. mb_put_uint16le(mbp, SMB_SKEYLEN);
  1732. mb_put_mem(mbp, (char *)ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM);
  1733. }
  1734. smb_rq_bend(rqp);
  1735. error = smb_rq_simple(rqp);
  1736. if (rqp->sr_errclass == ERRDOS && rqp->sr_serror == ERRnofiles) {
  1737. error = 0;
  1738. iseof = 1;
  1739. ctx->f_flags |= SMBFS_RDD_EOF;
  1740. } else if (error)
  1741. return (error);
  1742. smb_rq_getreply(rqp, &mdp);
  1743. error = md_get_uint8(mdp, &wc);
  1744. if (error)
  1745. return (error);
  1746. if (wc != 1)
  1747. return (iseof ? ENOENT : EBADRPC);
  1748. md_get_uint16le(mdp, &ec);
  1749. md_get_uint16le(mdp, &bc);
  1750. md_get_uint8(mdp, &bt);
  1751. error = md_get_uint16le(mdp, &dlen);
  1752. if (error)
  1753. return (error);
  1754. if (ec == 0)
  1755. return (ENOENT);
  1756. ctx->f_ecnt = ec;
  1757. if (bc < 3)
  1758. return (EBADRPC);
  1759. bc -= 3;
  1760. if (bt != SMB_DT_VARIABLE)
  1761. return (EBADRPC);
  1762. if (dlen != bc || dlen % SMB_DENTRYLEN != 0)
  1763. return (EBADRPC);
  1764. return (0);
  1765. }
  1766. /*ARGSUSED*/
  1767. static int
  1768. smbfs_smb_findopenLM1(struct smbfs_fctx *ctx, struct smbnode *dnp,
  1769. const char *wildcard, int wclen, uint16_t attr)
  1770. {
  1771. ctx->f_type = ft_LM1;
  1772. ctx->f_attrmask = attr;
  1773. if (wildcard) {
  1774. if (wclen == 1 && wildcard[0] == '*') {
  1775. ctx->f_wildcard = "*.*";
  1776. ctx->f_wclen = 3;
  1777. } else {
  1778. ctx->f_wildcard = wildcard;
  1779. ctx->f_wclen = wclen;
  1780. }
  1781. } else {
  1782. ctx->f_wildcard = NULL;
  1783. ctx->f_wclen = 0;
  1784. }
  1785. ctx->f_name = (char *)ctx->f_fname;
  1786. ctx->f_namesz = 0;
  1787. return (0);
  1788. }
  1789. static int
  1790. smbfs_smb_findnextLM1(struct smbfs_fctx *ctx, uint16_t limit)
  1791. {
  1792. struct mdchain *mdp;
  1793. struct smb_rq *rqp;
  1794. char *cp;
  1795. uint8_t battr;
  1796. uint16_t date, time;
  1797. uint32_t size;
  1798. int error;
  1799. struct timespec ts;
  1800. if (ctx->f_ecnt == 0) {
  1801. if (ctx->f_flags & SMBFS_RDD_EOF)
  1802. return (ENOENT);
  1803. ctx->f_left = ctx->f_limit = limit;
  1804. gethrestime(&ts);
  1805. error = smbfs_smb_search(ctx);
  1806. if (error)
  1807. return (error);
  1808. }
  1809. rqp = ctx->f_rq;
  1810. smb_rq_getreply(rqp, &mdp);
  1811. md_get_mem(mdp, (char *)ctx->f_skey, SMB_SKE

Large files files are truncated, but you can click here to view the full file