static char *get_local_name(struct file_list *flist,char *name) { STRUCT_STAT st; int e; if (verbose > 2) rprintf(FINFO,"get_local_name count=%d %s\n", flist->count, NS(name)); if (!name) return NULL; if (do_stat(name,&st) == 0) { if (S_ISDIR(st.st_mode)) { if (!push_dir(name)) { rsyserr(FERROR, errno, "push_dir#1 %s failed", full_fname(name)); exit_cleanup(RERR_FILESELECT); } return NULL; } if (flist->count > 1) { rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n"); exit_cleanup(RERR_FILESELECT); } return name; } if (flist->count <= 1 && ((e = strlen(name)) <= 1 || name[e-1] != '/')) return name; if (do_mkdir(name,0777 & ~orig_umask) != 0) { rsyserr(FERROR, errno, "mkdir %s failed", full_fname(name)); exit_cleanup(RERR_FILEIO); } if (verbose > 0) rprintf(FINFO, "created directory %s\n", safe_fname(name)); if (dry_run) { dry_run++; return NULL; } if (!push_dir(name)) { rsyserr(FERROR, errno, "push_dir#2 %s failed", full_fname(name)); exit_cleanup(RERR_FILESELECT); } return NULL; }
t_dir *get_dir(char *path, t_option *option) { DIR *rep; FDIR *file; FSTAT sfile; t_dir *dir; char *tfile; rep = opendir(path); dir = 0; if (rep == 0) { display_error(path); return (0); } while ((file = readdir(rep)) != 0) { tfile = cat_path(path, file->d_name); if (option->opt[7] == 1) stat(tfile, &sfile); else lstat(tfile, &sfile); dir = push_dir(dir, file->d_name, sfile, tfile); free(tfile); } closedir(rep); return (dir); }
void AllTextures::Parse_textureDir(std::istream &is){ std::string line; std::string scriptPath; Tim::String::get_line(is, line, true, true); if (line == "ScriptPath:") { Tim::String::get_line(is, line, true, true); scriptPath = std::string(line); AllTextures* dir=new AllTextures(folder_path+scriptPath); push_dir(dir); } }
static svn_error_t * start_element(int *elem, void *baton, int parent_state, const char *nspace, const char *elt_name, const char **atts) { replay_baton_t *rb = baton; const svn_ra_neon__xml_elm_t *elm = svn_ra_neon__lookup_xml_elem(editor_report_elements, nspace, elt_name); if (! elm) { *elem = NE_XML_DECLINE; return SVN_NO_ERROR; } if (parent_state == ELEM_root) { /* If we're at the root of the tree, the element has to be the editor * report itself. */ if (elm->id != ELEM_editor_report) return UNEXPECTED_ELEMENT(nspace, elt_name); } else if (parent_state != ELEM_editor_report) { /* If we're not at the root, our parent has to be the editor report, * since we don't actually nest any elements. */ return UNEXPECTED_ELEMENT(nspace, elt_name); } switch (elm->id) { case ELEM_target_revision: { const char *crev = svn_xml_get_attr_value("rev", atts); if (! crev) return MISSING_ATTR(nspace, elt_name, "rev"); else return rb->editor->set_target_revision(rb->edit_baton, SVN_STR_TO_REV(crev), rb->pool); } break; case ELEM_open_root: { const char *crev = svn_xml_get_attr_value("rev", atts); if (! crev) return MISSING_ATTR(nspace, elt_name, "rev"); else { apr_pool_t *subpool = svn_pool_create(rb->pool); void *dir_baton; SVN_ERR(rb->editor->open_root(rb->edit_baton, SVN_STR_TO_REV(crev), subpool, &dir_baton)); push_dir(rb, dir_baton, "", subpool); } } break; case ELEM_delete_entry: { const char *path = svn_xml_get_attr_value("name", atts); const char *crev = svn_xml_get_attr_value("rev", atts); if (! path) return MISSING_ATTR(nspace, elt_name, "name"); else if (! crev) return MISSING_ATTR(nspace, elt_name, "rev"); else { dir_item_t *di = &TOP_DIR(rb); SVN_ERR(rb->editor->delete_entry(path, SVN_STR_TO_REV(crev), di->baton, di->pool)); } } break; case ELEM_open_directory: case ELEM_add_directory: { const char *crev = svn_xml_get_attr_value("rev", atts); const char *name = svn_xml_get_attr_value("name", atts); if (! name) return MISSING_ATTR(nspace, elt_name, "name"); else { dir_item_t *parent = &TOP_DIR(rb); apr_pool_t *subpool = svn_pool_create(parent->pool); svn_revnum_t rev; void *dir_baton; if (crev) rev = SVN_STR_TO_REV(crev); else rev = SVN_INVALID_REVNUM; if (elm->id == ELEM_open_directory) SVN_ERR(rb->editor->open_directory(name, parent->baton, rev, subpool, &dir_baton)); else if (elm->id == ELEM_add_directory) { const char *cpath = svn_xml_get_attr_value("copyfrom-path", atts); crev = svn_xml_get_attr_value("copyfrom-rev", atts); if (crev) rev = SVN_STR_TO_REV(crev); else rev = SVN_INVALID_REVNUM; SVN_ERR(rb->editor->add_directory(name, parent->baton, cpath, rev, subpool, &dir_baton)); } else SVN_ERR_MALFUNCTION(); push_dir(rb, dir_baton, name, subpool); } } break; case ELEM_open_file: case ELEM_add_file: { const char *path = svn_xml_get_attr_value("name", atts); svn_revnum_t rev; dir_item_t *parent = &TOP_DIR(rb); if (! path) return MISSING_ATTR(nspace, elt_name, "name"); svn_pool_clear(parent->file_pool); if (elm->id == ELEM_add_file) { const char *cpath = svn_xml_get_attr_value("copyfrom-path", atts); const char *crev = svn_xml_get_attr_value("copyfrom-rev", atts); if (crev) rev = SVN_STR_TO_REV(crev); else rev = SVN_INVALID_REVNUM; SVN_ERR(rb->editor->add_file(path, parent->baton, cpath, rev, parent->file_pool, &rb->file_baton)); } else { const char *crev = svn_xml_get_attr_value("rev", atts); if (crev) rev = SVN_STR_TO_REV(crev); else rev = SVN_INVALID_REVNUM; SVN_ERR(rb->editor->open_file(path, parent->baton, rev, parent->file_pool, &rb->file_baton)); } } break; case ELEM_apply_textdelta: if (! rb->file_baton) return svn_error_create (SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, _("Got apply-textdelta element without preceding " "add-file or open-file")); else { const char *checksum = svn_xml_get_attr_value("checksum", atts); SVN_ERR(rb->editor->apply_textdelta(rb->file_baton, checksum, TOP_DIR(rb).file_pool, &rb->whandler, &rb->whandler_baton)); rb->svndiff_decoder = svn_txdelta_parse_svndiff (rb->whandler, rb->whandler_baton, TRUE, TOP_DIR(rb).file_pool); rb->base64_decoder = svn_base64_decode(rb->svndiff_decoder, TOP_DIR(rb).file_pool); } break; case ELEM_close_file: if (! rb->file_baton) return svn_error_create (SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, _("Got close-file element without preceding " "add-file or open-file")); else { const char *checksum = svn_xml_get_attr_value("checksum", atts); SVN_ERR(rb->editor->close_file(rb->file_baton, checksum, TOP_DIR(rb).file_pool)); rb->file_baton = NULL; } break; case ELEM_close_directory: if (rb->dirs->nelts == 0) return svn_error_create (SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, _("Got close-directory element without ever opening " "a directory")); else { dir_item_t *di = &TOP_DIR(rb); SVN_ERR(rb->editor->close_directory(di->baton, di->pool)); svn_pool_destroy(di->pool); apr_array_pop(rb->dirs); } break; case ELEM_change_file_prop: case ELEM_change_dir_prop: { const char *name = svn_xml_get_attr_value("name", atts); if (! name) return MISSING_ATTR(nspace, elt_name, "name"); else { svn_pool_clear(rb->prop_pool); if (svn_xml_get_attr_value("del", atts)) rb->prop_accum = NULL; else rb->prop_accum = svn_stringbuf_create("", rb->prop_pool); rb->prop_name = apr_pstrdup(rb->prop_pool, name); } } break; } *elem = elm->id; return SVN_NO_ERROR; }
static int rsync_module(int fd, int i) { int argc=0; char *argv[MAX_ARGS]; char **argp; char line[MAXPATHLEN]; uid_t uid = (uid_t)-2; gid_t gid = (gid_t)-2; char *p; char *addr = client_addr(fd); char *host = client_name(fd); char *name = lp_name(i); int use_chroot = lp_use_chroot(i); int start_glob=0; int ret; char *request=NULL; extern int am_sender; extern int remote_version; extern int am_root; if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) { rprintf(FERROR,"rsync denied on module %s from %s (%s)\n", name, client_name(fd), client_addr(fd)); io_printf(fd,"@ERROR: access denied to %s from %s (%s)\n", name, client_name(fd), client_addr(fd)); return -1; } if (!claim_connection(lp_lock_file(i), lp_max_connections(i))) { if (errno) { rprintf(FERROR,"failed to open lock file %s : %s\n", lp_lock_file(i), strerror(errno)); io_printf(fd,"@ERROR: failed to open lock file %s : %s\n", lp_lock_file(i), strerror(errno)); } else { rprintf(FERROR,"max connections (%d) reached\n", lp_max_connections(i)); io_printf(fd,"@ERROR: max connections (%d) reached - try again later\n", lp_max_connections(i)); } return -1; } auth_user = auth_server(fd, i, addr, "@RSYNCD: AUTHREQD "); if (!auth_user) { rprintf(FERROR,"auth failed on module %s from %s (%s)\n", name, client_name(fd), client_addr(fd)); io_printf(fd,"@ERROR: auth failed on module %s\n",name); return -1; } module_id = i; if (lp_read_only(i)) read_only = 1; am_root = (getuid() == 0); if (am_root) { p = lp_uid(i); if (!name_to_uid(p, &uid)) { if (!isdigit(*p)) { rprintf(FERROR,"Invalid uid %s\n", p); io_printf(fd,"@ERROR: invalid uid\n"); return -1; } uid = atoi(p); } p = lp_gid(i); if (!name_to_gid(p, &gid)) { if (!isdigit(*p)) { rprintf(FERROR,"Invalid gid %s\n", p); io_printf(fd,"@ERROR: invalid gid\n"); return -1; } gid = atoi(p); } } p = lp_include_from(i); add_exclude_file(p, 1, 1); p = lp_include(i); add_include_line(p); p = lp_exclude_from(i); add_exclude_file(p, 1, 0); p = lp_exclude(i); add_exclude_line(p); log_open(); if (use_chroot) { if (chroot(lp_path(i))) { rprintf(FERROR,"chroot %s failed\n", lp_path(i)); io_printf(fd,"@ERROR: chroot failed\n"); return -1; } if (!push_dir("/", 0)) { rprintf(FERROR,"chdir %s failed\n", lp_path(i)); io_printf(fd,"@ERROR: chdir failed\n"); return -1; } } else { if (!push_dir(lp_path(i), 0)) { rprintf(FERROR,"chdir %s failed\n", lp_path(i)); io_printf(fd,"@ERROR: chdir failed\n"); return -1; } } if (am_root) { if (setgid(gid)) { rprintf(FERROR,"setgid %d failed\n", gid); io_printf(fd,"@ERROR: setgid failed\n"); return -1; } if (setuid(uid)) { rprintf(FERROR,"setuid %d failed\n", uid); io_printf(fd,"@ERROR: setuid failed\n"); return -1; } am_root = (getuid() == 0); } io_printf(fd,"@RSYNCD: OK\n"); argv[argc++] = "rsyncd"; while (1) { if (!read_line(fd, line, sizeof(line)-1)) { return -1; } if (!*line) break; p = line; argv[argc] = strdup(p); if (!argv[argc]) { return -1; } if (start_glob) { if (start_glob == 1) { request = strdup(p); start_glob++; } glob_expand(name, argv, &argc, MAX_ARGS, !use_chroot); } else { argc++; } if (strcmp(line,".") == 0) { start_glob = 1; } if (argc == MAX_ARGS) { return -1; } } if (!use_chroot) { /* * Note that this is applied to all parameters, whether or not * they are filenames, but no other legal parameters contain * the forms that need to be sanitized so it doesn't hurt; * it is not known at this point which parameters are files * and which aren't. */ for (i = 1; i < argc; i++) { sanitize_path(argv[i]); } } ret = parse_arguments(argc, argv, 0); if (request) { if (*auth_user) { rprintf(FINFO,"rsync %s %s from %s@%s (%s)\n", am_sender?"on":"to", request, auth_user, host, addr); } else { rprintf(FINFO,"rsync %s %s from %s (%s)\n", am_sender?"on":"to", request, host, addr); } free(request); } #if !TRIDGE /* don't allow the logs to be flooded too fast */ if (verbose > 1) verbose = 1; #endif argc -= optind; argp = argv + optind; optind = 0; if (remote_version > 17 && am_sender) io_start_multiplex_out(fd); if (!ret) { option_error(); } if (lp_timeout(i)) { extern int io_timeout; io_timeout = lp_timeout(i); } start_server(fd, fd, argc, argp); return 0; }
/* Thread: scan */ static void process_directory(char *path, int flags) { DIR *dirp; struct dirent buf; struct dirent *de; char entry[PATH_MAX]; char *deref; struct stat sb; struct watch_info wi; #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) struct kevent kev; #endif int type; int ret; DPRINTF(E_DBG, L_SCAN, "Processing directory %s (flags = 0x%x)\n", path, flags); dirp = opendir(path); if (!dirp) { DPRINTF(E_LOG, L_SCAN, "Could not open directory %s: %s\n", path, strerror(errno)); return; } /* Check if compilation and/or podcast directory */ type = 0; if (check_speciallib(path, "compilations")) type |= F_SCAN_TYPE_COMPILATION; if (check_speciallib(path, "podcasts")) type |= F_SCAN_TYPE_PODCAST; if (check_speciallib(path, "audiobooks")) type |= F_SCAN_TYPE_AUDIOBOOK; for (;;) { if (scan_exit) break; ret = readdir_r(dirp, &buf, &de); if (ret != 0) { DPRINTF(E_LOG, L_SCAN, "readdir_r error in %s: %s\n", path, strerror(errno)); break; } if (de == NULL) break; if (buf.d_name[0] == '.') continue; ret = snprintf(entry, sizeof(entry), "%s/%s", path, buf.d_name); if ((ret < 0) || (ret >= sizeof(entry))) { DPRINTF(E_LOG, L_SCAN, "Skipping %s/%s, PATH_MAX exceeded\n", path, buf.d_name); continue; } ret = lstat(entry, &sb); if (ret < 0) { DPRINTF(E_LOG, L_SCAN, "Skipping %s, lstat() failed: %s\n", entry, strerror(errno)); continue; } if (S_ISLNK(sb.st_mode)) { deref = m_realpath(entry); if (!deref) { DPRINTF(E_LOG, L_SCAN, "Skipping %s, could not dereference symlink: %s\n", entry, strerror(errno)); continue; } ret = stat(deref, &sb); if (ret < 0) { DPRINTF(E_LOG, L_SCAN, "Skipping %s, stat() failed: %s\n", deref, strerror(errno)); free(deref); continue; } ret = snprintf(entry, sizeof(entry), "%s", deref); free(deref); if ((ret < 0) || (ret >= sizeof(entry))) { DPRINTF(E_LOG, L_SCAN, "Skipping %s, PATH_MAX exceeded\n", deref); continue; } } if (S_ISREG(sb.st_mode)) { if (!(flags & F_SCAN_FAST)) process_file(entry, sb.st_mtime, sb.st_size, F_SCAN_TYPE_FILE | type, flags); } else if (S_ISFIFO(sb.st_mode)) { if (!(flags & F_SCAN_FAST)) process_file(entry, sb.st_mtime, sb.st_size, F_SCAN_TYPE_PIPE | type, flags); } else if (S_ISDIR(sb.st_mode)) push_dir(&dirstack, entry); else DPRINTF(E_LOG, L_SCAN, "Skipping %s, not a directory, symlink, pipe nor regular file\n", entry); } closedir(dirp); memset(&wi, 0, sizeof(struct watch_info)); #if defined(__linux__) /* Add inotify watch */ wi.wd = inotify_add_watch(inofd, path, IN_ATTRIB | IN_CREATE | IN_DELETE | IN_CLOSE_WRITE | IN_MOVE | IN_DELETE | IN_MOVE_SELF); if (wi.wd < 0) { DPRINTF(E_WARN, L_SCAN, "Could not create inotify watch for %s: %s\n", path, strerror(errno)); return; } if (!(flags & F_SCAN_MOVED)) { wi.cookie = 0; wi.path = path; db_watch_add(&wi); } #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) memset(&kev, 0, sizeof(struct kevent)); wi.wd = open(path, O_RDONLY | O_NONBLOCK); if (wi.wd < 0) { DPRINTF(E_WARN, L_SCAN, "Could not open directory %s for watching: %s\n", path, strerror(errno)); return; } /* Add kevent */ EV_SET(&kev, wi.wd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_DELETE | NOTE_WRITE | NOTE_RENAME, 0, NULL); ret = kevent(inofd, &kev, 1, NULL, 0, NULL); if (ret < 0) { DPRINTF(E_WARN, L_SCAN, "Could not add kevent for %s: %s\n", path, strerror(errno)); close(wi.wd); return; } wi.cookie = 0; wi.path = path; db_watch_add(&wi); #endif }
/* Thread: scan */ static void kqueue_cb(int fd, short event, void *arg) { struct kevent kev; struct timespec ts; struct watch_info wi; struct watch_enum we; struct stacked_dir *rescan; struct stacked_dir *d; struct stacked_dir *dprev; char *path; uint32_t wd; int d_len; int w_len; int need_rescan; int ret; ts.tv_sec = 0; ts.tv_nsec = 0; we.cookie = 0; rescan = NULL; DPRINTF(E_DBG, L_SCAN, "Library changed!\n"); /* We can only monitor directories with kqueue; to monitor files, we'd need * to have an open fd on every file in the library, which is totally insane. * Unfortunately, that means we only know when directories get renamed, * deleted or changed. We don't get directory/file names when directories/files * are created/deleted/renamed in the directory, so we have to rescan. */ while (kevent(fd, NULL, 0, &kev, 1, &ts) > 0) { /* This should not happen, and if it does, we'll end up in * an infinite loop. */ if (kev.filter != EVFILT_VNODE) continue; wi.wd = kev.ident; ret = db_watch_get_bywd(&wi); if (ret < 0) { DPRINTF(E_LOG, L_SCAN, "Found no matching watch for kevent, killing this event\n"); close(kev.ident); continue; } /* Whatever the type of event that happened, disable matching watches and * files before we trigger an eventual rescan. */ we.match = wi.path; ret = db_watch_enum_start(&we); if (ret < 0) { free(wi.path); continue; } while ((db_watch_enum_fetchwd(&we, &wd) == 0) && (wd)) { close(wd); } db_watch_enum_end(&we); db_watch_delete_bymatch(wi.path); close(wi.wd); db_watch_delete_bywd(wi.wd); /* Disable files */ db_file_disable_bymatch(wi.path, "", 0); db_pl_disable_bymatch(wi.path, "", 0); if (kev.flags & EV_ERROR) { DPRINTF(E_LOG, L_SCAN, "kevent reports EV_ERROR (%s): %s\n", wi.path, strerror(kev.data)); ret = access(wi.path, F_OK); if (ret != 0) { free(wi.path); continue; } /* The directory still exists, so try to add it back to the library */ kev.fflags |= NOTE_WRITE; } /* No further action on NOTE_DELETE & NOTE_RENAME; NOTE_WRITE on the * parent directory will trigger a rescan in both cases and the * renamed directory will be picked up then. */ if (kev.fflags & NOTE_WRITE) { DPRINTF(E_DBG, L_SCAN, "Got NOTE_WRITE (%s)\n", wi.path); need_rescan = 1; w_len = strlen(wi.path); /* Abusing stacked_dir a little bit here */ dprev = NULL; d = rescan; while (d) { d_len = strlen(d->path); if (d_len > w_len) { /* Stacked dir child of watch dir? */ if ((d->path[w_len] == '/') && (strncmp(d->path, wi.path, w_len) == 0)) { DPRINTF(E_DBG, L_SCAN, "Watched directory is a parent\n"); if (dprev) dprev->next = d->next; else rescan = d->next; free(d->path); free(d); if (dprev) d = dprev->next; else d = rescan; continue; } } else if (w_len > d_len) { /* Watch dir child of stacked dir? */ if ((wi.path[d_len] == '/') && (strncmp(wi.path, d->path, d_len) == 0)) { DPRINTF(E_DBG, L_SCAN, "Watched directory is a child\n"); need_rescan = 0; break; } } else if (strcmp(wi.path, d->path) == 0) { DPRINTF(E_DBG, L_SCAN, "Watched directory already listed\n"); need_rescan = 0; break; } dprev = d; d = d->next; } if (need_rescan) push_dir(&rescan, wi.path); } free(wi.path); } while ((path = pop_dir(&rescan))) { process_directories(path, 0); free(path); if (rescan) DPRINTF(E_LOG, L_SCAN, "WARNING: unhandled leftover directories\n"); } event_add(&inoev, NULL); }
/* Thread: scan */ static void process_directory(char *path, int flags) { struct stacked_dir *bulkstack; DIR *dirp; struct dirent buf; struct dirent *de; char entry[PATH_MAX]; char *deref; struct stat sb; struct watch_info wi; #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) struct kevent kev; #endif int compilation; int ret; if (flags & F_SCAN_BULK) { /* Save our directory stack so it won't get handled inside * the event loop - not its business, we're in bulk mode here. */ bulkstack = dirstack; dirstack = NULL; /* Run the event loop */ event_base_loop(evbase_scan, EVLOOP_ONCE | EVLOOP_NONBLOCK); /* Restore our directory stack */ dirstack = bulkstack; if (scan_exit) return; } DPRINTF(E_DBG, L_SCAN, "Processing directory %s (flags = 0x%x)\n", path, flags); dirp = opendir(path); if (!dirp) { DPRINTF(E_LOG, L_SCAN, "Could not open directory %s: %s\n", path, strerror(errno)); return; } /* Check for a compilation directory */ compilation = check_compilation(path); for (;;) { ret = readdir_r(dirp, &buf, &de); if (ret != 0) { DPRINTF(E_LOG, L_SCAN, "readdir_r error in %s: %s\n", path, strerror(errno)); break; } if (de == NULL) break; if (buf.d_name[0] == '.') continue; ret = snprintf(entry, sizeof(entry), "%s/%s", path, buf.d_name); if ((ret < 0) || (ret >= sizeof(entry))) { DPRINTF(E_LOG, L_SCAN, "Skipping %s/%s, PATH_MAX exceeded\n", path, buf.d_name); continue; } ret = lstat(entry, &sb); if (ret < 0) { DPRINTF(E_LOG, L_SCAN, "Skipping %s, lstat() failed: %s\n", entry, strerror(errno)); continue; } if (S_ISLNK(sb.st_mode)) { deref = m_realpath(entry); if (!deref) { DPRINTF(E_LOG, L_SCAN, "Skipping %s, could not dereference symlink: %s\n", entry, strerror(errno)); continue; } ret = stat(deref, &sb); if (ret < 0) { DPRINTF(E_LOG, L_SCAN, "Skipping %s, stat() failed: %s\n", deref, strerror(errno)); free(deref); continue; } ret = snprintf(entry, sizeof(entry), "%s", deref); free(deref); if ((ret < 0) || (ret >= sizeof(entry))) { DPRINTF(E_LOG, L_SCAN, "Skipping %s, PATH_MAX exceeded\n", deref); continue; } } if (S_ISREG(sb.st_mode)) process_file(entry, sb.st_mtime, sb.st_size, compilation, flags); else if (S_ISDIR(sb.st_mode)) push_dir(&dirstack, entry); else DPRINTF(E_LOG, L_SCAN, "Skipping %s, not a directory, symlink nor regular file\n", entry); } closedir(dirp); memset(&wi, 0, sizeof(struct watch_info)); #if defined(__linux__) /* Add inotify watch */ wi.wd = inotify_add_watch(inofd, path, IN_CREATE | IN_DELETE | IN_MODIFY | IN_CLOSE_WRITE | IN_MOVE | IN_DELETE | IN_MOVE_SELF); if (wi.wd < 0) { DPRINTF(E_WARN, L_SCAN, "Could not create inotify watch for %s: %s\n", path, strerror(errno)); return; } if (!(flags & F_SCAN_RESCAN)) { wi.cookie = 0; wi.path = path; db_watch_add(&wi); } #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) memset(&kev, 0, sizeof(struct kevent)); wi.wd = open(path, O_RDONLY | O_NONBLOCK); if (wi.wd < 0) { DPRINTF(E_WARN, L_SCAN, "Could not open directory %s for watching: %s\n", path, strerror(errno)); return; } /* Add kevent */ EV_SET(&kev, wi.wd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_DELETE | NOTE_WRITE | NOTE_RENAME, 0, NULL); ret = kevent(inofd, &kev, 1, NULL, 0, NULL); if (ret < 0) { DPRINTF(E_WARN, L_SCAN, "Could not add kevent for %s: %s\n", path, strerror(errno)); close(wi.wd); return; } wi.cookie = 0; wi.path = path; db_watch_add(&wi); #endif }
static void process_directory(char *path, int parent_id, int flags) { DIR *dirp; struct dirent buf; struct dirent *de; char entry[PATH_MAX]; char *deref; struct stat sb; struct watch_info wi; int type; char virtual_path[PATH_MAX]; int dir_id; int ret; DPRINTF(E_DBG, L_SCAN, "Processing directory %s (flags = 0x%x)\n", path, flags); dirp = opendir(path); if (!dirp) { DPRINTF(E_LOG, L_SCAN, "Could not open directory %s: %s\n", path, strerror(errno)); return; } /* Add/update directories table */ ret = create_virtual_path(path, virtual_path, sizeof(virtual_path)); if (ret < 0) return; dir_id = db_directory_addorupdate(virtual_path, 0, parent_id); if (dir_id <= 0) { DPRINTF(E_LOG, L_SCAN, "Insert or update of directory failed '%s'\n", virtual_path); } /* Check if compilation and/or podcast directory */ type = 0; if (check_speciallib(path, "compilations")) type |= F_SCAN_TYPE_COMPILATION; if (check_speciallib(path, "podcasts")) type |= F_SCAN_TYPE_PODCAST; if (check_speciallib(path, "audiobooks")) type |= F_SCAN_TYPE_AUDIOBOOK; for (;;) { if (scan_exit) break; ret = readdir_r(dirp, &buf, &de); if (ret != 0) { DPRINTF(E_LOG, L_SCAN, "readdir_r error in %s: %s\n", path, strerror(errno)); break; } if (de == NULL) break; if (buf.d_name[0] == '.') continue; ret = snprintf(entry, sizeof(entry), "%s/%s", path, buf.d_name); if ((ret < 0) || (ret >= sizeof(entry))) { DPRINTF(E_LOG, L_SCAN, "Skipping %s/%s, PATH_MAX exceeded\n", path, buf.d_name); continue; } ret = lstat(entry, &sb); if (ret < 0) { DPRINTF(E_LOG, L_SCAN, "Skipping %s, lstat() failed: %s\n", entry, strerror(errno)); continue; } if (S_ISLNK(sb.st_mode)) { deref = m_realpath(entry); if (!deref) { DPRINTF(E_LOG, L_SCAN, "Skipping %s, could not dereference symlink: %s\n", entry, strerror(errno)); continue; } ret = stat(deref, &sb); if (ret < 0) { DPRINTF(E_LOG, L_SCAN, "Skipping %s, stat() failed: %s\n", deref, strerror(errno)); free(deref); continue; } ret = snprintf(entry, sizeof(entry), "%s", deref); free(deref); if ((ret < 0) || (ret >= sizeof(entry))) { DPRINTF(E_LOG, L_SCAN, "Skipping %s, PATH_MAX exceeded\n", deref); continue; } } if (S_ISREG(sb.st_mode)) { if (!(flags & F_SCAN_FAST)) process_file(entry, sb.st_mtime, sb.st_size, F_SCAN_TYPE_FILE | type, flags, dir_id); } else if (S_ISFIFO(sb.st_mode)) { if (!(flags & F_SCAN_FAST)) process_file(entry, sb.st_mtime, sb.st_size, F_SCAN_TYPE_PIPE | type, flags, dir_id); } else if (S_ISDIR(sb.st_mode)) push_dir(&dirstack, entry, dir_id); else DPRINTF(E_LOG, L_SCAN, "Skipping %s, not a directory, symlink, pipe nor regular file\n", entry); } closedir(dirp); memset(&wi, 0, sizeof(struct watch_info)); // Add inotify watch (for FreeBSD we limit the flags so only dirs will be // opened, otherwise we will be opening way too many files) #if defined(__linux__) wi.wd = inotify_add_watch(inofd, path, IN_ATTRIB | IN_CREATE | IN_DELETE | IN_CLOSE_WRITE | IN_MOVE | IN_DELETE | IN_MOVE_SELF); #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) wi.wd = inotify_add_watch(inofd, path, IN_CREATE | IN_DELETE | IN_MOVE); #endif if (wi.wd < 0) { DPRINTF(E_WARN, L_SCAN, "Could not create inotify watch for %s: %s\n", path, strerror(errno)); return; } if (!(flags & F_SCAN_MOVED)) { wi.cookie = 0; wi.path = path; db_watch_add(&wi); } }
static void do_server_recv(int f_in, int f_out, int argc,char *argv[]) { int status; struct file_list *flist; char *local_name = NULL; char *dir = NULL; int save_verbose = verbose; if (filesfrom_fd >= 0) { /* We can't mix messages with files-from data on the socket, * so temporarily turn off verbose messages. */ verbose = 0; } if (verbose > 2) { rprintf(FINFO, "server_recv(%d) starting pid=%ld\n", argc, (long)getpid()); } if (am_daemon && lp_read_only(module_id)) { rprintf(FERROR,"ERROR: module is read only\n"); exit_cleanup(RERR_SYNTAX); return; } if (argc > 0) { dir = argv[0]; argc--; argv++; if (!am_daemon && !push_dir(dir)) { rsyserr(FERROR, errno, "push_dir#4 %s failed", full_fname(dir)); exit_cleanup(RERR_FILESELECT); } } io_start_buffering_in(); recv_filter_list(f_in); if (filesfrom_fd >= 0) { /* We need to send the files-from names to the sender at the * same time that we receive the file-list from them, so we * need the IO routines to automatically write out the names * onto our f_out socket as we read the file-list. This * avoids both deadlock and extra delays/buffers. */ io_set_filesfrom_fds(filesfrom_fd, f_out); filesfrom_fd = -1; } flist = recv_file_list(f_in); verbose = save_verbose; if (!flist) { rprintf(FERROR,"server_recv: recv_file_list error\n"); exit_cleanup(RERR_FILESELECT); } the_file_list = flist; if (argc > 0) { if (strcmp(dir,".")) { argv[0] += strlen(dir); if (argv[0][0] == '/') argv[0]++; } local_name = get_local_name(flist,argv[0]); } status = do_recv(f_in,f_out,flist,local_name); exit_cleanup(status); }
static void do_server_sender(int f_in, int f_out, int argc,char *argv[]) { int i; struct file_list *flist; char *dir = argv[0]; if (verbose > 2) { rprintf(FINFO, "server_sender starting pid=%ld\n", (long)getpid()); } if (am_daemon && lp_write_only(module_id)) { rprintf(FERROR, "ERROR: module is write only\n"); exit_cleanup(RERR_SYNTAX); return; } if (am_daemon && lp_read_only(module_id) && remove_sent_files) { rprintf(FERROR, "ERROR: --remove-sent-files cannot be used with a read-only module\n"); exit_cleanup(RERR_SYNTAX); return; } if (!relative_paths && !push_dir(dir)) { rsyserr(FERROR, errno, "push_dir#3 %s failed", full_fname(dir)); exit_cleanup(RERR_FILESELECT); } argc--; argv++; if (strcmp(dir,".")) { int l = strlen(dir); if (strcmp(dir,"/") == 0) l = 0; for (i = 0; i < argc; i++) argv[i] += l+1; } if (argc == 0 && (recurse || list_only)) { argc = 1; argv--; argv[0] = "."; } flist = send_file_list(f_out,argc,argv); if (!flist || flist->count == 0) { exit_cleanup(0); } the_file_list = flist; io_start_buffering_in(); io_start_buffering_out(); send_files(flist,f_out,f_in); io_flush(FULL_FLUSH); handle_stats(f_out); if (protocol_version >= 24) read_final_goodbye(f_in, f_out); io_flush(FULL_FLUSH); exit_cleanup(0); }
int main(int argc,char *argv[]) { int ret; int orig_argc = argc; char **orig_argv = argv; signal(SIGUSR1, sigusr1_handler); signal(SIGUSR2, sigusr2_handler); signal(SIGCHLD, sigchld_handler); #ifdef MAINTAINER_MODE signal(SIGSEGV, rsync_panic_handler); signal(SIGFPE, rsync_panic_handler); signal(SIGABRT, rsync_panic_handler); signal(SIGBUS, rsync_panic_handler); #endif /* def MAINTAINER_MODE */ starttime = time(NULL); am_root = (MY_UID() == 0); memset(&stats, 0, sizeof(stats)); if (argc < 2) { usage(FERROR); exit_cleanup(RERR_SYNTAX); } /* we set a 0 umask so that correct file permissions can be * carried across */ orig_umask = (int)umask(0); if (!parse_arguments(&argc, (const char ***) &argv, 1)) { /* FIXME: We ought to call the same error-handling * code here, rather than relying on getopt. */ option_error(); exit_cleanup(RERR_SYNTAX); } signal(SIGINT,SIGNAL_CAST sig_int); signal(SIGHUP,SIGNAL_CAST sig_int); signal(SIGTERM,SIGNAL_CAST sig_int); /* Ignore SIGPIPE; we consistently check error codes and will * see the EPIPE. */ signal(SIGPIPE, SIG_IGN); #if defined CONFIG_LOCALE && defined HAVE_SETLOCALE setlocale(LC_CTYPE, ""); #endif /* Initialize push_dir here because on some old systems getcwd * (implemented by forking "pwd" and reading its output) doesn't * work when there are other child processes. Also, on all systems * that implement getcwd that way "pwd" can't be found after chroot. */ push_dir(NULL); init_flist(); if ((write_batch || read_batch) && !am_server) { if (write_batch) write_batch_shell_file(orig_argc, orig_argv, argc); if (read_batch && strcmp(batch_name, "-") == 0) batch_fd = STDIN_FILENO; else { batch_fd = do_open(batch_name, write_batch ? O_WRONLY | O_CREAT | O_TRUNC : O_RDONLY, S_IRUSR | S_IWUSR); } if (batch_fd < 0) { rsyserr(FERROR, errno, "Batch file %s open error", full_fname(batch_name)); exit_cleanup(RERR_FILEIO); } if (read_batch) read_stream_flags(batch_fd); } if (write_batch < 0) dry_run = 1; if (am_daemon && !am_server) return daemon_main(); if (argc < 1) { usage(FERROR); exit_cleanup(RERR_SYNTAX); } if (am_server) { set_nonblocking(STDIN_FILENO); set_nonblocking(STDOUT_FILENO); if (am_daemon) return start_daemon(STDIN_FILENO, STDOUT_FILENO); start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv); } ret = start_client(argc, argv); if (ret == -1) exit_cleanup(RERR_STARTCLIENT); else exit_cleanup(ret); return ret; }