Print this page
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-4083 Upstream changes from illumos 5917 and 5995
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
SMB-50 User-mode SMB server
 Includes work by these authors:
 Thomas Keiser <thomas.keiser@nexenta.com>
 Albert Lee <trisk@nexenta.com>
SMB-65 SMB server in non-global zones (use zone_kcred())
SMB-65 SMB server in non-global zones (data structure changes)
Many things move to the smb_server_t object, and
many functions gain an sv arg (which server).
        
*** 18,28 ****
   *
   * CDDL HEADER END
   */
  /*
   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
!  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
   */
  
  #include <sys/types.h>
  #include <sys/param.h>
  #include <sys/sunddi.h>
--- 18,28 ----
   *
   * CDDL HEADER END
   */
  /*
   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
!  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
   */
  
  #include <sys/types.h>
  #include <sys/param.h>
  #include <sys/sunddi.h>
*** 349,363 ****
   * in the directory entry.
   *
   * smb_unmangle should only be called on names for which
   * smb_maybe_mangled() is true
   *
!  * File systems which support VFSFT_EDIRENT_FLAGS will return the
!  * directory entries as a buffer of edirent_t structure. Others will
!  * return a buffer of dirent64_t structures. A union is used for the
!  * the pointer into the buffer (bufptr, edp and dp).
!  * The ed_name/d_name is NULL terminated by the file system.
   *
   * Returns:
   *   0       - SUCCESS. Unmangled name is returned in namebuf.
   *   EINVAL  - a parameter was invalid.
   *   ENOTDIR - dnode is not a directory node.
--- 349,360 ----
   * in the directory entry.
   *
   * smb_unmangle should only be called on names for which
   * smb_maybe_mangled() is true
   *
!  * The flags arg is no longer used, but retained just to avoid
!  * changing the many callers of this function.
   *
   * Returns:
   *   0       - SUCCESS. Unmangled name is returned in namebuf.
   *   EINVAL  - a parameter was invalid.
   *   ENOTDIR - dnode is not a directory node.
*** 366,390 ****
  #define SMB_UNMANGLE_BUFSIZE    (4 * 1024)
  int
  smb_unmangle(smb_node_t *dnode, char *name, char *namebuf,
      int buflen, uint32_t flags)
  {
!         int             err, eof, bufsize, reclen;
          uint64_t        offset;
          ino64_t         ino;
-         boolean_t       is_edp;
          char            *namep, *buf;
          char            shortname[SMB_SHORTNAMELEN];
          vnode_t         *vp;
!         union {
!                 char            *u_bufptr;
!                 edirent_t       *u_edp;
!                 dirent64_t      *u_dp;
!         } u;
! #define bufptr          u.u_bufptr
! #define edp             u.u_edp
! #define dp              u.u_dp
  
          if (dnode == NULL || name == NULL || namebuf == NULL || buflen == 0)
                  return (EINVAL);
  
          ASSERT(smb_maybe_mangled(name) == B_TRUE);
--- 363,383 ----
  #define SMB_UNMANGLE_BUFSIZE    (4 * 1024)
  int
  smb_unmangle(smb_node_t *dnode, char *name, char *namebuf,
      int buflen, uint32_t flags)
  {
!         _NOTE(ARGUNUSED(flags)) // avoid changing all callers
!         int             err, eof, bufsize;
          uint64_t        offset;
          ino64_t         ino;
          char            *namep, *buf;
          char            shortname[SMB_SHORTNAMELEN];
          vnode_t         *vp;
!         char            *bufptr;
!         dirent64_t      *dp;
!         cred_t          *cr = zone_kcred();
!         int             rc = ENOENT;
  
          if (dnode == NULL || name == NULL || namebuf == NULL || buflen == 0)
                  return (EINVAL);
  
          ASSERT(smb_maybe_mangled(name) == B_TRUE);
*** 392,450 ****
          if (!smb_node_is_dir(dnode))
                  return (ENOTDIR);
  
          vp = dnode->vp;
          *namebuf = '\0';
-         is_edp = vfs_has_feature(vp->v_vfsp, VFSFT_DIRENTFLAGS);
  
          buf = kmem_alloc(SMB_UNMANGLE_BUFSIZE, KM_SLEEP);
!         bufsize = SMB_UNMANGLE_BUFSIZE;
!         offset = 0;
  
!         while ((err = smb_vop_readdir(vp, offset, buf, &bufsize,
!             &eof, flags, zone_kcred())) == 0) {
                  if (bufsize == 0) {
!                         err = ENOENT;
                          break;
                  }
- 
                  bufptr = buf;
!                 reclen = 0;
  
!                 while ((bufptr += reclen) < buf + bufsize) {
!                         if (is_edp) {
!                                 reclen = edp->ed_reclen;
!                                 offset = edp->ed_off;
!                                 ino = edp->ed_ino;
!                                 namep = edp->ed_name;
!                         } else {
!                                 reclen = dp->d_reclen;
                                  offset = dp->d_off;
                                  ino = dp->d_ino;
                                  namep = dp->d_name;
-                         }
  
                          /* skip non utf8 filename */
                          if (u8_validate(namep, strlen(namep), NULL,
                              U8_VALIDATE_ENTIRE, &err) < 0)
                                  continue;
  
                          smb_mangle(namep, ino, shortname, SMB_SHORTNAMELEN);
- 
                          if (smb_strcasecmp(name, shortname, 0) == 0) {
                                  (void) strlcpy(namebuf, namep, buflen);
!                                 kmem_free(buf, SMB_UNMANGLE_BUFSIZE);
!                                 return (0);
!                         }
!                 }
! 
!                 if (eof) {
!                         err = ENOENT;
                          break;
                  }
- 
-                 bufsize = SMB_UNMANGLE_BUFSIZE;
          }
  
          kmem_free(buf, SMB_UNMANGLE_BUFSIZE);
!         return (err);
  }
--- 385,448 ----
          if (!smb_node_is_dir(dnode))
                  return (ENOTDIR);
  
          vp = dnode->vp;
          *namebuf = '\0';
  
          buf = kmem_alloc(SMB_UNMANGLE_BUFSIZE, KM_SLEEP);
!         bufptr = buf;
!         bufsize = 0;
!         offset = 0;     // next entry offset
!         eof = B_FALSE;
  
!         for (;;) {
!                 /*
!                  * Read some entries, if buffer empty or
!                  * we've scanned all of it.  Flags zero
!                  * (no edirent, no ABE wanted here)
!                  */
!                 if (bufsize <= 0) {
!                         bufsize = SMB_UNMANGLE_BUFSIZE;
!                         rc = smb_vop_readdir(vp, offset, buf,
!                             &bufsize, &eof, 0, cr);
!                         if (rc != 0)
!                                 break; /* error */
                          if (bufsize == 0) {
!                                 eof = B_TRUE;
!                                 rc = ENOENT;
                                  break;
                          }
                          bufptr = buf;
!                 }
!                 /* LINTED pointer alignment */
!                 dp = (dirent64_t *)bufptr;
  
!                 /*
!                  * Partial records are not supposed to happen,
!                  * but let's be defensive. If this happens,
!                  * restart at the current offset.
!                  */
!                 bufptr += dp->d_reclen;
!                 bufsize -= dp->d_reclen;
!                 if (bufsize < 0)
!                         continue;
! 
                  offset = dp->d_off;
                  ino = dp->d_ino;
                  namep = dp->d_name;
  
                  /* skip non utf8 filename */
                  if (u8_validate(namep, strlen(namep), NULL,
                      U8_VALIDATE_ENTIRE, &err) < 0)
                          continue;
  
                  smb_mangle(namep, ino, shortname, SMB_SHORTNAMELEN);
                  if (smb_strcasecmp(name, shortname, 0) == 0) {
                          (void) strlcpy(namebuf, namep, buflen);
!                         rc = 0;
                          break;
                  }
          }
  
          kmem_free(buf, SMB_UNMANGLE_BUFSIZE);
!         return (rc);
  }