INT64_T chirp_alloc_rmall(const char *path) { if(!alloc_enabled) return cfs->rmall(path); int result = chirp_alloc_unlink(path); if(result == 0) { return 0; } else if(errno != EISDIR) { return -1; } else { struct chirp_dir *dir; struct chirp_dirent *d; char subpath[CHIRP_PATH_MAX]; dir = chirp_alloc_opendir(path); if(!dir) return -1; result = 0; while((d = chirp_alloc_readdir(dir))) { if(!strcmp(d->name, ".")) continue; if(!strcmp(d->name, "..")) continue; if(!strncmp(d->name, ".__ ", 3)) continue; sprintf(subpath, "%s/%s", path, d->name); result = chirp_alloc_rmall(subpath); if(result != 0) break; } chirp_alloc_closedir(dir); if(result == 0) { return chirp_alloc_rmdir(path); } else { return result; } } }
static INT64_T chirp_thirdput_recursive(const char *subject, const char *lpath, const char *hostname, const char *rpath, const char *hostsubject, time_t stoptime) { struct chirp_stat info; INT64_T size = 0, result; char newlpath[CHIRP_PATH_MAX]; char newrpath[CHIRP_PATH_MAX]; int save_errno; int my_target_acl = 0; result = chirp_alloc_lstat(lpath, &info); if(result < 0) return result; if(S_ISDIR(info.cst_mode)) { CHIRP_FILE *aclfile; struct chirp_dir *dir; struct chirp_dirent *d; char aclsubject[CHIRP_PATH_MAX]; int aclflags; if(!chirp_acl_check_dir(lpath, subject, CHIRP_ACL_LIST)) return -1; // create the directory, but do not fail if it already exists result = chirp_reli_mkdir(hostname, rpath, 0700, stoptime); if(result < 0 && errno != EEXIST) return result; // set the access control to include the initiator result = chirp_reli_setacl(hostname, rpath, subject, "rwldax", stoptime); if(result < 0 && errno != EACCES) return result; // transfer each of the directory contents recurisvely dir = chirp_alloc_opendir(lpath); while((d = chirp_alloc_readdir(dir))) { if(!strcmp(d->name, ".")) continue; if(!strcmp(d->name, "..")) continue; if(!strncmp(d->name, ".__", 3)) continue; sprintf(newlpath, "%s/%s", lpath, d->name); sprintf(newrpath, "%s/%s", rpath, d->name); result = chirp_thirdput_recursive(subject, newlpath, hostname, newrpath, hostsubject, stoptime); if(result >= 0) { size += result; } else { result = -1; break; } } save_errno = errno; // finally, set the acl to duplicate the source directory, // but do not take away permissions from me or the initiator chirp_alloc_closedir(dir); aclfile = chirp_acl_open(lpath); if(!aclfile) return -1; while(chirp_acl_read(aclfile, aclsubject, &aclflags)) { // wait until the last minute to take away my permissions if(!strcmp(aclsubject, hostsubject)) { my_target_acl = aclflags; } // do not take permissions away from the initiator if(!strcmp(aclsubject, subject)) { continue; } chirp_reli_setacl(hostname, rpath, aclsubject, chirp_acl_flags_to_text(aclflags), stoptime); } chirp_acl_close(aclfile); // after setting everything else, then set my permissions from the ACL chirp_reli_setacl(hostname, rpath, hostsubject, chirp_acl_flags_to_text(my_target_acl), stoptime); errno = save_errno; if(result >= 0) { return size; } else { return -1; } } else if(S_ISLNK(info.cst_mode)) { if(!chirp_acl_check(lpath, subject, CHIRP_ACL_READ)) return -1; result = chirp_alloc_readlink(lpath, newlpath, sizeof(newlpath)); if(result < 0) return -1; return chirp_reli_symlink(hostname, newlpath, rpath, stoptime); } else if(S_ISREG(info.cst_mode)) { if(!chirp_acl_check(lpath, subject, CHIRP_ACL_READ)) return -1; int fd = chirp_alloc_open(lpath, O_RDONLY, 0); if(fd >= 0) { FILE *stream = fdopen(fd, "r"); if(stream) { result = chirp_reli_putfile(hostname, rpath, stream, info.cst_mode, info.cst_size, stoptime); save_errno = errno; fclose(stream); errno = save_errno; return result; } else { result = -1; } } else { return -1; } } else { return 0; } return -1; }
static int search_directory(const char *subject, const char * const base, char *fullpath, const char *pattern, int flags, struct link *l, time_t stoptime) { if(strlen(pattern) == 0) return 0; debug(D_DEBUG, "search_directory(subject = `%s', base = `%s', fullpath = `%s', pattern = `%s', flags = %d, ...)", subject, base, fullpath, pattern, flags); int access_flags = search_to_access(flags); int includeroot = flags & CHIRP_SEARCH_INCLUDEROOT; int metadata = flags & CHIRP_SEARCH_METADATA; int stopatfirst = flags & CHIRP_SEARCH_STOPATFIRST; int result = 0; void *dirp = chirp_fs_local_opendir(fullpath); char *current = fullpath + strlen(fullpath); /* point to end to current directory */ if(dirp) { errno = 0; struct chirp_dirent *entry; while((entry = chirp_fs_local_readdir(dirp))) { char *name = entry->name; if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0 || strncmp(name, ".__", 3) == 0) continue; sprintf(current, "/%s", name); if(search_match_file(pattern, base)) { const char *matched = includeroot ? fullpath+strlen(chirp_root_path) : base; /* add strlen(chirp_root_path) to strip out */ result += 1; if (access_flags == F_OK || chirp_fs_local_access(fullpath, access_flags) == 0) { if(metadata) { /* A match was found, but the matched file couldn't be statted. Generate a result and an error. */ struct chirp_stat buf; if((chirp_fs_local_stat(fullpath, &buf)) == -1) { link_putfstring(l, "0:%s::\n", stoptime, matched); // FIXME is this a bug? link_putfstring(l, "%d:%d:%s:\n", stoptime, errno, CHIRP_SEARCH_ERR_STAT, matched); } else { link_putfstring(l, "0:%s:%s:\n", stoptime, matched, chirp_stat_string(&buf)); if(stopatfirst) return 1; } } else { link_putfstring(l, "0:%s::\n", stoptime, matched); if(stopatfirst) return 1; } } /* FIXME access failure */ } if(cfs_isdir(fullpath) && search_should_recurse(base, pattern)) { if(chirp_acl_check_dir(fullpath, subject, CHIRP_ACL_LIST)) { int n = search_directory(subject, base, fullpath, pattern, flags, l, stoptime); if(n > 0) { result += n; if(stopatfirst) return result; } } else { link_putfstring(l, "%d:%d:%s:\n", stoptime, EPERM, CHIRP_SEARCH_ERR_OPEN, fullpath); } } *current = '\0'; /* clear current entry */ errno = 0; } if(errno) link_putfstring(l, "%d:%d:%s:\n", stoptime, errno, CHIRP_SEARCH_ERR_READ, fullpath); errno = 0; chirp_alloc_closedir(dirp); if(errno) link_putfstring(l, "%d:%d:%s:\n", stoptime, errno, CHIRP_SEARCH_ERR_CLOSE, fullpath); } else { link_putfstring(l, "%d:%d:%s:\n", stoptime, errno, CHIRP_SEARCH_ERR_OPEN, fullpath); } return result; }