void setup_watches (const char *dir) { DIR *dirfd = opendir(dir); char fullent[PATH_MAX]; int dirlen = strlen(dir); memcpy(fullent, dir, dirlen); fullent[dirlen] = '/'; struct dirent *ent; if (!dirfd) { if (errno == ENOENT || errno == EACCES) return; die_errno("opendir"); } while ((ent = xreaddir(dirfd))) { int entlen = strlen(ent->d_name); if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue; memcpy(fullent+dirlen+1, ent->d_name, entlen); fullent[dirlen+1+entlen] = '\0'; if (is_ignored(fullent)) continue; if (!isdir(fullent)) continue; if (!setup_one_watch(fullent)) setup_watches(fullent); } if (closedir(dirfd)) die_errno("closedir"); }
void handle_event(struct inotify_event *ev) { char *wdp; int i, j; if (ev->wd < 0) return; wdp = wdpaths[ev->wd]; if (!wdp) return; if (ev->mask & IN_ISDIR && ev->mask & IN_CREATE) { char buf[PATH_MAX]; strcpy(buf, wdp); strcat(buf, "/"); strcat(buf, ev->name); if (is_ignored(buf)) return; if (!setup_one_watch(buf)) setup_watches(buf); return; } /* inotify shows directory events in the parent too; ignore them there */ if (ev->len && ev->mask & IN_ISDIR) return; if (ev->mask & IN_IGNORED) { wdpaths[ev->wd] = NULL; for (i = 0; i < HIST; i++) { if (!lru[i]) break; if (strcmp(wdp, lru[i])) continue; for (j = i; j < HIST-1; j++) lru[j] = lru[j+1]; lru[HIST-1] = NULL; break; } free(wdp); return; } #ifdef DEBUG if (ev->mask != IN_ACCESS) fprintf(stdout, "%08x %s %s %s\n", ev->mask, event_msg(ev->mask), wdp, ev->len ? ev->name : "(none)"); #endif for (i = 0; i < HIST; i++) { if (!lru[i]) break; if (strcmp(wdp, lru[i])) continue; if (i == 0) return; for (j = i; j > 0; j--) lru[j] = lru[j-1]; lru[0] = wdp; return; } for (j = HIST-1; j > 0; j--) lru[j] = lru[j-1]; lru[0] = wdp; }
int process_subprocess_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct subprocess_data *mdata = data; struct sol_flow_node_type_process_subprocess_options *opts = (struct sol_flow_node_type_process_subprocess_options *)options; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_PROCESS_SUBPROCESS_OPTIONS_API_VERSION, -EINVAL); mdata->node = node; sol_vector_init(&mdata->write_data, sizeof(struct write_data)); if (pipe2(mdata->pipes.out, O_NONBLOCK | O_CLOEXEC) < 0) { SOL_WRN("Failed to create out pipe"); return -errno; } if (pipe2(mdata->pipes.in, O_NONBLOCK | O_CLOEXEC) < 0) { SOL_WRN("Failed to create in pipe"); goto in_err; } if (pipe2(mdata->pipes.err, O_NONBLOCK | O_CLOEXEC) < 0) { SOL_WRN("Failed to create err pipe"); goto err_err; } mdata->command = strdup(opts->command); SOL_NULL_CHECK_GOTO(mdata->command, flags_err); if (opts->start) { if (setup_watches(mdata) < 0) goto watch_err; mdata->fork_run = sol_platform_linux_fork_run(on_fork, on_fork_exit, mdata); SOL_NULL_CHECK_GOTO(mdata->fork_run, err); } return 0; err: sol_fd_del(mdata->watches.in); sol_fd_del(mdata->watches.err); watch_err: free(mdata->command); flags_err: close(mdata->pipes.err[0]); close(mdata->pipes.err[1]); err_err: close(mdata->pipes.in[0]); close(mdata->pipes.in[1]); in_err: close(mdata->pipes.out[0]); close(mdata->pipes.out[1]); return -errno; }
int process_subprocess_start_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct subprocess_data *mdata = data; if (mdata->fork_run) return 0; if (setup_watches(mdata) < 0) return -1; mdata->fork_run = sol_platform_linux_fork_run(on_fork, on_fork_exit, mdata); SOL_NULL_CHECK_GOTO(mdata->fork_run, fork_err); return 0; fork_err: sol_fd_del(mdata->watches.err); mdata->watches.err = NULL; sol_fd_del(mdata->watches.in); mdata->watches.in = NULL; return -1; }
int main (int argc, char *argv[]) { int sock, conn; char *sockname; struct sockaddr_un addr, peer; socklen_t peer_sz; fd_set rfds; int ret; int maxfd; read_ignore_file(); ifd = inotify_init(); if (ifd < 0) die_errno("inotify_init"); setup_watches(expanduser("~")); setup_watches("/media"); sockname = expanduser(SOCKNAME); unlink(sockname); /* errors deliberately ignored */ sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) die_errno("socket"); memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, sockname, sizeof(addr.sun_path)-1); if (bind(sock, (struct sockaddr *) &addr, sizeof(addr))) die_errno("bind"); if (listen(sock, 10)) die_errno("listen"); maxfd = sock; if (ifd > maxfd) maxfd = ifd; maxfd++; while (1) { FD_ZERO(&rfds); FD_SET(ifd, &rfds); FD_SET(sock, &rfds); ret = select(maxfd, &rfds, NULL, NULL, NULL); if (ret == -1) die_errno("select"); if (!ret) continue; if (FD_ISSET(ifd, &rfds)) handle_inotify(); if (FD_ISSET(sock, &rfds)) { conn = accept(sock, (struct sockaddr *) &peer, &peer_sz); if (conn < 0) die_errno("accept"); send_lru(conn); close(conn); /* errors ignored */ } } /* we never get here, but meh */ if (close(sock) < 0) die_errno("close"); return 0; }