mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-11-01 02:21:16 +00:00
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull CIFS update from Steve French: "Adds SMB2 rmdir/mkdir capability to the SMB2/SMB2.1 support in cifs. I am holding up a few more days on merging the remainder of the SMB2/SMB2.1 enablement although it is nearing review completion, in order to address some review comments from Jeff Layton on a few of the subsequent SMB2 patches, and also to debug an unrelated cifs problem that Pavel discovered." * 'for-next' of git://git.samba.org/sfrench/cifs-2.6: CIFS: Add SMB2 support for rmdir CIFS: Move rmdir code to ops struct CIFS: Add SMB2 support for mkdir operation CIFS: Separate protocol specific part from mkdir CIFS: Simplify cifs_mkdir call
This commit is contained in:
commit
630103ea2c
8 changed files with 270 additions and 158 deletions
|
@ -246,6 +246,16 @@ struct smb_version_operations {
|
||||||
bool (*can_echo)(struct TCP_Server_Info *);
|
bool (*can_echo)(struct TCP_Server_Info *);
|
||||||
/* send echo request */
|
/* send echo request */
|
||||||
int (*echo)(struct TCP_Server_Info *);
|
int (*echo)(struct TCP_Server_Info *);
|
||||||
|
/* create directory */
|
||||||
|
int (*mkdir)(const unsigned int, struct cifs_tcon *, const char *,
|
||||||
|
struct cifs_sb_info *);
|
||||||
|
/* set info on created directory */
|
||||||
|
void (*mkdir_setinfo)(struct inode *, const char *,
|
||||||
|
struct cifs_sb_info *, struct cifs_tcon *,
|
||||||
|
const unsigned int);
|
||||||
|
/* remove directory */
|
||||||
|
int (*rmdir)(const unsigned int, struct cifs_tcon *, const char *,
|
||||||
|
struct cifs_sb_info *);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct smb_version_values {
|
struct smb_version_values {
|
||||||
|
|
|
@ -289,18 +289,15 @@ extern int CIFSSMBUnixSetFileInfo(const unsigned int xid,
|
||||||
u16 fid, u32 pid_of_opener);
|
u16 fid, u32 pid_of_opener);
|
||||||
|
|
||||||
extern int CIFSSMBUnixSetPathInfo(const unsigned int xid,
|
extern int CIFSSMBUnixSetPathInfo(const unsigned int xid,
|
||||||
struct cifs_tcon *tcon, char *file_name,
|
struct cifs_tcon *tcon, const char *file_name,
|
||||||
const struct cifs_unix_set_info_args *args,
|
const struct cifs_unix_set_info_args *args,
|
||||||
const struct nls_table *nls_codepage,
|
const struct nls_table *nls_codepage,
|
||||||
int remap_special_chars);
|
int remap);
|
||||||
|
|
||||||
extern int CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
const char *newName,
|
const char *name, struct cifs_sb_info *cifs_sb);
|
||||||
const struct nls_table *nls_codepage,
|
|
||||||
int remap_special_chars);
|
|
||||||
extern int CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
const char *name, const struct nls_table *nls_codepage,
|
const char *name, struct cifs_sb_info *cifs_sb);
|
||||||
int remap_special_chars);
|
|
||||||
extern int CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
const char *name, __u16 type,
|
const char *name, __u16 type,
|
||||||
const struct nls_table *nls_codepage,
|
const struct nls_table *nls_codepage,
|
||||||
|
|
|
@ -948,15 +948,15 @@ DelFileRetry:
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon,
|
CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
|
||||||
const char *dirName, const struct nls_table *nls_codepage,
|
struct cifs_sb_info *cifs_sb)
|
||||||
int remap)
|
|
||||||
{
|
{
|
||||||
DELETE_DIRECTORY_REQ *pSMB = NULL;
|
DELETE_DIRECTORY_REQ *pSMB = NULL;
|
||||||
DELETE_DIRECTORY_RSP *pSMBr = NULL;
|
DELETE_DIRECTORY_RSP *pSMBr = NULL;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int bytes_returned;
|
int bytes_returned;
|
||||||
int name_len;
|
int name_len;
|
||||||
|
int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
|
||||||
|
|
||||||
cFYI(1, "In CIFSSMBRmDir");
|
cFYI(1, "In CIFSSMBRmDir");
|
||||||
RmDirRetry:
|
RmDirRetry:
|
||||||
|
@ -966,14 +966,15 @@ RmDirRetry:
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, dirName,
|
name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, cifs_sb->local_nls,
|
||||||
|
remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
} else { /* BB improve check for buffer overruns BB */
|
} else { /* BB improve check for buffer overruns BB */
|
||||||
name_len = strnlen(dirName, PATH_MAX);
|
name_len = strnlen(name, PATH_MAX);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
strncpy(pSMB->DirName, dirName, name_len);
|
strncpy(pSMB->DirName, name, name_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
pSMB->BufferFormat = 0x04;
|
pSMB->BufferFormat = 0x04;
|
||||||
|
@ -992,14 +993,15 @@ RmDirRetry:
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon,
|
CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
|
||||||
const char *name, const struct nls_table *nls_codepage, int remap)
|
struct cifs_sb_info *cifs_sb)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
CREATE_DIRECTORY_REQ *pSMB = NULL;
|
CREATE_DIRECTORY_REQ *pSMB = NULL;
|
||||||
CREATE_DIRECTORY_RSP *pSMBr = NULL;
|
CREATE_DIRECTORY_RSP *pSMBr = NULL;
|
||||||
int bytes_returned;
|
int bytes_returned;
|
||||||
int name_len;
|
int name_len;
|
||||||
|
int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
|
||||||
|
|
||||||
cFYI(1, "In CIFSSMBMkDir");
|
cFYI(1, "In CIFSSMBMkDir");
|
||||||
MkDirRetry:
|
MkDirRetry:
|
||||||
|
@ -1010,7 +1012,8 @@ MkDirRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
|
name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, cifs_sb->local_nls,
|
||||||
|
remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
} else { /* BB improve check for buffer overruns BB */
|
} else { /* BB improve check for buffer overruns BB */
|
||||||
|
@ -5943,7 +5946,7 @@ CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
|
||||||
int
|
int
|
||||||
CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
|
CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
char *fileName,
|
const char *file_name,
|
||||||
const struct cifs_unix_set_info_args *args,
|
const struct cifs_unix_set_info_args *args,
|
||||||
const struct nls_table *nls_codepage, int remap)
|
const struct nls_table *nls_codepage, int remap)
|
||||||
{
|
{
|
||||||
|
@ -5964,14 +5967,14 @@ setPermsRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
|
cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
} else { /* BB improve the check for buffer overruns BB */
|
} else { /* BB improve the check for buffer overruns BB */
|
||||||
name_len = strnlen(fileName, PATH_MAX);
|
name_len = strnlen(file_name, PATH_MAX);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
strncpy(pSMB->FileName, fileName, name_len);
|
strncpy(pSMB->FileName, file_name, name_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
params = 6 + name_len;
|
params = 6 + name_len;
|
||||||
|
|
302
fs/cifs/inode.c
302
fs/cifs/inode.c
|
@ -1219,16 +1219,153 @@ unlink_out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cifs_mkdir_qinfo(struct inode *inode, struct dentry *dentry, umode_t mode,
|
||||||
|
const char *full_path, struct cifs_sb_info *cifs_sb,
|
||||||
|
struct cifs_tcon *tcon, const unsigned int xid)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
struct inode *newinode = NULL;
|
||||||
|
|
||||||
|
if (tcon->unix_ext)
|
||||||
|
rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb,
|
||||||
|
xid);
|
||||||
|
else
|
||||||
|
rc = cifs_get_inode_info(&newinode, full_path, NULL,
|
||||||
|
inode->i_sb, xid, NULL);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
d_instantiate(dentry, newinode);
|
||||||
|
/*
|
||||||
|
* setting nlink not necessary except in cases where we failed to get it
|
||||||
|
* from the server or was set bogus
|
||||||
|
*/
|
||||||
|
if ((dentry->d_inode) && (dentry->d_inode->i_nlink < 2))
|
||||||
|
set_nlink(dentry->d_inode, 2);
|
||||||
|
|
||||||
|
mode &= ~current_umask();
|
||||||
|
/* must turn on setgid bit if parent dir has it */
|
||||||
|
if (inode->i_mode & S_ISGID)
|
||||||
|
mode |= S_ISGID;
|
||||||
|
|
||||||
|
if (tcon->unix_ext) {
|
||||||
|
struct cifs_unix_set_info_args args = {
|
||||||
|
.mode = mode,
|
||||||
|
.ctime = NO_CHANGE_64,
|
||||||
|
.atime = NO_CHANGE_64,
|
||||||
|
.mtime = NO_CHANGE_64,
|
||||||
|
.device = 0,
|
||||||
|
};
|
||||||
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||||
|
args.uid = (__u64)current_fsuid();
|
||||||
|
if (inode->i_mode & S_ISGID)
|
||||||
|
args.gid = (__u64)inode->i_gid;
|
||||||
|
else
|
||||||
|
args.gid = (__u64)current_fsgid();
|
||||||
|
} else {
|
||||||
|
args.uid = NO_CHANGE_64;
|
||||||
|
args.gid = NO_CHANGE_64;
|
||||||
|
}
|
||||||
|
CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
|
||||||
|
cifs_sb->local_nls,
|
||||||
|
cifs_sb->mnt_cifs_flags &
|
||||||
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
} else {
|
||||||
|
struct TCP_Server_Info *server = tcon->ses->server;
|
||||||
|
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
|
||||||
|
(mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
|
||||||
|
server->ops->mkdir_setinfo(newinode, full_path, cifs_sb,
|
||||||
|
tcon, xid);
|
||||||
|
if (dentry->d_inode) {
|
||||||
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
|
||||||
|
dentry->d_inode->i_mode = (mode | S_IFDIR);
|
||||||
|
|
||||||
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||||
|
dentry->d_inode->i_uid = current_fsuid();
|
||||||
|
if (inode->i_mode & S_ISGID)
|
||||||
|
dentry->d_inode->i_gid = inode->i_gid;
|
||||||
|
else
|
||||||
|
dentry->d_inode->i_gid =
|
||||||
|
current_fsgid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
|
||||||
|
const char *full_path, struct cifs_sb_info *cifs_sb,
|
||||||
|
struct cifs_tcon *tcon, const unsigned int xid)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
u32 oplock = 0;
|
||||||
|
FILE_UNIX_BASIC_INFO *info = NULL;
|
||||||
|
struct inode *newinode = NULL;
|
||||||
|
struct cifs_fattr fattr;
|
||||||
|
|
||||||
|
info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
|
||||||
|
if (info == NULL) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto posix_mkdir_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
mode &= ~current_umask();
|
||||||
|
rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
|
||||||
|
NULL /* netfid */, info, &oplock, full_path,
|
||||||
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||||
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
if (rc == -EOPNOTSUPP)
|
||||||
|
goto posix_mkdir_out;
|
||||||
|
else if (rc) {
|
||||||
|
cFYI(1, "posix mkdir returned 0x%x", rc);
|
||||||
|
d_drop(dentry);
|
||||||
|
goto posix_mkdir_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->Type == cpu_to_le32(-1))
|
||||||
|
/* no return info, go query for it */
|
||||||
|
goto posix_mkdir_get_info;
|
||||||
|
/*
|
||||||
|
* BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
|
||||||
|
* need to set uid/gid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
|
||||||
|
cifs_fill_uniqueid(inode->i_sb, &fattr);
|
||||||
|
newinode = cifs_iget(inode->i_sb, &fattr);
|
||||||
|
if (!newinode)
|
||||||
|
goto posix_mkdir_get_info;
|
||||||
|
|
||||||
|
d_instantiate(dentry, newinode);
|
||||||
|
|
||||||
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
|
cFYI(1, "instantiated dentry %p %s to inode %p", dentry,
|
||||||
|
dentry->d_name.name, newinode);
|
||||||
|
|
||||||
|
if (newinode->i_nlink != 2)
|
||||||
|
cFYI(1, "unexpected number of links %d", newinode->i_nlink);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
posix_mkdir_out:
|
||||||
|
kfree(info);
|
||||||
|
return rc;
|
||||||
|
posix_mkdir_get_info:
|
||||||
|
rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
|
||||||
|
xid);
|
||||||
|
goto posix_mkdir_out;
|
||||||
|
}
|
||||||
|
|
||||||
int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
|
int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
|
||||||
{
|
{
|
||||||
int rc = 0, tmprc;
|
int rc = 0;
|
||||||
unsigned int xid;
|
unsigned int xid;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct tcon_link *tlink;
|
struct tcon_link *tlink;
|
||||||
struct cifs_tcon *tcon;
|
struct cifs_tcon *tcon;
|
||||||
char *full_path = NULL;
|
struct TCP_Server_Info *server;
|
||||||
struct inode *newinode = NULL;
|
char *full_path;
|
||||||
struct cifs_fattr fattr;
|
|
||||||
|
|
||||||
cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode);
|
cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode);
|
||||||
|
|
||||||
|
@ -1248,145 +1385,29 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
|
||||||
|
|
||||||
if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||||
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
||||||
u32 oplock = 0;
|
rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
|
||||||
FILE_UNIX_BASIC_INFO *pInfo =
|
tcon, xid);
|
||||||
kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
|
if (rc != -EOPNOTSUPP)
|
||||||
if (pInfo == NULL) {
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto mkdir_out;
|
goto mkdir_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
mode &= ~current_umask();
|
server = tcon->ses->server;
|
||||||
rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT,
|
|
||||||
mode, NULL /* netfid */, pInfo, &oplock,
|
|
||||||
full_path, cifs_sb->local_nls,
|
|
||||||
cifs_sb->mnt_cifs_flags &
|
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
if (rc == -EOPNOTSUPP) {
|
|
||||||
kfree(pInfo);
|
|
||||||
goto mkdir_retry_old;
|
|
||||||
} else if (rc) {
|
|
||||||
cFYI(1, "posix mkdir returned 0x%x", rc);
|
|
||||||
d_drop(direntry);
|
|
||||||
} else {
|
|
||||||
if (pInfo->Type == cpu_to_le32(-1)) {
|
|
||||||
/* no return info, go query for it */
|
|
||||||
kfree(pInfo);
|
|
||||||
goto mkdir_get_info;
|
|
||||||
}
|
|
||||||
/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
|
|
||||||
to set uid/gid */
|
|
||||||
|
|
||||||
cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb);
|
if (!server->ops->mkdir) {
|
||||||
cifs_fill_uniqueid(inode->i_sb, &fattr);
|
rc = -ENOSYS;
|
||||||
newinode = cifs_iget(inode->i_sb, &fattr);
|
|
||||||
if (!newinode) {
|
|
||||||
kfree(pInfo);
|
|
||||||
goto mkdir_get_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
d_instantiate(direntry, newinode);
|
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_DEBUG2
|
|
||||||
cFYI(1, "instantiated dentry %p %s to inode %p",
|
|
||||||
direntry, direntry->d_name.name, newinode);
|
|
||||||
|
|
||||||
if (newinode->i_nlink != 2)
|
|
||||||
cFYI(1, "unexpected number of links %d",
|
|
||||||
newinode->i_nlink);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
kfree(pInfo);
|
|
||||||
goto mkdir_out;
|
goto mkdir_out;
|
||||||
}
|
}
|
||||||
mkdir_retry_old:
|
|
||||||
/* BB add setting the equivalent of mode via CreateX w/ACLs */
|
/* BB add setting the equivalent of mode via CreateX w/ACLs */
|
||||||
rc = CIFSSMBMkDir(xid, tcon, full_path, cifs_sb->local_nls,
|
rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cFYI(1, "cifs_mkdir returned 0x%x", rc);
|
cFYI(1, "cifs_mkdir returned 0x%x", rc);
|
||||||
d_drop(direntry);
|
d_drop(direntry);
|
||||||
} else {
|
goto mkdir_out;
|
||||||
mkdir_get_info:
|
|
||||||
if (tcon->unix_ext)
|
|
||||||
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
|
||||||
inode->i_sb, xid);
|
|
||||||
else
|
|
||||||
rc = cifs_get_inode_info(&newinode, full_path, NULL,
|
|
||||||
inode->i_sb, xid, NULL);
|
|
||||||
|
|
||||||
d_instantiate(direntry, newinode);
|
|
||||||
/* setting nlink not necessary except in cases where we
|
|
||||||
* failed to get it from the server or was set bogus */
|
|
||||||
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
|
|
||||||
set_nlink(direntry->d_inode, 2);
|
|
||||||
|
|
||||||
mode &= ~current_umask();
|
|
||||||
/* must turn on setgid bit if parent dir has it */
|
|
||||||
if (inode->i_mode & S_ISGID)
|
|
||||||
mode |= S_ISGID;
|
|
||||||
|
|
||||||
if (tcon->unix_ext) {
|
|
||||||
struct cifs_unix_set_info_args args = {
|
|
||||||
.mode = mode,
|
|
||||||
.ctime = NO_CHANGE_64,
|
|
||||||
.atime = NO_CHANGE_64,
|
|
||||||
.mtime = NO_CHANGE_64,
|
|
||||||
.device = 0,
|
|
||||||
};
|
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
|
||||||
args.uid = (__u64)current_fsuid();
|
|
||||||
if (inode->i_mode & S_ISGID)
|
|
||||||
args.gid = (__u64)inode->i_gid;
|
|
||||||
else
|
|
||||||
args.gid = (__u64)current_fsgid();
|
|
||||||
} else {
|
|
||||||
args.uid = NO_CHANGE_64;
|
|
||||||
args.gid = NO_CHANGE_64;
|
|
||||||
}
|
|
||||||
CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
|
|
||||||
cifs_sb->local_nls,
|
|
||||||
cifs_sb->mnt_cifs_flags &
|
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
} else {
|
|
||||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
|
|
||||||
(mode & S_IWUGO) == 0) {
|
|
||||||
FILE_BASIC_INFO pInfo;
|
|
||||||
struct cifsInodeInfo *cifsInode;
|
|
||||||
u32 dosattrs;
|
|
||||||
|
|
||||||
memset(&pInfo, 0, sizeof(pInfo));
|
|
||||||
cifsInode = CIFS_I(newinode);
|
|
||||||
dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
|
|
||||||
pInfo.Attributes = cpu_to_le32(dosattrs);
|
|
||||||
tmprc = CIFSSMBSetPathInfo(xid, tcon,
|
|
||||||
full_path, &pInfo,
|
|
||||||
cifs_sb->local_nls,
|
|
||||||
cifs_sb->mnt_cifs_flags &
|
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
if (tmprc == 0)
|
|
||||||
cifsInode->cifsAttrs = dosattrs;
|
|
||||||
}
|
|
||||||
if (direntry->d_inode) {
|
|
||||||
if (cifs_sb->mnt_cifs_flags &
|
|
||||||
CIFS_MOUNT_DYNPERM)
|
|
||||||
direntry->d_inode->i_mode =
|
|
||||||
(mode | S_IFDIR);
|
|
||||||
|
|
||||||
if (cifs_sb->mnt_cifs_flags &
|
|
||||||
CIFS_MOUNT_SET_UID) {
|
|
||||||
direntry->d_inode->i_uid =
|
|
||||||
current_fsuid();
|
|
||||||
if (inode->i_mode & S_ISGID)
|
|
||||||
direntry->d_inode->i_gid =
|
|
||||||
inode->i_gid;
|
|
||||||
else
|
|
||||||
direntry->d_inode->i_gid =
|
|
||||||
current_fsgid();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
|
||||||
|
xid);
|
||||||
mkdir_out:
|
mkdir_out:
|
||||||
/*
|
/*
|
||||||
* Force revalidate to get parent dir info when needed since cached
|
* Force revalidate to get parent dir info when needed since cached
|
||||||
|
@ -1405,7 +1426,8 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
||||||
unsigned int xid;
|
unsigned int xid;
|
||||||
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 TCP_Server_Info *server;
|
||||||
char *full_path = NULL;
|
char *full_path = NULL;
|
||||||
struct cifsInodeInfo *cifsInode;
|
struct cifsInodeInfo *cifsInode;
|
||||||
|
|
||||||
|
@ -1425,10 +1447,16 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
||||||
rc = PTR_ERR(tlink);
|
rc = PTR_ERR(tlink);
|
||||||
goto rmdir_exit;
|
goto rmdir_exit;
|
||||||
}
|
}
|
||||||
pTcon = tlink_tcon(tlink);
|
tcon = tlink_tcon(tlink);
|
||||||
|
server = tcon->ses->server;
|
||||||
|
|
||||||
rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
|
if (!server->ops->rmdir) {
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
rc = -ENOSYS;
|
||||||
|
cifs_put_tlink(tlink);
|
||||||
|
goto rmdir_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
|
||||||
cifs_put_tlink(tlink);
|
cifs_put_tlink(tlink);
|
||||||
|
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
|
|
|
@ -586,6 +586,27 @@ cifs_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cifs_mkdir_setinfo(struct inode *inode, const char *full_path,
|
||||||
|
struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon,
|
||||||
|
const unsigned int xid)
|
||||||
|
{
|
||||||
|
FILE_BASIC_INFO info;
|
||||||
|
struct cifsInodeInfo *cifsInode;
|
||||||
|
u32 dosattrs;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
|
cifsInode = CIFS_I(inode);
|
||||||
|
dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
|
||||||
|
info.Attributes = cpu_to_le32(dosattrs);
|
||||||
|
rc = CIFSSMBSetPathInfo(xid, tcon, full_path, &info, cifs_sb->local_nls,
|
||||||
|
cifs_sb->mnt_cifs_flags &
|
||||||
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
if (rc == 0)
|
||||||
|
cifsInode->cifsAttrs = dosattrs;
|
||||||
|
}
|
||||||
|
|
||||||
struct smb_version_operations smb1_operations = {
|
struct smb_version_operations smb1_operations = {
|
||||||
.send_cancel = send_nt_cancel,
|
.send_cancel = send_nt_cancel,
|
||||||
.compare_fids = cifs_compare_fids,
|
.compare_fids = cifs_compare_fids,
|
||||||
|
@ -620,6 +641,9 @@ struct smb_version_operations smb1_operations = {
|
||||||
.get_srv_inum = cifs_get_srv_inum,
|
.get_srv_inum = cifs_get_srv_inum,
|
||||||
.build_path_to_root = cifs_build_path_to_root,
|
.build_path_to_root = cifs_build_path_to_root,
|
||||||
.echo = CIFSSMBEcho,
|
.echo = CIFSSMBEcho,
|
||||||
|
.mkdir = CIFSSMBMkDir,
|
||||||
|
.mkdir_setinfo = cifs_mkdir_setinfo,
|
||||||
|
.rmdir = CIFSSMBRmDir,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct smb_version_values smb1_values = {
|
struct smb_version_values smb1_values = {
|
||||||
|
|
|
@ -122,3 +122,42 @@ out:
|
||||||
kfree(smb2_data);
|
kfree(smb2_data);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
|
||||||
|
struct cifs_sb_info *cifs_sb)
|
||||||
|
{
|
||||||
|
return smb2_open_op_close(xid, tcon, cifs_sb, name,
|
||||||
|
FILE_WRITE_ATTRIBUTES, FILE_CREATE, 0,
|
||||||
|
CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
smb2_mkdir_setinfo(struct inode *inode, const char *name,
|
||||||
|
struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon,
|
||||||
|
const unsigned int xid)
|
||||||
|
{
|
||||||
|
FILE_BASIC_INFO data;
|
||||||
|
struct cifsInodeInfo *cifs_i;
|
||||||
|
u32 dosattrs;
|
||||||
|
int tmprc;
|
||||||
|
|
||||||
|
memset(&data, 0, sizeof(data));
|
||||||
|
cifs_i = CIFS_I(inode);
|
||||||
|
dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
|
||||||
|
data.Attributes = cpu_to_le32(dosattrs);
|
||||||
|
tmprc = smb2_open_op_close(xid, tcon, cifs_sb, name,
|
||||||
|
FILE_WRITE_ATTRIBUTES, FILE_CREATE, 0,
|
||||||
|
CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO);
|
||||||
|
if (tmprc == 0)
|
||||||
|
cifs_i->cifsAttrs = dosattrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
|
||||||
|
struct cifs_sb_info *cifs_sb)
|
||||||
|
{
|
||||||
|
return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
|
||||||
|
0, CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE,
|
||||||
|
NULL, SMB2_OP_DELETE);
|
||||||
|
}
|
||||||
|
|
|
@ -318,6 +318,9 @@ struct smb_version_operations smb21_operations = {
|
||||||
.query_path_info = smb2_query_path_info,
|
.query_path_info = smb2_query_path_info,
|
||||||
.get_srv_inum = smb2_get_srv_inum,
|
.get_srv_inum = smb2_get_srv_inum,
|
||||||
.build_path_to_root = smb2_build_path_to_root,
|
.build_path_to_root = smb2_build_path_to_root,
|
||||||
|
.mkdir = smb2_mkdir,
|
||||||
|
.mkdir_setinfo = smb2_mkdir_setinfo,
|
||||||
|
.rmdir = smb2_rmdir,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct smb_version_values smb21_values = {
|
struct smb_version_values smb21_values = {
|
||||||
|
|
|
@ -52,6 +52,14 @@ extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
struct cifs_sb_info *cifs_sb,
|
struct cifs_sb_info *cifs_sb,
|
||||||
const char *full_path, FILE_ALL_INFO *data,
|
const char *full_path, FILE_ALL_INFO *data,
|
||||||
bool *adjust_tz);
|
bool *adjust_tz);
|
||||||
|
extern int smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
const char *name, struct cifs_sb_info *cifs_sb);
|
||||||
|
extern void smb2_mkdir_setinfo(struct inode *inode, const char *full_path,
|
||||||
|
struct cifs_sb_info *cifs_sb,
|
||||||
|
struct cifs_tcon *tcon, const unsigned int xid);
|
||||||
|
extern int smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
const char *name, struct cifs_sb_info *cifs_sb);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SMB2 Worker functions - most of protocol specific implementation details
|
* SMB2 Worker functions - most of protocol specific implementation details
|
||||||
* are contained within these calls.
|
* are contained within these calls.
|
||||||
|
|
Loading…
Reference in a new issue