Merge branch 'for-linus' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "A set of cifs fixes (mostly for symlinks, and SMB2 xattrs) and cleanups" * 'for-linus' of git://git.samba.org/sfrench/cifs-2.6: cifs: Fix check for regular file in couldbe_mf_symlink() [CIFS] Fix SMB2 mounts so they don't try to set or get xattrs via cifs CIFS: Cleanup cifs open codepath CIFS: Remove extra indentation in cifs_sfu_type CIFS: Cleanup cifs_mknod CIFS: Cleanup CIFSSMBOpen cifs: Add support for follow_link on dfs shares under posix extensions cifs: move unix extension call to cifs_query_symlink() cifs: Re-order M-F Symlink code cifs: Add create MFSymlinks to protocol ops struct cifs: use protocol specific call for query_mf_symlink() cifs: Rename MF symlink function names cifs: Rename and cleanup open_query_close_cifs_symlink() cifs: Fix memory leak in cifs_hardlink()
This commit is contained in:
commit
0f44bc36ba
@ -895,9 +895,10 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
|
|||||||
int oplock = 0;
|
int oplock = 0;
|
||||||
unsigned int xid;
|
unsigned int xid;
|
||||||
int rc, create_options = 0;
|
int rc, create_options = 0;
|
||||||
__u16 fid;
|
|
||||||
struct cifs_tcon *tcon;
|
struct cifs_tcon *tcon;
|
||||||
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
||||||
|
struct cifs_fid fid;
|
||||||
|
struct cifs_open_parms oparms;
|
||||||
|
|
||||||
if (IS_ERR(tlink))
|
if (IS_ERR(tlink))
|
||||||
return ERR_CAST(tlink);
|
return ERR_CAST(tlink);
|
||||||
@ -908,12 +909,19 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
|
|||||||
if (backup_cred(cifs_sb))
|
if (backup_cred(cifs_sb))
|
||||||
create_options |= CREATE_OPEN_BACKUP_INTENT;
|
create_options |= CREATE_OPEN_BACKUP_INTENT;
|
||||||
|
|
||||||
rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL,
|
oparms.tcon = tcon;
|
||||||
create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
|
oparms.cifs_sb = cifs_sb;
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
oparms.desired_access = READ_CONTROL;
|
||||||
|
oparms.create_options = create_options;
|
||||||
|
oparms.disposition = FILE_OPEN;
|
||||||
|
oparms.path = path;
|
||||||
|
oparms.fid = &fid;
|
||||||
|
oparms.reconnect = false;
|
||||||
|
|
||||||
|
rc = CIFS_open(xid, &oparms, &oplock, NULL);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
|
rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
|
||||||
CIFSSMBClose(xid, tcon, fid);
|
CIFSSMBClose(xid, tcon, fid.netfid);
|
||||||
}
|
}
|
||||||
|
|
||||||
cifs_put_tlink(tlink);
|
cifs_put_tlink(tlink);
|
||||||
@ -950,10 +958,11 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
|
|||||||
int oplock = 0;
|
int oplock = 0;
|
||||||
unsigned int xid;
|
unsigned int xid;
|
||||||
int rc, access_flags, create_options = 0;
|
int rc, access_flags, create_options = 0;
|
||||||
__u16 fid;
|
|
||||||
struct cifs_tcon *tcon;
|
struct cifs_tcon *tcon;
|
||||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||||
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
||||||
|
struct cifs_fid fid;
|
||||||
|
struct cifs_open_parms oparms;
|
||||||
|
|
||||||
if (IS_ERR(tlink))
|
if (IS_ERR(tlink))
|
||||||
return PTR_ERR(tlink);
|
return PTR_ERR(tlink);
|
||||||
@ -969,18 +978,25 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
|
|||||||
else
|
else
|
||||||
access_flags = WRITE_DAC;
|
access_flags = WRITE_DAC;
|
||||||
|
|
||||||
rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags,
|
oparms.tcon = tcon;
|
||||||
create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
|
oparms.cifs_sb = cifs_sb;
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
oparms.desired_access = access_flags;
|
||||||
|
oparms.create_options = create_options;
|
||||||
|
oparms.disposition = FILE_OPEN;
|
||||||
|
oparms.path = path;
|
||||||
|
oparms.fid = &fid;
|
||||||
|
oparms.reconnect = false;
|
||||||
|
|
||||||
|
rc = CIFS_open(xid, &oparms, &oplock, NULL);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cifs_dbg(VFS, "Unable to open file to set ACL\n");
|
cifs_dbg(VFS, "Unable to open file to set ACL\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag);
|
rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
|
||||||
cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
|
cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
|
||||||
|
|
||||||
CIFSSMBClose(xid, tcon, fid);
|
CIFSSMBClose(xid, tcon, fid.netfid);
|
||||||
out:
|
out:
|
||||||
free_xid(xid);
|
free_xid(xid);
|
||||||
cifs_put_tlink(tlink);
|
cifs_put_tlink(tlink);
|
||||||
|
@ -370,8 +370,12 @@ struct smb_version_operations {
|
|||||||
void (*new_lease_key)(struct cifs_fid *);
|
void (*new_lease_key)(struct cifs_fid *);
|
||||||
int (*generate_signingkey)(struct cifs_ses *);
|
int (*generate_signingkey)(struct cifs_ses *);
|
||||||
int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *);
|
int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *);
|
||||||
int (*query_mf_symlink)(const unsigned char *, char *, unsigned int *,
|
int (*query_mf_symlink)(unsigned int, struct cifs_tcon *,
|
||||||
struct cifs_sb_info *, unsigned int);
|
struct cifs_sb_info *, const unsigned char *,
|
||||||
|
char *, unsigned int *);
|
||||||
|
int (*create_mf_symlink)(unsigned int, struct cifs_tcon *,
|
||||||
|
struct cifs_sb_info *, const unsigned char *,
|
||||||
|
char *, unsigned int *);
|
||||||
/* if we can do cache read operations */
|
/* if we can do cache read operations */
|
||||||
bool (*is_read_op)(__u32);
|
bool (*is_read_op)(__u32);
|
||||||
/* set oplock level for the inode */
|
/* set oplock level for the inode */
|
||||||
@ -385,6 +389,12 @@ struct smb_version_operations {
|
|||||||
struct cifsFileInfo *target_file, u64 src_off, u64 len,
|
struct cifsFileInfo *target_file, u64 src_off, u64 len,
|
||||||
u64 dest_off);
|
u64 dest_off);
|
||||||
int (*validate_negotiate)(const unsigned int, struct cifs_tcon *);
|
int (*validate_negotiate)(const unsigned int, struct cifs_tcon *);
|
||||||
|
ssize_t (*query_all_EAs)(const unsigned int, struct cifs_tcon *,
|
||||||
|
const unsigned char *, const unsigned char *, char *,
|
||||||
|
size_t, const struct nls_table *, int);
|
||||||
|
int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
|
||||||
|
const char *, const void *, const __u16,
|
||||||
|
const struct nls_table *, int);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct smb_version_values {
|
struct smb_version_values {
|
||||||
|
@ -362,11 +362,8 @@ extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
const struct nls_table *nls_codepage);
|
const struct nls_table *nls_codepage);
|
||||||
extern int CIFSSMB_set_compression(const unsigned int xid,
|
extern int CIFSSMB_set_compression(const unsigned int xid,
|
||||||
struct cifs_tcon *tcon, __u16 fid);
|
struct cifs_tcon *tcon, __u16 fid);
|
||||||
extern int CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms,
|
||||||
const char *fileName, const int disposition,
|
int *oplock, FILE_ALL_INFO *buf);
|
||||||
const int access_flags, const int omode,
|
|
||||||
__u16 *netfid, int *pOplock, FILE_ALL_INFO *,
|
|
||||||
const struct nls_table *nls_codepage, int remap);
|
|
||||||
extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
const char *fileName, const int disposition,
|
const char *fileName, const int disposition,
|
||||||
const int access_flags, const int omode,
|
const int access_flags, const int omode,
|
||||||
@ -476,8 +473,8 @@ extern int CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
|
const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
|
||||||
extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
|
extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
|
||||||
extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr);
|
extern bool couldbe_mf_symlink(const struct cifs_fattr *fattr);
|
||||||
extern int CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
|
extern int check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
|
||||||
struct cifs_sb_info *cifs_sb,
|
struct cifs_sb_info *cifs_sb,
|
||||||
struct cifs_fattr *fattr,
|
struct cifs_fattr *fattr,
|
||||||
const unsigned char *path);
|
const unsigned char *path);
|
||||||
@ -496,7 +493,12 @@ void cifs_writev_complete(struct work_struct *work);
|
|||||||
struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages,
|
struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages,
|
||||||
work_func_t complete);
|
work_func_t complete);
|
||||||
void cifs_writedata_release(struct kref *refcount);
|
void cifs_writedata_release(struct kref *refcount);
|
||||||
int open_query_close_cifs_symlink(const unsigned char *path, char *pbuf,
|
int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
|
||||||
unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb,
|
struct cifs_sb_info *cifs_sb,
|
||||||
unsigned int xid);
|
const unsigned char *path, char *pbuf,
|
||||||
|
unsigned int *pbytes_read);
|
||||||
|
int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
struct cifs_sb_info *cifs_sb,
|
||||||
|
const unsigned char *path, char *pbuf,
|
||||||
|
unsigned int *pbytes_written);
|
||||||
#endif /* _CIFSPROTO_H */
|
#endif /* _CIFSPROTO_H */
|
||||||
|
@ -1273,104 +1273,124 @@ OldOpenRetry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
|
CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
|
||||||
const char *fileName, const int openDisposition,
|
FILE_ALL_INFO *buf)
|
||||||
const int access_flags, const int create_options, __u16 *netfid,
|
|
||||||
int *pOplock, FILE_ALL_INFO *pfile_info,
|
|
||||||
const struct nls_table *nls_codepage, int remap)
|
|
||||||
{
|
{
|
||||||
int rc = -EACCES;
|
int rc = -EACCES;
|
||||||
OPEN_REQ *pSMB = NULL;
|
OPEN_REQ *req = NULL;
|
||||||
OPEN_RSP *pSMBr = NULL;
|
OPEN_RSP *rsp = NULL;
|
||||||
int bytes_returned;
|
int bytes_returned;
|
||||||
int name_len;
|
int name_len;
|
||||||
__u16 count;
|
__u16 count;
|
||||||
|
struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
|
||||||
|
struct cifs_tcon *tcon = oparms->tcon;
|
||||||
|
int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
|
||||||
|
const struct nls_table *nls = cifs_sb->local_nls;
|
||||||
|
int create_options = oparms->create_options;
|
||||||
|
int desired_access = oparms->desired_access;
|
||||||
|
int disposition = oparms->disposition;
|
||||||
|
const char *path = oparms->path;
|
||||||
|
|
||||||
openRetry:
|
openRetry:
|
||||||
rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
|
rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
|
||||||
(void **) &pSMBr);
|
(void **)&rsp);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
pSMB->AndXCommand = 0xFF; /* none */
|
/* no commands go after this */
|
||||||
|
req->AndXCommand = 0xFF;
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
count = 1; /* account for one byte pad to word boundary */
|
/* account for one byte pad to word boundary */
|
||||||
name_len =
|
count = 1;
|
||||||
cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
|
name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
|
||||||
fileName, PATH_MAX, nls_codepage, remap);
|
path, PATH_MAX, nls, remap);
|
||||||
name_len++; /* trailing null */
|
/* trailing null */
|
||||||
|
name_len++;
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
pSMB->NameLength = cpu_to_le16(name_len);
|
req->NameLength = cpu_to_le16(name_len);
|
||||||
} else { /* BB improve check for buffer overruns BB */
|
} else {
|
||||||
count = 0; /* no pad */
|
/* BB improve check for buffer overruns BB */
|
||||||
name_len = strnlen(fileName, PATH_MAX);
|
/* no pad */
|
||||||
name_len++; /* trailing null */
|
count = 0;
|
||||||
pSMB->NameLength = cpu_to_le16(name_len);
|
name_len = strnlen(path, PATH_MAX);
|
||||||
strncpy(pSMB->fileName, fileName, name_len);
|
/* trailing null */
|
||||||
|
name_len++;
|
||||||
|
req->NameLength = cpu_to_le16(name_len);
|
||||||
|
strncpy(req->fileName, path, name_len);
|
||||||
}
|
}
|
||||||
if (*pOplock & REQ_OPLOCK)
|
|
||||||
pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
|
|
||||||
else if (*pOplock & REQ_BATCHOPLOCK)
|
|
||||||
pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
|
|
||||||
pSMB->DesiredAccess = cpu_to_le32(access_flags);
|
|
||||||
pSMB->AllocationSize = 0;
|
|
||||||
/* set file as system file if special file such
|
|
||||||
as fifo and server expecting SFU style and
|
|
||||||
no Unix extensions */
|
|
||||||
if (create_options & CREATE_OPTION_SPECIAL)
|
|
||||||
pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
|
|
||||||
else
|
|
||||||
pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
|
|
||||||
|
|
||||||
/* XP does not handle ATTR_POSIX_SEMANTICS */
|
if (*oplock & REQ_OPLOCK)
|
||||||
/* but it helps speed up case sensitive checks for other
|
req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
|
||||||
servers such as Samba */
|
else if (*oplock & REQ_BATCHOPLOCK)
|
||||||
|
req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
|
||||||
|
|
||||||
|
req->DesiredAccess = cpu_to_le32(desired_access);
|
||||||
|
req->AllocationSize = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set file as system file if special file such as fifo and server
|
||||||
|
* expecting SFU style and no Unix extensions.
|
||||||
|
*/
|
||||||
|
if (create_options & CREATE_OPTION_SPECIAL)
|
||||||
|
req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
|
||||||
|
else
|
||||||
|
req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
|
||||||
|
* sensitive checks for other servers such as Samba.
|
||||||
|
*/
|
||||||
if (tcon->ses->capabilities & CAP_UNIX)
|
if (tcon->ses->capabilities & CAP_UNIX)
|
||||||
pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
|
req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
|
||||||
|
|
||||||
if (create_options & CREATE_OPTION_READONLY)
|
if (create_options & CREATE_OPTION_READONLY)
|
||||||
pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
|
req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
|
||||||
|
|
||||||
|
req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
|
||||||
|
req->CreateDisposition = cpu_to_le32(disposition);
|
||||||
|
req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
|
||||||
|
|
||||||
pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
|
|
||||||
pSMB->CreateDisposition = cpu_to_le32(openDisposition);
|
|
||||||
pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
|
|
||||||
/* BB Expirement with various impersonation levels and verify */
|
/* BB Expirement with various impersonation levels and verify */
|
||||||
pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
|
req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
|
||||||
pSMB->SecurityFlags =
|
req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
|
||||||
SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
|
|
||||||
|
|
||||||
count += name_len;
|
count += name_len;
|
||||||
inc_rfc1001_len(pSMB, count);
|
inc_rfc1001_len(req, count);
|
||||||
|
|
||||||
pSMB->ByteCount = cpu_to_le16(count);
|
req->ByteCount = cpu_to_le16(count);
|
||||||
/* long_op set to 1 to allow for oplock break timeouts */
|
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
|
||||||
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
|
(struct smb_hdr *)rsp, &bytes_returned, 0);
|
||||||
(struct smb_hdr *)pSMBr, &bytes_returned, 0);
|
|
||||||
cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
|
cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cifs_dbg(FYI, "Error in Open = %d\n", rc);
|
cifs_dbg(FYI, "Error in Open = %d\n", rc);
|
||||||
} else {
|
cifs_buf_release(req);
|
||||||
*pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
|
if (rc == -EAGAIN)
|
||||||
*netfid = pSMBr->Fid; /* cifs fid stays in le */
|
goto openRetry;
|
||||||
/* Let caller know file was created so we can set the mode. */
|
return rc;
|
||||||
/* Do we care about the CreateAction in any other cases? */
|
|
||||||
if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
|
|
||||||
*pOplock |= CIFS_CREATE_ACTION;
|
|
||||||
if (pfile_info) {
|
|
||||||
memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
|
|
||||||
36 /* CreationTime to Attributes */);
|
|
||||||
/* the file_info buf is endian converted by caller */
|
|
||||||
pfile_info->AllocationSize = pSMBr->AllocationSize;
|
|
||||||
pfile_info->EndOfFile = pSMBr->EndOfFile;
|
|
||||||
pfile_info->NumberOfLinks = cpu_to_le32(1);
|
|
||||||
pfile_info->DeletePending = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cifs_buf_release(pSMB);
|
/* 1 byte no need to le_to_cpu */
|
||||||
if (rc == -EAGAIN)
|
*oplock = rsp->OplockLevel;
|
||||||
goto openRetry;
|
/* cifs fid stays in le */
|
||||||
|
oparms->fid->netfid = rsp->Fid;
|
||||||
|
|
||||||
|
/* Let caller know file was created so we can set the mode. */
|
||||||
|
/* Do we care about the CreateAction in any other cases? */
|
||||||
|
if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
|
||||||
|
*oplock |= CIFS_CREATE_ACTION;
|
||||||
|
|
||||||
|
if (buf) {
|
||||||
|
/* copy from CreationTime to Attributes */
|
||||||
|
memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
|
||||||
|
/* the file_info buf is endian converted by caller */
|
||||||
|
buf->AllocationSize = rsp->AllocationSize;
|
||||||
|
buf->EndOfFile = rsp->EndOfFile;
|
||||||
|
buf->NumberOfLinks = cpu_to_le32(1);
|
||||||
|
buf->DeletePending = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cifs_buf_release(req);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,12 +565,13 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
|
|||||||
int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL;
|
int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct tcon_link *tlink;
|
struct tcon_link *tlink;
|
||||||
struct cifs_tcon *pTcon;
|
struct cifs_tcon *tcon;
|
||||||
struct cifs_io_parms io_parms;
|
struct cifs_io_parms io_parms;
|
||||||
char *full_path = NULL;
|
char *full_path = NULL;
|
||||||
struct inode *newinode = NULL;
|
struct inode *newinode = NULL;
|
||||||
int oplock = 0;
|
int oplock = 0;
|
||||||
u16 fileHandle;
|
struct cifs_fid fid;
|
||||||
|
struct cifs_open_parms oparms;
|
||||||
FILE_ALL_INFO *buf = NULL;
|
FILE_ALL_INFO *buf = NULL;
|
||||||
unsigned int bytes_written;
|
unsigned int bytes_written;
|
||||||
struct win_dev *pdev;
|
struct win_dev *pdev;
|
||||||
@ -583,7 +584,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
|
|||||||
if (IS_ERR(tlink))
|
if (IS_ERR(tlink))
|
||||||
return PTR_ERR(tlink);
|
return PTR_ERR(tlink);
|
||||||
|
|
||||||
pTcon = tlink_tcon(tlink);
|
tcon = tlink_tcon(tlink);
|
||||||
|
|
||||||
xid = get_xid();
|
xid = get_xid();
|
||||||
|
|
||||||
@ -593,7 +594,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
|
|||||||
goto mknod_out;
|
goto mknod_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pTcon->unix_ext) {
|
if (tcon->unix_ext) {
|
||||||
struct cifs_unix_set_info_args args = {
|
struct cifs_unix_set_info_args args = {
|
||||||
.mode = mode & ~current_umask(),
|
.mode = mode & ~current_umask(),
|
||||||
.ctime = NO_CHANGE_64,
|
.ctime = NO_CHANGE_64,
|
||||||
@ -608,7 +609,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
|
|||||||
args.uid = INVALID_UID; /* no change */
|
args.uid = INVALID_UID; /* no change */
|
||||||
args.gid = INVALID_GID; /* no change */
|
args.gid = INVALID_GID; /* no change */
|
||||||
}
|
}
|
||||||
rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
|
rc = CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
@ -640,42 +641,44 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
|
|||||||
if (backup_cred(cifs_sb))
|
if (backup_cred(cifs_sb))
|
||||||
create_options |= CREATE_OPEN_BACKUP_INTENT;
|
create_options |= CREATE_OPEN_BACKUP_INTENT;
|
||||||
|
|
||||||
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE,
|
oparms.tcon = tcon;
|
||||||
GENERIC_WRITE, create_options,
|
oparms.cifs_sb = cifs_sb;
|
||||||
&fileHandle, &oplock, buf, cifs_sb->local_nls,
|
oparms.desired_access = GENERIC_WRITE;
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
oparms.create_options = create_options;
|
||||||
|
oparms.disposition = FILE_CREATE;
|
||||||
|
oparms.path = full_path;
|
||||||
|
oparms.fid = &fid;
|
||||||
|
oparms.reconnect = false;
|
||||||
|
|
||||||
|
rc = CIFS_open(xid, &oparms, &oplock, buf);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto mknod_out;
|
goto mknod_out;
|
||||||
|
|
||||||
/* BB Do not bother to decode buf since no local inode yet to put
|
/*
|
||||||
* timestamps in, but we can reuse it safely */
|
* BB Do not bother to decode buf since no local inode yet to put
|
||||||
|
* timestamps in, but we can reuse it safely.
|
||||||
|
*/
|
||||||
|
|
||||||
pdev = (struct win_dev *)buf;
|
pdev = (struct win_dev *)buf;
|
||||||
io_parms.netfid = fileHandle;
|
io_parms.netfid = fid.netfid;
|
||||||
io_parms.pid = current->tgid;
|
io_parms.pid = current->tgid;
|
||||||
io_parms.tcon = pTcon;
|
io_parms.tcon = tcon;
|
||||||
io_parms.offset = 0;
|
io_parms.offset = 0;
|
||||||
io_parms.length = sizeof(struct win_dev);
|
io_parms.length = sizeof(struct win_dev);
|
||||||
if (S_ISCHR(mode)) {
|
if (S_ISCHR(mode)) {
|
||||||
memcpy(pdev->type, "IntxCHR", 8);
|
memcpy(pdev->type, "IntxCHR", 8);
|
||||||
pdev->major =
|
pdev->major = cpu_to_le64(MAJOR(device_number));
|
||||||
cpu_to_le64(MAJOR(device_number));
|
pdev->minor = cpu_to_le64(MINOR(device_number));
|
||||||
pdev->minor =
|
rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev,
|
||||||
cpu_to_le64(MINOR(device_number));
|
NULL, 0);
|
||||||
rc = CIFSSMBWrite(xid, &io_parms,
|
|
||||||
&bytes_written, (char *)pdev,
|
|
||||||
NULL, 0);
|
|
||||||
} else if (S_ISBLK(mode)) {
|
} else if (S_ISBLK(mode)) {
|
||||||
memcpy(pdev->type, "IntxBLK", 8);
|
memcpy(pdev->type, "IntxBLK", 8);
|
||||||
pdev->major =
|
pdev->major = cpu_to_le64(MAJOR(device_number));
|
||||||
cpu_to_le64(MAJOR(device_number));
|
pdev->minor = cpu_to_le64(MINOR(device_number));
|
||||||
pdev->minor =
|
rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev,
|
||||||
cpu_to_le64(MINOR(device_number));
|
NULL, 0);
|
||||||
rc = CIFSSMBWrite(xid, &io_parms,
|
|
||||||
&bytes_written, (char *)pdev,
|
|
||||||
NULL, 0);
|
|
||||||
} /* else if (S_ISFIFO) */
|
} /* else if (S_ISFIFO) */
|
||||||
CIFSSMBClose(xid, pTcon, fileHandle);
|
CIFSSMBClose(xid, tcon, fid.netfid);
|
||||||
d_drop(direntry);
|
d_drop(direntry);
|
||||||
|
|
||||||
/* FIXME: add code here to set EAs */
|
/* FIXME: add code here to set EAs */
|
||||||
|
@ -678,7 +678,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Can not refresh inode by passing in file_info buf to be returned by
|
* Can not refresh inode by passing in file_info buf to be returned by
|
||||||
* CIFSSMBOpen and then calling get_inode_info with returned buf since
|
* ops->open and then calling get_inode_info with returned buf since
|
||||||
* file might have write behind data that needs to be flushed and server
|
* file might have write behind data that needs to be flushed and server
|
||||||
* version of file size can be stale. If we knew for sure that inode was
|
* version of file size can be stale. If we knew for sure that inode was
|
||||||
* not dirty locally we could do this.
|
* not dirty locally we could do this.
|
||||||
|
186
fs/cifs/inode.c
186
fs/cifs/inode.c
@ -383,10 +383,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||||||
|
|
||||||
/* check for Minshall+French symlinks */
|
/* check for Minshall+French symlinks */
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
|
||||||
int tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr,
|
int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
|
||||||
full_path);
|
full_path);
|
||||||
if (tmprc)
|
if (tmprc)
|
||||||
cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
|
cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*pinode == NULL) {
|
if (*pinode == NULL) {
|
||||||
@ -404,18 +404,20 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
|
cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
|
||||||
struct cifs_sb_info *cifs_sb, unsigned int xid)
|
struct cifs_sb_info *cifs_sb, unsigned int xid)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
int oplock = 0;
|
int oplock = 0;
|
||||||
__u16 netfid;
|
|
||||||
struct tcon_link *tlink;
|
struct tcon_link *tlink;
|
||||||
struct cifs_tcon *tcon;
|
struct cifs_tcon *tcon;
|
||||||
|
struct cifs_fid fid;
|
||||||
|
struct cifs_open_parms oparms;
|
||||||
struct cifs_io_parms io_parms;
|
struct cifs_io_parms io_parms;
|
||||||
char buf[24];
|
char buf[24];
|
||||||
unsigned int bytes_read;
|
unsigned int bytes_read;
|
||||||
char *pbuf;
|
char *pbuf;
|
||||||
|
int buf_type = CIFS_NO_BUFFER;
|
||||||
|
|
||||||
pbuf = buf;
|
pbuf = buf;
|
||||||
|
|
||||||
@ -436,62 +438,69 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
|
|||||||
return PTR_ERR(tlink);
|
return PTR_ERR(tlink);
|
||||||
tcon = tlink_tcon(tlink);
|
tcon = tlink_tcon(tlink);
|
||||||
|
|
||||||
rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
|
oparms.tcon = tcon;
|
||||||
CREATE_NOT_DIR, &netfid, &oplock, NULL,
|
oparms.cifs_sb = cifs_sb;
|
||||||
cifs_sb->local_nls,
|
oparms.desired_access = GENERIC_READ;
|
||||||
cifs_sb->mnt_cifs_flags &
|
oparms.create_options = CREATE_NOT_DIR;
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
oparms.disposition = FILE_OPEN;
|
||||||
if (rc == 0) {
|
oparms.path = path;
|
||||||
int buf_type = CIFS_NO_BUFFER;
|
oparms.fid = &fid;
|
||||||
/* Read header */
|
oparms.reconnect = false;
|
||||||
io_parms.netfid = netfid;
|
|
||||||
io_parms.pid = current->tgid;
|
rc = CIFS_open(xid, &oparms, &oplock, NULL);
|
||||||
io_parms.tcon = tcon;
|
if (rc) {
|
||||||
io_parms.offset = 0;
|
cifs_put_tlink(tlink);
|
||||||
io_parms.length = 24;
|
return rc;
|
||||||
rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf,
|
|
||||||
&buf_type);
|
|
||||||
if ((rc == 0) && (bytes_read >= 8)) {
|
|
||||||
if (memcmp("IntxBLK", pbuf, 8) == 0) {
|
|
||||||
cifs_dbg(FYI, "Block device\n");
|
|
||||||
fattr->cf_mode |= S_IFBLK;
|
|
||||||
fattr->cf_dtype = DT_BLK;
|
|
||||||
if (bytes_read == 24) {
|
|
||||||
/* we have enough to decode dev num */
|
|
||||||
__u64 mjr; /* major */
|
|
||||||
__u64 mnr; /* minor */
|
|
||||||
mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
|
|
||||||
mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
|
|
||||||
fattr->cf_rdev = MKDEV(mjr, mnr);
|
|
||||||
}
|
|
||||||
} else if (memcmp("IntxCHR", pbuf, 8) == 0) {
|
|
||||||
cifs_dbg(FYI, "Char device\n");
|
|
||||||
fattr->cf_mode |= S_IFCHR;
|
|
||||||
fattr->cf_dtype = DT_CHR;
|
|
||||||
if (bytes_read == 24) {
|
|
||||||
/* we have enough to decode dev num */
|
|
||||||
__u64 mjr; /* major */
|
|
||||||
__u64 mnr; /* minor */
|
|
||||||
mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
|
|
||||||
mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
|
|
||||||
fattr->cf_rdev = MKDEV(mjr, mnr);
|
|
||||||
}
|
|
||||||
} else if (memcmp("IntxLNK", pbuf, 7) == 0) {
|
|
||||||
cifs_dbg(FYI, "Symlink\n");
|
|
||||||
fattr->cf_mode |= S_IFLNK;
|
|
||||||
fattr->cf_dtype = DT_LNK;
|
|
||||||
} else {
|
|
||||||
fattr->cf_mode |= S_IFREG; /* file? */
|
|
||||||
fattr->cf_dtype = DT_REG;
|
|
||||||
rc = -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fattr->cf_mode |= S_IFREG; /* then it is a file */
|
|
||||||
fattr->cf_dtype = DT_REG;
|
|
||||||
rc = -EOPNOTSUPP; /* or some unknown SFU type */
|
|
||||||
}
|
|
||||||
CIFSSMBClose(xid, tcon, netfid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read header */
|
||||||
|
io_parms.netfid = fid.netfid;
|
||||||
|
io_parms.pid = current->tgid;
|
||||||
|
io_parms.tcon = tcon;
|
||||||
|
io_parms.offset = 0;
|
||||||
|
io_parms.length = 24;
|
||||||
|
|
||||||
|
rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type);
|
||||||
|
if ((rc == 0) && (bytes_read >= 8)) {
|
||||||
|
if (memcmp("IntxBLK", pbuf, 8) == 0) {
|
||||||
|
cifs_dbg(FYI, "Block device\n");
|
||||||
|
fattr->cf_mode |= S_IFBLK;
|
||||||
|
fattr->cf_dtype = DT_BLK;
|
||||||
|
if (bytes_read == 24) {
|
||||||
|
/* we have enough to decode dev num */
|
||||||
|
__u64 mjr; /* major */
|
||||||
|
__u64 mnr; /* minor */
|
||||||
|
mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
|
||||||
|
mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
|
||||||
|
fattr->cf_rdev = MKDEV(mjr, mnr);
|
||||||
|
}
|
||||||
|
} else if (memcmp("IntxCHR", pbuf, 8) == 0) {
|
||||||
|
cifs_dbg(FYI, "Char device\n");
|
||||||
|
fattr->cf_mode |= S_IFCHR;
|
||||||
|
fattr->cf_dtype = DT_CHR;
|
||||||
|
if (bytes_read == 24) {
|
||||||
|
/* we have enough to decode dev num */
|
||||||
|
__u64 mjr; /* major */
|
||||||
|
__u64 mnr; /* minor */
|
||||||
|
mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
|
||||||
|
mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
|
||||||
|
fattr->cf_rdev = MKDEV(mjr, mnr);
|
||||||
|
}
|
||||||
|
} else if (memcmp("IntxLNK", pbuf, 7) == 0) {
|
||||||
|
cifs_dbg(FYI, "Symlink\n");
|
||||||
|
fattr->cf_mode |= S_IFLNK;
|
||||||
|
fattr->cf_dtype = DT_LNK;
|
||||||
|
} else {
|
||||||
|
fattr->cf_mode |= S_IFREG; /* file? */
|
||||||
|
fattr->cf_dtype = DT_REG;
|
||||||
|
rc = -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fattr->cf_mode |= S_IFREG; /* then it is a file */
|
||||||
|
fattr->cf_dtype = DT_REG;
|
||||||
|
rc = -EOPNOTSUPP; /* or some unknown SFU type */
|
||||||
|
}
|
||||||
|
CIFSSMBClose(xid, tcon, fid.netfid);
|
||||||
cifs_put_tlink(tlink);
|
cifs_put_tlink(tlink);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -800,10 +809,10 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
|
|||||||
|
|
||||||
/* check for Minshall+French symlinks */
|
/* check for Minshall+French symlinks */
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
|
||||||
tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr,
|
tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
|
||||||
full_path);
|
full_path);
|
||||||
if (tmprc)
|
if (tmprc)
|
||||||
cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
|
cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!*inode) {
|
if (!*inode) {
|
||||||
@ -1032,7 +1041,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
|
|||||||
{
|
{
|
||||||
int oplock = 0;
|
int oplock = 0;
|
||||||
int rc;
|
int rc;
|
||||||
__u16 netfid;
|
struct cifs_fid fid;
|
||||||
|
struct cifs_open_parms oparms;
|
||||||
struct inode *inode = dentry->d_inode;
|
struct inode *inode = dentry->d_inode;
|
||||||
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
|
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
|
||||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||||
@ -1055,10 +1065,16 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
|
oparms.tcon = tcon;
|
||||||
DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
|
oparms.cifs_sb = cifs_sb;
|
||||||
&netfid, &oplock, NULL, cifs_sb->local_nls,
|
oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
oparms.create_options = CREATE_NOT_DIR;
|
||||||
|
oparms.disposition = FILE_OPEN;
|
||||||
|
oparms.path = full_path;
|
||||||
|
oparms.fid = &fid;
|
||||||
|
oparms.reconnect = false;
|
||||||
|
|
||||||
|
rc = CIFS_open(xid, &oparms, &oplock, NULL);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -1079,7 +1095,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
|
|||||||
goto out_close;
|
goto out_close;
|
||||||
}
|
}
|
||||||
info_buf->Attributes = cpu_to_le32(dosattr);
|
info_buf->Attributes = cpu_to_le32(dosattr);
|
||||||
rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
|
rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
|
||||||
current->tgid);
|
current->tgid);
|
||||||
/* although we would like to mark the file hidden
|
/* although we would like to mark the file hidden
|
||||||
if that fails we will still try to rename it */
|
if that fails we will still try to rename it */
|
||||||
@ -1090,7 +1106,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* rename the file */
|
/* rename the file */
|
||||||
rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
|
rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
|
||||||
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
@ -1100,7 +1117,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
|
|||||||
|
|
||||||
/* try to set DELETE_ON_CLOSE */
|
/* try to set DELETE_ON_CLOSE */
|
||||||
if (!cifsInode->delete_pending) {
|
if (!cifsInode->delete_pending) {
|
||||||
rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid,
|
rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
|
||||||
current->tgid);
|
current->tgid);
|
||||||
/*
|
/*
|
||||||
* some samba versions return -ENOENT when we try to set the
|
* some samba versions return -ENOENT when we try to set the
|
||||||
@ -1120,7 +1137,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
|
|||||||
}
|
}
|
||||||
|
|
||||||
out_close:
|
out_close:
|
||||||
CIFSSMBClose(xid, tcon, netfid);
|
CIFSSMBClose(xid, tcon, fid.netfid);
|
||||||
out:
|
out:
|
||||||
kfree(info_buf);
|
kfree(info_buf);
|
||||||
cifs_put_tlink(tlink);
|
cifs_put_tlink(tlink);
|
||||||
@ -1132,13 +1149,13 @@ out:
|
|||||||
* them anyway.
|
* them anyway.
|
||||||
*/
|
*/
|
||||||
undo_rename:
|
undo_rename:
|
||||||
CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name,
|
CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
|
||||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
undo_setattr:
|
undo_setattr:
|
||||||
if (dosattr != origattr) {
|
if (dosattr != origattr) {
|
||||||
info_buf->Attributes = cpu_to_le32(origattr);
|
info_buf->Attributes = cpu_to_le32(origattr);
|
||||||
if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
|
if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
|
||||||
current->tgid))
|
current->tgid))
|
||||||
cifsInode->cifsAttrs = origattr;
|
cifsInode->cifsAttrs = origattr;
|
||||||
}
|
}
|
||||||
@ -1549,7 +1566,8 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
|
|||||||
struct tcon_link *tlink;
|
struct tcon_link *tlink;
|
||||||
struct cifs_tcon *tcon;
|
struct cifs_tcon *tcon;
|
||||||
struct TCP_Server_Info *server;
|
struct TCP_Server_Info *server;
|
||||||
__u16 srcfid;
|
struct cifs_fid fid;
|
||||||
|
struct cifs_open_parms oparms;
|
||||||
int oplock, rc;
|
int oplock, rc;
|
||||||
|
|
||||||
tlink = cifs_sb_tlink(cifs_sb);
|
tlink = cifs_sb_tlink(cifs_sb);
|
||||||
@ -1576,17 +1594,23 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
|
|||||||
if (to_dentry->d_parent != from_dentry->d_parent)
|
if (to_dentry->d_parent != from_dentry->d_parent)
|
||||||
goto do_rename_exit;
|
goto do_rename_exit;
|
||||||
|
|
||||||
|
oparms.tcon = tcon;
|
||||||
|
oparms.cifs_sb = cifs_sb;
|
||||||
/* open the file to be renamed -- we need DELETE perms */
|
/* open the file to be renamed -- we need DELETE perms */
|
||||||
rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE,
|
oparms.desired_access = DELETE;
|
||||||
CREATE_NOT_DIR, &srcfid, &oplock, NULL,
|
oparms.create_options = CREATE_NOT_DIR;
|
||||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
oparms.disposition = FILE_OPEN;
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
oparms.path = from_path;
|
||||||
|
oparms.fid = &fid;
|
||||||
|
oparms.reconnect = false;
|
||||||
|
|
||||||
|
rc = CIFS_open(xid, &oparms, &oplock, NULL);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid,
|
rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
|
||||||
(const char *) to_dentry->d_name.name,
|
(const char *) to_dentry->d_name.name,
|
||||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
CIFSSMBClose(xid, tcon, srcfid);
|
CIFSSMBClose(xid, tcon, fid.netfid);
|
||||||
}
|
}
|
||||||
do_rename_exit:
|
do_rename_exit:
|
||||||
cifs_put_tlink(tlink);
|
cifs_put_tlink(tlink);
|
||||||
|
345
fs/cifs/link.c
345
fs/cifs/link.c
@ -29,6 +29,10 @@
|
|||||||
#include "cifs_debug.h"
|
#include "cifs_debug.h"
|
||||||
#include "cifs_fs_sb.h"
|
#include "cifs_fs_sb.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M-F Symlink Functions - Begin
|
||||||
|
*/
|
||||||
|
|
||||||
#define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
|
#define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
|
||||||
#define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
|
#define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
|
||||||
#define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
|
#define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
|
||||||
@ -91,10 +95,8 @@ symlink_hash_err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
CIFSParseMFSymlink(const u8 *buf,
|
parse_mf_symlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len,
|
||||||
unsigned int buf_len,
|
char **_link_str)
|
||||||
unsigned int *_link_len,
|
|
||||||
char **_link_str)
|
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
unsigned int link_len;
|
unsigned int link_len;
|
||||||
@ -137,7 +139,7 @@ CIFSParseMFSymlink(const u8 *buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
|
format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
unsigned int link_len;
|
unsigned int link_len;
|
||||||
@ -180,120 +182,10 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
CIFSCreateMFSymLink(const unsigned int xid, struct cifs_tcon *tcon,
|
|
||||||
const char *fromName, const char *toName,
|
|
||||||
struct cifs_sb_info *cifs_sb)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
int oplock = 0;
|
|
||||||
int remap;
|
|
||||||
int create_options = CREATE_NOT_DIR;
|
|
||||||
__u16 netfid = 0;
|
|
||||||
u8 *buf;
|
|
||||||
unsigned int bytes_written = 0;
|
|
||||||
struct cifs_io_parms io_parms;
|
|
||||||
struct nls_table *nls_codepage;
|
|
||||||
|
|
||||||
nls_codepage = cifs_sb->local_nls;
|
|
||||||
remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
|
|
||||||
|
|
||||||
buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
|
|
||||||
if (!buf)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
rc = CIFSFormatMFSymlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
|
|
||||||
if (rc != 0) {
|
|
||||||
kfree(buf);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (backup_cred(cifs_sb))
|
|
||||||
create_options |= CREATE_OPEN_BACKUP_INTENT;
|
|
||||||
|
|
||||||
rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE,
|
|
||||||
create_options, &netfid, &oplock, NULL,
|
|
||||||
nls_codepage, remap);
|
|
||||||
if (rc != 0) {
|
|
||||||
kfree(buf);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
io_parms.netfid = netfid;
|
|
||||||
io_parms.pid = current->tgid;
|
|
||||||
io_parms.tcon = tcon;
|
|
||||||
io_parms.offset = 0;
|
|
||||||
io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
|
|
||||||
|
|
||||||
rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, buf, NULL, 0);
|
|
||||||
CIFSSMBClose(xid, tcon, netfid);
|
|
||||||
kfree(buf);
|
|
||||||
if (rc != 0)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
CIFSQueryMFSymLink(const unsigned int xid, struct cifs_tcon *tcon,
|
|
||||||
const unsigned char *searchName, char **symlinkinfo,
|
|
||||||
const struct nls_table *nls_codepage, int remap)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
int oplock = 0;
|
|
||||||
__u16 netfid = 0;
|
|
||||||
u8 *buf;
|
|
||||||
char *pbuf;
|
|
||||||
unsigned int bytes_read = 0;
|
|
||||||
int buf_type = CIFS_NO_BUFFER;
|
|
||||||
unsigned int link_len = 0;
|
|
||||||
struct cifs_io_parms io_parms;
|
|
||||||
FILE_ALL_INFO file_info;
|
|
||||||
|
|
||||||
rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ,
|
|
||||||
CREATE_NOT_DIR, &netfid, &oplock, &file_info,
|
|
||||||
nls_codepage, remap);
|
|
||||||
if (rc != 0)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
|
|
||||||
CIFSSMBClose(xid, tcon, netfid);
|
|
||||||
/* it's not a symlink */
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
|
|
||||||
if (!buf)
|
|
||||||
return -ENOMEM;
|
|
||||||
pbuf = buf;
|
|
||||||
io_parms.netfid = netfid;
|
|
||||||
io_parms.pid = current->tgid;
|
|
||||||
io_parms.tcon = tcon;
|
|
||||||
io_parms.offset = 0;
|
|
||||||
io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
|
|
||||||
|
|
||||||
rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type);
|
|
||||||
CIFSSMBClose(xid, tcon, netfid);
|
|
||||||
if (rc != 0) {
|
|
||||||
kfree(buf);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, symlinkinfo);
|
|
||||||
kfree(buf);
|
|
||||||
if (rc != 0)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr)
|
couldbe_mf_symlink(const struct cifs_fattr *fattr)
|
||||||
{
|
{
|
||||||
if (!(fattr->cf_mode & S_IFREG))
|
if (!S_ISREG(fattr->cf_mode))
|
||||||
/* it's not a symlink */
|
/* it's not a symlink */
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -304,66 +196,80 @@ CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
open_query_close_cifs_symlink(const unsigned char *path, char *pbuf,
|
create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb,
|
struct cifs_sb_info *cifs_sb, const char *fromName,
|
||||||
unsigned int xid)
|
const char *toName)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
int oplock = 0;
|
u8 *buf;
|
||||||
__u16 netfid = 0;
|
unsigned int bytes_written = 0;
|
||||||
struct tcon_link *tlink;
|
|
||||||
struct cifs_tcon *ptcon;
|
|
||||||
struct cifs_io_parms io_parms;
|
|
||||||
int buf_type = CIFS_NO_BUFFER;
|
|
||||||
FILE_ALL_INFO file_info;
|
|
||||||
|
|
||||||
tlink = cifs_sb_tlink(cifs_sb);
|
buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
|
||||||
if (IS_ERR(tlink))
|
if (!buf)
|
||||||
return PTR_ERR(tlink);
|
return -ENOMEM;
|
||||||
ptcon = tlink_tcon(tlink);
|
|
||||||
|
|
||||||
rc = CIFSSMBOpen(xid, ptcon, path, FILE_OPEN, GENERIC_READ,
|
rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
|
||||||
CREATE_NOT_DIR, &netfid, &oplock, &file_info,
|
if (rc)
|
||||||
cifs_sb->local_nls,
|
goto out;
|
||||||
cifs_sb->mnt_cifs_flags &
|
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
if (rc != 0) {
|
|
||||||
cifs_put_tlink(tlink);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
|
rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon, cifs_sb,
|
||||||
CIFSSMBClose(xid, ptcon, netfid);
|
fromName, buf, &bytes_written);
|
||||||
cifs_put_tlink(tlink);
|
if (rc)
|
||||||
/* it's not a symlink */
|
goto out;
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
io_parms.netfid = netfid;
|
if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
|
||||||
io_parms.pid = current->tgid;
|
rc = -EIO;
|
||||||
io_parms.tcon = ptcon;
|
out:
|
||||||
io_parms.offset = 0;
|
kfree(buf);
|
||||||
io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
|
|
||||||
|
|
||||||
rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
|
|
||||||
CIFSSMBClose(xid, ptcon, netfid);
|
|
||||||
cifs_put_tlink(tlink);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
int
|
query_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
|
struct cifs_sb_info *cifs_sb, const unsigned char *path,
|
||||||
struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
|
char **symlinkinfo)
|
||||||
const unsigned char *path)
|
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
u8 *buf = NULL;
|
u8 *buf = NULL;
|
||||||
unsigned int link_len = 0;
|
unsigned int link_len = 0;
|
||||||
unsigned int bytes_read = 0;
|
unsigned int bytes_read = 0;
|
||||||
|
|
||||||
if (!CIFSCouldBeMFSymlink(fattr))
|
buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
|
||||||
|
if (!buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (tcon->ses->server->ops->query_mf_symlink)
|
||||||
|
rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon,
|
||||||
|
cifs_sb, path, buf, &bytes_read);
|
||||||
|
else
|
||||||
|
rc = -ENOSYS;
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (bytes_read == 0) { /* not a symlink */
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = parse_mf_symlink(buf, bytes_read, &link_len, symlinkinfo);
|
||||||
|
out:
|
||||||
|
kfree(buf);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
|
||||||
|
const unsigned char *path)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
u8 *buf = NULL;
|
||||||
|
unsigned int link_len = 0;
|
||||||
|
unsigned int bytes_read = 0;
|
||||||
|
|
||||||
|
if (!couldbe_mf_symlink(fattr))
|
||||||
/* it's not a symlink */
|
/* it's not a symlink */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -372,8 +278,8 @@ CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (tcon->ses->server->ops->query_mf_symlink)
|
if (tcon->ses->server->ops->query_mf_symlink)
|
||||||
rc = tcon->ses->server->ops->query_mf_symlink(path, buf,
|
rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon,
|
||||||
&bytes_read, cifs_sb, xid);
|
cifs_sb, path, buf, &bytes_read);
|
||||||
else
|
else
|
||||||
rc = -ENOSYS;
|
rc = -ENOSYS;
|
||||||
|
|
||||||
@ -383,7 +289,7 @@ CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
if (bytes_read == 0) /* not a symlink */
|
if (bytes_read == 0) /* not a symlink */
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL);
|
rc = parse_mf_symlink(buf, bytes_read, &link_len, NULL);
|
||||||
if (rc == -EINVAL) {
|
if (rc == -EINVAL) {
|
||||||
/* it's not a symlink */
|
/* it's not a symlink */
|
||||||
rc = 0;
|
rc = 0;
|
||||||
@ -403,6 +309,95 @@ out:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SMB 1.0 Protocol specific functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
struct cifs_sb_info *cifs_sb, const unsigned char *path,
|
||||||
|
char *pbuf, unsigned int *pbytes_read)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
int oplock = 0;
|
||||||
|
struct cifs_fid fid;
|
||||||
|
struct cifs_open_parms oparms;
|
||||||
|
struct cifs_io_parms io_parms;
|
||||||
|
int buf_type = CIFS_NO_BUFFER;
|
||||||
|
FILE_ALL_INFO file_info;
|
||||||
|
|
||||||
|
oparms.tcon = tcon;
|
||||||
|
oparms.cifs_sb = cifs_sb;
|
||||||
|
oparms.desired_access = GENERIC_READ;
|
||||||
|
oparms.create_options = CREATE_NOT_DIR;
|
||||||
|
oparms.disposition = FILE_OPEN;
|
||||||
|
oparms.path = path;
|
||||||
|
oparms.fid = &fid;
|
||||||
|
oparms.reconnect = false;
|
||||||
|
|
||||||
|
rc = CIFS_open(xid, &oparms, &oplock, &file_info);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE))
|
||||||
|
/* it's not a symlink */
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
io_parms.netfid = fid.netfid;
|
||||||
|
io_parms.pid = current->tgid;
|
||||||
|
io_parms.tcon = tcon;
|
||||||
|
io_parms.offset = 0;
|
||||||
|
io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
|
||||||
|
|
||||||
|
rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
|
||||||
|
out:
|
||||||
|
CIFSSMBClose(xid, tcon, fid.netfid);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
struct cifs_sb_info *cifs_sb, const unsigned char *path,
|
||||||
|
char *pbuf, unsigned int *pbytes_written)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
int oplock = 0;
|
||||||
|
struct cifs_fid fid;
|
||||||
|
struct cifs_open_parms oparms;
|
||||||
|
struct cifs_io_parms io_parms;
|
||||||
|
int create_options = CREATE_NOT_DIR;
|
||||||
|
|
||||||
|
if (backup_cred(cifs_sb))
|
||||||
|
create_options |= CREATE_OPEN_BACKUP_INTENT;
|
||||||
|
|
||||||
|
oparms.tcon = tcon;
|
||||||
|
oparms.cifs_sb = cifs_sb;
|
||||||
|
oparms.desired_access = GENERIC_WRITE;
|
||||||
|
oparms.create_options = create_options;
|
||||||
|
oparms.disposition = FILE_OPEN;
|
||||||
|
oparms.path = path;
|
||||||
|
oparms.fid = &fid;
|
||||||
|
oparms.reconnect = false;
|
||||||
|
|
||||||
|
rc = CIFS_open(xid, &oparms, &oplock, NULL);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
io_parms.netfid = fid.netfid;
|
||||||
|
io_parms.pid = current->tgid;
|
||||||
|
io_parms.tcon = tcon;
|
||||||
|
io_parms.offset = 0;
|
||||||
|
io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
|
||||||
|
|
||||||
|
rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf, NULL, 0);
|
||||||
|
CIFSSMBClose(xid, tcon, fid.netfid);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M-F Symlink Functions - End
|
||||||
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
||||||
struct dentry *direntry)
|
struct dentry *direntry)
|
||||||
@ -438,8 +433,10 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
|||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
else {
|
else {
|
||||||
server = tcon->ses->server;
|
server = tcon->ses->server;
|
||||||
if (!server->ops->create_hardlink)
|
if (!server->ops->create_hardlink) {
|
||||||
return -ENOSYS;
|
rc = -ENOSYS;
|
||||||
|
goto cifs_hl_exit;
|
||||||
|
}
|
||||||
rc = server->ops->create_hardlink(xid, tcon, from_name, to_name,
|
rc = server->ops->create_hardlink(xid, tcon, from_name, to_name,
|
||||||
cifs_sb);
|
cifs_sb);
|
||||||
if ((rc == -EIO) || (rc == -EINVAL))
|
if ((rc == -EIO) || (rc == -EINVAL))
|
||||||
@ -530,15 +527,10 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
|
|||||||
* and fallback to UNIX Extensions Symlinks.
|
* and fallback to UNIX Extensions Symlinks.
|
||||||
*/
|
*/
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
|
||||||
rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path,
|
rc = query_mf_symlink(xid, tcon, cifs_sb, full_path,
|
||||||
cifs_sb->local_nls,
|
&target_path);
|
||||||
cifs_sb->mnt_cifs_flags &
|
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
|
|
||||||
if ((rc != 0) && cap_unix(tcon->ses))
|
if (rc != 0 && server->ops->query_symlink)
|
||||||
rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
|
|
||||||
cifs_sb->local_nls);
|
|
||||||
else if (rc != 0 && server->ops->query_symlink)
|
|
||||||
rc = server->ops->query_symlink(xid, tcon, full_path,
|
rc = server->ops->query_symlink(xid, tcon, full_path,
|
||||||
&target_path, cifs_sb);
|
&target_path, cifs_sb);
|
||||||
|
|
||||||
@ -587,8 +579,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
|
|||||||
|
|
||||||
/* BB what if DFS and this volume is on different share? BB */
|
/* BB what if DFS and this volume is on different share? BB */
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
|
||||||
rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname,
|
rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname);
|
||||||
cifs_sb);
|
|
||||||
else if (pTcon->unix_ext)
|
else if (pTcon->unix_ext)
|
||||||
rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
|
rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
|
||||||
cifs_sb->local_nls);
|
cifs_sb->local_nls);
|
||||||
|
@ -749,7 +749,7 @@ static int cifs_filldir(char *find_entry, struct file *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
|
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
|
||||||
CIFSCouldBeMFSymlink(&fattr))
|
couldbe_mf_symlink(&fattr))
|
||||||
/*
|
/*
|
||||||
* trying to get the type and mode can be slow,
|
* trying to get the type and mode can be slow,
|
||||||
* so just call those regular files for now, and mark
|
* so just call those regular files for now, and mark
|
||||||
|
@ -560,17 +560,24 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
if (!rc && (le32_to_cpu(data->Attributes) & ATTR_REPARSE)) {
|
if (!rc && (le32_to_cpu(data->Attributes) & ATTR_REPARSE)) {
|
||||||
int tmprc;
|
int tmprc;
|
||||||
int oplock = 0;
|
int oplock = 0;
|
||||||
__u16 netfid;
|
struct cifs_fid fid;
|
||||||
|
struct cifs_open_parms oparms;
|
||||||
|
|
||||||
|
oparms.tcon = tcon;
|
||||||
|
oparms.cifs_sb = cifs_sb;
|
||||||
|
oparms.desired_access = FILE_READ_ATTRIBUTES;
|
||||||
|
oparms.create_options = 0;
|
||||||
|
oparms.disposition = FILE_OPEN;
|
||||||
|
oparms.path = full_path;
|
||||||
|
oparms.fid = &fid;
|
||||||
|
oparms.reconnect = false;
|
||||||
|
|
||||||
/* Need to check if this is a symbolic link or not */
|
/* Need to check if this is a symbolic link or not */
|
||||||
tmprc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
|
tmprc = CIFS_open(xid, &oparms, &oplock, NULL);
|
||||||
FILE_READ_ATTRIBUTES, 0, &netfid, &oplock,
|
|
||||||
NULL, cifs_sb->local_nls,
|
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
if (tmprc == -EOPNOTSUPP)
|
if (tmprc == -EOPNOTSUPP)
|
||||||
*symlink = true;
|
*symlink = true;
|
||||||
else
|
else
|
||||||
CIFSSMBClose(xid, tcon, netfid);
|
CIFSSMBClose(xid, tcon, fid.netfid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@ -705,12 +712,7 @@ cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
|
|||||||
oparms->cifs_sb->local_nls,
|
oparms->cifs_sb->local_nls,
|
||||||
oparms->cifs_sb->mnt_cifs_flags
|
oparms->cifs_sb->mnt_cifs_flags
|
||||||
& CIFS_MOUNT_MAP_SPECIAL_CHR);
|
& CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
return CIFSSMBOpen(xid, oparms->tcon, oparms->path,
|
return CIFS_open(xid, oparms, oplock, buf);
|
||||||
oparms->disposition, oparms->desired_access,
|
|
||||||
oparms->create_options, &oparms->fid->netfid, oplock,
|
|
||||||
buf, oparms->cifs_sb->local_nls,
|
|
||||||
oparms->cifs_sb->mnt_cifs_flags &
|
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -761,8 +763,9 @@ smb_set_file_info(struct inode *inode, const char *full_path,
|
|||||||
{
|
{
|
||||||
int oplock = 0;
|
int oplock = 0;
|
||||||
int rc;
|
int rc;
|
||||||
__u16 netfid;
|
|
||||||
__u32 netpid;
|
__u32 netpid;
|
||||||
|
struct cifs_fid fid;
|
||||||
|
struct cifs_open_parms oparms;
|
||||||
struct cifsFileInfo *open_file;
|
struct cifsFileInfo *open_file;
|
||||||
struct cifsInodeInfo *cinode = CIFS_I(inode);
|
struct cifsInodeInfo *cinode = CIFS_I(inode);
|
||||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||||
@ -772,7 +775,7 @@ smb_set_file_info(struct inode *inode, const char *full_path,
|
|||||||
/* if the file is already open for write, just use that fileid */
|
/* if the file is already open for write, just use that fileid */
|
||||||
open_file = find_writable_file(cinode, true);
|
open_file = find_writable_file(cinode, true);
|
||||||
if (open_file) {
|
if (open_file) {
|
||||||
netfid = open_file->fid.netfid;
|
fid.netfid = open_file->fid.netfid;
|
||||||
netpid = open_file->pid;
|
netpid = open_file->pid;
|
||||||
tcon = tlink_tcon(open_file->tlink);
|
tcon = tlink_tcon(open_file->tlink);
|
||||||
goto set_via_filehandle;
|
goto set_via_filehandle;
|
||||||
@ -796,12 +799,17 @@ smb_set_file_info(struct inode *inode, const char *full_path,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n");
|
oparms.tcon = tcon;
|
||||||
rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
|
oparms.cifs_sb = cifs_sb;
|
||||||
SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
|
oparms.desired_access = SYNCHRONIZE | FILE_WRITE_ATTRIBUTES;
|
||||||
&netfid, &oplock, NULL, cifs_sb->local_nls,
|
oparms.create_options = CREATE_NOT_DIR;
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
oparms.disposition = FILE_OPEN;
|
||||||
|
oparms.path = full_path;
|
||||||
|
oparms.fid = &fid;
|
||||||
|
oparms.reconnect = false;
|
||||||
|
|
||||||
|
cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n");
|
||||||
|
rc = CIFS_open(xid, &oparms, &oplock, NULL);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
if (rc == -EIO)
|
if (rc == -EIO)
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
@ -811,12 +819,12 @@ smb_set_file_info(struct inode *inode, const char *full_path,
|
|||||||
netpid = current->tgid;
|
netpid = current->tgid;
|
||||||
|
|
||||||
set_via_filehandle:
|
set_via_filehandle:
|
||||||
rc = CIFSSMBSetFileInfo(xid, tcon, buf, netfid, netpid);
|
rc = CIFSSMBSetFileInfo(xid, tcon, buf, fid.netfid, netpid);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
cinode->cifsAttrs = le32_to_cpu(buf->Attributes);
|
cinode->cifsAttrs = le32_to_cpu(buf->Attributes);
|
||||||
|
|
||||||
if (open_file == NULL)
|
if (open_file == NULL)
|
||||||
CIFSSMBClose(xid, tcon, netfid);
|
CIFSSMBClose(xid, tcon, fid.netfid);
|
||||||
else
|
else
|
||||||
cifsFileInfo_put(open_file);
|
cifsFileInfo_put(open_file);
|
||||||
out:
|
out:
|
||||||
@ -907,6 +915,33 @@ cifs_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
|
|||||||
(__u8)type, wait, 0);
|
(__u8)type, wait, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cifs_unix_dfs_readlink(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
const unsigned char *searchName, char **symlinkinfo,
|
||||||
|
const struct nls_table *nls_codepage)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_CIFS_DFS_UPCALL
|
||||||
|
int rc;
|
||||||
|
unsigned int num_referrals = 0;
|
||||||
|
struct dfs_info3_param *referrals = NULL;
|
||||||
|
|
||||||
|
rc = get_dfs_path(xid, tcon->ses, searchName, nls_codepage,
|
||||||
|
&num_referrals, &referrals, 0);
|
||||||
|
|
||||||
|
if (!rc && num_referrals > 0) {
|
||||||
|
*symlinkinfo = kstrndup(referrals->node_name,
|
||||||
|
strlen(referrals->node_name),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!*symlinkinfo)
|
||||||
|
rc = -ENOMEM;
|
||||||
|
free_dfs_info_array(referrals, num_referrals);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
#else /* No DFS support */
|
||||||
|
return -EREMOTE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
const char *full_path, char **target_path,
|
const char *full_path, char **target_path,
|
||||||
@ -914,27 +949,47 @@ cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
int oplock = 0;
|
int oplock = 0;
|
||||||
__u16 netfid;
|
struct cifs_fid fid;
|
||||||
|
struct cifs_open_parms oparms;
|
||||||
|
|
||||||
cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
|
cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
|
||||||
|
|
||||||
rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
|
/* Check for unix extensions */
|
||||||
FILE_READ_ATTRIBUTES, OPEN_REPARSE_POINT, &netfid,
|
if (cap_unix(tcon->ses)) {
|
||||||
&oplock, NULL, cifs_sb->local_nls,
|
rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
cifs_sb->local_nls);
|
||||||
if (rc)
|
if (rc == -EREMOTE)
|
||||||
return rc;
|
rc = cifs_unix_dfs_readlink(xid, tcon, full_path,
|
||||||
|
target_path,
|
||||||
|
cifs_sb->local_nls);
|
||||||
|
|
||||||
rc = CIFSSMBQuerySymLink(xid, tcon, netfid, target_path,
|
goto out;
|
||||||
cifs_sb->local_nls);
|
|
||||||
if (rc) {
|
|
||||||
CIFSSMBClose(xid, tcon, netfid);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oparms.tcon = tcon;
|
||||||
|
oparms.cifs_sb = cifs_sb;
|
||||||
|
oparms.desired_access = FILE_READ_ATTRIBUTES;
|
||||||
|
oparms.create_options = OPEN_REPARSE_POINT;
|
||||||
|
oparms.disposition = FILE_OPEN;
|
||||||
|
oparms.path = full_path;
|
||||||
|
oparms.fid = &fid;
|
||||||
|
oparms.reconnect = false;
|
||||||
|
|
||||||
|
rc = CIFS_open(xid, &oparms, &oplock, NULL);
|
||||||
|
if (rc)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
rc = CIFSSMBQuerySymLink(xid, tcon, fid.netfid, target_path,
|
||||||
|
cifs_sb->local_nls);
|
||||||
|
if (rc)
|
||||||
|
goto out_close;
|
||||||
|
|
||||||
convert_delimiter(*target_path, '/');
|
convert_delimiter(*target_path, '/');
|
||||||
CIFSSMBClose(xid, tcon, netfid);
|
out_close:
|
||||||
cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
|
CIFSSMBClose(xid, tcon, fid.netfid);
|
||||||
|
out:
|
||||||
|
if (!rc)
|
||||||
|
cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1009,7 +1064,8 @@ struct smb_version_operations smb1_operations = {
|
|||||||
.mand_lock = cifs_mand_lock,
|
.mand_lock = cifs_mand_lock,
|
||||||
.mand_unlock_range = cifs_unlock_range,
|
.mand_unlock_range = cifs_unlock_range,
|
||||||
.push_mand_locks = cifs_push_mandatory_locks,
|
.push_mand_locks = cifs_push_mandatory_locks,
|
||||||
.query_mf_symlink = open_query_close_cifs_symlink,
|
.query_mf_symlink = cifs_query_mf_symlink,
|
||||||
|
.create_mf_symlink = cifs_create_mf_symlink,
|
||||||
.is_read_op = cifs_is_read_op,
|
.is_read_op = cifs_is_read_op,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,9 +82,11 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
|
|||||||
goto remove_ea_exit;
|
goto remove_ea_exit;
|
||||||
|
|
||||||
ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
|
ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
|
||||||
rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL,
|
if (pTcon->ses->server->ops->set_EA)
|
||||||
(__u16)0, cifs_sb->local_nls,
|
rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
full_path, ea_name, NULL, (__u16)0,
|
||||||
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||||
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
}
|
}
|
||||||
remove_ea_exit:
|
remove_ea_exit:
|
||||||
kfree(full_path);
|
kfree(full_path);
|
||||||
@ -149,18 +151,22 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
|
|||||||
cifs_dbg(FYI, "attempt to set cifs inode metadata\n");
|
cifs_dbg(FYI, "attempt to set cifs inode metadata\n");
|
||||||
|
|
||||||
ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
|
ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
|
||||||
rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
|
if (pTcon->ses->server->ops->set_EA)
|
||||||
(__u16)value_size, cifs_sb->local_nls,
|
rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
full_path, ea_name, ea_value, (__u16)value_size,
|
||||||
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||||
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
} else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)
|
} else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)
|
||||||
== 0) {
|
== 0) {
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||||
goto set_ea_exit;
|
goto set_ea_exit;
|
||||||
|
|
||||||
ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
|
ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
|
||||||
rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
|
if (pTcon->ses->server->ops->set_EA)
|
||||||
(__u16)value_size, cifs_sb->local_nls,
|
rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
full_path, ea_name, ea_value, (__u16)value_size,
|
||||||
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||||
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
} else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL,
|
} else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL,
|
||||||
strlen(CIFS_XATTR_CIFS_ACL)) == 0) {
|
strlen(CIFS_XATTR_CIFS_ACL)) == 0) {
|
||||||
#ifdef CONFIG_CIFS_ACL
|
#ifdef CONFIG_CIFS_ACL
|
||||||
@ -272,17 +278,21 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
|
|||||||
/* revalidate/getattr then populate from inode */
|
/* revalidate/getattr then populate from inode */
|
||||||
} /* BB add else when above is implemented */
|
} /* BB add else when above is implemented */
|
||||||
ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
|
ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
|
||||||
rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
|
if (pTcon->ses->server->ops->query_all_EAs)
|
||||||
buf_size, cifs_sb->local_nls,
|
rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
full_path, ea_name, ea_value, buf_size,
|
||||||
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||||
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
} else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
|
} else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||||
goto get_ea_exit;
|
goto get_ea_exit;
|
||||||
|
|
||||||
ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
|
ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
|
||||||
rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
|
if (pTcon->ses->server->ops->query_all_EAs)
|
||||||
buf_size, cifs_sb->local_nls,
|
rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
full_path, ea_name, ea_value, buf_size,
|
||||||
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||||
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
} else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
|
} else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
|
||||||
strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
|
strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
|
||||||
#ifdef CONFIG_CIFS_POSIX
|
#ifdef CONFIG_CIFS_POSIX
|
||||||
@ -400,11 +410,12 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
|
|||||||
/* if proc/fs/cifs/streamstoxattr is set then
|
/* if proc/fs/cifs/streamstoxattr is set then
|
||||||
search server for EAs or streams to
|
search server for EAs or streams to
|
||||||
returns as xattrs */
|
returns as xattrs */
|
||||||
rc = CIFSSMBQAllEAs(xid, pTcon, full_path, NULL, data,
|
|
||||||
buf_size, cifs_sb->local_nls,
|
|
||||||
cifs_sb->mnt_cifs_flags &
|
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
|
|
||||||
|
if (pTcon->ses->server->ops->query_all_EAs)
|
||||||
|
rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
|
||||||
|
full_path, NULL, data, buf_size,
|
||||||
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||||
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
list_ea_exit:
|
list_ea_exit:
|
||||||
kfree(full_path);
|
kfree(full_path);
|
||||||
free_xid(xid);
|
free_xid(xid);
|
||||||
|
Loading…
Reference in New Issue
Block a user