The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/smbfs/smbfs_smb.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 0c4b3c5a3a8fe774bcad774446d212bc


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.