Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ac67055e authored by Jeremy Allison's avatar Jeremy Allison Committed by Steve French
Browse files

[CIFS] POSIX extensions, SetFSInfo added



Signed-off-by: Steve French@sfrench@us.ibm.com
Signed-off-by: default avatarJeremy Allison <(jra@samba.org)>
parent dfb7533b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#define CIFS_MOUNT_DIRECT_IO    8 /* do not write nor read through page cache */
#define CIFS_MOUNT_NO_XATTR  0x10 /* if set - disable xattr support */
#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */

struct cifs_sb_info {
	struct cifsTconInfo *tcon;	/* primary mount */
+7 −0
Original line number Diff line number Diff line
@@ -309,6 +309,13 @@ CIFS_SB(struct super_block *sb)
	return sb->s_fs_info;
}

static inline const char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
{
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
		return '/';
	else
		return '\\';
}

/* one of these for every pending CIFS request to the server */
struct mid_q_entry {
+46 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@
#define TRANS2_FIND_FIRST             0x01
#define TRANS2_FIND_NEXT              0x02
#define TRANS2_QUERY_FS_INFORMATION   0x03
#define TRANS2_SET_FS_INFORMATION     0x04
#define TRANS2_QUERY_PATH_INFORMATION 0x05
#define TRANS2_SET_PATH_INFORMATION   0x06
#define TRANS2_QUERY_FILE_INFORMATION 0x07
@@ -1411,6 +1412,43 @@ typedef struct smb_com_transaction_qfsi_rsp {
	__u8 Pad;		/* may be three bytes *//* followed by data area */
} TRANSACTION2_QFSI_RSP;


/* SETFSInfo Levels */
#define SMB_SET_CIFS_UNIX_INFO    0x200
typedef struct smb_com_transaction2_setfsi_req {
	struct smb_hdr hdr;	/* wct = 15 */
	__le16 TotalParameterCount;
	__le16 TotalDataCount;
	__le16 MaxParameterCount;
	__le16 MaxDataCount;
	__u8 MaxSetupCount;
	__u8 Reserved;
	__le16 Flags;
	__le32 Timeout;
	__u16 Reserved2;
	__le16 ParameterCount;	/* 4 */
	__le16 ParameterOffset;
	__le16 DataCount;	/* 12 */
	__le16 DataOffset;
	__u8 SetupCount;	/* one */
	__u8 Reserved3;
	__le16 SubCommand;	/* TRANS2_SET_FS_INFORMATION */
	__le16 ByteCount;
	__u8 Pad;
	__u16 FileNum;		/* Parameters start. */
	__le16 InformationLevel;/* Parameters end. */
	__le16 ClientUnixMajor; /* Data start. */
	__le16 ClientUnixMinor;
	__le64 ClientUnixCap;   /* Data end */
} TRANSACTION2_SETFSI_REQ;

typedef struct smb_com_transaction2_setfsi_rsp {
	struct smb_hdr hdr;	/* wct = 10 */
	struct trans2_resp t2;
	__u16 ByteCount;
} TRANSACTION2_SETFSI_RSP;


typedef struct smb_com_transaction2_get_dfs_refer_req {
	struct smb_hdr hdr;	/* wct = 15 */
	__le16 TotalParameterCount;
@@ -1551,12 +1589,20 @@ typedef struct {
	__le16 MinorVersionNumber;
	__le64 Capability;
} FILE_SYSTEM_UNIX_INFO;	/* Unix extensions info, level 0x200 */

/* Version numbers for CIFS UNIX major and minor. */
#define CIFS_UNIX_MAJOR_VERSION 1
#define CIFS_UNIX_MINOR_VERSION 0

/* Linux/Unix extensions capability flags */
#define CIFS_UNIX_FCNTL_CAP             0x00000001 /* support for fcntl locks */
#define CIFS_UNIX_POSIX_ACL_CAP         0x00000002 /* support getfacl/setfacl */
#define CIFS_UNIX_XATTR_CAP             0x00000004 /* support new namespace   */
#define CIFS_UNIX_EXTATTR_CAP           0x00000008 /* support chattr/chflag   */
#define CIFS_UNIX_POSIX_PATHNAMES_CAP   0x00000010 /* Use POSIX pathnames on the wire. */

#define CIFS_POSIX_EXTENSIONS           0x00000010 /* support for new QFSInfo */

typedef struct {
	/* For undefined recommended transfer size return -1 in that field */
	__le32 OptimalTransferSize;  /* bsize on some os, iosize on other os */
+5 −2
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ extern unsigned int _GetXid(void);
extern void _FreeXid(unsigned int);
#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));}
extern char *build_path_from_dentry(struct dentry *);
extern char *build_path_from_dentry(struct dentry *, const struct cifs_sb_info *cifs_sb);
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
extern void renew_parental_timestamps(struct dentry *direntry);
extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
@@ -89,7 +89,7 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,

extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
            const char *searchName, const struct nls_table *nls_codepage,
            __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map);
            __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map, const char dirsep);

extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
            __u16 searchHandle, struct cifs_search_info * psrch_inf);
@@ -125,6 +125,9 @@ extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
			int remap);
extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
			struct kstatfs *FSData);
extern int CIFSSMBSETFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
			__u64 cap);

extern int CIFSSMBQFSAttributeInfo(const int xid,
			struct cifsTconInfo *tcon);
extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon);
+74 −3
Original line number Diff line number Diff line
@@ -2416,7 +2416,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
	      const char *searchName, 
	      const struct nls_table *nls_codepage,
	      __u16 *	pnetfid,
	      struct cifs_search_info * psrch_inf, int remap)
	      struct cifs_search_info * psrch_inf, int remap, const char dirsep)
{
/* level 257 SMB_ */
	TRANSACTION2_FFIRST_REQ *pSMB = NULL;
@@ -2443,7 +2443,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
		it got remapped to 0xF03A as if it were part of the
		directory name instead of a wildcard */
		name_len *= 2;
		pSMB->FileName[name_len] = '\\';
		pSMB->FileName[name_len] = dirsep;
		pSMB->FileName[name_len+1] = 0;
		pSMB->FileName[name_len+2] = '*';
		pSMB->FileName[name_len+3] = 0;
@@ -2457,7 +2457,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
		if(name_len > buffersize-header)
			free buffer exit; BB */
		strncpy(pSMB->FileName, searchName, name_len);
		pSMB->FileName[name_len] = '\\';
		pSMB->FileName[name_len] = dirsep;
		pSMB->FileName[name_len+1] = '*';
		pSMB->FileName[name_len+2] = 0;
		name_len += 3;
@@ -3265,6 +3265,77 @@ CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
	return rc;
}

int
CIFSSMBSETFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
{
/* level 0x200  SMB_SET_CIFS_UNIX_INFO */
	TRANSACTION2_SETFSI_REQ *pSMB = NULL;
	TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
	int rc = 0;
	int bytes_returned = 0;
	__u16 params, param_offset, offset, byte_count;

	cFYI(1, ("In SETFSUnixInfo"));
SETFSUnixRetry:
	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
		      (void **) &pSMBr);
	if (rc)
		return rc;

	params = 4;	/* 2 bytes zero followed by info level. */
	pSMB->MaxSetupCount = 0;
	pSMB->Reserved = 0;
	pSMB->Flags = 0;
	pSMB->Timeout = 0;
	pSMB->Reserved2 = 0;
	param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
	offset = param_offset + params;

	pSMB->MaxParameterCount = cpu_to_le16(4);
	pSMB->MaxDataCount = cpu_to_le16(100);	/* BB find exact max SMB PDU from sess structure BB */
	pSMB->SetupCount = 1;
	pSMB->Reserved3 = 0;
	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
	byte_count = 1 /* pad */ + params + 12;

	pSMB->DataCount = cpu_to_le16(12);
	pSMB->ParameterCount = cpu_to_le16(params);
	pSMB->TotalDataCount = pSMB->DataCount;
	pSMB->TotalParameterCount = pSMB->ParameterCount;
	pSMB->ParameterOffset = cpu_to_le16(param_offset);
	pSMB->DataOffset = cpu_to_le16(offset);

	/* Params. */
	pSMB->FileNum = 0;
	pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);

	/* Data. */
	pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
	pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
	pSMB->ClientUnixCap = cpu_to_le64(cap);

	pSMB->hdr.smb_buf_length += byte_count;
	pSMB->ByteCount = cpu_to_le16(byte_count);

	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
	if (rc) {
		cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
	} else {		/* decode response */
		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
		if (rc) {
			rc = -EIO;	/* bad smb */
		}
	}
	cifs_buf_release(pSMB);

	if (rc == -EAGAIN)
		goto SETFSUnixRetry;

	return rc;
}



int
CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
Loading