return 0;
}
-static int set_hidden_attr(const unsigned int xid,
- struct TCP_Server_Info *server,
- struct file *file)
+static int set_tmpfile_attr(const unsigned int xid, unsigned int oflags,
+ struct inode *inode, const char *full_path,
+ struct TCP_Server_Info *server)
{
- struct dentry *dentry = file->f_path.dentry;
- struct cifsInodeInfo *cinode = CIFS_I(d_inode(dentry));
- FILE_BASIC_INFO fi = {
- .Attributes = cpu_to_le32(cinode->cifsAttrs |
- ATTR_HIDDEN),
- };
- void *page = alloc_dentry_path();
- const char *full_path;
- int rc;
+ struct cifsInodeInfo *cinode = CIFS_I(inode);
+ FILE_BASIC_INFO fi;
- full_path = build_path_from_dentry(dentry, page);
- if (IS_ERR(full_path))
- rc = PTR_ERR(full_path);
- else
- rc = server->ops->set_file_info(d_inode(dentry),
- full_path, &fi, xid);
- free_dentry_path(page);
- return rc;
+ cinode->cifsAttrs |= ATTR_HIDDEN;
+ if (oflags & O_EXCL)
+ cinode->cifsAttrs |= ATTR_TEMPORARY;
+
+ fi = (FILE_BASIC_INFO) {
+ .Attributes = cpu_to_le32(cinode->cifsAttrs),
+ };
+ return server->ops->set_file_info(inode, full_path, &fi, xid);
}
/*
{
struct dentry *dentry = file->f_path.dentry;
struct cifs_sb_info *cifs_sb = CIFS_SB(dir);
+ char *path __free(kfree) = NULL, *name;
+ unsigned int oflags = file->f_flags;
size_t size = CIFS_TMPNAME_LEN + 1;
int retries = 0, max_retries = 16;
struct TCP_Server_Info *server;
struct cifs_tcon *tcon;
unsigned int sbflags;
struct inode *inode;
- char *path, *name;
unsigned int xid;
__u32 oplock;
int rc;
if (IS_ERR(path)) {
cifs_del_pending_open(&open);
rc = PTR_ERR(path);
+ path = NULL;
goto out;
}
CIFS_TMPNAME_PREFIX "%0*x",
CIFS_TMPNAME_COUNTER_LEN,
atomic_inc_return(&cifs_tmpcounter));
- rc = __cifs_do_create(dir, dentry, path, xid, tlink,
- file->f_flags, mode, &oplock,
- &fid, NULL, &inode);
+ rc = __cifs_do_create(dir, dentry, path, xid, tlink, oflags,
+ mode, &oplock, &fid, NULL, &inode);
if (!rc) {
set_nlink(inode, 0);
mark_inode_dirty(inode);
}
} while (unlikely(rc == -EEXIST) && ++retries < max_retries);
- kfree(path);
if (rc) {
cifs_del_pending_open(&open);
goto out;
goto err_open;
}
- rc = set_hidden_attr(xid, server, file);
+ rc = set_tmpfile_attr(xid, oflags, inode, path, server);
if (rc)
goto out;
return rc;
}
+static int clear_tmpfile_attr(const unsigned int xid, struct cifs_tcon *tcon,
+ struct inode *inode, const char *full_path)
+{
+ struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
+ struct cifsInodeInfo *cinode = CIFS_I(inode);
+ FILE_BASIC_INFO fi;
+
+ cinode->cifsAttrs &= ~(ATTR_TEMPORARY | ATTR_HIDDEN);
+ fi = (FILE_BASIC_INFO) {
+ .Attributes = cpu_to_le32(cinode->cifsAttrs),
+ };
+ return server->ops->set_file_info(inode, full_path, &fi, xid);
+}
+
int smb2_create_hardlink(const unsigned int xid,
struct cifs_tcon *tcon,
struct dentry *source_dentry,
struct inode *inode = source_dentry ? d_inode(source_dentry) : NULL;
__u32 co = file_create_options(source_dentry);
struct cifsFileInfo *cfile;
+ int rc;
- if (inode) {
- struct cifsInodeInfo *cinode = CIFS_I(inode);
- FILE_BASIC_INFO fi;
- __le32 attrs;
- int rc;
-
- if (!test_bit(CIFS_INO_TMPFILE, &CIFS_I(inode)->flags))
- goto out;
-
- attrs = cpu_to_le32(cinode->cifsAttrs & ~ATTR_HIDDEN);
- fi = (FILE_BASIC_INFO){ .Attributes = attrs, };
- rc = smb2_set_file_info(inode, from_name, &fi, xid);
+ if (inode && test_bit(CIFS_INO_TMPFILE, &CIFS_I(inode)->flags)) {
+ rc = clear_tmpfile_attr(xid, tcon, inode, from_name);
if (rc)
return rc;
}
-out:
cifs_get_writable_path(tcon, from_name, inode,
FIND_WITH_DELETE, &cfile);
return smb2_set_path_attr(xid, tcon, from_name, to_name,