static int ad_conv_v22ea_rf(const char *path, const struct stat *sp, const struct vol *vol) { EC_INIT; struct adouble adv2; struct adouble adea; LOG(log_debug, logtype_default,"ad_conv_v22ea_rf(\"%s\"): BEGIN", fullpathname(path)); if (S_ISDIR(sp->st_mode)) return 0; ad_init(&adea, vol); ad_init_old(&adv2, AD_VERSION2, adea.ad_options); /* Open and lock adouble:v2 file */ EC_ZERO( ad_open(&adv2, path, ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDWR) ); if (adv2.ad_rlen > 0) { EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) ); /* Create a adouble:ea resource fork */ EC_ZERO_LOG( ad_open(&adea, path, ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) ); EC_ZERO_LOG( copy_fork(ADEID_RFORK, &adea, &adv2) ); adea.ad_rlen = adv2.ad_rlen; ad_flush(&adea); } EC_CLEANUP: EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_RF) ); EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_RF) ); LOG(log_debug, logtype_default,"ad_conv_v22ea_rf(\"%s\"): END: %d", fullpathname(path), ret); EC_EXIT; }
/*! * Remove hexencoded dots and slashes (":2e" and ":2f") */ static int ad_conv_dehex(const char *path, const struct stat *sp, const struct vol *vol, const char **newpathp) { EC_INIT; static char buf[MAXPATHLEN]; const char *adpath, *p; int adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0; bstring newpath = NULL; LOG(log_debug, logtype_default,"ad_conv_dehex(\"%s\"): BEGIN", fullpathname(path)); *newpathp = NULL; if ((p = strchr(path, ':')) == NULL) goto EC_CLEANUP; EC_NULL( newpath = bfromcstr(path) ); EC_ZERO( bfindreplace(newpath, bfromcstr(":2e"), bfromcstr("."), 0) ); EC_ZERO( bfindreplace(newpath, bfromcstr(":2f"), bfromcstr(":"), 0) ); become_root(); if (adflags != ADFLAGS_DIR) rename(vol->ad_path(path, 0), vol->ad_path(bdata(newpath), 0)); rename(path, bdata(newpath)); unbecome_root(); strlcpy(buf, bdata(newpath), sizeof(buf)); *newpathp = buf; EC_CLEANUP: if (newpath) bdestroy(newpath); EC_EXIT; }
static int ad_conv_v22ea(const char *path, const struct stat *sp, const struct vol *vol) { EC_INIT; const char *adpath; int adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0; become_root(); EC_ZERO( ad_conv_v22ea_hf(path, sp, vol) ); EC_ZERO( ad_conv_v22ea_rf(path, sp, vol) ); EC_NULL( adpath = ad_path(path, adflags) ); LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): deleting adouble:v2 file: \"%s\"", path, fullpathname(adpath)); unlink(adpath); EC_CLEANUP: if (errno == ENOENT) EC_STATUS(0); unbecome_root(); EC_EXIT; }
static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode) { EC_INIT; int filedes = -1, eafd = -1; if ((filedes = open(path, O_RDONLY | (oflag & O_NOFOLLOW), mode)) == -1) { switch (errno) { case ENOENT: case EEXIST: case OPEN_NOFOLLOW_ERRNO: EC_FAIL; default: LOG(log_debug, logtype_default, "open(\"%s\"): %s", fullpathname(path), strerror(errno)); errno = ENOATTR; EC_FAIL; } } if ((eafd = openat(filedes, attrpath, oflag | O_XATTR, mode)) == -1) { switch (errno) { case ENOENT: case EEXIST: EC_FAIL; default: LOG(log_debug, logtype_default, "openat(\"%s\"): %s", fullpathname(path), strerror(errno)); errno = ENOATTR; EC_FAIL; } } EC_CLEANUP: if (filedes != -1) close(filedes); if (ret != 0) { if (eafd != -1) close(eafd); eafd = -1; } return eafd; }
/* ----------------------------- a dropbox is a folder where w is set but not r eg: rwx-wx-wx or rwx-wx-- rwx----wx (is not asked by a Mac with OS >= 8.0 ?) */ int stickydirmode(const char *name, const mode_t mode, const int dropbox, const mode_t v_umask) { int retval = 0; #ifdef DROPKLUDGE /* Turn on the sticky bit if this is a drop box, also turn off the setgid bit */ if ((dropbox & AFPVOL_DROPBOX)) { int uid; if ( ( (mode & S_IWOTH) && !(mode & S_IROTH)) || ( (mode & S_IWGRP) && !(mode & S_IRGRP)) ) { uid=geteuid(); if ( seteuid(0) < 0) { LOG(log_error, logtype_afpd, "stickydirmode: unable to seteuid root: %s", strerror(errno)); } if ( (retval=chmod( name, ( (DIRBITS | mode | S_ISVTX) & ~v_umask) )) < 0) { LOG(log_error, logtype_afpd, "stickydirmode: chmod \"%s\": %s", fullpathname(name), strerror(errno) ); } else { LOG(log_debug, logtype_afpd, "stickydirmode: chmod \"%s\": %s", fullpathname(name), strerror(retval) ); } seteuid(uid); return retval; } } #endif /* DROPKLUDGE */ /* * Ignore EPERM errors: We may be dealing with a directory that is * group writable, in which case chmod will fail. */ if ( (chmod( name, (DIRBITS | mode) & ~v_umask ) < 0) && errno != EPERM && !(errno == ENOENT && (dropbox & AFPVOL_NOADOUBLE)) ) { LOG(log_error, logtype_afpd, "stickydirmode: chmod \"%s\": %s", fullpathname(name), strerror(errno) ); retval = -1; } return retval; }
/*! * AppleDouble and encoding conversion on the fly * * @param path (r) path to file or directory * @param sp (r) stat(path) * @param vol (r) volume handle * @param newpath (w) if encoding changed, new name. Can be NULL. * * @returns -1 on internal error, otherwise 0. newpath is NULL if no character conversion was done, * otherwise newpath points to a static string with the converted name */ int ad_convert(const char *path, const struct stat *sp, const struct vol *vol, const char **newpath) { EC_INIT; const char *p; LOG(log_debug, logtype_default,"ad_convert(\"%s\"): BEGIN", fullpathname(path)); if (newpath) *newpath = NULL; if ((vol->v_adouble == AD_VERSION_EA) && !(vol->v_flags & AFPVOL_NOV2TOEACONV)) EC_ZERO( ad_conv_v22ea(path, sp, vol) ); if (vol->v_adouble == AD_VERSION_EA) { EC_ZERO( ad_conv_dehex(path, sp, vol, &p) ); if (p && newpath) *newpath = p; } EC_CLEANUP: LOG(log_debug, logtype_default,"ad_convert(\"%s\"): END: %d", fullpathname(path), ret); EC_EXIT; }
/* ----------------------------- */ static int for_each_adouble(const char *from, const char *name, rf_loop fn, void *data, int flag, mode_t v_umask) { char buf[ MAXPATHLEN + 1]; char *m; DIR *dp; struct dirent *de; int ret; if (NULL == ( dp = opendir( name)) ) { if (!flag) { LOG(log_error, logtype_afpd, "%s: opendir %s: %s", from, fullpathname(name),strerror(errno) ); return -1; } return 0; } strlcpy( buf, name, sizeof(buf)); strlcat( buf, "/", sizeof(buf) ); m = strchr( buf, '\0' ); ret = 0; while ((de = readdir(dp))) { if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { continue; } strlcat(buf, de->d_name, sizeof(buf)); if (fn && (ret = fn(de, buf, data, flag, v_umask))) { closedir(dp); return ret; } *m = 0; } closedir(dp); return ret; }
static int solaris_attropenat(int filedes, const char *path, const char *attrpath, int oflag, mode_t mode) { EC_INIT; int eafd = -1; if ((eafd = openat(filedes, attrpath, oflag | O_XATTR, mode)) == -1) { switch (errno) { case ENOENT: case EEXIST: EC_FAIL; default: LOG(log_debug, logtype_default, "openat(\"%s\"): %s", fullpathname(path), strerror(errno)); EC_FAIL; } } EC_CLEANUP: if (ret != 0) { if (eafd != -1) close(eafd); eafd = -1; } return eafd; }
static int ad_conv_v22ea_hf(const char *path, const struct stat *sp, const struct vol *vol) { EC_INIT; struct adouble adv2; struct adouble adea; const char *adpath; int adflags; uint32_t ctime, mtime, afpinfo = 0; char *emptyad; LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): BEGIN", fullpathname(path)); ad_init(&adea, vol); ad_init_old(&adv2, AD_VERSION2, adea.ad_options); adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0; /* Open and lock adouble:v2 file */ EC_ZERO( ad_open(&adv2, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR) ); EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) ); EC_NEG1_LOG( adv2.ad_ops->ad_header_read(path, &adv2, sp) ); /* Check if it's a non-empty header */ if (S_ISREG(sp->st_mode)) emptyad = &emptyfilad[0]; else emptyad = &emptydirad[0]; if (ad_getentrylen(&adv2, ADEID_COMMENT) != 0) goto copy; if (ad_getentryoff(&adv2, ADEID_FINDERI) && (ad_getentrylen(&adv2, ADEID_FINDERI) == ADEDLEN_FINDERI) && (memcmp(ad_entry(&adv2, ADEID_FINDERI), emptyad, ADEDLEN_FINDERI) != 0)) goto copy; if (ad_getentryoff(&adv2, ADEID_FILEDATESI)) { EC_ZERO_LOG( ad_getdate(&adv2, AD_DATE_CREATE | AD_DATE_UNIX, &ctime) ); EC_ZERO_LOG( ad_getdate(&adv2, AD_DATE_MODIFY | AD_DATE_UNIX, &mtime) ); if ((ctime != mtime) || (mtime != sp->st_mtime)) goto copy; } if (ad_getentryoff(&adv2, ADEID_AFPFILEI)) { if (memcmp(ad_entry(&adv2, ADEID_AFPFILEI), &afpinfo, ADEDLEN_AFPFILEI) != 0) goto copy; } LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): default adouble", fullpathname(path), ret); goto EC_CLEANUP; copy: /* Create a adouble:ea meta EA */ LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): copying adouble", fullpathname(path), ret); EC_ZERO_LOGSTR( ad_open(&adea, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE), "ad_conv_v22ea_hf(\"%s\"): error creating metadata EA: %s", fullpathname(path), strerror(errno)); EC_ZERO_LOG( ad_copy_header(&adea, &adv2) ); ad_flush(&adea); EC_CLEANUP: EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_SETSHRMD) ); EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_SETSHRMD) ); LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): END: %d", fullpathname(path), ret); EC_EXIT; }
int diff (int argc, char **argv) { char tmp[50]; int c, err = 0; int local = 0; int which; int option_index; is_rcs = (strcmp (command_name, "rcsfile") == 0); if (argc == -1) usage (diff_usage); have_rev1_label = have_rev2_label = 0; /* * Note that we catch all the valid arguments here, so that we can * intercept the -r arguments for doing revision diffs; and -l/-R for a * non-recursive/recursive diff. */ /* Clean out our global variables (multiroot can call us multiple times and the server can too, if the client sends several diff commands). */ if (opts == NULL) { opts_allocated = 1; opts = (char*)xmalloc (opts_allocated); } opts[0] = '\0'; diff_rev1 = NULL; diff_rev2 = NULL; diff_date1 = NULL; diff_date2 = NULL; optind = 0; while ((c = getopt_long (argc, argv, "+abcdefhilnpstuwy0123456789BHNRTC:D:F:I:L:U:V:W:k:r:", longopts, &option_index)) != -1) { switch (c) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'h': case 'i': case 'n': case 'p': case 's': case 't': case 'u': case 'w': case 'y': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'B': case 'H': case 'T': (void) sprintf (tmp, " -%c", (char) c); allocate_and_strcat (&opts, &opts_allocated, tmp); break; case 'L': if (have_rev1_label++) if (have_rev2_label++) { error (0, 0, "extra -L arguments ignored"); break; } allocate_and_strcat (&opts, &opts_allocated, " -L"); allocate_and_strcat (&opts, &opts_allocated, optarg); break; case 'C': case 'F': case 'I': case 'U': case 'V': case 'W': (void) sprintf (tmp, " -%c", (char) c); allocate_and_strcat (&opts, &opts_allocated, tmp); allocate_and_strcat (&opts, &opts_allocated, optarg); break; case 131: /* --ifdef. */ allocate_and_strcat (&opts, &opts_allocated, " --ifdef="); allocate_and_strcat (&opts, &opts_allocated, optarg); break; case 129: case 130: case 132: case 133: case 134: case 135: case 136: case 137: case 138: case 139: case 140: case 141: case 142: case 143: case 144: case 145: case 146: allocate_and_strcat (&opts, &opts_allocated, " --"); allocate_and_strcat (&opts, &opts_allocated, longopts[option_index].name); if (longopts[option_index].has_arg == 1 || (longopts[option_index].has_arg == 2 && optarg != NULL)) { allocate_and_strcat (&opts, &opts_allocated, "="); allocate_and_strcat (&opts, &opts_allocated, optarg); } break; case 'R': local = 0; break; case 'l': local = 1; break; case 'k': if (options) xfree (options); options = RCS_check_kflag (optarg,true,true); break; case 'r': if (diff_rev2 != NULL || diff_date2 != NULL) error (1, 0, "no more than two revisions/dates can be specified"); if (diff_rev1 != NULL || diff_date1 != NULL) diff_rev2 = optarg; else diff_rev1 = optarg; break; case 'D': if (diff_rev2 != NULL || diff_date2 != NULL) error (1, 0, "no more than two revisions/dates can be specified"); if (diff_rev1 != NULL || diff_date1 != NULL) diff_date2 = Make_Date (optarg); else diff_date1 = Make_Date (optarg); break; case 'N': empty_files = 1; break; case '?': default: usage (diff_usage); break; } } argc -= optind; argv += optind; /* make sure options is non-null */ if (!options) options = xstrdup (""); if (!is_rcs && current_parsed_root->isremote) { if (local) send_arg("-l"); if (empty_files) send_arg("-N"); send_option_string (opts); if (options[0] != '\0') option_with_arg ("-k", options); if (diff_rev1) option_with_arg ("-r", diff_rev1); if (diff_date1) client_senddate (diff_date1); if (diff_rev2) option_with_arg ("-r", diff_rev2); if (diff_date2) client_senddate (diff_date2); send_arg("--"); /* Send the current files unless diffing two revs from the archive */ if (diff_rev2 == NULL && diff_date2 == NULL) send_files (argc, argv, local, 0, 0); else send_files (argc, argv, local, 0, SEND_NO_CONTENTS); send_file_names (argc, argv, SEND_EXPAND_WILD); send_to_server ("diff\n", 0); err = get_responses_and_close (); xfree (options); options = NULL; return (err); } if(is_rcs) { int n; if(!argc) usage(diff_usage); for(n=0; n<argc; n++) { struct file_info finfo = {0}; const char *name; char *tmp = find_rcs_filename(argv[n]); if(!tmp) error(1,ENOENT,"%s",argv[n]); finfo.fullname=fullpathname(tmp, &name); finfo.file = xstrdup(name); char *ff = xstrdup(finfo.fullname); finfo.update_dir = ff; ff[(name-finfo.fullname)-1]='\0'; finfo.rcs = RCS_fopen(finfo.fullname); if(finfo.rcs) { ff = (char*)finfo.fullname; ff[strlen(finfo.fullname)-2]='\0'; ff = (char*)finfo.file; ff[strlen(finfo.file)-2]='\0'; err+=diff_fileproc(NULL,&finfo); freercsnode(&finfo.rcs); } else { error(1,ENOENT,"%s",tmp); err++; } xfree(finfo.fullname); xfree(finfo.file); xfree(finfo.update_dir); xfree(tmp); } } else { if (diff_rev1 != NULL) tag_check_valid (diff_rev1, argc, argv, local, 0, ""); if (diff_rev2 != NULL) tag_check_valid (diff_rev2, argc, argv, local, 0, ""); which = W_LOCAL; if (diff_rev1 != NULL || diff_date1 != NULL) which |= W_REPOS; /* start the recursion processor */ err = start_recursion (diff_fileproc, diff_filesdoneproc, (PREDIRENTPROC) NULL, diff_dirproc, diff_dirleaveproc, NULL, argc, argv, local, which, 0, 1, (char *) NULL, NULL, 1, verify_read, diff_rev1); } /* clean up */ xfree (options); options = NULL; if (diff_date1 != NULL) xfree (diff_date1); if (diff_date2 != NULL) xfree (diff_date2); return (err); }