Print this page
6879933 Let SMBFS support extensible attributes per. PSARC 2007/315

@@ -112,10 +112,11 @@
 static int      smbfssetattr(vnode_t *, struct vattr *, int, cred_t *);
 static int      smbfs_accessx(void *, int, cred_t *);
 static int      smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
                         caller_context_t *);
 static void     smbfs_rele_fid(smbnode_t *, struct smb_cred *);
+static uint32_t xvattr_to_dosattr(smbnode_t *, struct vattr *);
 
 /*
  * These are the vnode ops routines which implement the vnode interface to
  * the networked file system.  These routines just take their parameters,
  * make them look networkish by putting the right info into interface structs,

@@ -836,14 +837,10 @@
 
 
 /*
  * Return either cached or remote attributes. If get remote attr
  * use them to check and invalidate caches, then cache the new attributes.
- *
- * XXX
- * This op should eventually support PSARC 2007/315, Extensible Attribute
- * Interfaces, for richer metadata.
  */
 /* ARGSUSED */
 static int
 smbfs_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
         caller_context_t *ct)

@@ -887,15 +884,10 @@
         return (smbfsgetattr(vp, vap, cr));
 }
 
 /* smbfsgetattr() in smbfs_client.c */
 
-/*
- * XXX
- * This op should eventually support PSARC 2007/315, Extensible Attribute
- * Interfaces, for richer metadata.
- */
 /*ARGSUSED4*/
 static int
 smbfs_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
                 caller_context_t *ct)
 {

@@ -977,10 +969,11 @@
         struct smb_cred scred;
         int             cerror, modified = 0;
         unsigned short  fid;
         int have_fid = 0;
         uint32_t rights = 0;
+        uint32_t dosattr = 0;
 
         ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone);
 
         /*
          * There are no settable attributes on the XATTR dir,

@@ -1007,14 +1000,22 @@
         if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
                 return (EINTR);
         smb_credinit(&scred, cr);
 
         /*
+         * If the caller has provided extensible attributes,
+         * map those into DOS attributes supported by SMB.
+         * Note: zero means "no change".
+         */
+        if (mask & AT_XVATTR)
+                dosattr = xvattr_to_dosattr(np, vap);
+
+        /*
          * Will we need an open handle for this setattr?
          * If so, what rights will we need?
          */
-        if (mask & (AT_ATIME | AT_MTIME)) {
+        if (dosattr || (mask & (AT_ATIME | AT_MTIME))) {
                 rights |=
                     SA_RIGHT_FILE_WRITE_ATTRIBUTES;
         }
         if (mask & AT_SIZE) {
                 rights |=

@@ -1026,11 +1027,11 @@
          * Only SIZE really requires a handle, but it's
          * simpler and more reliable to set via a handle.
          * Some servers like NT4 won't set times by path.
          * Also, we're usually setting everything anyway.
          */
-        if (mask & (AT_SIZE | AT_ATIME | AT_MTIME)) {
+        if (rights != 0) {
                 error = smbfs_smb_tmpopen(np, rights, &scred, &fid);
                 if (error) {
                         SMBVDEBUG("error %d opening %s\n",
                             error, np->n_rpath);
                         goto out;

@@ -1083,18 +1084,18 @@
          * Note: create_time is different from ctime.
          */
         mtime = ((mask & AT_MTIME) ? &vap->va_mtime : 0);
         atime = ((mask & AT_ATIME) ? &vap->va_atime : 0);
 
-        if (mtime || atime) {
+        if (dosattr || mtime || atime) {
                 /*
                  * Always use the handle-based set attr call now.
                  * Not trying to set DOS attributes here so pass zero.
                  */
                 ASSERT(have_fid);
                 error = smbfs_smb_setfattr(np, fid,
-                    0, mtime, atime, &scred);
+                    dosattr, mtime, atime, &scred);
                 if (error) {
                         SMBVDEBUG("set times error %d file %s\n",
                             error, np->n_rpath);
                 } else {
                         modified = 1;

@@ -1122,10 +1123,68 @@
 
         return (error);
 }
 
 /*
+ * Helper function for extensible system attributes (PSARC 2007/315)
+ * Compute the DOS attribute word to pass to _setfattr (see above).
+ * This returns zero IFF no change is being made to attributes.
+ * Otherwise return the new attributes or SMB_EFA_NORMAL.
+ */
+static uint32_t
+xvattr_to_dosattr(smbnode_t *np, struct vattr *vap)
+{
+        xvattr_t *xvap = (xvattr_t *)vap;
+        xoptattr_t *xoap = NULL;
+        uint32_t attr = np->r_attr.fa_attr;
+        boolean_t anyset = B_FALSE;
+
+        if ((xoap = xva_getxoptattr(xvap)) == NULL)
+                return (0);
+
+        if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) {
+                if (xoap->xoa_archive)
+                        attr |= SMB_FA_ARCHIVE;
+                else
+                        attr &= ~SMB_FA_ARCHIVE;
+                XVA_SET_RTN(xvap, XAT_ARCHIVE);
+                anyset = B_TRUE;
+        }
+        if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) {
+                if (xoap->xoa_system)
+                        attr |= SMB_FA_SYSTEM;
+                else
+                        attr &= ~SMB_FA_SYSTEM;
+                XVA_SET_RTN(xvap, XAT_SYSTEM);
+                anyset = B_TRUE;
+        }
+        if (XVA_ISSET_REQ(xvap, XAT_READONLY)) {
+                if (xoap->xoa_readonly)
+                        attr |= SMB_FA_RDONLY;
+                else
+                        attr &= ~SMB_FA_RDONLY;
+                XVA_SET_RTN(xvap, XAT_READONLY);
+                anyset = B_TRUE;
+        }
+        if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
+                if (xoap->xoa_hidden)
+                        attr |= SMB_FA_HIDDEN;
+                else
+                        attr &= ~SMB_FA_HIDDEN;
+                XVA_SET_RTN(xvap, XAT_HIDDEN);
+                anyset = B_TRUE;
+        }
+
+        if (anyset == B_FALSE)
+                return (0);     /* no change */
+        if (attr == 0)
+                attr = SMB_EFA_NORMAL;
+
+        return (attr);
+}
+
+/*
  * smbfs_access_rwx()
  * Common function for smbfs_access, etc.
  *
  * The security model implemented by the FS is unusual
  * due to the current "single user mounts" restriction:

@@ -2990,10 +3049,15 @@
                         *valp = smbfs_xa_exists(vp, cr);
                         break;
                 }
                 return (EINVAL);
 
+        case _PC_SATTR_ENABLED:
+        case _PC_SATTR_EXISTS:
+                *valp = 1;
+                break;
+
         case _PC_TIMESTAMP_RESOLUTION:
                 /*
                  * Windows times are tenths of microseconds
                  * (multiples of 100 nanoseconds).
                  */