root/fs/cifs/smb2inode.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. free_set_inf_compound
  2. smb2_compound_op
  3. move_smb2_info_to_cifs
  4. smb2_query_path_info
  5. smb2_mkdir
  6. smb2_mkdir_setinfo
  7. smb2_rmdir
  8. smb2_unlink
  9. smb2_set_path_attr
  10. smb2_rename_path
  11. smb2_create_hardlink
  12. smb2_set_path_size
  13. smb2_set_file_info

   1 /*
   2  *   fs/cifs/smb2inode.c
   3  *
   4  *   Copyright (C) International Business Machines  Corp., 2002, 2011
   5  *                 Etersoft, 2012
   6  *   Author(s): Pavel Shilovsky (pshilovsky@samba.org),
   7  *              Steve French (sfrench@us.ibm.com)
   8  *
   9  *   This library is free software; you can redistribute it and/or modify
  10  *   it under the terms of the GNU Lesser General Public License as published
  11  *   by the Free Software Foundation; either version 2.1 of the License, or
  12  *   (at your option) any later version.
  13  *
  14  *   This library is distributed in the hope that it will be useful,
  15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  17  *   the GNU Lesser General Public License for more details.
  18  *
  19  *   You should have received a copy of the GNU Lesser General Public License
  20  *   along with this library; if not, write to the Free Software
  21  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22  */
  23 #include <linux/fs.h>
  24 #include <linux/stat.h>
  25 #include <linux/slab.h>
  26 #include <linux/pagemap.h>
  27 #include <asm/div64.h>
  28 #include "cifsfs.h"
  29 #include "cifspdu.h"
  30 #include "cifsglob.h"
  31 #include "cifsproto.h"
  32 #include "cifs_debug.h"
  33 #include "cifs_fs_sb.h"
  34 #include "cifs_unicode.h"
  35 #include "fscache.h"
  36 #include "smb2glob.h"
  37 #include "smb2pdu.h"
  38 #include "smb2proto.h"
  39 
  40 static void
  41 free_set_inf_compound(struct smb_rqst *rqst)
  42 {
  43         if (rqst[1].rq_iov)
  44                 SMB2_set_info_free(&rqst[1]);
  45         if (rqst[2].rq_iov)
  46                 SMB2_close_free(&rqst[2]);
  47 }
  48 
  49 
  50 static int
  51 smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
  52                  struct cifs_sb_info *cifs_sb, const char *full_path,
  53                  __u32 desired_access, __u32 create_disposition,
  54                  __u32 create_options, umode_t mode, void *ptr, int command,
  55                  struct cifsFileInfo *cfile)
  56 {
  57         int rc;
  58         __le16 *utf16_path = NULL;
  59         __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
  60         struct cifs_open_parms oparms;
  61         struct cifs_fid fid;
  62         struct cifs_ses *ses = tcon->ses;
  63         int num_rqst = 0;
  64         struct smb_rqst rqst[3];
  65         int resp_buftype[3];
  66         struct kvec rsp_iov[3];
  67         struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
  68         struct kvec qi_iov[1];
  69         struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
  70         struct kvec close_iov[1];
  71         struct smb2_query_info_rsp *qi_rsp = NULL;
  72         int flags = 0;
  73         __u8 delete_pending[8] = {1, 0, 0, 0, 0, 0, 0, 0};
  74         unsigned int size[2];
  75         void *data[2];
  76         struct smb2_file_rename_info rename_info;
  77         struct smb2_file_link_info link_info;
  78         int len;
  79 
  80         if (smb3_encryption_required(tcon))
  81                 flags |= CIFS_TRANSFORM_REQ;
  82 
  83         memset(rqst, 0, sizeof(rqst));
  84         resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
  85         memset(rsp_iov, 0, sizeof(rsp_iov));
  86 
  87         /* We already have a handle so we can skip the open */
  88         if (cfile)
  89                 goto after_open;
  90 
  91         /* Open */
  92         utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
  93         if (!utf16_path) {
  94                 rc = -ENOMEM;
  95                 goto finished;
  96         }
  97 
  98         oparms.tcon = tcon;
  99         oparms.desired_access = desired_access;
 100         oparms.disposition = create_disposition;
 101         oparms.create_options = create_options;
 102         if (backup_cred(cifs_sb))
 103                 oparms.create_options |= CREATE_OPEN_BACKUP_INTENT;
 104         oparms.fid = &fid;
 105         oparms.reconnect = false;
 106         oparms.mode = mode;
 107 
 108         memset(&open_iov, 0, sizeof(open_iov));
 109         rqst[num_rqst].rq_iov = open_iov;
 110         rqst[num_rqst].rq_nvec = SMB2_CREATE_IOV_SIZE;
 111         rc = SMB2_open_init(tcon, &rqst[num_rqst], &oplock, &oparms,
 112                             utf16_path);
 113         kfree(utf16_path);
 114         if (rc)
 115                 goto finished;
 116 
 117         smb2_set_next_command(tcon, &rqst[num_rqst]);
 118  after_open:
 119         num_rqst++;
 120         rc = 0;
 121 
 122         /* Operation */
 123         switch (command) {
 124         case SMB2_OP_QUERY_INFO:
 125                 memset(&qi_iov, 0, sizeof(qi_iov));
 126                 rqst[num_rqst].rq_iov = qi_iov;
 127                 rqst[num_rqst].rq_nvec = 1;
 128 
 129                 if (cfile)
 130                         rc = SMB2_query_info_init(tcon, &rqst[num_rqst],
 131                                 cfile->fid.persistent_fid,
 132                                 cfile->fid.volatile_fid,
 133                                 FILE_ALL_INFORMATION,
 134                                 SMB2_O_INFO_FILE, 0,
 135                                 sizeof(struct smb2_file_all_info) +
 136                                           PATH_MAX * 2, 0, NULL);
 137                 else {
 138                         rc = SMB2_query_info_init(tcon, &rqst[num_rqst],
 139                                 COMPOUND_FID,
 140                                 COMPOUND_FID,
 141                                  FILE_ALL_INFORMATION,
 142                                 SMB2_O_INFO_FILE, 0,
 143                                 sizeof(struct smb2_file_all_info) +
 144                                           PATH_MAX * 2, 0, NULL);
 145                         if (!rc) {
 146                                 smb2_set_next_command(tcon, &rqst[num_rqst]);
 147                                 smb2_set_related(&rqst[num_rqst]);
 148                         }
 149                 }
 150 
 151                 if (rc)
 152                         goto finished;
 153                 num_rqst++;
 154                 trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid,
 155                                                      full_path);
 156                 break;
 157         case SMB2_OP_DELETE:
 158                 trace_smb3_delete_enter(xid, ses->Suid, tcon->tid, full_path);
 159                 break;
 160         case SMB2_OP_MKDIR:
 161                 /*
 162                  * Directories are created through parameters in the
 163                  * SMB2_open() call.
 164                  */
 165                 trace_smb3_mkdir_enter(xid, ses->Suid, tcon->tid, full_path);
 166                 break;
 167         case SMB2_OP_RMDIR:
 168                 memset(&si_iov, 0, sizeof(si_iov));
 169                 rqst[num_rqst].rq_iov = si_iov;
 170                 rqst[num_rqst].rq_nvec = 1;
 171 
 172                 size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */
 173                 data[0] = &delete_pending[0];
 174 
 175                 rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID,
 176                                         COMPOUND_FID, current->tgid,
 177                                         FILE_DISPOSITION_INFORMATION,
 178                                         SMB2_O_INFO_FILE, 0, data, size);
 179                 if (rc)
 180                         goto finished;
 181                 smb2_set_next_command(tcon, &rqst[num_rqst]);
 182                 smb2_set_related(&rqst[num_rqst++]);
 183                 trace_smb3_rmdir_enter(xid, ses->Suid, tcon->tid, full_path);
 184                 break;
 185         case SMB2_OP_SET_EOF:
 186                 memset(&si_iov, 0, sizeof(si_iov));
 187                 rqst[num_rqst].rq_iov = si_iov;
 188                 rqst[num_rqst].rq_nvec = 1;
 189 
 190                 size[0] = 8; /* sizeof __le64 */
 191                 data[0] = ptr;
 192 
 193                 rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID,
 194                                         COMPOUND_FID, current->tgid,
 195                                         FILE_END_OF_FILE_INFORMATION,
 196                                         SMB2_O_INFO_FILE, 0, data, size);
 197                 if (rc)
 198                         goto finished;
 199                 smb2_set_next_command(tcon, &rqst[num_rqst]);
 200                 smb2_set_related(&rqst[num_rqst++]);
 201                 trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path);
 202                 break;
 203         case SMB2_OP_SET_INFO:
 204                 memset(&si_iov, 0, sizeof(si_iov));
 205                 rqst[num_rqst].rq_iov = si_iov;
 206                 rqst[num_rqst].rq_nvec = 1;
 207 
 208 
 209                 size[0] = sizeof(FILE_BASIC_INFO);
 210                 data[0] = ptr;
 211 
 212                 if (cfile)
 213                         rc = SMB2_set_info_init(tcon, &rqst[num_rqst],
 214                                 cfile->fid.persistent_fid,
 215                                 cfile->fid.volatile_fid, current->tgid,
 216                                 FILE_BASIC_INFORMATION,
 217                                 SMB2_O_INFO_FILE, 0, data, size);
 218                 else {
 219                         rc = SMB2_set_info_init(tcon, &rqst[num_rqst],
 220                                 COMPOUND_FID,
 221                                 COMPOUND_FID, current->tgid,
 222                                 FILE_BASIC_INFORMATION,
 223                                 SMB2_O_INFO_FILE, 0, data, size);
 224                         if (!rc) {
 225                                 smb2_set_next_command(tcon, &rqst[num_rqst]);
 226                                 smb2_set_related(&rqst[num_rqst]);
 227                         }
 228                 }
 229 
 230                 if (rc)
 231                         goto finished;
 232                 num_rqst++;
 233                 trace_smb3_set_info_compound_enter(xid, ses->Suid, tcon->tid,
 234                                                    full_path);
 235                 break;
 236         case SMB2_OP_RENAME:
 237                 memset(&si_iov, 0, sizeof(si_iov));
 238                 rqst[num_rqst].rq_iov = si_iov;
 239                 rqst[num_rqst].rq_nvec = 2;
 240 
 241                 len = (2 * UniStrnlen((wchar_t *)ptr, PATH_MAX));
 242 
 243                 rename_info.ReplaceIfExists = 1;
 244                 rename_info.RootDirectory = 0;
 245                 rename_info.FileNameLength = cpu_to_le32(len);
 246 
 247                 size[0] = sizeof(struct smb2_file_rename_info);
 248                 data[0] = &rename_info;
 249 
 250                 size[1] = len + 2 /* null */;
 251                 data[1] = (__le16 *)ptr;
 252 
 253                 if (cfile)
 254                         rc = SMB2_set_info_init(tcon, &rqst[num_rqst],
 255                                                 cfile->fid.persistent_fid,
 256                                                 cfile->fid.volatile_fid,
 257                                         current->tgid, FILE_RENAME_INFORMATION,
 258                                         SMB2_O_INFO_FILE, 0, data, size);
 259                 else {
 260                         rc = SMB2_set_info_init(tcon, &rqst[num_rqst],
 261                                         COMPOUND_FID, COMPOUND_FID,
 262                                         current->tgid, FILE_RENAME_INFORMATION,
 263                                         SMB2_O_INFO_FILE, 0, data, size);
 264                         if (!rc) {
 265                                 smb2_set_next_command(tcon, &rqst[num_rqst]);
 266                                 smb2_set_related(&rqst[num_rqst]);
 267                         }
 268                 }
 269                 if (rc)
 270                         goto finished;
 271                 num_rqst++;
 272                 trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path);
 273                 break;
 274         case SMB2_OP_HARDLINK:
 275                 memset(&si_iov, 0, sizeof(si_iov));
 276                 rqst[num_rqst].rq_iov = si_iov;
 277                 rqst[num_rqst].rq_nvec = 2;
 278 
 279                 len = (2 * UniStrnlen((wchar_t *)ptr, PATH_MAX));
 280 
 281                 link_info.ReplaceIfExists = 0;
 282                 link_info.RootDirectory = 0;
 283                 link_info.FileNameLength = cpu_to_le32(len);
 284 
 285                 size[0] = sizeof(struct smb2_file_link_info);
 286                 data[0] = &link_info;
 287 
 288                 size[1] = len + 2 /* null */;
 289                 data[1] = (__le16 *)ptr;
 290 
 291                 rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID,
 292                                         COMPOUND_FID, current->tgid,
 293                                         FILE_LINK_INFORMATION,
 294                                         SMB2_O_INFO_FILE, 0, data, size);
 295                 if (rc)
 296                         goto finished;
 297                 smb2_set_next_command(tcon, &rqst[num_rqst]);
 298                 smb2_set_related(&rqst[num_rqst++]);
 299                 trace_smb3_hardlink_enter(xid, ses->Suid, tcon->tid, full_path);
 300                 break;
 301         default:
 302                 cifs_dbg(VFS, "Invalid command\n");
 303                 rc = -EINVAL;
 304         }
 305         if (rc)
 306                 goto finished;
 307 
 308         /* We already have a handle so we can skip the close */
 309         if (cfile)
 310                 goto after_close;
 311         /* Close */
 312         memset(&close_iov, 0, sizeof(close_iov));
 313         rqst[num_rqst].rq_iov = close_iov;
 314         rqst[num_rqst].rq_nvec = 1;
 315         rc = SMB2_close_init(tcon, &rqst[num_rqst], COMPOUND_FID,
 316                              COMPOUND_FID);
 317         smb2_set_related(&rqst[num_rqst]);
 318         if (rc)
 319                 goto finished;
 320  after_close:
 321         num_rqst++;
 322 
 323         if (cfile) {
 324                 cifsFileInfo_put(cfile);
 325                 cfile = NULL;
 326                 rc = compound_send_recv(xid, ses, flags, num_rqst - 2,
 327                                         &rqst[1], &resp_buftype[1],
 328                                         &rsp_iov[1]);
 329         } else
 330                 rc = compound_send_recv(xid, ses, flags, num_rqst,
 331                                         rqst, resp_buftype,
 332                                         rsp_iov);
 333 
 334  finished:
 335         if (cfile)
 336                 cifsFileInfo_put(cfile);
 337 
 338         SMB2_open_free(&rqst[0]);
 339         if (rc == -EREMCHG) {
 340                 printk_once(KERN_WARNING "server share %s deleted\n",
 341                             tcon->treeName);
 342                 tcon->need_reconnect = true;
 343         }
 344 
 345         switch (command) {
 346         case SMB2_OP_QUERY_INFO:
 347                 if (rc == 0) {
 348                         qi_rsp = (struct smb2_query_info_rsp *)
 349                                 rsp_iov[1].iov_base;
 350                         rc = smb2_validate_and_copy_iov(
 351                                 le16_to_cpu(qi_rsp->OutputBufferOffset),
 352                                 le32_to_cpu(qi_rsp->OutputBufferLength),
 353                                 &rsp_iov[1], sizeof(struct smb2_file_all_info),
 354                                 ptr);
 355                 }
 356                 if (rqst[1].rq_iov)
 357                         SMB2_query_info_free(&rqst[1]);
 358                 if (rqst[2].rq_iov)
 359                         SMB2_close_free(&rqst[2]);
 360                 if (rc)
 361                         trace_smb3_query_info_compound_err(xid,  ses->Suid,
 362                                                 tcon->tid, rc);
 363                 else
 364                         trace_smb3_query_info_compound_done(xid, ses->Suid,
 365                                                 tcon->tid);
 366                 break;
 367         case SMB2_OP_DELETE:
 368                 if (rc)
 369                         trace_smb3_delete_err(xid,  ses->Suid, tcon->tid, rc);
 370                 else
 371                         trace_smb3_delete_done(xid, ses->Suid, tcon->tid);
 372                 if (rqst[1].rq_iov)
 373                         SMB2_close_free(&rqst[1]);
 374                 break;
 375         case SMB2_OP_MKDIR:
 376                 if (rc)
 377                         trace_smb3_mkdir_err(xid,  ses->Suid, tcon->tid, rc);
 378                 else
 379                         trace_smb3_mkdir_done(xid, ses->Suid, tcon->tid);
 380                 if (rqst[1].rq_iov)
 381                         SMB2_close_free(&rqst[1]);
 382                 break;
 383         case SMB2_OP_HARDLINK:
 384                 if (rc)
 385                         trace_smb3_hardlink_err(xid,  ses->Suid, tcon->tid, rc);
 386                 else
 387                         trace_smb3_hardlink_done(xid, ses->Suid, tcon->tid);
 388                 free_set_inf_compound(rqst);
 389                 break;
 390         case SMB2_OP_RENAME:
 391                 if (rc)
 392                         trace_smb3_rename_err(xid,  ses->Suid, tcon->tid, rc);
 393                 else
 394                         trace_smb3_rename_done(xid, ses->Suid, tcon->tid);
 395                 free_set_inf_compound(rqst);
 396                 break;
 397         case SMB2_OP_RMDIR:
 398                 if (rc)
 399                         trace_smb3_rmdir_err(xid,  ses->Suid, tcon->tid, rc);
 400                 else
 401                         trace_smb3_rmdir_done(xid, ses->Suid, tcon->tid);
 402                 free_set_inf_compound(rqst);
 403                 break;
 404         case SMB2_OP_SET_EOF:
 405                 if (rc)
 406                         trace_smb3_set_eof_err(xid,  ses->Suid, tcon->tid, rc);
 407                 else
 408                         trace_smb3_set_eof_done(xid, ses->Suid, tcon->tid);
 409                 free_set_inf_compound(rqst);
 410                 break;
 411         case SMB2_OP_SET_INFO:
 412                 if (rc)
 413                         trace_smb3_set_info_compound_err(xid,  ses->Suid,
 414                                                 tcon->tid, rc);
 415                 else
 416                         trace_smb3_set_info_compound_done(xid, ses->Suid,
 417                                                 tcon->tid);
 418                 free_set_inf_compound(rqst);
 419                 break;
 420         }
 421         free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
 422         free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
 423         free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
 424         return rc;
 425 }
 426 
 427 void
 428 move_smb2_info_to_cifs(FILE_ALL_INFO *dst, struct smb2_file_all_info *src)
 429 {
 430         memcpy(dst, src, (size_t)(&src->CurrentByteOffset) - (size_t)src);
 431         dst->CurrentByteOffset = src->CurrentByteOffset;
 432         dst->Mode = src->Mode;
 433         dst->AlignmentRequirement = src->AlignmentRequirement;
 434         dst->IndexNumber1 = 0; /* we don't use it */
 435 }
 436 
 437 int
 438 smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
 439                      struct cifs_sb_info *cifs_sb, const char *full_path,
 440                      FILE_ALL_INFO *data, bool *adjust_tz, bool *symlink)
 441 {
 442         int rc;
 443         struct smb2_file_all_info *smb2_data;
 444         __u32 create_options = 0;
 445         struct cifs_fid fid;
 446         bool no_cached_open = tcon->nohandlecache;
 447         struct cifsFileInfo *cfile;
 448 
 449         *adjust_tz = false;
 450         *symlink = false;
 451 
 452         smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
 453                             GFP_KERNEL);
 454         if (smb2_data == NULL)
 455                 return -ENOMEM;
 456 
 457         /* If it is a root and its handle is cached then use it */
 458         if (!strlen(full_path) && !no_cached_open) {
 459                 rc = open_shroot(xid, tcon, &fid);
 460                 if (rc)
 461                         goto out;
 462 
 463                 if (tcon->crfid.file_all_info_is_valid) {
 464                         move_smb2_info_to_cifs(data,
 465                                                &tcon->crfid.file_all_info);
 466                 } else {
 467                         rc = SMB2_query_info(xid, tcon, fid.persistent_fid,
 468                                              fid.volatile_fid, smb2_data);
 469                         if (!rc)
 470                                 move_smb2_info_to_cifs(data, smb2_data);
 471                 }
 472                 close_shroot(&tcon->crfid);
 473                 goto out;
 474         }
 475 
 476         if (backup_cred(cifs_sb))
 477                 create_options |= CREATE_OPEN_BACKUP_INTENT;
 478 
 479         cifs_get_readable_path(tcon, full_path, &cfile);
 480         rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
 481                               FILE_READ_ATTRIBUTES, FILE_OPEN, create_options,
 482                               ACL_NO_MODE, smb2_data, SMB2_OP_QUERY_INFO, cfile);
 483         if (rc == -EOPNOTSUPP) {
 484                 *symlink = true;
 485                 create_options |= OPEN_REPARSE_POINT;
 486 
 487                 /* Failed on a symbolic link - query a reparse point info */
 488                 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
 489                                       FILE_READ_ATTRIBUTES, FILE_OPEN,
 490                                       create_options, ACL_NO_MODE,
 491                                       smb2_data, SMB2_OP_QUERY_INFO, NULL);
 492         }
 493         if (rc)
 494                 goto out;
 495 
 496         move_smb2_info_to_cifs(data, smb2_data);
 497 out:
 498         kfree(smb2_data);
 499         return rc;
 500 }
 501 
 502 int
 503 smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode,
 504            struct cifs_tcon *tcon, const char *name,
 505            struct cifs_sb_info *cifs_sb)
 506 {
 507         return smb2_compound_op(xid, tcon, cifs_sb, name,
 508                                 FILE_WRITE_ATTRIBUTES, FILE_CREATE,
 509                                 CREATE_NOT_FILE, mode, NULL, SMB2_OP_MKDIR,
 510                                 NULL);
 511 }
 512 
 513 void
 514 smb2_mkdir_setinfo(struct inode *inode, const char *name,
 515                    struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon,
 516                    const unsigned int xid)
 517 {
 518         FILE_BASIC_INFO data;
 519         struct cifsInodeInfo *cifs_i;
 520         struct cifsFileInfo *cfile;
 521         u32 dosattrs;
 522         int tmprc;
 523 
 524         memset(&data, 0, sizeof(data));
 525         cifs_i = CIFS_I(inode);
 526         dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
 527         data.Attributes = cpu_to_le32(dosattrs);
 528         cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile);
 529         tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
 530                                  FILE_WRITE_ATTRIBUTES, FILE_CREATE,
 531                                  CREATE_NOT_FILE, ACL_NO_MODE,
 532                                  &data, SMB2_OP_SET_INFO, cfile);
 533         if (tmprc == 0)
 534                 cifs_i->cifsAttrs = dosattrs;
 535 }
 536 
 537 int
 538 smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
 539            struct cifs_sb_info *cifs_sb)
 540 {
 541         return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
 542                                 CREATE_NOT_FILE, ACL_NO_MODE,
 543                                 NULL, SMB2_OP_RMDIR, NULL);
 544 }
 545 
 546 int
 547 smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
 548             struct cifs_sb_info *cifs_sb)
 549 {
 550         return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
 551                                 CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT,
 552                                 ACL_NO_MODE, NULL, SMB2_OP_DELETE, NULL);
 553 }
 554 
 555 static int
 556 smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
 557                    const char *from_name, const char *to_name,
 558                    struct cifs_sb_info *cifs_sb, __u32 access, int command,
 559                    struct cifsFileInfo *cfile)
 560 {
 561         __le16 *smb2_to_name = NULL;
 562         int rc;
 563 
 564         smb2_to_name = cifs_convert_path_to_utf16(to_name, cifs_sb);
 565         if (smb2_to_name == NULL) {
 566                 rc = -ENOMEM;
 567                 goto smb2_rename_path;
 568         }
 569         rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access,
 570                               FILE_OPEN, 0, ACL_NO_MODE, smb2_to_name,
 571                               command, cfile);
 572 smb2_rename_path:
 573         kfree(smb2_to_name);
 574         return rc;
 575 }
 576 
 577 int
 578 smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon,
 579                  const char *from_name, const char *to_name,
 580                  struct cifs_sb_info *cifs_sb)
 581 {
 582         struct cifsFileInfo *cfile;
 583 
 584         cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile);
 585 
 586         return smb2_set_path_attr(xid, tcon, from_name, to_name,
 587                                   cifs_sb, DELETE, SMB2_OP_RENAME, cfile);
 588 }
 589 
 590 int
 591 smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
 592                      const char *from_name, const char *to_name,
 593                      struct cifs_sb_info *cifs_sb)
 594 {
 595         return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
 596                                   FILE_READ_ATTRIBUTES, SMB2_OP_HARDLINK,
 597                                   NULL);
 598 }
 599 
 600 int
 601 smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
 602                    const char *full_path, __u64 size,
 603                    struct cifs_sb_info *cifs_sb, bool set_alloc)
 604 {
 605         __le64 eof = cpu_to_le64(size);
 606 
 607         return smb2_compound_op(xid, tcon, cifs_sb, full_path,
 608                                 FILE_WRITE_DATA, FILE_OPEN, 0, ACL_NO_MODE,
 609                                 &eof, SMB2_OP_SET_EOF, NULL);
 610 }
 611 
 612 int
 613 smb2_set_file_info(struct inode *inode, const char *full_path,
 614                    FILE_BASIC_INFO *buf, const unsigned int xid)
 615 {
 616         struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
 617         struct tcon_link *tlink;
 618         int rc;
 619 
 620         if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) &&
 621             (buf->LastWriteTime == 0) && (buf->ChangeTime == 0) &&
 622             (buf->Attributes == 0))
 623                 return 0; /* would be a no op, no sense sending this */
 624 
 625         tlink = cifs_sb_tlink(cifs_sb);
 626         if (IS_ERR(tlink))
 627                 return PTR_ERR(tlink);
 628 
 629         rc = smb2_compound_op(xid, tlink_tcon(tlink), cifs_sb, full_path,
 630                               FILE_WRITE_ATTRIBUTES, FILE_OPEN,
 631                               0, ACL_NO_MODE, buf, SMB2_OP_SET_INFO, NULL);
 632         cifs_put_tlink(tlink);
 633         return rc;
 634 }

/* [<][>][^][v][top][bottom][index][help] */