1/* 2 * Copyright (c) 1990,1993 Regents of The University of Michigan. 3 * All Rights Reserved. See COPYRIGHT. 4 */ 5 6#ifdef HAVE_CONFIG_H 7#include "config.h" 8#endif /* HAVE_CONFIG_H */ 9 10#include <stdio.h> 11#include <stdlib.h> 12/* STDC check */ 13#if STDC_HEADERS 14#include <string.h> 15#else /* STDC_HEADERS */ 16#ifndef HAVE_STRCHR 17#define strchr index 18#define strrchr index 19#endif /* HAVE_STRCHR */ 20char *strchr (), *strrchr (); 21#ifndef HAVE_MEMCPY 22#define memcpy(d,s,n) bcopy ((s), (d), (n)) 23#define memmove(d,s,n) bcopy ((s), (d), (n)) 24#endif /* ! HAVE_MEMCPY */ 25#endif /* STDC_HEADERS */ 26 27#ifdef HAVE_STRINGS_H 28#include <strings.h> 29#endif 30#include <errno.h> 31#include <sys/param.h> 32 33#include <atalk/adouble.h> 34#include <atalk/vfs.h> 35#include <atalk/afp.h> 36#include <atalk/util.h> 37#include <atalk/cnid.h> 38#include <atalk/logger.h> 39#include <atalk/unix.h> 40#include <atalk/bstrlib.h> 41#include <atalk/bstradd.h> 42#include <atalk/acl.h> 43#include <atalk/globals.h> 44#include <atalk/fce_api.h> 45 46#include "directory.h" 47#include "dircache.h" 48#include "desktop.h" 49#include "volume.h" 50#include "fork.h" 51#include "file.h" 52#include "filedir.h" 53#include "unix.h" 54 55/* foxconn add start, improvemennt of time machine backup rate, 56 Jonathan 2012/08/22 */ 57#define TIME_MACHINE_WA 58 59#ifdef DROPKLUDGE 60int matchfile2dirperms( 61/* Since it's kinda' big; I decided against an 62 inline function */ 63 char *upath, 64 struct vol *vol, 65 int did) 66/* The below code changes the way file ownership is determined in the name of 67 fixing dropboxes. It has known security problem. See the netatalk FAQ for 68 more information */ 69{ 70 struct stat st, sb; 71 struct dir *dir; 72 char *adpath; 73 uid_t uid; 74 int ret = AFP_OK; 75#ifdef DEBUG 76 LOG(log_debug9, logtype_afpd, "begin matchfile2dirperms:"); 77#endif 78 79 if (stat(upath, &st ) < 0) { 80 LOG(log_error, logtype_afpd, "Could not stat %s: %s", upath, strerror(errno)); 81 return AFPERR_NOOBJ ; 82 } 83 84 adpath = vol->vfs->ad_path( upath, ADFLAGS_HF ); 85 /* FIXME dirsearch doesn't move cwd to did ! */ 86 if (( dir = dirlookup( vol, did )) == NULL ) { 87 LOG(log_error, logtype_afpd, "matchfile2dirperms: Unable to get directory info."); 88 ret = AFPERR_NOOBJ; 89 } 90 else if (stat(".", &sb) < 0) { 91 LOG(log_error, logtype_afpd, 92 "matchfile2dirperms: Error checking directory \"%s\": %s", 93 dir->d_m_name, strerror(errno)); 94 ret = AFPERR_NOOBJ; 95 } 96 else { 97 uid=geteuid(); 98 if ( uid != sb.st_uid ) 99 { 100 seteuid(0); 101 if (lchown(upath, sb.st_uid, sb.st_gid) < 0) 102 { 103 LOG(log_error, logtype_afpd, 104 "matchfile2dirperms(%s): Error changing owner/gid: %s", 105 upath, strerror(errno)); 106 ret = AFPERR_ACCESS; 107 } 108 else if ((!S_ISLNK(st->st_mode)) && (chmod(upath,(st.st_mode&~default_options.umask)| S_IRGRP| S_IROTH) < 0)) 109 { 110 LOG(log_error, logtype_afpd, 111 "matchfile2dirperms(%s): Error adding file read permissions: %s", 112 upath, strerror(errno)); 113 ret = AFPERR_ACCESS; 114 } 115 else if (lchown(adpath, sb.st_uid, sb.st_gid) < 0) 116 { 117 LOG(log_error, logtype_afpd, 118 "matchfile2dirperms(%s): Error changing AppleDouble owner/gid: %s", 119 adpath, strerror(errno)); 120 ret = AFPERR_ACCESS; 121 } 122 else if (chmod(adpath, (st.st_mode&~default_options.umask)| S_IRGRP| S_IROTH) < 0) 123 { 124 LOG(log_error, logtype_afpd, 125 "matchfile2dirperms(%s): Error adding AD file read permissions: %s", 126 adpath, strerror(errno)); 127 ret = AFPERR_ACCESS; 128 } 129 seteuid(uid); 130 } 131 } /* end else if stat success */ 132 133#ifdef DEBUG 134 LOG(log_debug9, logtype_afpd, "end matchfile2dirperms:"); 135#endif 136 return ret; 137} 138#endif 139 140int afp_getfildirparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) 141{ 142 struct stat *st; 143 struct vol *vol; 144 struct dir *dir; 145 u_int32_t did; 146 int ret; 147 size_t buflen; 148 u_int16_t fbitmap, dbitmap, vid; 149 struct path *s_path; 150 151 *rbuflen = 0; 152 ibuf += 2; 153 154 memcpy( &vid, ibuf, sizeof( vid )); 155 ibuf += sizeof( vid ); 156 if (NULL == ( vol = getvolbyvid( vid )) ) { 157 /* was AFPERR_PARAM but it helps OS 10.3 when a volume has been removed 158 * from the list. 159 */ 160 return( AFPERR_ACCESS ); 161 } 162 163 memcpy( &did, ibuf, sizeof( did )); 164 ibuf += sizeof( did ); 165 166 if (NULL == ( dir = dirlookup( vol, did )) ) { 167 return afp_errno; 168 } 169 170 memcpy( &fbitmap, ibuf, sizeof( fbitmap )); 171 fbitmap = ntohs( fbitmap ); 172 ibuf += sizeof( fbitmap ); 173 memcpy( &dbitmap, ibuf, sizeof( dbitmap )); 174 dbitmap = ntohs( dbitmap ); 175 ibuf += sizeof( dbitmap ); 176 177 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { 178 return get_afp_errno(AFPERR_NOOBJ); 179 } 180 181 LOG(log_debug, logtype_afpd, "getfildirparams(vid:%u, did:%u, f/d:%04x/%04x) {cwdid:%u, cwd: %s, name:'%s'}", 182 ntohs(vid), ntohl(dir->d_did), fbitmap, dbitmap, 183 ntohl(curdir->d_did), cfrombstr(curdir->d_fullpath), s_path->u_name); 184 185 st = &s_path->st; 186 if (!s_path->st_valid) { 187 /* it's a dir and it should be there 188 * because we chdir in it in cname or 189 * it's curdir (maybe deleted, but then we can't know). 190 * So we need to try harder. 191 */ 192 of_statdir(vol, s_path); 193 } 194 if ( s_path->st_errno != 0 ) { 195 if (afp_errno != AFPERR_ACCESS) { 196 return( AFPERR_NOOBJ ); 197 } 198 } 199 200 201 buflen = 0; 202 if (S_ISDIR(st->st_mode)) { 203 if (dbitmap) { 204 dir = s_path->d_dir; 205 if (!dir) 206 return AFPERR_NOOBJ; 207 208 ret = getdirparams(vol, dbitmap, s_path, dir, 209 rbuf + 3 * sizeof( u_int16_t ), &buflen ); 210 if (ret != AFP_OK ) 211 return( ret ); 212 } 213 /* this is a directory */ 214 *(rbuf + 2 * sizeof( u_int16_t )) = (char) FILDIRBIT_ISDIR; 215 } else { 216 if (fbitmap && AFP_OK != (ret = getfilparams(vol, fbitmap, s_path, curdir, 217 rbuf + 3 * sizeof( u_int16_t ), &buflen )) ) { 218 return( ret ); 219 } 220 /* this is a file */ 221 *(rbuf + 2 * sizeof( u_int16_t )) = FILDIRBIT_ISFILE; 222 } 223 *rbuflen = buflen + 3 * sizeof( u_int16_t ); 224 fbitmap = htons( fbitmap ); 225 memcpy( rbuf, &fbitmap, sizeof( fbitmap )); 226 rbuf += sizeof( fbitmap ); 227 dbitmap = htons( dbitmap ); 228 memcpy( rbuf, &dbitmap, sizeof( dbitmap )); 229 rbuf += sizeof( dbitmap ) + sizeof( u_char ); 230 *rbuf = 0; 231 232 return( AFP_OK ); 233} 234 235int afp_setfildirparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) 236{ 237 struct stat *st; 238 struct vol *vol; 239 struct dir *dir; 240 struct path *path; 241 u_int16_t vid, bitmap; 242 int did, rc; 243 244 *rbuflen = 0; 245 ibuf += 2; 246 memcpy( &vid, ibuf, sizeof(vid)); 247 ibuf += sizeof( vid ); 248 249 if (NULL == ( vol = getvolbyvid( vid )) ) { 250 return( AFPERR_PARAM ); 251 } 252 253 if (vol->v_flags & AFPVOL_RO) 254 return AFPERR_VLOCK; 255 256 memcpy( &did, ibuf, sizeof( did)); 257 ibuf += sizeof( did); 258 259 if (NULL == ( dir = dirlookup( vol, did )) ) { 260 return afp_errno; 261 } 262 263 memcpy( &bitmap, ibuf, sizeof( bitmap )); 264 bitmap = ntohs( bitmap ); 265 ibuf += sizeof( bitmap ); 266 267 if (NULL == ( path = cname( vol, dir, &ibuf ))) { 268 return get_afp_errno(AFPERR_NOOBJ); 269 } 270 271 st = &path->st; 272 if (!path->st_valid) { 273 /* it's a dir and it should be there 274 * because we chdir in it in cname 275 */ 276 of_statdir(vol, path); 277 } 278 279 if ( path->st_errno != 0 ) { 280 if (afp_errno != AFPERR_ACCESS) 281 return( AFPERR_NOOBJ ); 282 } 283 /* 284 * If ibuf is odd, make it even. 285 */ 286 if ((u_long)ibuf & 1 ) { 287 ibuf++; 288 } 289 290 if (S_ISDIR(st->st_mode)) { 291 rc = setdirparams(vol, path, bitmap, ibuf ); 292 } else { 293 rc = setfilparams(vol, path, bitmap, ibuf ); 294 } 295 if ( rc == AFP_OK ) { 296 setvoltime(obj, vol ); 297 } 298 299 return( rc ); 300} 301 302/* -------------------------------------------- 303 Factorise some checks on a pathname 304*/ 305int check_name(const struct vol *vol, char *name) 306{ 307 /* check for illegal characters in the unix filename */ 308 if (!wincheck(vol, name)) 309 return AFPERR_PARAM; 310 311 if ((vol->v_flags & AFPVOL_NOHEX) && strchr(name, '/')) 312 return AFPERR_PARAM; 313 314 if (!vol->vfs->vfs_validupath(vol, name)) { 315 LOG(log_error, logtype_afpd, "check_name: illegal name: '%s'", name); 316 return AFPERR_EXIST; 317 } 318 319 /* check for vetoed filenames */ 320 if (veto_file(vol->v_veto, name)) 321 return AFPERR_EXIST; 322 return 0; 323} 324 325/* ------------------------- 326 move and rename sdir:oldname to curdir:newname in volume vol 327 special care is needed for lock 328*/ 329static int moveandrename(const struct vol *vol, 330 struct dir *sdir, 331 int sdir_fd, 332 char *oldname, 333 char *newname, 334 int isdir) 335{ 336 char *oldunixname = NULL; 337 char *upath; 338 int rc; 339 struct stat *st, nst; 340 int adflags; 341 struct adouble ad; 342 struct adouble *adp; 343 struct ofork *opened = NULL; 344 struct path path; 345 cnid_t id; 346 int cwd_fd = -1; 347 348 LOG(log_debug, logtype_afpd, 349 "moveandrename: [\"%s\"/\"%s\"] -> \"%s\"", 350 cfrombstr(sdir->d_u_name), oldname, newname); 351 352 ad_init(&ad, vol->v_adouble, vol->v_ad_options); 353 adp = &ad; 354 adflags = 0; 355 356 if (!isdir) { 357 if ((oldunixname = strdup(mtoupath(vol, oldname, sdir->d_did, utf8_encoding()))) == NULL) 358 return AFPERR_PARAM; /* can't convert */ 359 id = cnid_get(vol->v_cdb, sdir->d_did, oldunixname, strlen(oldunixname)); 360 361#ifndef HAVE_ATFUNCS 362 /* Need full path */ 363 free(oldunixname); 364 if ((oldunixname = strdup(ctoupath(vol, sdir, oldname))) == NULL) 365 return AFPERR_PARAM; /* pathname too long */ 366#endif /* HAVE_ATFUNCS */ 367 368 path.st_valid = 0; 369 path.u_name = oldunixname; 370 371#ifdef HAVE_ATFUNCS 372 opened = of_findnameat(sdir_fd, &path); 373#else 374 opened = of_findname(&path); 375#endif /* HAVE_ATFUNCS */ 376 377 if (opened) { 378 /* reuse struct adouble so it won't break locks */ 379 adp = opened->of_ad; 380 } 381 } else { 382 id = sdir->d_did; /* we already have the CNID */ 383 if ((oldunixname = strdup(ctoupath( vol, dirlookup(vol, sdir->d_pdid), oldname))) == NULL) 384 return AFPERR_PARAM; 385 adflags = ADFLAGS_DIR; 386 } 387 388 /* 389 * oldunixname now points to either 390 * a) full pathname of the source fs object (if renameat is not available) 391 * b) the oldname (renameat is available) 392 * we are in the dest folder so we need to use 393 * a) oldunixname for ad_open 394 * b) fchdir sdir_fd before eg ad_open or use *at functions where appropiate 395 */ 396 397 if (sdir_fd != -1) { 398 if ((cwd_fd = open(".", O_RDONLY)) == -1) 399 return AFPERR_MISC; 400 if (fchdir(sdir_fd) != 0) { 401 rc = AFPERR_MISC; 402 goto exit; 403 } 404 } 405 if (!ad_metadata(oldunixname, adflags, adp)) { 406 u_int16_t bshort; 407 408 ad_getattr(adp, &bshort); 409 ad_close_metadata( adp); 410 if ((bshort & htons(ATTRBIT_NORENAME))) { 411 rc = AFPERR_OLOCK; 412 goto exit; 413 } 414 } 415 if (sdir_fd != -1) { 416 if (fchdir(cwd_fd) != 0) { 417 LOG(log_error, logtype_afpd, "moveandrename: %s", strerror(errno) ); 418 rc = AFPERR_MISC; 419 goto exit; 420 } 421 } 422 423 if (NULL == (upath = mtoupath(vol, newname, curdir->d_did, utf8_encoding()))){ 424 rc = AFPERR_PARAM; 425 goto exit; 426 } 427 path.u_name = upath; 428 st = &path.st; 429 if (0 != (rc = check_name(vol, upath))) { 430 goto exit; 431 } 432 433 /* source == destination. we just silently accept this. */ 434 if ((!isdir && curdir == sdir) || (isdir && curdir->d_did == sdir->d_pdid)) { 435 if (strcmp(oldname, newname) == 0) { 436 rc = AFP_OK; 437 goto exit; 438 } 439 440 if (stat(upath, st) == 0 || caseenumerate(vol, &path, curdir) == 0) { 441 if (!stat(oldunixname, &nst) && !(nst.st_dev == st->st_dev && nst.st_ino == st->st_ino) ) { 442 /* not the same file */ 443 rc = AFPERR_EXIST; 444 goto exit; 445 } 446 errno = 0; 447 } 448 } else if (stat(upath, st ) == 0 || caseenumerate(vol, &path, curdir) == 0) { 449 rc = AFPERR_EXIST; 450 goto exit; 451 } 452 453 if ( !isdir ) { 454 path.st_valid = 1; 455 path.st_errno = errno; 456 if (of_findname(&path)) { 457 rc = AFPERR_EXIST; /* was AFPERR_BUSY; */ 458 } else { 459 rc = renamefile(vol, sdir_fd, oldunixname, upath, newname, adp ); 460 if (rc == AFP_OK) 461 of_rename(vol, opened, sdir, oldname, curdir, newname); 462 } 463 } else { 464 rc = renamedir(vol, sdir_fd, oldunixname, upath, sdir, curdir, newname); 465 } 466 if ( rc == AFP_OK && id ) { 467 /* renaming may have moved the file/dir across a filesystem */ 468 if (stat(upath, st) < 0) { 469 rc = AFPERR_MISC; 470 goto exit; 471 } 472 473 /* Remove it from the cache */ 474 struct dir *cacheddir = dircache_search_by_did(vol, id); 475 if (cacheddir) { 476 LOG(log_warning, logtype_afpd,"Still cached: \"%s/%s\"", getcwdpath(), upath); 477 (void)dir_remove(vol, cacheddir); 478 } 479 480 /* Fixup adouble info */ 481 if (!ad_metadata(upath, adflags, adp)) { 482 ad_setid(adp, st->st_dev, st->st_ino, id, curdir->d_did, vol->v_stamp); 483 ad_flush(adp); 484 ad_close_metadata(adp); 485 } 486 487 /* fix up the catalog entry */ 488 cnid_update(vol->v_cdb, id, st, curdir->d_did, upath, strlen(upath)); 489 } 490 491exit: 492 if (cwd_fd != -1) 493 close(cwd_fd); 494 if (oldunixname) 495 free(oldunixname); 496 return rc; 497} 498 499/* -------------------------------------------- */ 500int afp_rename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) 501{ 502 struct vol *vol; 503 struct dir *sdir; 504 char *oldname, *newname; 505 struct path *path; 506 u_int32_t did; 507 int plen; 508 u_int16_t vid; 509 int isdir = 0; 510 int rc; 511 512 *rbuflen = 0; 513 ibuf += 2; 514 515 memcpy( &vid, ibuf, sizeof( vid )); 516 ibuf += sizeof( vid ); 517 if (NULL == ( vol = getvolbyvid( vid )) ) { 518 return( AFPERR_PARAM ); 519 } 520 521 if (vol->v_flags & AFPVOL_RO) 522 return AFPERR_VLOCK; 523 524 memcpy( &did, ibuf, sizeof( did )); 525 ibuf += sizeof( did ); 526 if (NULL == ( sdir = dirlookup( vol, did )) ) { 527 return afp_errno; 528 } 529 530 /* source pathname */ 531 if (NULL == ( path = cname( vol, sdir, &ibuf )) ) { 532 return get_afp_errno(AFPERR_NOOBJ); 533 } 534 535 sdir = curdir; 536 newname = obj->newtmp; 537 oldname = obj->oldtmp; 538 isdir = path_isadir(path); 539 if ( *path->m_name != '\0' ) { 540 strcpy(oldname, path->m_name); /* an extra copy for of_rename */ 541 if (isdir) { 542 /* curdir parent dir, need to move sdir back */ 543 sdir = path->d_dir; 544 } 545 } 546 else { 547 if ( sdir->d_did == DIRDID_ROOT ) { /* root directory */ 548 return( AFPERR_NORENAME ); 549 } 550 /* move to destination dir */ 551 if ( movecwd( vol, dirlookup(vol, sdir->d_pdid) ) < 0 ) { 552 return afp_errno; 553 } 554 memcpy(oldname, cfrombstr(sdir->d_m_name), blength(sdir->d_m_name) +1); 555 } 556 557 /* another place where we know about the path type */ 558 if ((plen = copy_path_name(vol, newname, ibuf)) < 0) { 559 return( AFPERR_PARAM ); 560 } 561 562 if (!plen) { 563 return AFP_OK; /* newname == oldname same dir */ 564 } 565 566 rc = moveandrename(vol, sdir, -1, oldname, newname, isdir); 567 if ( rc == AFP_OK ) { 568 setvoltime(obj, vol ); 569 } 570 571 return( rc ); 572} 573 574/* ------------------------------- */ 575int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) 576{ 577 struct vol *vol; 578 struct dir *dir; 579 struct path *s_path; 580 char *upath; 581 int did, rc; 582 u_int16_t vid; 583 584 *rbuflen = 0; 585 ibuf += 2; 586 587 memcpy( &vid, ibuf, sizeof( vid )); 588 ibuf += sizeof( vid ); 589 if (NULL == ( vol = getvolbyvid( vid )) ) { 590 return( AFPERR_PARAM ); 591 } 592 593 if (vol->v_flags & AFPVOL_RO) 594 return AFPERR_VLOCK; 595 596 memcpy( &did, ibuf, sizeof( did )); 597 ibuf += sizeof( int ); 598 599 if (NULL == ( dir = dirlookup( vol, did )) ) { 600 return afp_errno; 601 } 602 603 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { 604 return get_afp_errno(AFPERR_NOOBJ); 605 } 606 607 upath = s_path->u_name; 608 if ( path_isadir( s_path) ) { 609 if (*s_path->m_name != '\0' || curdir->d_did == DIRDID_ROOT) { 610 rc = AFPERR_ACCESS; 611 } else { 612 /* we have to cache this, the structs are lost in deletcurdir*/ 613 /* but we need the positive returncode to send our event */ 614 bstring dname; 615 if ((dname = bstrcpy(curdir->d_u_name)) == NULL) 616 return AFPERR_MISC; 617 if ((rc = deletecurdir(vol)) == AFP_OK) 618 fce_register_delete_dir(cfrombstr(dname)); 619 bdestroy(dname); 620 } 621 } else if (of_findname(s_path)) { 622 rc = AFPERR_BUSY; 623 } else { 624 /* it's a file st_valid should always be true 625 * only test for ENOENT because EACCES needs 626 * to read meta data in deletefile 627 */ 628 if (s_path->st_valid && s_path->st_errno == ENOENT) { 629 rc = AFPERR_NOOBJ; 630 } else { 631 if ((rc = deletefile(vol, -1, upath, 1)) == AFP_OK) { 632 fce_register_delete_file( s_path ); 633 if (vol->v_tm_used < s_path->st.st_size) 634 vol->v_tm_used = 0; 635 else 636 vol->v_tm_used -= s_path->st.st_size; 637 } 638 struct dir *cachedfile; 639 if ((cachedfile = dircache_search_by_name(vol, dir, upath, strlen(upath)))) { 640 dircache_remove(vol, cachedfile, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX); 641 dir_free(cachedfile); 642 } 643 } 644 } 645 if ( rc == AFP_OK ) { 646 curdir->d_offcnt--; 647/* foxconn add start, Jonathan 2012/08/22 */ 648#ifdef TIME_MACHINE_WA 649 afp_bandsdid_decreaseOffcnt(curdir->d_did); 650#endif 651 setvoltime(obj, vol ); 652 } 653 654 return( rc ); 655} 656/* ------------------------ */ 657char *absupath(const struct vol *vol, struct dir *dir, char *u) 658{ 659 static char pathbuf[MAXPATHLEN + 1]; 660 bstring path; 661 662 if (u == NULL || dir == NULL || vol == NULL) 663 return NULL; 664 665 if ((path = bstrcpy(dir->d_fullpath)) == NULL) 666 return NULL; 667 if (bcatcstr(path, "/") != BSTR_OK) 668 return NULL; 669 if (bcatcstr(path, u) != BSTR_OK) 670 return NULL; 671 if (path->slen > MAXPATHLEN) 672 return NULL; 673 674 LOG(log_debug, logtype_afpd, "absupath: %s", cfrombstr(path)); 675 676 strncpy(pathbuf, cfrombstr(path), blength(path) + 1); 677 bdestroy(path); 678 679 return(pathbuf); 680} 681 682char *ctoupath(const struct vol *vol, struct dir *dir, char *name) 683{ 684 if (vol == NULL || dir == NULL || name == NULL) 685 return NULL; 686 return absupath(vol, dir, mtoupath(vol, name, dir->d_did, utf8_encoding())); 687} 688 689/* ------------------------- */ 690int afp_moveandrename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) 691{ 692 struct vol *vol; 693 struct dir *sdir, *ddir; 694 int isdir; 695 char *oldname, *newname; 696 struct path *path; 697 int did; 698 int pdid; 699 int plen; 700 u_int16_t vid; 701 int rc; 702#ifdef DROPKLUDGE 703 int retvalue; 704#endif /* DROPKLUDGE */ 705 int sdir_fd = -1; 706 707 708 *rbuflen = 0; 709 ibuf += 2; 710 711 memcpy( &vid, ibuf, sizeof( vid )); 712 ibuf += sizeof( vid ); 713 if (NULL == ( vol = getvolbyvid( vid )) ) { 714 return( AFPERR_PARAM ); 715 } 716 717 if (vol->v_flags & AFPVOL_RO) 718 return AFPERR_VLOCK; 719 720 /* source did followed by dest did */ 721 memcpy( &did, ibuf, sizeof( did )); 722 ibuf += sizeof( int ); 723 if (NULL == ( sdir = dirlookup( vol, did )) ) { 724 return afp_errno; /* was AFPERR_PARAM */ 725 } 726 727 memcpy( &did, ibuf, sizeof( did )); 728 ibuf += sizeof( int ); 729 730 /* source pathname */ 731 if (NULL == ( path = cname( vol, sdir, &ibuf )) ) { 732 return get_afp_errno(AFPERR_NOOBJ); 733 } 734 735 sdir = curdir; 736 newname = obj->newtmp; 737 oldname = obj->oldtmp; 738 739 isdir = path_isadir(path); 740 if ( *path->m_name != '\0' ) { 741 if (isdir) { 742 sdir = path->d_dir; 743 } 744 strcpy(oldname, path->m_name); /* an extra copy for of_rename */ 745 } else { 746 memcpy(oldname, cfrombstr(sdir->d_m_name), blength(sdir->d_m_name) + 1); 747 } 748 749#ifdef HAVE_ATFUNCS 750 if ((sdir_fd = open(".", O_RDONLY)) == -1) 751 return AFPERR_MISC; 752#endif 753 754 /* get the destination directory */ 755 if (NULL == ( ddir = dirlookup( vol, did )) ) { 756 rc = afp_errno; /* was AFPERR_PARAM */ 757 goto exit; 758 } 759 if (NULL == ( path = cname( vol, ddir, &ibuf ))) { 760 rc = AFPERR_NOOBJ; 761 goto exit; 762 } 763 pdid = curdir->d_did; 764 if ( *path->m_name != '\0' ) { 765 rc = path_error(path, AFPERR_NOOBJ); 766 goto exit; 767 } 768 769 /* one more place where we know about path type */ 770 if ((plen = copy_path_name(vol, newname, ibuf)) < 0) { 771 rc = AFPERR_PARAM; 772 goto exit; 773 } 774 775 if (!plen) { 776 strcpy(newname, oldname); 777 } 778 779 /* This does the work */ 780 LOG(log_debug, logtype_afpd, "afp_move(oldname:'%s', newname:'%s', isdir:%u)", 781 oldname, newname, isdir); 782 rc = moveandrename(vol, sdir, sdir_fd, oldname, newname, isdir); 783 784 if ( rc == AFP_OK ) { 785 char *upath = mtoupath(vol, newname, pdid, utf8_encoding()); 786 787 if (NULL == upath) { 788 rc = AFPERR_PARAM; 789 goto exit; 790 } 791 curdir->d_offcnt++; 792/* foxconn add start, Jonathan 2012/08/22 */ 793#ifdef TIME_MACHINE_WA 794 afp_bandsdid_IncreaseOffcnt(curdir->d_did); 795#endif 796 797 sdir->d_offcnt--; 798/* foxconn add start, Jonathan 2012/08/22 */ 799#ifdef TIME_MACHINE_WA 800 afp_bandsdid_decreaseOffcnt(sdir->d_did); 801#endif 802#ifdef DROPKLUDGE 803 if (vol->v_flags & AFPVOL_DROPBOX) { 804 /* FIXME did is not always the source id */ 805 if ((retvalue=matchfile2dirperms (upath, vol, did)) != AFP_OK) { 806 rc = retvalue; 807 goto exit; 808 } 809 } 810 else 811#endif /* DROPKLUDGE */ 812 /* if unix priv don't try to match perm with dest folder */ 813 if (!isdir && !vol_unix_priv(vol)) { 814 int admode = ad_mode("", 0777) | vol->v_fperm; 815 816 setfilmode(upath, admode, NULL, vol->v_umask); 817 vol->vfs->vfs_setfilmode(vol, upath, admode, NULL); 818 } 819 setvoltime(obj, vol ); 820 } 821 822exit: 823#ifdef HAVE_ATFUNCS 824 if (sdir_fd != -1) 825 close(sdir_fd); 826#endif 827 828 return( rc ); 829} 830 831int veto_file(const char*veto_str, const char*path) 832/* given a veto_str like "abc/zxc/" and path "abc", return 1 833 * veto_str should be '/' delimited 834 * if path matches any one of the veto_str elements exactly, then 1 is returned 835 * otherwise, 0 is returned. 836 */ 837{ 838 int i; /* index to veto_str */ 839 int j; /* index to path */ 840 841 if ((veto_str == NULL) || (path == NULL)) 842 return 0; 843 844 for(i=0, j=0; veto_str[i] != '\0'; i++) { 845 if (veto_str[i] == '/') { 846 if ((j>0) && (path[j] == '\0')) { 847 LOG(log_debug, logtype_afpd, "vetoed file:'%s'", path); 848 return 1; 849 } 850 j = 0; 851 } else { 852 if (veto_str[i] != path[j]) { 853 while ((veto_str[i] != '/') 854 && (veto_str[i] != '\0')) 855 i++; 856 j = 0; 857 continue; 858 } 859 j++; 860 } 861 } 862 return 0; 863} 864 865