int smb3_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; struct cifs_fid fid; struct cifs_open_parms oparms; struct cifs_io_parms io_parms; int create_options = CREATE_NOT_DIR; __le16 *utf16_path; __u8 oplock = SMB2_OPLOCK_LEVEL_EXCLUSIVE; struct kvec iov[2]; if (backup_cred(cifs_sb)) create_options |= CREATE_OPEN_BACKUP_INTENT; cifs_dbg(FYI, "%s: path: %s\n", __func__, path); utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); if (!utf16_path) return -ENOMEM; oparms.tcon = tcon; oparms.cifs_sb = cifs_sb; oparms.desired_access = GENERIC_WRITE; oparms.create_options = create_options; oparms.disposition = FILE_CREATE; oparms.fid = &fid; oparms.reconnect = false; rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL); if (rc) { kfree(utf16_path); 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; io_parms.persistent_fid = fid.persistent_fid; io_parms.volatile_fid = fid.volatile_fid; /* iov[0] is reserved for smb header */ iov[1].iov_base = pbuf; iov[1].iov_len = CIFS_MF_SYMLINK_FILE_SIZE; rc = SMB2_write(xid, &io_parms, pbytes_written, iov, 1); /* Make sure we wrote all of the symlink data */ if ((rc == 0) && (*pbytes_written != CIFS_MF_SYMLINK_FILE_SIZE)) rc = -EIO; SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); kfree(utf16_path); return rc; }
static int smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path, __u32 desired_access, __u32 create_disposition, __u32 file_attributes, __u32 create_options, void *data, int command) { int rc, tmprc = 0; u64 persistent_fid, volatile_fid; __le16 *utf16_path; utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); if (!utf16_path) return -ENOMEM; rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid, desired_access, create_disposition, file_attributes, create_options); if (rc) { kfree(utf16_path); return rc; } switch (command) { case SMB2_OP_DELETE: break; case SMB2_OP_QUERY_INFO: tmprc = SMB2_query_info(xid, tcon, persistent_fid, volatile_fid, (struct smb2_file_all_info *)data); break; case SMB2_OP_MKDIR: /* * Directories are created through parameters in the * SMB2_open() call. */ break; default: cERROR(1, "Invalid command"); break; } rc = SMB2_close(xid, tcon, persistent_fid, volatile_fid); if (tmprc) rc = tmprc; kfree(utf16_path); return rc; }
static int smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path, __u32 desired_access, __u32 create_disposition, __u32 create_options, void *data, int command) { int rc, tmprc = 0; __le16 *utf16_path; __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; struct cifs_open_parms oparms; struct cifs_fid fid; utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); if (!utf16_path) return -ENOMEM; oparms.tcon = tcon; oparms.desired_access = desired_access; oparms.share_access = FILE_SHARE_ALL; oparms.disposition = create_disposition; oparms.create_options = create_options; oparms.fid = &fid; oparms.reconnect = false; rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL); if (rc) { kfree(utf16_path); return rc; } switch (command) { case SMB2_OP_DELETE: break; case SMB2_OP_QUERY_INFO: tmprc = SMB2_query_info(xid, tcon, fid.persistent_fid, fid.volatile_fid, (struct smb2_file_all_info *)data); break; case SMB2_OP_MKDIR: /* * Directories are created through parameters in the * SMB2_open() call. */ break; case SMB2_OP_RENAME: tmprc = SMB2_rename(xid, tcon, fid.persistent_fid, fid.volatile_fid, (__le16 *)data); break; case SMB2_OP_HARDLINK: tmprc = SMB2_set_hardlink(xid, tcon, fid.persistent_fid, fid.volatile_fid, (__le16 *)data); break; case SMB2_OP_SET_EOF: tmprc = SMB2_set_eof(xid, tcon, fid.persistent_fid, fid.volatile_fid, current->tgid, (__le64 *)data, false); break; case SMB2_OP_SET_INFO: tmprc = SMB2_set_info(xid, tcon, fid.persistent_fid, fid.volatile_fid, (FILE_BASIC_INFO *)data); break; default: cifs_dbg(VFS, "Invalid command\n"); break; } rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); if (tmprc) rc = tmprc; kfree(utf16_path); return rc; }
int smb3_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; struct cifs_fid fid; struct cifs_open_parms oparms; struct cifs_io_parms io_parms; int buf_type = CIFS_NO_BUFFER; __le16 *utf16_path; __u8 oplock = SMB2_OPLOCK_LEVEL_II; struct smb2_file_all_info *pfile_info = NULL; oparms.tcon = tcon; oparms.cifs_sb = cifs_sb; oparms.desired_access = GENERIC_READ; oparms.create_options = CREATE_NOT_DIR; if (backup_cred(cifs_sb)) oparms.create_options |= CREATE_OPEN_BACKUP_INTENT; oparms.disposition = FILE_OPEN; oparms.fid = &fid; oparms.reconnect = false; utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); if (utf16_path == NULL) return -ENOMEM; pfile_info = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2, GFP_KERNEL); if (pfile_info == NULL) { kfree(utf16_path); return -ENOMEM; } rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL); if (rc) goto qmf_out_open_fail; if (pfile_info->EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { /* it's not a symlink */ rc = -ENOENT; /* Is there a better rc to return? */ goto qmf_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; io_parms.persistent_fid = fid.persistent_fid; io_parms.volatile_fid = fid.volatile_fid; rc = SMB2_read(xid, &io_parms, pbytes_read, &pbuf, &buf_type); qmf_out: SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); qmf_out_open_fail: kfree(utf16_path); kfree(pfile_info); return rc; }