root/source4/ntvfs/posix/pvfs_rename.c

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

DEFINITIONS

This source file includes following definitions.
  1. pvfs_do_rename
  2. pvfs_resolve_wildcard_component
  3. pvfs_resolve_wildcard
  4. pvfs_retry_rename
  5. pvfs_rename_setup_retry
  6. pvfs_rename_one
  7. pvfs_rename_wildcard
  8. pvfs_rename_mv
  9. pvfs_rename_stream
  10. pvfs_rename_nt
  11. pvfs_rename

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    POSIX NTVFS backend - rename
   5 
   6    Copyright (C) Andrew Tridgell 2004
   7 
   8    This program is free software; you can redistribute it and/or modify
   9    it under the terms of the GNU General Public License as published by
  10    the Free Software Foundation; either version 3 of the License, or
  11    (at your option) any later version.
  12    
  13    This program is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16    GNU General Public License for more details.
  17    
  18    You should have received a copy of the GNU General Public License
  19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 #include "includes.h"
  23 #include "vfs_posix.h"
  24 #include "librpc/gen_ndr/security.h"
  25 #include "param/param.h"
  26 
  27 
  28 /*
  29   do a file rename, and send any notify triggers
  30 */
  31 NTSTATUS pvfs_do_rename(struct pvfs_state *pvfs,
     /* [<][>][^][v][top][bottom][index][help] */
  32                         struct odb_lock *lck,
  33                         const struct pvfs_filename *name1,
  34                         const char *name2)
  35 {
  36         const char *r1, *r2;
  37         uint32_t mask;
  38         NTSTATUS status;
  39 
  40         if (rename(name1->full_name, name2) == -1) {
  41                 return pvfs_map_errno(pvfs, errno);
  42         }
  43 
  44         status = odb_rename(lck, name2);
  45         NT_STATUS_NOT_OK_RETURN(status);
  46 
  47         if (name1->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
  48                 mask = FILE_NOTIFY_CHANGE_DIR_NAME;
  49         } else {
  50                 mask = FILE_NOTIFY_CHANGE_FILE_NAME;
  51         }
  52         /* 
  53            renames to the same directory cause a OLD_NAME->NEW_NAME notify.
  54            renames to a different directory are considered a remove/add 
  55         */
  56         r1 = strrchr_m(name1->full_name, '/');
  57         r2 = strrchr_m(name2, '/');
  58 
  59         if ((r1-name1->full_name) != (r2-name2) ||
  60             strncmp(name1->full_name, name2, r1-name1->full_name) != 0) {
  61                 notify_trigger(pvfs->notify_context, 
  62                                NOTIFY_ACTION_REMOVED, 
  63                                mask,
  64                                name1->full_name);
  65                 notify_trigger(pvfs->notify_context, 
  66                                NOTIFY_ACTION_ADDED, 
  67                                mask,
  68                                name2);
  69         } else {
  70                 notify_trigger(pvfs->notify_context, 
  71                                NOTIFY_ACTION_OLD_NAME, 
  72                                mask,
  73                                name1->full_name);
  74                 notify_trigger(pvfs->notify_context, 
  75                                NOTIFY_ACTION_NEW_NAME, 
  76                                mask,
  77                                name2);
  78         }
  79 
  80         /* this is a strange one. w2k3 gives an additional event for CHANGE_ATTRIBUTES
  81            and CHANGE_CREATION on the new file when renaming files, but not 
  82            directories */
  83         if ((name1->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) == 0) {
  84                 notify_trigger(pvfs->notify_context, 
  85                                NOTIFY_ACTION_MODIFIED, 
  86                                FILE_NOTIFY_CHANGE_ATTRIBUTES|FILE_NOTIFY_CHANGE_CREATION,
  87                                name2);
  88         }
  89         
  90         return NT_STATUS_OK;
  91 }
  92 
  93 
  94 /*
  95   resolve a wildcard rename pattern. This works on one component of the name
  96 */
  97 static const char *pvfs_resolve_wildcard_component(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
  98                                                    struct smb_iconv_convenience *iconv_convenience,
  99                                                    const char *fname, 
 100                                                    const char *pattern)
 101 {
 102         const char *p1, *p2;
 103         char *dest, *d;
 104 
 105         /* the length is bounded by the length of the two strings combined */
 106         dest = talloc_array(mem_ctx, char, strlen(fname) + strlen(pattern) + 1);
 107         if (dest == NULL) {
 108                 return NULL;
 109         }
 110 
 111         p1 = fname;
 112         p2 = pattern;
 113         d = dest;
 114 
 115         while (*p2) {
 116                 codepoint_t c1, c2;
 117                 size_t c_size1, c_size2;
 118                 c1 = next_codepoint_convenience(iconv_convenience, p1, &c_size1);
 119                 c2 = next_codepoint_convenience(iconv_convenience, p2, &c_size2);
 120                 if (c2 == '?') {
 121                         d += push_codepoint(iconv_convenience, d, c1);
 122                 } else if (c2 == '*') {
 123                         memcpy(d, p1, strlen(p1));
 124                         d += strlen(p1);
 125                         break;
 126                 } else {
 127                         d += push_codepoint(iconv_convenience, d, c2);
 128                 }
 129 
 130                 p1 += c_size1;
 131                 p2 += c_size2;
 132         }
 133 
 134         *d = 0;
 135 
 136         talloc_set_name_const(dest, dest);
 137 
 138         return dest;
 139 }
 140 
 141 /*
 142   resolve a wildcard rename pattern.
 143 */
 144 static const char *pvfs_resolve_wildcard(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 145                                          struct smb_iconv_convenience *iconv_convenience,
 146                                          const char *fname, 
 147                                          const char *pattern)
 148 {
 149         const char *base1, *base2;
 150         const char *ext1, *ext2;
 151         char *p;
 152 
 153         /* break into base part plus extension */
 154         p = strrchr_m(fname, '.');
 155         if (p == NULL) {
 156                 ext1 = "";
 157                 base1 = fname;
 158         } else {
 159                 ext1 = talloc_strdup(mem_ctx, p+1);
 160                 base1 = talloc_strndup(mem_ctx, fname, p-fname);
 161         }
 162         if (ext1 == NULL || base1 == NULL) {
 163                 return NULL;
 164         }
 165 
 166         p = strrchr_m(pattern, '.');
 167         if (p == NULL) {
 168                 ext2 = "";
 169                 base2 = fname;
 170         } else {
 171                 ext2 = talloc_strdup(mem_ctx, p+1);
 172                 base2 = talloc_strndup(mem_ctx, pattern, p-pattern);
 173         }
 174         if (ext2 == NULL || base2 == NULL) {
 175                 return NULL;
 176         }
 177 
 178         base1 = pvfs_resolve_wildcard_component(mem_ctx, iconv_convenience, base1, base2);
 179         ext1 = pvfs_resolve_wildcard_component(mem_ctx, iconv_convenience, ext1, ext2);
 180         if (base1 == NULL || ext1 == NULL) {
 181                 return NULL;
 182         }
 183 
 184         if (*ext1 == 0) {
 185                 return base1;
 186         }
 187 
 188         return talloc_asprintf(mem_ctx, "%s.%s", base1, ext1);
 189 }
 190 
 191 /*
 192   retry an rename after a sharing violation
 193 */
 194 static void pvfs_retry_rename(struct pvfs_odb_retry *r,
     /* [<][>][^][v][top][bottom][index][help] */
 195                               struct ntvfs_module_context *ntvfs,
 196                               struct ntvfs_request *req,
 197                               void *_io,
 198                               void *private_data,
 199                               enum pvfs_wait_notice reason)
 200 {
 201         union smb_rename *io = talloc_get_type(_io, union smb_rename);
 202         NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
 203 
 204         talloc_free(r);
 205 
 206         switch (reason) {
 207         case PVFS_WAIT_CANCEL:
 208 /*TODO*/
 209                 status = NT_STATUS_CANCELLED;
 210                 break;
 211         case PVFS_WAIT_TIMEOUT:
 212                 /* if it timed out, then give the failure
 213                    immediately */
 214 /*TODO*/
 215                 status = NT_STATUS_SHARING_VIOLATION;
 216                 break;
 217         case PVFS_WAIT_EVENT:
 218 
 219                 /* try the open again, which could trigger another retry setup
 220                    if it wants to, so we have to unmark the async flag so we
 221                    will know if it does a second async reply */
 222                 req->async_states->state &= ~NTVFS_ASYNC_STATE_ASYNC;
 223 
 224                 status = pvfs_rename(ntvfs, req, io);
 225                 if (req->async_states->state & NTVFS_ASYNC_STATE_ASYNC) {
 226                         /* the 2nd try also replied async, so we don't send
 227                            the reply yet */
 228                         return;
 229                 }
 230 
 231                 /* re-mark it async, just in case someone up the chain does
 232                    paranoid checking */
 233                 req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
 234                 break;
 235         }
 236 
 237         /* send the reply up the chain */
 238         req->async_states->status = status;
 239         req->async_states->send_fn(req);
 240 }
 241 
 242 /*
 243   setup for a rename retry after a sharing violation
 244   or a non granted oplock
 245 */
 246 static NTSTATUS pvfs_rename_setup_retry(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 247                                         struct ntvfs_request *req,
 248                                         union smb_rename *io,
 249                                         struct odb_lock *lck,
 250                                         NTSTATUS status)
 251 {
 252         struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
 253                                   struct pvfs_state);
 254         struct timeval end_time;
 255 
 256         if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
 257                 end_time = timeval_add(&req->statistics.request_time,
 258                                        0, pvfs->sharing_violation_delay);
 259         } else if (NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
 260                 end_time = timeval_add(&req->statistics.request_time,
 261                                        pvfs->oplock_break_timeout, 0);
 262         } else {
 263                 return NT_STATUS_INTERNAL_ERROR;
 264         }
 265 
 266         return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, io, NULL,
 267                                     pvfs_retry_rename);
 268 }
 269 
 270 /*
 271   rename one file from a wildcard set
 272 */
 273 static NTSTATUS pvfs_rename_one(struct pvfs_state *pvfs, 
     /* [<][>][^][v][top][bottom][index][help] */
 274                                 struct ntvfs_request *req, 
 275                                 const char *dir_path,
 276                                 const char *fname1,
 277                                 const char *fname2,
 278                                 uint16_t attrib)
 279 {
 280         struct pvfs_filename *name1, *name2;
 281         TALLOC_CTX *mem_ctx = talloc_new(req);
 282         struct odb_lock *lck = NULL;
 283         NTSTATUS status;
 284 
 285         /* resolve the wildcard pattern for this name */
 286         fname2 = pvfs_resolve_wildcard(mem_ctx, lp_iconv_convenience(pvfs->ntvfs->ctx->lp_ctx), fname1, fname2);
 287         if (fname2 == NULL) {
 288                 return NT_STATUS_NO_MEMORY;
 289         }
 290 
 291         /* get a pvfs_filename source object */
 292         status = pvfs_resolve_partial(pvfs, mem_ctx, 
 293                                       dir_path, fname1,
 294                                       PVFS_RESOLVE_NO_OPENDB,
 295                                       &name1);
 296         if (!NT_STATUS_IS_OK(status)) {
 297                 goto failed;
 298         }
 299 
 300         /* make sure its matches the given attributes */
 301         status = pvfs_match_attrib(pvfs, name1, attrib, 0);
 302         if (!NT_STATUS_IS_OK(status)) {
 303                 goto failed;
 304         }
 305 
 306         status = pvfs_can_rename(pvfs, req, name1, &lck);
 307         if (!NT_STATUS_IS_OK(status)) {
 308                 talloc_free(lck);
 309                 goto failed;
 310         }
 311 
 312         /* get a pvfs_filename dest object */
 313         status = pvfs_resolve_partial(pvfs, mem_ctx, 
 314                                       dir_path, fname2,
 315                                       PVFS_RESOLVE_NO_OPENDB,
 316                                       &name2);
 317         if (NT_STATUS_IS_OK(status)) {
 318                 status = pvfs_can_delete(pvfs, req, name2, NULL);
 319                 if (!NT_STATUS_IS_OK(status)) {
 320                         goto failed;
 321                 }
 322         }
 323 
 324         status = NT_STATUS_OK;
 325 
 326         fname2 = talloc_asprintf(mem_ctx, "%s/%s", dir_path, fname2);
 327         if (fname2 == NULL) {
 328                 return NT_STATUS_NO_MEMORY;
 329         }
 330 
 331         status = pvfs_do_rename(pvfs, lck, name1, fname2);
 332 
 333 failed:
 334         talloc_free(mem_ctx);
 335         return status;
 336 }
 337 
 338 
 339 /*
 340   rename a set of files with wildcards
 341 */
 342 static NTSTATUS pvfs_rename_wildcard(struct pvfs_state *pvfs, 
     /* [<][>][^][v][top][bottom][index][help] */
 343                                      struct ntvfs_request *req, 
 344                                      union smb_rename *ren, 
 345                                      struct pvfs_filename *name1, 
 346                                      struct pvfs_filename *name2)
 347 {
 348         struct pvfs_dir *dir;
 349         NTSTATUS status;
 350         off_t ofs = 0;
 351         const char *fname, *fname2, *dir_path;
 352         uint16_t attrib = ren->rename.in.attrib;
 353         int total_renamed = 0;
 354 
 355         /* get list of matching files */
 356         status = pvfs_list_start(pvfs, name1, req, &dir);
 357         if (!NT_STATUS_IS_OK(status)) {
 358                 return status;
 359         }
 360 
 361         status = NT_STATUS_NO_SUCH_FILE;
 362 
 363         dir_path = pvfs_list_unix_path(dir);
 364 
 365         /* only allow wildcard renames within a directory */
 366         if (strncmp(dir_path, name2->full_name, strlen(dir_path)) != 0 ||
 367             name2->full_name[strlen(dir_path)] != '/' ||
 368             strchr(name2->full_name + strlen(dir_path) + 1, '/')) {
 369                 return NT_STATUS_INVALID_PARAMETER;
 370         }
 371 
 372         fname2 = talloc_strdup(name2, name2->full_name + strlen(dir_path) + 1);
 373         if (fname2 == NULL) {
 374                 return NT_STATUS_NO_MEMORY;
 375         }
 376 
 377         while ((fname = pvfs_list_next(dir, &ofs))) {
 378                 status = pvfs_rename_one(pvfs, req, 
 379                                          dir_path,
 380                                          fname, fname2, attrib);
 381                 if (NT_STATUS_IS_OK(status)) {
 382                         total_renamed++;
 383                 }
 384         }
 385 
 386         if (total_renamed == 0) {
 387                 return status;
 388         }
 389 
 390         return NT_STATUS_OK;
 391 }
 392 
 393 /*
 394   rename a set of files - SMBmv interface
 395 */
 396 static NTSTATUS pvfs_rename_mv(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 397                                struct ntvfs_request *req, union smb_rename *ren)
 398 {
 399         struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
 400                                   struct pvfs_state);
 401         NTSTATUS status;
 402         struct pvfs_filename *name1, *name2;
 403         struct odb_lock *lck = NULL;
 404 
 405         /* resolve the cifs name to a posix name */
 406         status = pvfs_resolve_name(pvfs, req, ren->rename.in.pattern1, 
 407                                    PVFS_RESOLVE_WILDCARD, &name1);
 408         if (!NT_STATUS_IS_OK(status)) {
 409                 return status;
 410         }
 411 
 412         status = pvfs_resolve_name(pvfs, req, ren->rename.in.pattern2, 
 413                                    PVFS_RESOLVE_WILDCARD, &name2);
 414         if (!NT_STATUS_IS_OK(status)) {
 415                 return status;
 416         }
 417 
 418         if (name1->has_wildcard || name2->has_wildcard) {
 419                 return pvfs_rename_wildcard(pvfs, req, ren, name1, name2);
 420         }
 421 
 422         if (!name1->exists) {
 423                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 424         }
 425 
 426         if (strcmp(name1->full_name, name2->full_name) == 0) {
 427                 return NT_STATUS_OK;
 428         }
 429 
 430         if (name2->exists) {
 431                 return NT_STATUS_OBJECT_NAME_COLLISION;
 432         }
 433 
 434         status = pvfs_match_attrib(pvfs, name1, ren->rename.in.attrib, 0);
 435         if (!NT_STATUS_IS_OK(status)) {
 436                 return status;
 437         }
 438 
 439         status = pvfs_access_check_parent(pvfs, req, name2, SEC_DIR_ADD_FILE);
 440         if (!NT_STATUS_IS_OK(status)) {
 441                 return status;
 442         }
 443 
 444         status = pvfs_can_rename(pvfs, req, name1, &lck);
 445         /*
 446          * on a sharing violation we need to retry when the file is closed by
 447          * the other user, or after 1 second
 448          * on a non granted oplock we need to retry when the file is closed by
 449          * the other user, or after 30 seconds
 450          */
 451         if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
 452              NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) &&
 453             (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
 454                 return pvfs_rename_setup_retry(pvfs->ntvfs, req, ren, lck, status);
 455         }
 456 
 457         if (!NT_STATUS_IS_OK(status)) {
 458                 return status;
 459         }
 460 
 461         status = pvfs_do_rename(pvfs, lck, name1, name2->full_name);
 462         if (!NT_STATUS_IS_OK(status)) {
 463                 return status;
 464         }
 465         
 466         return NT_STATUS_OK;
 467 }
 468 
 469 
 470 /*
 471   rename a stream
 472 */
 473 static NTSTATUS pvfs_rename_stream(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 474                                    struct ntvfs_request *req, union smb_rename *ren,
 475                                    struct pvfs_filename *name1)
 476 {
 477         struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
 478                                   struct pvfs_state);
 479         NTSTATUS status;
 480         struct odb_lock *lck = NULL;
 481 
 482         if (name1->has_wildcard) {
 483                 return NT_STATUS_INVALID_PARAMETER;
 484         }
 485 
 486         if (ren->ntrename.in.new_name[0] != ':') {
 487                 return NT_STATUS_INVALID_PARAMETER;
 488         }
 489 
 490         if (!name1->exists) {
 491                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 492         }
 493 
 494         if (ren->ntrename.in.flags != RENAME_FLAG_RENAME) {
 495                 return NT_STATUS_INVALID_PARAMETER;
 496         }
 497 
 498         status = pvfs_can_rename(pvfs, req, name1, &lck);
 499         /*
 500          * on a sharing violation we need to retry when the file is closed by
 501          * the other user, or after 1 second
 502          * on a non granted oplock we need to retry when the file is closed by
 503          * the other user, or after 30 seconds
 504          */
 505         if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
 506              NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) &&
 507             (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
 508                 return pvfs_rename_setup_retry(pvfs->ntvfs, req, ren, lck, status);
 509         }
 510         if (!NT_STATUS_IS_OK(status)) {
 511                 return status;
 512         }
 513 
 514         status = pvfs_access_check_simple(pvfs, req, name1, SEC_FILE_WRITE_ATTRIBUTE);
 515         NT_STATUS_NOT_OK_RETURN(status);
 516 
 517         status = pvfs_stream_rename(pvfs, name1, -1, 
 518                                     ren->ntrename.in.new_name+1);
 519         NT_STATUS_NOT_OK_RETURN(status);
 520         
 521         return NT_STATUS_OK;
 522 }
 523 
 524 /*
 525   rename a set of files - ntrename interface
 526 */
 527 static NTSTATUS pvfs_rename_nt(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 528                                struct ntvfs_request *req, union smb_rename *ren)
 529 {
 530         struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
 531                                   struct pvfs_state);
 532         NTSTATUS status;
 533         struct pvfs_filename *name1, *name2;
 534         struct odb_lock *lck = NULL;
 535 
 536         switch (ren->ntrename.in.flags) {
 537         case RENAME_FLAG_RENAME:
 538         case RENAME_FLAG_HARD_LINK:
 539         case RENAME_FLAG_COPY:
 540         case RENAME_FLAG_MOVE_CLUSTER_INFORMATION:
 541                 break;
 542         default:
 543                 return NT_STATUS_ACCESS_DENIED;
 544         }
 545 
 546         /* resolve the cifs name to a posix name */
 547         status = pvfs_resolve_name(pvfs, req, ren->ntrename.in.old_name, 
 548                                    PVFS_RESOLVE_WILDCARD | PVFS_RESOLVE_STREAMS, &name1);
 549         if (!NT_STATUS_IS_OK(status)) {
 550                 return status;
 551         }
 552 
 553         if (name1->stream_name) {
 554                 /* stream renames need to be handled separately */
 555                 return pvfs_rename_stream(ntvfs, req, ren, name1);
 556         }
 557 
 558         status = pvfs_resolve_name(pvfs, req, ren->ntrename.in.new_name, 
 559                                    PVFS_RESOLVE_WILDCARD, &name2);
 560         if (!NT_STATUS_IS_OK(status)) {
 561                 return status;
 562         }
 563 
 564         if (name1->has_wildcard || name2->has_wildcard) {
 565                 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
 566         }
 567 
 568         if (!name1->exists) {
 569                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 570         }
 571 
 572         if (strcmp(name1->full_name, name2->full_name) == 0) {
 573                 return NT_STATUS_OK;
 574         }
 575 
 576         if (name2->exists) {
 577                 return NT_STATUS_OBJECT_NAME_COLLISION;
 578         }
 579 
 580         status = pvfs_match_attrib(pvfs, name1, ren->ntrename.in.attrib, 0);
 581         if (!NT_STATUS_IS_OK(status)) {
 582                 return status;
 583         }
 584 
 585         status = pvfs_can_rename(pvfs, req, name1, &lck);
 586         /*
 587          * on a sharing violation we need to retry when the file is closed by
 588          * the other user, or after 1 second
 589          * on a non granted oplock we need to retry when the file is closed by
 590          * the other user, or after 30 seconds
 591          */
 592         if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
 593              NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) &&
 594             (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
 595                 return pvfs_rename_setup_retry(pvfs->ntvfs, req, ren, lck, status);
 596         }
 597         if (!NT_STATUS_IS_OK(status)) {
 598                 return status;
 599         }
 600 
 601         switch (ren->ntrename.in.flags) {
 602         case RENAME_FLAG_RENAME:
 603                 status = pvfs_access_check_parent(pvfs, req, name2, SEC_DIR_ADD_FILE);
 604                 NT_STATUS_NOT_OK_RETURN(status);
 605                 status = pvfs_do_rename(pvfs, lck, name1, name2->full_name);
 606                 NT_STATUS_NOT_OK_RETURN(status);
 607                 break;
 608 
 609         case RENAME_FLAG_HARD_LINK:
 610                 status = pvfs_access_check_parent(pvfs, req, name2, SEC_DIR_ADD_FILE);
 611                 NT_STATUS_NOT_OK_RETURN(status);
 612                 if (link(name1->full_name, name2->full_name) == -1) {
 613                         return pvfs_map_errno(pvfs, errno);
 614                 }
 615                 break;
 616 
 617         case RENAME_FLAG_COPY:
 618                 status = pvfs_access_check_parent(pvfs, req, name2, SEC_DIR_ADD_FILE);
 619                 NT_STATUS_NOT_OK_RETURN(status);
 620                 return pvfs_copy_file(pvfs, name1, name2);
 621 
 622         case RENAME_FLAG_MOVE_CLUSTER_INFORMATION:
 623                 return NT_STATUS_INVALID_PARAMETER;
 624 
 625         default:
 626                 return NT_STATUS_ACCESS_DENIED;
 627         }
 628 
 629         
 630         return NT_STATUS_OK;
 631 }
 632 
 633 /*
 634   rename a set of files - ntrename interface
 635 */
 636 NTSTATUS pvfs_rename(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 637                      struct ntvfs_request *req, union smb_rename *ren)
 638 {
 639         struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
 640                                   struct pvfs_state);
 641         struct pvfs_file *f;
 642 
 643         switch (ren->generic.level) {
 644         case RAW_RENAME_RENAME:
 645                 return pvfs_rename_mv(ntvfs, req, ren);
 646 
 647         case RAW_RENAME_NTRENAME:
 648                 return pvfs_rename_nt(ntvfs, req, ren);
 649 
 650         case RAW_RENAME_NTTRANS:
 651                 f = pvfs_find_fd(pvfs, req, ren->nttrans.in.file.ntvfs);
 652                 if (!f) {
 653                         return NT_STATUS_INVALID_HANDLE;
 654                 }
 655 
 656                 /* wk23 ignores the request */
 657                 return NT_STATUS_OK;
 658 
 659         default:
 660                 break;
 661         }
 662 
 663         return NT_STATUS_INVALID_LEVEL;
 664 }
 665 

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