1139776Simp/*- 275374Sbp * Copyright (c) 2000-2001 Boris Popov 375374Sbp * All rights reserved. 475374Sbp * 575374Sbp * Redistribution and use in source and binary forms, with or without 675374Sbp * modification, are permitted provided that the following conditions 775374Sbp * are met: 875374Sbp * 1. Redistributions of source code must retain the above copyright 975374Sbp * notice, this list of conditions and the following disclaimer. 1075374Sbp * 2. Redistributions in binary form must reproduce the above copyright 1175374Sbp * notice, this list of conditions and the following disclaimer in the 1275374Sbp * documentation and/or other materials provided with the distribution. 1375374Sbp * 1475374Sbp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1575374Sbp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1675374Sbp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1775374Sbp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1875374Sbp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1975374Sbp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2075374Sbp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2175374Sbp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2275374Sbp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2375374Sbp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2475374Sbp * SUCH DAMAGE. 2575374Sbp * 2675374Sbp * $FreeBSD: releng/11.0/sys/fs/smbfs/smbfs_smb.c 293679 2016-01-11 18:11:06Z ae $ 2775374Sbp */ 2875374Sbp#include <sys/param.h> 2975374Sbp#include <sys/systm.h> 3075374Sbp#include <sys/kernel.h> 3175374Sbp#include <sys/malloc.h> 3275374Sbp#include <sys/proc.h> 3375374Sbp#include <sys/lock.h> 3475374Sbp#include <sys/vnode.h> 3575374Sbp#include <sys/mbuf.h> 3675374Sbp#include <sys/mount.h> 37227650Skevlo#include <sys/endian.h> 3875374Sbp 3975374Sbp#ifdef USE_MD5_HASH 4075374Sbp#include <sys/md5.h> 4175374Sbp#endif 4275374Sbp 4375374Sbp#include <netsmb/smb.h> 4475374Sbp#include <netsmb/smb_subr.h> 4575374Sbp#include <netsmb/smb_rq.h> 4675374Sbp#include <netsmb/smb_conn.h> 4775374Sbp 4875374Sbp#include <fs/smbfs/smbfs.h> 4975374Sbp#include <fs/smbfs/smbfs_node.h> 5075374Sbp#include <fs/smbfs/smbfs_subr.h> 5175374Sbp 5275374Sbp/* 5375374Sbp * Lack of inode numbers leads us to the problem of generating them. 5475374Sbp * Partially this problem can be solved by having a dir/file cache 5575374Sbp * with inode numbers generated from the incremented by one counter. 5675374Sbp * However this way will require too much kernel memory, gives all 5775374Sbp * sorts of locking and consistency problems, not to mentinon counter overflows. 5875374Sbp * So, I'm decided to use a hash function to generate pseudo random (and unique) 5975374Sbp * inode numbers. 6075374Sbp */ 6175374Sbpstatic long 6275374Sbpsmbfs_getino(struct smbnode *dnp, const char *name, int nmlen) 6375374Sbp{ 6475374Sbp#ifdef USE_MD5_HASH 6575374Sbp MD5_CTX md5; 6675374Sbp u_int32_t state[4]; 6775374Sbp long ino; 6875374Sbp int i; 6975374Sbp 7075374Sbp MD5Init(&md5); 7175374Sbp MD5Update(&md5, name, nmlen); 7275374Sbp MD5Final((u_char *)state, &md5); 7375374Sbp for (i = 0, ino = 0; i < 4; i++) 7475374Sbp ino += state[i]; 7575374Sbp return dnp->n_ino + ino; 7675374Sbp#endif 7775374Sbp u_int32_t ino; 7875374Sbp 7975374Sbp ino = dnp->n_ino + smbfs_hash(name, nmlen); 8075374Sbp if (ino <= 2) 8175374Sbp ino += 3; 8275374Sbp return ino; 8375374Sbp} 8475374Sbp 8575374Sbpstatic int 8675374Sbpsmbfs_smb_lockandx(struct smbnode *np, int op, u_int32_t pid, off_t start, off_t end, 8775374Sbp struct smb_cred *scred) 8875374Sbp{ 8975374Sbp struct smb_share *ssp = np->n_mount->sm_share; 90242386Sdavide struct smb_rq *rqp; 9175374Sbp struct mbchain *mbp; 9275374Sbp u_char ltype = 0; 9375374Sbp int error; 9475374Sbp 9575374Sbp if (op == SMB_LOCK_SHARED) 9675374Sbp ltype |= SMB_LOCKING_ANDX_SHARED_LOCK; 97252558Sdavide 98252558Sdavide error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scred, &rqp); 99252558Sdavide if (error) 100252558Sdavide return (error); 10175374Sbp smb_rq_getrequest(rqp, &mbp); 10275374Sbp smb_rq_wstart(rqp); 103103533Sbp mb_put_uint8(mbp, 0xff); /* secondary command */ 10475374Sbp mb_put_uint8(mbp, 0); /* MBZ */ 10575374Sbp mb_put_uint16le(mbp, 0); 10675374Sbp mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 10775374Sbp mb_put_uint8(mbp, ltype); /* locktype */ 10875374Sbp mb_put_uint8(mbp, 0); /* oplocklevel - 0 seems is NO_OPLOCK */ 109103533Sbp mb_put_uint32le(mbp, 0); /* timeout - break immediately */ 11075374Sbp mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 1 : 0); 11175374Sbp mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 0 : 1); 11275374Sbp smb_rq_wend(rqp); 11375374Sbp smb_rq_bstart(rqp); 11475374Sbp mb_put_uint16le(mbp, pid); 11575374Sbp mb_put_uint32le(mbp, start); 11675374Sbp mb_put_uint32le(mbp, end - start); 11775374Sbp smb_rq_bend(rqp); 11875374Sbp error = smb_rq_simple(rqp); 11975374Sbp smb_rq_done(rqp); 12075374Sbp return error; 12175374Sbp} 12275374Sbp 12375374Sbpint 12475374Sbpsmbfs_smb_lock(struct smbnode *np, int op, caddr_t id, 12575374Sbp off_t start, off_t end, struct smb_cred *scred) 12675374Sbp{ 12775374Sbp struct smb_share *ssp = np->n_mount->sm_share; 12875374Sbp 12975374Sbp if (SMB_DIALECT(SSTOVC(ssp)) < SMB_DIALECT_LANMAN1_0) 13075374Sbp /* 13175374Sbp * TODO: use LOCK_BYTE_RANGE here. 13275374Sbp */ 13375374Sbp return EINVAL; 13475374Sbp else 135106595Sjhb return smbfs_smb_lockandx(np, op, (uintptr_t)id, start, end, scred); 13675374Sbp} 13775374Sbp 138264494Saestatic int 139264494Saesmbfs_query_info_fs(struct smb_share *ssp, struct statfs *sbp, 14075374Sbp struct smb_cred *scred) 14175374Sbp{ 14275374Sbp struct smb_t2rq *t2p; 14375374Sbp struct mbchain *mbp; 14475374Sbp struct mdchain *mdp; 145264494Sae uint32_t bsize, bpu; 146264494Sae int64_t units, funits; 147264494Sae int error; 148264494Sae 149264494Sae error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION, 150264494Sae scred, &t2p); 151264494Sae if (error) 152264494Sae return (error); 153264494Sae mbp = &t2p->t2_tparam; 154264494Sae mb_init(mbp); 155264494Sae mb_put_uint16le(mbp, SMB_QUERY_FS_SIZE_INFO); 156264494Sae t2p->t2_maxpcount = 2; 157264494Sae t2p->t2_maxdcount = sizeof(int64_t) * 2 + sizeof(uint32_t) * 2; 158264494Sae error = smb_t2_request(t2p); 159264494Sae if (error) { 160264494Sae smb_t2_done(t2p); 161264494Sae return (error); 162264494Sae } 163264494Sae mdp = &t2p->t2_rdata; 164264494Sae md_get_int64le(mdp, &units); 165264494Sae md_get_int64le(mdp, &funits); 166264494Sae md_get_uint32le(mdp, &bpu); 167264494Sae md_get_uint32le(mdp, &bsize); 168264494Sae sbp->f_bsize = bpu * bsize; /* fundamental filesystem block size */ 169264494Sae sbp->f_blocks= (uint64_t)units; /* total data blocks in filesystem */ 170264494Sae sbp->f_bfree = (uint64_t)funits;/* free blocks in fs */ 171264494Sae sbp->f_bavail= (uint64_t)funits;/* free blocks avail to non-superuser */ 172264494Sae sbp->f_files = 0xffff; /* total file nodes in filesystem */ 173264494Sae sbp->f_ffree = 0xffff; /* free file nodes in fs */ 174264494Sae smb_t2_done(t2p); 175264494Sae return (0); 176264494Sae} 177264494Sae 178264494Sae 179264494Saestatic int 180264494Saesmbfs_query_info_alloc(struct smb_share *ssp, struct statfs *sbp, 181264494Sae struct smb_cred *scred) 182264494Sae{ 183264494Sae struct smb_t2rq *t2p; 184264494Sae struct mbchain *mbp; 185264494Sae struct mdchain *mdp; 18675374Sbp u_int16_t bsize; 18775374Sbp u_int32_t units, bpu, funits; 18875374Sbp int error; 18975374Sbp 19075374Sbp error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION, 19175374Sbp scred, &t2p); 19275374Sbp if (error) 19375374Sbp return error; 19475374Sbp mbp = &t2p->t2_tparam; 19575374Sbp mb_init(mbp); 19675374Sbp mb_put_uint16le(mbp, SMB_INFO_ALLOCATION); 19775374Sbp t2p->t2_maxpcount = 4; 19875374Sbp t2p->t2_maxdcount = 4 * 4 + 2; 19975374Sbp error = smb_t2_request(t2p); 20075374Sbp if (error) { 20175374Sbp smb_t2_done(t2p); 20275374Sbp return error; 20375374Sbp } 20475374Sbp mdp = &t2p->t2_rdata; 20575374Sbp md_get_uint32(mdp, NULL); /* fs id */ 20675374Sbp md_get_uint32le(mdp, &bpu); 20775374Sbp md_get_uint32le(mdp, &units); 20875374Sbp md_get_uint32le(mdp, &funits); 20975374Sbp md_get_uint16le(mdp, &bsize); 21096755Strhodes sbp->f_bsize = bpu * bsize; /* fundamental filesystem block size */ 21196755Strhodes sbp->f_blocks= units; /* total data blocks in filesystem */ 21275374Sbp sbp->f_bfree = funits; /* free blocks in fs */ 21375374Sbp sbp->f_bavail= funits; /* free blocks avail to non-superuser */ 21496755Strhodes sbp->f_files = 0xffff; /* total file nodes in filesystem */ 21575374Sbp sbp->f_ffree = 0xffff; /* free file nodes in fs */ 21675374Sbp smb_t2_done(t2p); 21775374Sbp return 0; 21875374Sbp} 21975374Sbp 220264494Saestatic int 221264494Saesmbfs_query_info_disk(struct smb_share *ssp, struct statfs *sbp, 22275374Sbp struct smb_cred *scred) 22375374Sbp{ 224242386Sdavide struct smb_rq *rqp; 22575374Sbp struct mdchain *mdp; 22675374Sbp u_int16_t units, bpu, bsize, funits; 22775374Sbp int error; 22875374Sbp 229252558Sdavide error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_QUERY_INFORMATION_DISK, 230252558Sdavide scred, &rqp); 231252558Sdavide if (error) 232252558Sdavide return (error); 23375374Sbp smb_rq_wstart(rqp); 23475374Sbp smb_rq_wend(rqp); 23575374Sbp smb_rq_bstart(rqp); 23675374Sbp smb_rq_bend(rqp); 23775374Sbp error = smb_rq_simple(rqp); 23875374Sbp if (error) { 23975374Sbp smb_rq_done(rqp); 24075374Sbp return error; 24175374Sbp } 24275374Sbp smb_rq_getreply(rqp, &mdp); 24375374Sbp md_get_uint16le(mdp, &units); 24475374Sbp md_get_uint16le(mdp, &bpu); 24575374Sbp md_get_uint16le(mdp, &bsize); 24675374Sbp md_get_uint16le(mdp, &funits); 24796755Strhodes sbp->f_bsize = bpu * bsize; /* fundamental filesystem block size */ 24896755Strhodes sbp->f_blocks= units; /* total data blocks in filesystem */ 24975374Sbp sbp->f_bfree = funits; /* free blocks in fs */ 25075374Sbp sbp->f_bavail= funits; /* free blocks avail to non-superuser */ 25196755Strhodes sbp->f_files = 0xffff; /* total file nodes in filesystem */ 25275374Sbp sbp->f_ffree = 0xffff; /* free file nodes in fs */ 25375374Sbp smb_rq_done(rqp); 25475374Sbp return 0; 25575374Sbp} 25675374Sbp 257264494Saeint 258264494Saesmbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp, 259264494Sae struct smb_cred *scred) 260264494Sae{ 261264494Sae 262264494Sae if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0) { 263264494Sae if (smbfs_query_info_fs(ssp, sbp, scred) == 0) 264264494Sae return (0); 265264494Sae if (smbfs_query_info_alloc(ssp, sbp, scred) == 0) 266264494Sae return (0); 267264494Sae } 268264494Sae return (smbfs_query_info_disk(ssp, sbp, scred)); 269264494Sae} 270264494Sae 271103533Sbpstatic int 272103533Sbpsmbfs_smb_seteof(struct smbnode *np, int64_t newsize, struct smb_cred *scred) 273103533Sbp{ 274103533Sbp struct smb_t2rq *t2p; 275103533Sbp struct smb_share *ssp = np->n_mount->sm_share; 276103533Sbp struct mbchain *mbp; 277103533Sbp int error; 278103533Sbp 279103533Sbp error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION, 280103533Sbp scred, &t2p); 281103533Sbp if (error) 282103533Sbp return error; 283103533Sbp mbp = &t2p->t2_tparam; 284103533Sbp mb_init(mbp); 285103533Sbp mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 286103533Sbp mb_put_uint16le(mbp, SMB_SET_FILE_END_OF_FILE_INFO); 287103533Sbp mb_put_uint32le(mbp, 0); 288103533Sbp mbp = &t2p->t2_tdata; 289103533Sbp mb_init(mbp); 290103533Sbp mb_put_int64le(mbp, newsize); 291103533Sbp mb_put_uint32le(mbp, 0); /* padding */ 292103533Sbp mb_put_uint16le(mbp, 0); 293103533Sbp t2p->t2_maxpcount = 2; 294103533Sbp t2p->t2_maxdcount = 0; 295103533Sbp error = smb_t2_request(t2p); 296103533Sbp smb_t2_done(t2p); 297103533Sbp return error; 298103533Sbp} 299103533Sbp 300103533Sbpstatic int 301103533Sbpsmb_smb_flush(struct smbnode *np, struct smb_cred *scred) 302103533Sbp{ 303103533Sbp struct smb_share *ssp = np->n_mount->sm_share; 304242386Sdavide struct smb_rq *rqp; 305103533Sbp struct mbchain *mbp; 306103533Sbp int error; 307103533Sbp 308124434Stjr if ((np->n_flag & NOPEN) == 0 || !SMBTOV(np) || 309116486Stjr SMBTOV(np)->v_type != VREG) 310108470Sschweikh return 0; /* not a regular open file */ 311252558Sdavide error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_FLUSH, scred, &rqp); 312252558Sdavide if (error) 313103533Sbp return (error); 314103533Sbp smb_rq_getrequest(rqp, &mbp); 315103533Sbp smb_rq_wstart(rqp); 316103533Sbp mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 317103533Sbp smb_rq_wend(rqp); 318103533Sbp smb_rq_bstart(rqp); 319103533Sbp smb_rq_bend(rqp); 320103533Sbp error = smb_rq_simple(rqp); 321103533Sbp smb_rq_done(rqp); 322103533Sbp if (!error) 323103533Sbp np->n_flag &= ~NFLUSHWIRE; 324103533Sbp return (error); 325103533Sbp} 326103533Sbp 32775374Sbpint 328103533Sbpsmbfs_smb_flush(struct smbnode *np, struct smb_cred *scred) 329103533Sbp{ 330103533Sbp if (np->n_flag & NFLUSHWIRE) 331103533Sbp return (smb_smb_flush(np, scred)); 332103533Sbp return (0); 333103533Sbp} 334103533Sbp 335103533Sbpint 336293679Saesmbfs_smb_setfsize(struct smbnode *np, int64_t newsize, struct smb_cred *scred) 33775374Sbp{ 33875374Sbp struct smb_share *ssp = np->n_mount->sm_share; 339242386Sdavide struct smb_rq *rqp; 34075374Sbp struct mbchain *mbp; 34175374Sbp int error; 34275374Sbp 343293679Sae if (!smbfs_smb_seteof(np, newsize, scred)) { 344103533Sbp np->n_flag |= NFLUSHWIRE; 345103533Sbp return (0); 346103533Sbp } 347293679Sae /* XXX: We should use SMB_COM_WRITE_ANDX to support large offsets */ 348252558Sdavide error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp); 349252558Sdavide if (error) 350252558Sdavide return (error); 35175374Sbp smb_rq_getrequest(rqp, &mbp); 35275374Sbp smb_rq_wstart(rqp); 35375374Sbp mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 35475374Sbp mb_put_uint16le(mbp, 0); 355293679Sae mb_put_uint32le(mbp, (uint32_t)newsize); 35675374Sbp mb_put_uint16le(mbp, 0); 35775374Sbp smb_rq_wend(rqp); 35875374Sbp smb_rq_bstart(rqp); 35975374Sbp mb_put_uint8(mbp, SMB_DT_DATA); 36075374Sbp mb_put_uint16le(mbp, 0); 36175374Sbp smb_rq_bend(rqp); 36275374Sbp error = smb_rq_simple(rqp); 36375374Sbp smb_rq_done(rqp); 36475374Sbp return error; 36575374Sbp} 36675374Sbp 367103533Sbpint 368103533Sbpsmbfs_smb_query_info(struct smbnode *np, const char *name, int len, 369103533Sbp struct smbfattr *fap, struct smb_cred *scred) 370103533Sbp{ 371242386Sdavide struct smb_rq *rqp; 372103533Sbp struct smb_share *ssp = np->n_mount->sm_share; 373103533Sbp struct mbchain *mbp; 374103533Sbp struct mdchain *mdp; 375103533Sbp u_int8_t wc; 376103533Sbp int error; 377103533Sbp u_int16_t wattr; 378103533Sbp u_int32_t lint; 37975374Sbp 380252558Sdavide error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_QUERY_INFORMATION, scred, 381252558Sdavide &rqp); 382252558Sdavide if (error) 383252558Sdavide return (error); 384103533Sbp smb_rq_getrequest(rqp, &mbp); 385103533Sbp smb_rq_wstart(rqp); 386103533Sbp smb_rq_wend(rqp); 387103533Sbp smb_rq_bstart(rqp); 388103533Sbp mb_put_uint8(mbp, SMB_DT_ASCII); 389103533Sbp do { 390103533Sbp error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, len); 391103533Sbp if (error) 392103533Sbp break; 393103533Sbp smb_rq_bend(rqp); 394103533Sbp error = smb_rq_simple(rqp); 395103533Sbp if (error) 396103533Sbp break; 397103533Sbp smb_rq_getreply(rqp, &mdp); 398103533Sbp if (md_get_uint8(mdp, &wc) != 0 || wc != 10) { 399103533Sbp error = EBADRPC; 400103533Sbp break; 401103533Sbp } 402103533Sbp md_get_uint16le(mdp, &wattr); 403103533Sbp fap->fa_attr = wattr; 404103533Sbp /* 405103533Sbp * Be careful using the time returned here, as 406103533Sbp * with FAT on NT4SP6, at least, the time returned is low 407103533Sbp * 32 bits of 100s of nanoseconds (since 1601) so it rolls 408103533Sbp * over about every seven minutes! 409103533Sbp */ 410103533Sbp md_get_uint32le(mdp, &lint); /* specs: secs since 1970 */ 411103533Sbp if (lint) /* avoid bogus zero returns */ 412103533Sbp smb_time_server2local(lint, SSTOVC(ssp)->vc_sopt.sv_tz, 413103533Sbp &fap->fa_mtime); 414103533Sbp md_get_uint32le(mdp, &lint); 415103533Sbp fap->fa_size = lint; 416103533Sbp } while(0); 417103533Sbp smb_rq_done(rqp); 418103533Sbp return error; 419103533Sbp} 420103533Sbp 42175374Sbp/* 42275374Sbp * Set DOS file attributes. mtime should be NULL for dialects above lm10 42375374Sbp */ 42475374Sbpint 42575374Sbpsmbfs_smb_setpattr(struct smbnode *np, u_int16_t attr, struct timespec *mtime, 42675374Sbp struct smb_cred *scred) 42775374Sbp{ 428242386Sdavide struct smb_rq *rqp; 42975374Sbp struct smb_share *ssp = np->n_mount->sm_share; 43075374Sbp struct mbchain *mbp; 43175374Sbp u_long time; 43275374Sbp int error, svtz; 43375374Sbp 434252558Sdavide error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_SET_INFORMATION, scred, 435252558Sdavide &rqp); 436252558Sdavide if (error) 437252558Sdavide return (error); 43875374Sbp svtz = SSTOVC(ssp)->vc_sopt.sv_tz; 43975374Sbp smb_rq_getrequest(rqp, &mbp); 44075374Sbp smb_rq_wstart(rqp); 44175374Sbp mb_put_uint16le(mbp, attr); 44275374Sbp if (mtime) { 44375374Sbp smb_time_local2server(mtime, svtz, &time); 44475374Sbp } else 44575374Sbp time = 0; 44675374Sbp mb_put_uint32le(mbp, time); /* mtime */ 44775374Sbp mb_put_mem(mbp, NULL, 5 * 2, MB_MZERO); 44875374Sbp smb_rq_wend(rqp); 44975374Sbp smb_rq_bstart(rqp); 45075374Sbp mb_put_uint8(mbp, SMB_DT_ASCII); 45175374Sbp do { 45275374Sbp error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0); 45375374Sbp if (error) 45475374Sbp break; 45575374Sbp mb_put_uint8(mbp, SMB_DT_ASCII); 456227650Skevlo if (SMB_UNICODE_STRINGS(SSTOVC(ssp))) { 457227650Skevlo mb_put_padbyte(mbp); 458227650Skevlo mb_put_uint8(mbp, 0); /* 1st byte of NULL Unicode char */ 459227650Skevlo } 46075374Sbp mb_put_uint8(mbp, 0); 46175374Sbp smb_rq_bend(rqp); 46275374Sbp error = smb_rq_simple(rqp); 463163993Sbp if (error) { 464163993Sbp SMBERROR("smb_rq_simple(rqp) => error %d\n", error); 46575374Sbp break; 466163993Sbp } 46775374Sbp } while(0); 46875374Sbp smb_rq_done(rqp); 46975374Sbp return error; 47075374Sbp} 47175374Sbp 47275374Sbp/* 47375374Sbp * Note, win95 doesn't support this call. 47475374Sbp */ 47575374Sbpint 47675374Sbpsmbfs_smb_setptime2(struct smbnode *np, struct timespec *mtime, 47775374Sbp struct timespec *atime, int attr, struct smb_cred *scred) 47875374Sbp{ 47975374Sbp struct smb_t2rq *t2p; 48075374Sbp struct smb_share *ssp = np->n_mount->sm_share; 48175374Sbp struct smb_vc *vcp = SSTOVC(ssp); 48275374Sbp struct mbchain *mbp; 48375374Sbp u_int16_t date, time; 48475374Sbp int error, tzoff; 48575374Sbp 48675374Sbp error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_PATH_INFORMATION, 48775374Sbp scred, &t2p); 48875374Sbp if (error) 48975374Sbp return error; 49075374Sbp mbp = &t2p->t2_tparam; 49175374Sbp mb_init(mbp); 49275374Sbp mb_put_uint16le(mbp, SMB_INFO_STANDARD); 49375374Sbp mb_put_uint32le(mbp, 0); /* MBZ */ 494103533Sbp /* mb_put_uint8(mbp, SMB_DT_ASCII); specs incorrect */ 49575374Sbp error = smbfs_fullpath(mbp, vcp, np, NULL, 0); 49675374Sbp if (error) { 49775374Sbp smb_t2_done(t2p); 49875374Sbp return error; 49975374Sbp } 50075374Sbp tzoff = vcp->vc_sopt.sv_tz; 50175374Sbp mbp = &t2p->t2_tdata; 50275374Sbp mb_init(mbp); 50375374Sbp mb_put_uint32le(mbp, 0); /* creation time */ 50475374Sbp if (atime) 50575374Sbp smb_time_unix2dos(atime, tzoff, &date, &time, NULL); 50675374Sbp else 50775374Sbp time = date = 0; 50875374Sbp mb_put_uint16le(mbp, date); 50975374Sbp mb_put_uint16le(mbp, time); 51075374Sbp if (mtime) 51175374Sbp smb_time_unix2dos(mtime, tzoff, &date, &time, NULL); 51275374Sbp else 51375374Sbp time = date = 0; 51475374Sbp mb_put_uint16le(mbp, date); 51575374Sbp mb_put_uint16le(mbp, time); 51675374Sbp mb_put_uint32le(mbp, 0); /* file size */ 51775374Sbp mb_put_uint32le(mbp, 0); /* allocation unit size */ 51875374Sbp mb_put_uint16le(mbp, attr); /* DOS attr */ 51975374Sbp mb_put_uint32le(mbp, 0); /* EA size */ 52075374Sbp t2p->t2_maxpcount = 5 * 2; 52175374Sbp t2p->t2_maxdcount = vcp->vc_txmax; 52275374Sbp error = smb_t2_request(t2p); 52375374Sbp smb_t2_done(t2p); 52475374Sbp return error; 52575374Sbp} 52675374Sbp 52775374Sbp/* 52875374Sbp * NT level. Specially for win9x 52975374Sbp */ 53075374Sbpint 53175374Sbpsmbfs_smb_setpattrNT(struct smbnode *np, u_short attr, struct timespec *mtime, 53275374Sbp struct timespec *atime, struct smb_cred *scred) 53375374Sbp{ 53475374Sbp struct smb_t2rq *t2p; 53575374Sbp struct smb_share *ssp = np->n_mount->sm_share; 53675374Sbp struct smb_vc *vcp = SSTOVC(ssp); 53775374Sbp struct mbchain *mbp; 53875374Sbp int64_t tm; 53975374Sbp int error, tzoff; 54075374Sbp 54175374Sbp error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_PATH_INFORMATION, 54275374Sbp scred, &t2p); 54375374Sbp if (error) 54475374Sbp return error; 54575374Sbp mbp = &t2p->t2_tparam; 54675374Sbp mb_init(mbp); 54775374Sbp mb_put_uint16le(mbp, SMB_SET_FILE_BASIC_INFO); 54875374Sbp mb_put_uint32le(mbp, 0); /* MBZ */ 549103533Sbp /* mb_put_uint8(mbp, SMB_DT_ASCII); specs incorrect */ 55075374Sbp error = smbfs_fullpath(mbp, vcp, np, NULL, 0); 55175374Sbp if (error) { 55275374Sbp smb_t2_done(t2p); 55375374Sbp return error; 55475374Sbp } 55575374Sbp tzoff = vcp->vc_sopt.sv_tz; 55675374Sbp mbp = &t2p->t2_tdata; 55775374Sbp mb_init(mbp); 55875374Sbp mb_put_int64le(mbp, 0); /* creation time */ 55975374Sbp if (atime) { 56075374Sbp smb_time_local2NT(atime, tzoff, &tm); 56175374Sbp } else 56275374Sbp tm = 0; 56375374Sbp mb_put_int64le(mbp, tm); 56475374Sbp if (mtime) { 56575374Sbp smb_time_local2NT(mtime, tzoff, &tm); 56675374Sbp } else 56775374Sbp tm = 0; 56875374Sbp mb_put_int64le(mbp, tm); 56975374Sbp mb_put_int64le(mbp, tm); /* change time */ 57075374Sbp mb_put_uint32le(mbp, attr); /* attr */ 57175374Sbp t2p->t2_maxpcount = 24; 57275374Sbp t2p->t2_maxdcount = 56; 57375374Sbp error = smb_t2_request(t2p); 57475374Sbp smb_t2_done(t2p); 57575374Sbp return error; 57675374Sbp} 57775374Sbp 57875374Sbp/* 57975374Sbp * Set file atime and mtime. Doesn't supported by core dialect. 58075374Sbp */ 58175374Sbpint 58275374Sbpsmbfs_smb_setftime(struct smbnode *np, struct timespec *mtime, 58375374Sbp struct timespec *atime, struct smb_cred *scred) 58475374Sbp{ 585242386Sdavide struct smb_rq *rqp; 58675374Sbp struct smb_share *ssp = np->n_mount->sm_share; 58775374Sbp struct mbchain *mbp; 58875374Sbp u_int16_t date, time; 58975374Sbp int error, tzoff; 59075374Sbp 591252558Sdavide error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_SET_INFORMATION2, scred, 592252558Sdavide &rqp); 593252558Sdavide if (error) 594252558Sdavide return (error); 59575374Sbp tzoff = SSTOVC(ssp)->vc_sopt.sv_tz; 59675374Sbp smb_rq_getrequest(rqp, &mbp); 59775374Sbp smb_rq_wstart(rqp); 59875374Sbp mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 59975374Sbp mb_put_uint32le(mbp, 0); /* creation time */ 60075374Sbp 60175374Sbp if (atime) 60275374Sbp smb_time_unix2dos(atime, tzoff, &date, &time, NULL); 60375374Sbp else 60475374Sbp time = date = 0; 60575374Sbp mb_put_uint16le(mbp, date); 60675374Sbp mb_put_uint16le(mbp, time); 60775374Sbp if (mtime) 60875374Sbp smb_time_unix2dos(mtime, tzoff, &date, &time, NULL); 60975374Sbp else 61075374Sbp time = date = 0; 61175374Sbp mb_put_uint16le(mbp, date); 61275374Sbp mb_put_uint16le(mbp, time); 61375374Sbp smb_rq_wend(rqp); 61475374Sbp smb_rq_bstart(rqp); 61575374Sbp smb_rq_bend(rqp); 61675374Sbp error = smb_rq_simple(rqp); 61775374Sbp SMBSDEBUG("%d\n", error); 61875374Sbp smb_rq_done(rqp); 61975374Sbp return error; 62075374Sbp} 62175374Sbp 62275374Sbp/* 62375374Sbp * Set DOS file attributes. 624223843Sjonathan * Looks like this call can be used only if SMB_CAP_NT_SMBS bit is on. 62575374Sbp */ 62675374Sbpint 62775374Sbpsmbfs_smb_setfattrNT(struct smbnode *np, u_int16_t attr, struct timespec *mtime, 62875374Sbp struct timespec *atime, struct smb_cred *scred) 62975374Sbp{ 63075374Sbp struct smb_t2rq *t2p; 63175374Sbp struct smb_share *ssp = np->n_mount->sm_share; 63275374Sbp struct mbchain *mbp; 63375374Sbp int64_t tm; 63475374Sbp int error, svtz; 63575374Sbp 63675374Sbp error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION, 63775374Sbp scred, &t2p); 63875374Sbp if (error) 63975374Sbp return error; 64075374Sbp svtz = SSTOVC(ssp)->vc_sopt.sv_tz; 64175374Sbp mbp = &t2p->t2_tparam; 64275374Sbp mb_init(mbp); 64375374Sbp mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 64475374Sbp mb_put_uint16le(mbp, SMB_SET_FILE_BASIC_INFO); 64575374Sbp mb_put_uint32le(mbp, 0); 64675374Sbp mbp = &t2p->t2_tdata; 64775374Sbp mb_init(mbp); 64875374Sbp mb_put_int64le(mbp, 0); /* creation time */ 64975374Sbp if (atime) { 65075374Sbp smb_time_local2NT(atime, svtz, &tm); 65175374Sbp } else 65275374Sbp tm = 0; 65375374Sbp mb_put_int64le(mbp, tm); 65475374Sbp if (mtime) { 65575374Sbp smb_time_local2NT(mtime, svtz, &tm); 65675374Sbp } else 65775374Sbp tm = 0; 65875374Sbp mb_put_int64le(mbp, tm); 65975374Sbp mb_put_int64le(mbp, tm); /* change time */ 66075374Sbp mb_put_uint16le(mbp, attr); 66175374Sbp mb_put_uint32le(mbp, 0); /* padding */ 66275374Sbp mb_put_uint16le(mbp, 0); 66375374Sbp t2p->t2_maxpcount = 2; 66475374Sbp t2p->t2_maxdcount = 0; 66575374Sbp error = smb_t2_request(t2p); 66675374Sbp smb_t2_done(t2p); 66775374Sbp return error; 66875374Sbp} 66975374Sbp 67075374Sbp 67175374Sbpint 67275374Sbpsmbfs_smb_open(struct smbnode *np, int accmode, struct smb_cred *scred) 67375374Sbp{ 674242386Sdavide struct smb_rq *rqp; 67575374Sbp struct smb_share *ssp = np->n_mount->sm_share; 67675374Sbp struct mbchain *mbp; 67775374Sbp struct mdchain *mdp; 67875374Sbp u_int8_t wc; 67975374Sbp u_int16_t fid, wattr, grantedmode; 68075374Sbp int error; 68175374Sbp 682252558Sdavide error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_OPEN, scred, &rqp); 683252558Sdavide if (error) 684252558Sdavide return (error); 68575374Sbp smb_rq_getrequest(rqp, &mbp); 68675374Sbp smb_rq_wstart(rqp); 68775374Sbp mb_put_uint16le(mbp, accmode); 68875374Sbp mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN); 68975374Sbp smb_rq_wend(rqp); 69075374Sbp smb_rq_bstart(rqp); 69175374Sbp mb_put_uint8(mbp, SMB_DT_ASCII); 69275374Sbp do { 69375374Sbp error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0); 69475374Sbp if (error) 69575374Sbp break; 69675374Sbp smb_rq_bend(rqp); 69775374Sbp error = smb_rq_simple(rqp); 69875374Sbp if (error) 69975374Sbp break; 70075374Sbp smb_rq_getreply(rqp, &mdp); 70175374Sbp if (md_get_uint8(mdp, &wc) != 0 || wc != 7) { 70275374Sbp error = EBADRPC; 70375374Sbp break; 70475374Sbp } 70575374Sbp md_get_uint16(mdp, &fid); 70675374Sbp md_get_uint16le(mdp, &wattr); 70775374Sbp md_get_uint32(mdp, NULL); /* mtime */ 70875374Sbp md_get_uint32(mdp, NULL); /* fsize */ 70975374Sbp md_get_uint16le(mdp, &grantedmode); 71075374Sbp /* 71175374Sbp * TODO: refresh attributes from this reply 71275374Sbp */ 71375374Sbp } while(0); 71475374Sbp smb_rq_done(rqp); 71575374Sbp if (error) 71675374Sbp return error; 71775374Sbp np->n_fid = fid; 71875374Sbp np->n_rwstate = grantedmode; 71975374Sbp return 0; 72075374Sbp} 72175374Sbp 72275374Sbp 72375374Sbpint 72475374Sbpsmbfs_smb_close(struct smb_share *ssp, u_int16_t fid, struct timespec *mtime, 72575374Sbp struct smb_cred *scred) 72675374Sbp{ 727242386Sdavide struct smb_rq *rqp; 72875374Sbp struct mbchain *mbp; 72975374Sbp u_long time; 73075374Sbp int error; 73175374Sbp 732252558Sdavide error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_CLOSE, scred, &rqp); 733252558Sdavide if (error) 734252558Sdavide return (error); 73575374Sbp smb_rq_getrequest(rqp, &mbp); 73675374Sbp smb_rq_wstart(rqp); 73775374Sbp mb_put_mem(mbp, (caddr_t)&fid, sizeof(fid), MB_MSYSTEM); 73875374Sbp if (mtime) { 73975374Sbp smb_time_local2server(mtime, SSTOVC(ssp)->vc_sopt.sv_tz, &time); 74075374Sbp } else 74175374Sbp time = 0; 74275374Sbp mb_put_uint32le(mbp, time); 74375374Sbp smb_rq_wend(rqp); 74475374Sbp smb_rq_bstart(rqp); 74575374Sbp smb_rq_bend(rqp); 74675374Sbp error = smb_rq_simple(rqp); 74775374Sbp smb_rq_done(rqp); 74875374Sbp return error; 74975374Sbp} 75075374Sbp 75175374Sbpint 75275374Sbpsmbfs_smb_create(struct smbnode *dnp, const char *name, int nmlen, 75375374Sbp struct smb_cred *scred) 75475374Sbp{ 755242386Sdavide struct smb_rq *rqp; 75675374Sbp struct smb_share *ssp = dnp->n_mount->sm_share; 75775374Sbp struct mbchain *mbp; 75875374Sbp struct mdchain *mdp; 75975374Sbp struct timespec ctime; 76075374Sbp u_int8_t wc; 76175374Sbp u_int16_t fid; 76275374Sbp u_long tm; 76375374Sbp int error; 76475374Sbp 765252558Sdavide error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_CREATE, scred, &rqp); 766252558Sdavide if (error) 767252558Sdavide return (error); 76875374Sbp smb_rq_getrequest(rqp, &mbp); 76975374Sbp smb_rq_wstart(rqp); 77075374Sbp mb_put_uint16le(mbp, SMB_FA_ARCHIVE); /* attributes */ 77175374Sbp nanotime(&ctime); 77275374Sbp smb_time_local2server(&ctime, SSTOVC(ssp)->vc_sopt.sv_tz, &tm); 77375374Sbp mb_put_uint32le(mbp, tm); 77475374Sbp smb_rq_wend(rqp); 77575374Sbp smb_rq_bstart(rqp); 77675374Sbp mb_put_uint8(mbp, SMB_DT_ASCII); 77775374Sbp error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, nmlen); 77875374Sbp if (!error) { 77975374Sbp smb_rq_bend(rqp); 78075374Sbp error = smb_rq_simple(rqp); 78175374Sbp if (!error) { 78275374Sbp smb_rq_getreply(rqp, &mdp); 78375374Sbp md_get_uint8(mdp, &wc); 78475374Sbp if (wc == 1) 78575374Sbp md_get_uint16(mdp, &fid); 78675374Sbp else 78775374Sbp error = EBADRPC; 78875374Sbp } 78975374Sbp } 79075374Sbp smb_rq_done(rqp); 79175374Sbp if (error) 79275374Sbp return error; 79375374Sbp smbfs_smb_close(ssp, fid, &ctime, scred); 79475374Sbp return error; 79575374Sbp} 79675374Sbp 79775374Sbpint 79875374Sbpsmbfs_smb_delete(struct smbnode *np, struct smb_cred *scred) 79975374Sbp{ 800242386Sdavide struct smb_rq *rqp; 80175374Sbp struct smb_share *ssp = np->n_mount->sm_share; 80275374Sbp struct mbchain *mbp; 80375374Sbp int error; 80475374Sbp 805252558Sdavide error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_DELETE, scred, &rqp); 806252558Sdavide if (error) 807252558Sdavide return (error); 80875374Sbp smb_rq_getrequest(rqp, &mbp); 80975374Sbp smb_rq_wstart(rqp); 81075374Sbp mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN); 81175374Sbp smb_rq_wend(rqp); 81275374Sbp smb_rq_bstart(rqp); 81375374Sbp mb_put_uint8(mbp, SMB_DT_ASCII); 81475374Sbp error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0); 81575374Sbp if (!error) { 81675374Sbp smb_rq_bend(rqp); 81775374Sbp error = smb_rq_simple(rqp); 81875374Sbp } 81975374Sbp smb_rq_done(rqp); 82075374Sbp return error; 82175374Sbp} 82275374Sbp 82375374Sbpint 82475374Sbpsmbfs_smb_rename(struct smbnode *src, struct smbnode *tdnp, 82575374Sbp const char *tname, int tnmlen, struct smb_cred *scred) 82675374Sbp{ 827242386Sdavide struct smb_rq *rqp; 82875374Sbp struct smb_share *ssp = src->n_mount->sm_share; 82975374Sbp struct mbchain *mbp; 83075374Sbp int error; 83175374Sbp 832252558Sdavide error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_RENAME, scred, &rqp); 833252558Sdavide if (error) 834252558Sdavide return (error); 83575374Sbp smb_rq_getrequest(rqp, &mbp); 83675374Sbp smb_rq_wstart(rqp); 83775374Sbp mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN); 83875374Sbp smb_rq_wend(rqp); 83975374Sbp smb_rq_bstart(rqp); 84075374Sbp mb_put_uint8(mbp, SMB_DT_ASCII); 84175374Sbp do { 84275374Sbp error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, 0); 84375374Sbp if (error) 84475374Sbp break; 84575374Sbp mb_put_uint8(mbp, SMB_DT_ASCII); 84675374Sbp error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, tnmlen); 84775374Sbp if (error) 84875374Sbp break; 84975374Sbp smb_rq_bend(rqp); 85075374Sbp error = smb_rq_simple(rqp); 85175374Sbp } while(0); 85275374Sbp smb_rq_done(rqp); 85375374Sbp return error; 85475374Sbp} 85575374Sbp 85675374Sbpint 85775374Sbpsmbfs_smb_move(struct smbnode *src, struct smbnode *tdnp, 85875374Sbp const char *tname, int tnmlen, u_int16_t flags, struct smb_cred *scred) 85975374Sbp{ 860242386Sdavide struct smb_rq *rqp; 86175374Sbp struct smb_share *ssp = src->n_mount->sm_share; 86275374Sbp struct mbchain *mbp; 86375374Sbp int error; 86475374Sbp 865252558Sdavide error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_MOVE, scred, &rqp); 866252558Sdavide if (error) 867252558Sdavide return (error); 86875374Sbp smb_rq_getrequest(rqp, &mbp); 86975374Sbp smb_rq_wstart(rqp); 87075374Sbp mb_put_uint16le(mbp, SMB_TID_UNKNOWN); 87175374Sbp mb_put_uint16le(mbp, 0x20); /* delete target file */ 87275374Sbp mb_put_uint16le(mbp, flags); 87375374Sbp smb_rq_wend(rqp); 87475374Sbp smb_rq_bstart(rqp); 87575374Sbp mb_put_uint8(mbp, SMB_DT_ASCII); 87675374Sbp do { 87775374Sbp error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, 0); 87875374Sbp if (error) 87975374Sbp break; 88075374Sbp mb_put_uint8(mbp, SMB_DT_ASCII); 88175374Sbp error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, tnmlen); 88275374Sbp if (error) 88375374Sbp break; 88475374Sbp smb_rq_bend(rqp); 88575374Sbp error = smb_rq_simple(rqp); 88675374Sbp } while(0); 88775374Sbp smb_rq_done(rqp); 88875374Sbp return error; 88975374Sbp} 89075374Sbp 89175374Sbpint 89275374Sbpsmbfs_smb_mkdir(struct smbnode *dnp, const char *name, int len, 89375374Sbp struct smb_cred *scred) 89475374Sbp{ 895242386Sdavide struct smb_rq *rqp; 89675374Sbp struct smb_share *ssp = dnp->n_mount->sm_share; 89775374Sbp struct mbchain *mbp; 89875374Sbp int error; 89975374Sbp 900252558Sdavide error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_CREATE_DIRECTORY, scred, 901252558Sdavide &rqp); 902252558Sdavide if (error) 903252558Sdavide return (error); 90475374Sbp smb_rq_getrequest(rqp, &mbp); 90575374Sbp smb_rq_wstart(rqp); 90675374Sbp smb_rq_wend(rqp); 90775374Sbp smb_rq_bstart(rqp); 90875374Sbp mb_put_uint8(mbp, SMB_DT_ASCII); 90975374Sbp error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, len); 91075374Sbp if (!error) { 91175374Sbp smb_rq_bend(rqp); 91275374Sbp error = smb_rq_simple(rqp); 91375374Sbp } 91475374Sbp smb_rq_done(rqp); 91575374Sbp return error; 91675374Sbp} 91775374Sbp 91875374Sbpint 91975374Sbpsmbfs_smb_rmdir(struct smbnode *np, struct smb_cred *scred) 92075374Sbp{ 921242386Sdavide struct smb_rq *rqp; 92275374Sbp struct smb_share *ssp = np->n_mount->sm_share; 92375374Sbp struct mbchain *mbp; 92475374Sbp int error; 92575374Sbp 926252558Sdavide error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_DELETE_DIRECTORY, scred, 927252558Sdavide &rqp); 928252558Sdavide if (error) 929252558Sdavide return (error); 93075374Sbp smb_rq_getrequest(rqp, &mbp); 93175374Sbp smb_rq_wstart(rqp); 93275374Sbp smb_rq_wend(rqp); 93375374Sbp smb_rq_bstart(rqp); 93475374Sbp mb_put_uint8(mbp, SMB_DT_ASCII); 93575374Sbp error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0); 93675374Sbp if (!error) { 93775374Sbp smb_rq_bend(rqp); 93875374Sbp error = smb_rq_simple(rqp); 93975374Sbp } 94075374Sbp smb_rq_done(rqp); 94175374Sbp return error; 94275374Sbp} 94375374Sbp 94475374Sbpstatic int 94575374Sbpsmbfs_smb_search(struct smbfs_fctx *ctx) 94675374Sbp{ 94775374Sbp struct smb_vc *vcp = SSTOVC(ctx->f_ssp); 94875374Sbp struct smb_rq *rqp; 94975374Sbp struct mbchain *mbp; 95075374Sbp struct mdchain *mdp; 95175374Sbp u_int8_t wc, bt; 95275374Sbp u_int16_t ec, dlen, bc; 95375374Sbp int maxent, error, iseof = 0; 95475374Sbp 95575374Sbp maxent = min(ctx->f_left, (vcp->vc_txmax - SMB_HDRLEN - 3) / SMB_DENTRYLEN); 95675374Sbp if (ctx->f_rq) { 95775374Sbp smb_rq_done(ctx->f_rq); 95875374Sbp ctx->f_rq = NULL; 95975374Sbp } 96075374Sbp error = smb_rq_alloc(SSTOCP(ctx->f_ssp), SMB_COM_SEARCH, ctx->f_scred, &rqp); 96175374Sbp if (error) 962252558Sdavide return (error); 96375374Sbp ctx->f_rq = rqp; 96475374Sbp smb_rq_getrequest(rqp, &mbp); 96575374Sbp smb_rq_wstart(rqp); 96675374Sbp mb_put_uint16le(mbp, maxent); /* max entries to return */ 96775374Sbp mb_put_uint16le(mbp, ctx->f_attrmask); 96875374Sbp smb_rq_wend(rqp); 96975374Sbp smb_rq_bstart(rqp); 97075374Sbp mb_put_uint8(mbp, SMB_DT_ASCII); /* buffer format */ 97175374Sbp if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 97275374Sbp error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard, ctx->f_wclen); 97375374Sbp if (error) 97475374Sbp return error; 97575374Sbp mb_put_uint8(mbp, SMB_DT_VARIABLE); 97675374Sbp mb_put_uint16le(mbp, 0); /* context length */ 97775374Sbp ctx->f_flags &= ~SMBFS_RDD_FINDFIRST; 97875374Sbp } else { 979227650Skevlo if (SMB_UNICODE_STRINGS(vcp)) { 980227650Skevlo mb_put_padbyte(mbp); 981227650Skevlo mb_put_uint8(mbp, 0); 982227650Skevlo } 98375374Sbp mb_put_uint8(mbp, 0); /* file name length */ 98475374Sbp mb_put_uint8(mbp, SMB_DT_VARIABLE); 98575374Sbp mb_put_uint16le(mbp, SMB_SKEYLEN); 98675374Sbp mb_put_mem(mbp, ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM); 98775374Sbp } 98875374Sbp smb_rq_bend(rqp); 98975374Sbp error = smb_rq_simple(rqp); 99075374Sbp if (error) { 99175374Sbp if (rqp->sr_errclass == ERRDOS && rqp->sr_serror == ERRnofiles) { 99275374Sbp error = 0; 99375374Sbp iseof = 1; 99475374Sbp ctx->f_flags |= SMBFS_RDD_EOF; 99575374Sbp } else 99675374Sbp return error; 99775374Sbp } 99875374Sbp smb_rq_getreply(rqp, &mdp); 99975374Sbp md_get_uint8(mdp, &wc); 100075374Sbp if (wc != 1) 100175374Sbp return iseof ? ENOENT : EBADRPC; 100275374Sbp md_get_uint16le(mdp, &ec); 100375374Sbp if (ec == 0) 100475374Sbp return ENOENT; 100575374Sbp ctx->f_ecnt = ec; 100675374Sbp md_get_uint16le(mdp, &bc); 100775374Sbp if (bc < 3) 100875374Sbp return EBADRPC; 100975374Sbp bc -= 3; 101075374Sbp md_get_uint8(mdp, &bt); 101175374Sbp if (bt != SMB_DT_VARIABLE) 101275374Sbp return EBADRPC; 101375374Sbp md_get_uint16le(mdp, &dlen); 101475374Sbp if (dlen != bc || dlen % SMB_DENTRYLEN != 0) 101575374Sbp return EBADRPC; 101675374Sbp return 0; 101775374Sbp} 101875374Sbp 101975374Sbpstatic int 102075374Sbpsmbfs_findopenLM1(struct smbfs_fctx *ctx, struct smbnode *dnp, 102175374Sbp const char *wildcard, int wclen, int attr, struct smb_cred *scred) 102275374Sbp{ 102375374Sbp ctx->f_attrmask = attr; 102475374Sbp if (wildcard) { 102575374Sbp if (wclen == 1 && wildcard[0] == '*') { 102675374Sbp ctx->f_wildcard = "*.*"; 102775374Sbp ctx->f_wclen = 3; 102875374Sbp } else { 102975374Sbp ctx->f_wildcard = wildcard; 103075374Sbp ctx->f_wclen = wclen; 103175374Sbp } 103275374Sbp } else { 103375374Sbp ctx->f_wildcard = NULL; 103475374Sbp ctx->f_wclen = 0; 103575374Sbp } 103675374Sbp ctx->f_name = ctx->f_fname; 103775374Sbp return 0; 103875374Sbp} 103975374Sbp 104075374Sbpstatic int 104175374Sbpsmbfs_findnextLM1(struct smbfs_fctx *ctx, int limit) 104275374Sbp{ 104375374Sbp struct mdchain *mbp; 104475374Sbp struct smb_rq *rqp; 104575374Sbp char *cp; 104675374Sbp u_int8_t battr; 104775374Sbp u_int16_t date, time; 104875374Sbp u_int32_t size; 104975374Sbp int error; 105075374Sbp 105175374Sbp if (ctx->f_ecnt == 0) { 105275374Sbp if (ctx->f_flags & SMBFS_RDD_EOF) 105375374Sbp return ENOENT; 105475374Sbp ctx->f_left = ctx->f_limit = limit; 105575374Sbp error = smbfs_smb_search(ctx); 105675374Sbp if (error) 105775374Sbp return error; 105875374Sbp } 105975374Sbp rqp = ctx->f_rq; 106075374Sbp smb_rq_getreply(rqp, &mbp); 106175374Sbp md_get_mem(mbp, ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM); 106275374Sbp md_get_uint8(mbp, &battr); 106375374Sbp md_get_uint16le(mbp, &time); 106475374Sbp md_get_uint16le(mbp, &date); 106575374Sbp md_get_uint32le(mbp, &size); 106675374Sbp cp = ctx->f_name; 106775374Sbp md_get_mem(mbp, cp, sizeof(ctx->f_fname), MB_MSYSTEM); 106875374Sbp cp[sizeof(ctx->f_fname) - 1] = 0; 106975374Sbp cp += strlen(cp) - 1; 107075374Sbp while (*cp == ' ' && cp >= ctx->f_name) 107175374Sbp *cp-- = 0; 107275374Sbp ctx->f_attr.fa_attr = battr; 107375374Sbp smb_dos2unixtime(date, time, 0, rqp->sr_vc->vc_sopt.sv_tz, 107475374Sbp &ctx->f_attr.fa_mtime); 107575374Sbp ctx->f_attr.fa_size = size; 107675374Sbp ctx->f_nmlen = strlen(ctx->f_name); 107775374Sbp ctx->f_ecnt--; 107875374Sbp ctx->f_left--; 107975374Sbp return 0; 108075374Sbp} 108175374Sbp 108275374Sbpstatic int 108375374Sbpsmbfs_findcloseLM1(struct smbfs_fctx *ctx) 108475374Sbp{ 108575374Sbp if (ctx->f_rq) 108675374Sbp smb_rq_done(ctx->f_rq); 108775374Sbp return 0; 108875374Sbp} 108975374Sbp 109075374Sbp/* 109175374Sbp * TRANS2_FIND_FIRST2/NEXT2, used for NT LM12 dialect 109275374Sbp */ 109375374Sbpstatic int 109475374Sbpsmbfs_smb_trans2find2(struct smbfs_fctx *ctx) 109575374Sbp{ 109675374Sbp struct smb_t2rq *t2p; 109775374Sbp struct smb_vc *vcp = SSTOVC(ctx->f_ssp); 109875374Sbp struct mbchain *mbp; 109975374Sbp struct mdchain *mdp; 110075374Sbp u_int16_t tw, flags; 110175374Sbp int error; 110275374Sbp 110375374Sbp if (ctx->f_t2) { 110475374Sbp smb_t2_done(ctx->f_t2); 110575374Sbp ctx->f_t2 = NULL; 110675374Sbp } 110775374Sbp ctx->f_flags &= ~SMBFS_RDD_GOTRNAME; 110875374Sbp flags = 8 | 2; /* <resume> | <close if EOS> */ 110975374Sbp if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) { 111075374Sbp flags |= 1; /* close search after this request */ 111175374Sbp ctx->f_flags |= SMBFS_RDD_NOCLOSE; 111275374Sbp } 111375374Sbp if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 111475374Sbp error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_FIRST2, 111575374Sbp ctx->f_scred, &t2p); 111675374Sbp if (error) 111775374Sbp return error; 111875374Sbp ctx->f_t2 = t2p; 111975374Sbp mbp = &t2p->t2_tparam; 112075374Sbp mb_init(mbp); 112175374Sbp mb_put_uint16le(mbp, ctx->f_attrmask); 112275374Sbp mb_put_uint16le(mbp, ctx->f_limit); 112375374Sbp mb_put_uint16le(mbp, flags); 112475374Sbp mb_put_uint16le(mbp, ctx->f_infolevel); 112575374Sbp mb_put_uint32le(mbp, 0); 112675374Sbp error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard, ctx->f_wclen); 112775374Sbp if (error) 112875374Sbp return error; 112975374Sbp } else { 113075374Sbp error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_NEXT2, 113175374Sbp ctx->f_scred, &t2p); 113275374Sbp if (error) 113375374Sbp return error; 113475374Sbp ctx->f_t2 = t2p; 113575374Sbp mbp = &t2p->t2_tparam; 113675374Sbp mb_init(mbp); 113775374Sbp mb_put_mem(mbp, (caddr_t)&ctx->f_Sid, 2, MB_MSYSTEM); 113875374Sbp mb_put_uint16le(mbp, ctx->f_limit); 113975374Sbp mb_put_uint16le(mbp, ctx->f_infolevel); 114075374Sbp mb_put_uint32le(mbp, 0); /* resume key */ 114175374Sbp mb_put_uint16le(mbp, flags); 114275374Sbp if (ctx->f_rname) 1143227650Skevlo mb_put_mem(mbp, ctx->f_rname, ctx->f_rnamelen + 1, MB_MSYSTEM); 114475374Sbp else 114575374Sbp mb_put_uint8(mbp, 0); /* resume file name */ 114675374Sbp#if 0 114775374Sbp struct timeval tv; 114875374Sbp tv.tv_sec = 0; 114975374Sbp tv.tv_usec = 200 * 1000; /* 200ms */ 115075374Sbp if (vcp->vc_flags & SMBC_WIN95) { 115175374Sbp /* 115275374Sbp * some implementations suggests to sleep here 115375374Sbp * for 200ms, due to the bug in the Win95. 115475374Sbp * I've didn't notice any problem, but put code 115575374Sbp * for it. 115675374Sbp */ 1157167086Sjhb pause("fix95", tvtohz(&tv)); 115875374Sbp } 115975374Sbp#endif 116075374Sbp } 116175374Sbp t2p->t2_maxpcount = 5 * 2; 116275374Sbp t2p->t2_maxdcount = vcp->vc_txmax; 116375374Sbp error = smb_t2_request(t2p); 116475374Sbp if (error) 116575374Sbp return error; 116675374Sbp mdp = &t2p->t2_rparam; 116775374Sbp if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 116875374Sbp if ((error = md_get_uint16(mdp, &ctx->f_Sid)) != 0) 116975374Sbp return error; 117075374Sbp ctx->f_flags &= ~SMBFS_RDD_FINDFIRST; 117175374Sbp } 117275374Sbp if ((error = md_get_uint16le(mdp, &tw)) != 0) 117375374Sbp return error; 117475374Sbp ctx->f_ecnt = tw; 117575374Sbp if ((error = md_get_uint16le(mdp, &tw)) != 0) 117675374Sbp return error; 117775374Sbp if (tw) 117875374Sbp ctx->f_flags |= SMBFS_RDD_EOF | SMBFS_RDD_NOCLOSE; 117975374Sbp if ((error = md_get_uint16le(mdp, &tw)) != 0) 118075374Sbp return error; 118175374Sbp if ((error = md_get_uint16le(mdp, &tw)) != 0) 118275374Sbp return error; 1183152678Sbp if (ctx->f_ecnt == 0) { 1184152678Sbp ctx->f_flags |= SMBFS_RDD_EOF | SMBFS_RDD_NOCLOSE; 118575374Sbp return ENOENT; 1186152678Sbp } 118775374Sbp ctx->f_rnameofs = tw; 118875374Sbp mdp = &t2p->t2_rdata; 118975374Sbp if (mdp->md_top == NULL) { 119075374Sbp printf("bug: ecnt = %d, but data is NULL (please report)\n", ctx->f_ecnt); 119175374Sbp return ENOENT; 119275374Sbp } 119375374Sbp if (mdp->md_top->m_len == 0) { 119475374Sbp printf("bug: ecnt = %d, but m_len = 0 and m_next = %p (please report)\n", ctx->f_ecnt,mbp->mb_top->m_next); 119575374Sbp return ENOENT; 119675374Sbp } 119775374Sbp ctx->f_eofs = 0; 119875374Sbp return 0; 119975374Sbp} 120075374Sbp 120175374Sbpstatic int 120275374Sbpsmbfs_smb_findclose2(struct smbfs_fctx *ctx) 120375374Sbp{ 1204242386Sdavide struct smb_rq *rqp; 120575374Sbp struct mbchain *mbp; 120675374Sbp int error; 120775374Sbp 1208252558Sdavide error = smb_rq_alloc(SSTOCP(ctx->f_ssp), SMB_COM_FIND_CLOSE2, 1209252558Sdavide ctx->f_scred, &rqp); 1210252558Sdavide if (error) 1211252558Sdavide return (error); 121275374Sbp smb_rq_getrequest(rqp, &mbp); 121375374Sbp smb_rq_wstart(rqp); 121475374Sbp mb_put_mem(mbp, (caddr_t)&ctx->f_Sid, 2, MB_MSYSTEM); 121575374Sbp smb_rq_wend(rqp); 121675374Sbp smb_rq_bstart(rqp); 121775374Sbp smb_rq_bend(rqp); 121875374Sbp error = smb_rq_simple(rqp); 121975374Sbp smb_rq_done(rqp); 122075374Sbp return error; 122175374Sbp} 122275374Sbp 122375374Sbpstatic int 122475374Sbpsmbfs_findopenLM2(struct smbfs_fctx *ctx, struct smbnode *dnp, 122575374Sbp const char *wildcard, int wclen, int attr, struct smb_cred *scred) 122675374Sbp{ 1227227650Skevlo if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) { 1228227650Skevlo ctx->f_name = malloc(SMB_MAXFNAMELEN * 2, M_SMBFSDATA, M_WAITOK); 1229227650Skevlo } else 1230227650Skevlo ctx->f_name = malloc(SMB_MAXFNAMELEN, M_SMBFSDATA, M_WAITOK); 123175374Sbp ctx->f_infolevel = SMB_DIALECT(SSTOVC(ctx->f_ssp)) < SMB_DIALECT_NTLM0_12 ? 123275374Sbp SMB_INFO_STANDARD : SMB_FIND_FILE_DIRECTORY_INFO; 123375374Sbp ctx->f_attrmask = attr; 123475374Sbp ctx->f_wildcard = wildcard; 123575374Sbp ctx->f_wclen = wclen; 123675374Sbp return 0; 123775374Sbp} 123875374Sbp 123975374Sbpstatic int 124075374Sbpsmbfs_findnextLM2(struct smbfs_fctx *ctx, int limit) 124175374Sbp{ 124275374Sbp struct mdchain *mbp; 124375374Sbp struct smb_t2rq *t2p; 124475374Sbp char *cp; 124575374Sbp u_int8_t tb; 124675374Sbp u_int16_t date, time, wattr; 124775374Sbp u_int32_t size, next, dattr; 124875374Sbp int64_t lint; 124975374Sbp int error, svtz, cnt, fxsz, nmlen, recsz; 125075374Sbp 125175374Sbp if (ctx->f_ecnt == 0) { 125275374Sbp if (ctx->f_flags & SMBFS_RDD_EOF) 125375374Sbp return ENOENT; 125475374Sbp ctx->f_left = ctx->f_limit = limit; 125575374Sbp error = smbfs_smb_trans2find2(ctx); 125675374Sbp if (error) 125775374Sbp return error; 125875374Sbp } 125975374Sbp t2p = ctx->f_t2; 126075374Sbp mbp = &t2p->t2_rdata; 126175374Sbp svtz = SSTOVC(ctx->f_ssp)->vc_sopt.sv_tz; 126275374Sbp switch (ctx->f_infolevel) { 126375374Sbp case SMB_INFO_STANDARD: 126475374Sbp next = 0; 126575374Sbp fxsz = 0; 126675374Sbp md_get_uint16le(mbp, &date); 126775374Sbp md_get_uint16le(mbp, &time); /* creation time */ 126875374Sbp md_get_uint16le(mbp, &date); 126975374Sbp md_get_uint16le(mbp, &time); /* access time */ 127075374Sbp smb_dos2unixtime(date, time, 0, svtz, &ctx->f_attr.fa_atime); 127175374Sbp md_get_uint16le(mbp, &date); 127275374Sbp md_get_uint16le(mbp, &time); /* access time */ 127375374Sbp smb_dos2unixtime(date, time, 0, svtz, &ctx->f_attr.fa_mtime); 127475374Sbp md_get_uint32le(mbp, &size); 127575374Sbp ctx->f_attr.fa_size = size; 127675374Sbp md_get_uint32(mbp, NULL); /* allocation size */ 127775374Sbp md_get_uint16le(mbp, &wattr); 127875374Sbp ctx->f_attr.fa_attr = wattr; 127975374Sbp md_get_uint8(mbp, &tb); 128075374Sbp size = nmlen = tb; 128175374Sbp fxsz = 23; 128275374Sbp recsz = next = 24 + nmlen; /* docs misses zero byte at end */ 128375374Sbp break; 128475374Sbp case SMB_FIND_FILE_DIRECTORY_INFO: 128575374Sbp md_get_uint32le(mbp, &next); 128675374Sbp md_get_uint32(mbp, NULL); /* file index */ 128775374Sbp md_get_int64(mbp, NULL); /* creation time */ 128875374Sbp md_get_int64le(mbp, &lint); 128975374Sbp smb_time_NT2local(lint, svtz, &ctx->f_attr.fa_atime); 129075374Sbp md_get_int64le(mbp, &lint); 129175374Sbp smb_time_NT2local(lint, svtz, &ctx->f_attr.fa_mtime); 129275374Sbp md_get_int64le(mbp, &lint); 129375374Sbp smb_time_NT2local(lint, svtz, &ctx->f_attr.fa_ctime); 129475374Sbp md_get_int64le(mbp, &lint); /* file size */ 129575374Sbp ctx->f_attr.fa_size = lint; 129675374Sbp md_get_int64(mbp, NULL); /* real size (should use) */ 129782039Sbp md_get_uint32le(mbp, &dattr); /* EA */ 129875374Sbp ctx->f_attr.fa_attr = dattr; 129975374Sbp md_get_uint32le(mbp, &size); /* name len */ 130075374Sbp fxsz = 64; 130175374Sbp recsz = next ? next : fxsz + size; 130275374Sbp break; 130375374Sbp default: 130475374Sbp SMBERROR("unexpected info level %d\n", ctx->f_infolevel); 130575374Sbp return EINVAL; 130675374Sbp } 1307227650Skevlo if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) { 1308227650Skevlo nmlen = min(size, SMB_MAXFNAMELEN * 2); 1309227650Skevlo } else 1310227650Skevlo nmlen = min(size, SMB_MAXFNAMELEN); 131175374Sbp cp = ctx->f_name; 131275374Sbp error = md_get_mem(mbp, cp, nmlen, MB_MSYSTEM); 131375374Sbp if (error) 131475374Sbp return error; 131575374Sbp if (next) { 131675374Sbp cnt = next - nmlen - fxsz; 131775374Sbp if (cnt > 0) 131875374Sbp md_get_mem(mbp, NULL, cnt, MB_MSYSTEM); 131975374Sbp else if (cnt < 0) { 132075374Sbp SMBERROR("out of sync\n"); 132175374Sbp return EBADRPC; 132275374Sbp } 132375374Sbp } 1324227650Skevlo if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) { 1325227650Skevlo if (nmlen > 1 && cp[nmlen - 1] == 0 && cp[nmlen - 2] == 0) 1326227650Skevlo nmlen -= 2; 1327227650Skevlo } else 1328227650Skevlo if (nmlen && cp[nmlen - 1] == 0) 1329227650Skevlo nmlen--; 133075374Sbp if (nmlen == 0) 133175374Sbp return EBADRPC; 133275374Sbp 133375374Sbp next = ctx->f_eofs + recsz; 133475374Sbp if (ctx->f_rnameofs && (ctx->f_flags & SMBFS_RDD_GOTRNAME) == 0 && 133575374Sbp (ctx->f_rnameofs >= ctx->f_eofs && ctx->f_rnameofs < next)) { 133675374Sbp /* 133775374Sbp * Server needs a resume filename. 133875374Sbp */ 133975374Sbp if (ctx->f_rnamelen <= nmlen) { 134075374Sbp if (ctx->f_rname) 134175374Sbp free(ctx->f_rname, M_SMBFSDATA); 1342111119Simp ctx->f_rname = malloc(nmlen + 1, M_SMBFSDATA, M_WAITOK); 134375374Sbp ctx->f_rnamelen = nmlen; 134475374Sbp } 134575374Sbp bcopy(ctx->f_name, ctx->f_rname, nmlen); 134675374Sbp ctx->f_rname[nmlen] = 0; 134775374Sbp ctx->f_flags |= SMBFS_RDD_GOTRNAME; 134875374Sbp } 134975374Sbp ctx->f_nmlen = nmlen; 135075374Sbp ctx->f_eofs = next; 135175374Sbp ctx->f_ecnt--; 135275374Sbp ctx->f_left--; 135375374Sbp return 0; 135475374Sbp} 135575374Sbp 135675374Sbpstatic int 135775374Sbpsmbfs_findcloseLM2(struct smbfs_fctx *ctx) 135875374Sbp{ 135975374Sbp if (ctx->f_name) 136075374Sbp free(ctx->f_name, M_SMBFSDATA); 136175374Sbp if (ctx->f_t2) 136275374Sbp smb_t2_done(ctx->f_t2); 136375374Sbp if ((ctx->f_flags & SMBFS_RDD_NOCLOSE) == 0) 136475374Sbp smbfs_smb_findclose2(ctx); 136575374Sbp return 0; 136675374Sbp} 136775374Sbp 136875374Sbpint 136975374Sbpsmbfs_findopen(struct smbnode *dnp, const char *wildcard, int wclen, int attr, 137075374Sbp struct smb_cred *scred, struct smbfs_fctx **ctxpp) 137175374Sbp{ 137275374Sbp struct smbfs_fctx *ctx; 137375374Sbp int error; 137475374Sbp 1375242092Sdavide ctx = malloc(sizeof(*ctx), M_SMBFSDATA, M_WAITOK | M_ZERO); 137675374Sbp ctx->f_ssp = dnp->n_mount->sm_share; 137775374Sbp ctx->f_dnp = dnp; 137875374Sbp ctx->f_flags = SMBFS_RDD_FINDFIRST; 137975374Sbp ctx->f_scred = scred; 138075374Sbp if (SMB_DIALECT(SSTOVC(ctx->f_ssp)) < SMB_DIALECT_LANMAN2_0 || 1381138490Sphk (dnp->n_mount->sm_flags & SMBFS_MOUNT_NO_LONG)) { 138275374Sbp ctx->f_flags |= SMBFS_RDD_USESEARCH; 138375374Sbp error = smbfs_findopenLM1(ctx, dnp, wildcard, wclen, attr, scred); 138475374Sbp } else 138575374Sbp error = smbfs_findopenLM2(ctx, dnp, wildcard, wclen, attr, scred); 138675374Sbp if (error) 138775374Sbp smbfs_findclose(ctx, scred); 138875374Sbp else 138975374Sbp *ctxpp = ctx; 139075374Sbp return error; 139175374Sbp} 139275374Sbp 139375374Sbpint 139475374Sbpsmbfs_findnext(struct smbfs_fctx *ctx, int limit, struct smb_cred *scred) 139575374Sbp{ 139675374Sbp int error; 139775374Sbp 139875374Sbp if (limit == 0) 139975374Sbp limit = 1000000; 140075374Sbp else if (limit > 1) 140175374Sbp limit *= 4; /* imperical */ 140275374Sbp ctx->f_scred = scred; 140375374Sbp for (;;) { 140475374Sbp if (ctx->f_flags & SMBFS_RDD_USESEARCH) { 140575374Sbp error = smbfs_findnextLM1(ctx, limit); 140675374Sbp } else 140775374Sbp error = smbfs_findnextLM2(ctx, limit); 140875374Sbp if (error) 140975374Sbp return error; 1410227650Skevlo if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) { 1411227650Skevlo if ((ctx->f_nmlen == 2 && 1412227650Skevlo *(u_int16_t *)ctx->f_name == htole16(0x002e)) || 1413227650Skevlo (ctx->f_nmlen == 4 && 1414227650Skevlo *(u_int32_t *)ctx->f_name == htole32(0x002e002e))) 1415227650Skevlo continue; 1416227650Skevlo } else 1417227650Skevlo if ((ctx->f_nmlen == 1 && ctx->f_name[0] == '.') || 1418227650Skevlo (ctx->f_nmlen == 2 && ctx->f_name[0] == '.' && 1419227650Skevlo ctx->f_name[1] == '.')) 1420227650Skevlo continue; 142175374Sbp break; 142275374Sbp } 1423145872Stakawata smbfs_fname_tolocal(SSTOVC(ctx->f_ssp), ctx->f_name, &ctx->f_nmlen, 1424145872Stakawata ctx->f_dnp->n_mount->sm_caseopt); 142575374Sbp ctx->f_attr.fa_ino = smbfs_getino(ctx->f_dnp, ctx->f_name, ctx->f_nmlen); 142675374Sbp return 0; 142775374Sbp} 142875374Sbp 142975374Sbpint 143075374Sbpsmbfs_findclose(struct smbfs_fctx *ctx, struct smb_cred *scred) 143175374Sbp{ 143275374Sbp ctx->f_scred = scred; 143375374Sbp if (ctx->f_flags & SMBFS_RDD_USESEARCH) { 143475374Sbp smbfs_findcloseLM1(ctx); 143575374Sbp } else 143675374Sbp smbfs_findcloseLM2(ctx); 143775374Sbp if (ctx->f_rname) 143875374Sbp free(ctx->f_rname, M_SMBFSDATA); 143975374Sbp free(ctx, M_SMBFSDATA); 144075374Sbp return 0; 144175374Sbp} 144275374Sbp 144375374Sbpint 144475374Sbpsmbfs_smb_lookup(struct smbnode *dnp, const char *name, int nmlen, 144575374Sbp struct smbfattr *fap, struct smb_cred *scred) 144675374Sbp{ 144775374Sbp struct smbfs_fctx *ctx; 144875374Sbp int error; 144975374Sbp 145075374Sbp if (dnp == NULL || (dnp->n_ino == 2 && name == NULL)) { 145175374Sbp bzero(fap, sizeof(*fap)); 145275374Sbp fap->fa_attr = SMB_FA_DIR; 145375374Sbp fap->fa_ino = 2; 145475374Sbp return 0; 145575374Sbp } 1456248101Sdavide MPASS(!(nmlen == 2 && name[0] == '.' && name[1] == '.')); 1457248101Sdavide MPASS(!(nmlen == 1 && name[0] == '.')); 1458248101Sdavide ASSERT_VOP_ELOCKED(dnp->n_vnode, "smbfs_smb_lookup"); 145975374Sbp error = smbfs_findopen(dnp, name, nmlen, 146075374Sbp SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, scred, &ctx); 146175374Sbp if (error) 146275374Sbp return error; 146375374Sbp ctx->f_flags |= SMBFS_RDD_FINDSINGLE; 146475374Sbp error = smbfs_findnext(ctx, 1, scred); 146575374Sbp if (error == 0) { 146675374Sbp *fap = ctx->f_attr; 146775374Sbp if (name == NULL) 146875374Sbp fap->fa_ino = dnp->n_ino; 146975374Sbp } 147075374Sbp smbfs_findclose(ctx, scred); 147175374Sbp return error; 147275374Sbp} 1473