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