static int walk_tree(const char* path, watch_node* parent, array* ignores) { if (is_ignored(path, ignores)) { return ERR_IGNORE; } DIR* dir = opendir(path); if (dir == NULL) { if (errno == EACCES) { return ERR_IGNORE; } else if (errno == ENOTDIR) { // flat root return add_watch(path, parent); } userlog(LOG_ERR, "opendir(%s): %s", path, strerror(errno)); return ERR_CONTINUE; } int id = add_watch(path, parent); if (id < 0) { closedir(dir); return id; } struct dirent* entry; char subdir[PATH_MAX]; strcpy(subdir, path); if (subdir[strlen(subdir) - 1] != '/') { strcat(subdir, "/"); } char* p = subdir + strlen(subdir); while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { continue; } strcpy(p, entry->d_name); if (!is_directory(entry, subdir)) { continue; } int subdir_id = walk_tree(subdir, table_get(watches, id), ignores); if (subdir_id < 0 && subdir_id != ERR_IGNORE) { rm_watch(id, true); id = subdir_id; break; } } closedir(dir); return id; }
static void watch_toggled(DBusWatch *watch, void *data) { if (dbus_watch_get_enabled(watch)) add_watch(watch, data); else remove_watch(watch, data); }
/** * The callback for when the main thread has issued a command to the run loop * thread. Reads all the pending commands and executes them */ static void command_callback( CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *context) { int fd = CFFileDescriptorGetNativeDescriptor(fdref); struct thread_env *thread_env = (struct thread_env *)context; struct command *to_do = NULL; struct command *to_free = NULL; clear_pipe(fd); do { to_do = *(thread_env->commands); } while (OSAtomicCompareAndSwapPtr(to_do, NULL, (void *)(thread_env->commands)) == false); while (to_do != NULL) { switch (to_do->type) { case ADD_WATCH: add_watch(to_do->arg, thread_env); break; case RM_WATCH: // hh_server doesn't need this at the moment. Shouldn't be too hard to // do...just need to map of paths to FSEvent streams. fprintf(stderr, "fsevents impl doesn't support removing watches yet\n"); break; } to_free = to_do; to_do = to_do->next; free(to_free->arg); free(to_free); } // For some reason you have to re-enable this callback every bloody time CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack); }
bool kqueue_monitor::scan(const string& path, bool is_root_path) { struct stat fd_stat; if (!lstat_path(path, fd_stat)) return false; if (follow_symlinks && S_ISLNK(fd_stat.st_mode)) { string link_path; if (read_link_path(path, link_path)) return scan(link_path); return false; } bool is_dir = S_ISDIR(fd_stat.st_mode); if (!is_dir && !is_root_path && directory_only) return true; if (!is_dir && !accept_path(path)) return true; if (!add_watch(path, fd_stat)) return false; if (!recursive) return true; if (!is_dir) return true; vector<string> children = get_directory_children(path); for (string& child : children) { if (child.compare(".") == 0 || child.compare("..") == 0) continue; scan(path + "/" + child, false); } return true; }
void listen_primary_changed_signal(GDBusSignalCallback handler, gpointer data, GDestroyNotify data_free_func) { GError* err = NULL; static GDBusConnection* conn = NULL; if (conn == NULL ) { conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &err); } if (err != NULL) { g_warning("[%s] get dbus failed: %s\n", __func__, err->message); g_clear_error(&err); return; } add_watch(conn, DISPLAY_PATH, DISPLAY_INTERFACE, PRIMARY_CHANGED_SIGNAL); g_dbus_connection_signal_subscribe(conn, DISPLAY_NAME, DISPLAY_INTERFACE, PRIMARY_CHANGED_SIGNAL, DISPLAY_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE, handler, data, data_free_func); }
static void toggle_watch(DBusWatch *w, void *data) { show_debug(__FILE__,__FUNCTION__,__LINE__,"toggling dbus watch watch=%p\n", w); if (dbus_watch_get_enabled(w)) add_watch(w, data); else remove_watch(w, data); }
static int handle_add_repo (SeafWTMonitor *monitor, const char *repo_id, const char *worktree) { FSEventStreamRef stream = add_watch (monitor, repo_id, worktree); if (!stream) return -1; return 0; }
static void toggle_watch(DBusWatch *w, void *data) { printf(" WATCH: toggle dbus watch watch=%p\n", w); if (dbus_watch_get_enabled(w)) add_watch(w, data); else remove_watch(w, data); }
static int handle_add_repo (SeafWTMonitorPriv *priv, const char *repo_id, long *handle) { g_assert (handle); FSEventStreamRef stream = add_watch (priv, repo_id); if (!stream) return -1; *handle = (long)stream; return 0; }
static void watch_toggled(DBusWatch *watch, void *data) { /* Because we just exit on OOM, enable/disable is * no different from add/remove */ if (dbus_watch_get_enabled(watch)) add_watch(watch, data); else remove_watch(watch, data); }
static int walk_tree(int path_len, watch_node* parent, bool recursive, array* mounts) { for (int j=0; j<array_size(mounts); j++) { char* mount = array_get(mounts, j); if (strncmp(path_buf, mount, strlen(mount)) == 0) { userlog(LOG_DEBUG, "watch path '%s' crossed mount point '%s' - skipping", path_buf, mount); return ERR_IGNORE; } } DIR* dir = NULL; if (recursive) { if ((dir = opendir(path_buf)) == NULL) { if (errno == EACCES || errno == ENOENT || errno == ENOTDIR) { userlog(LOG_DEBUG, "opendir(%s): %d", path_buf, errno); return ERR_IGNORE; } else { userlog(LOG_ERR, "opendir(%s): %s", path_buf, strerror(errno)); return ERR_CONTINUE; } } } int id = add_watch(path_len, parent); if (dir == NULL) { return id; } else if (id < 0) { closedir(dir); return id; } path_buf[path_len] = '/'; struct dirent* entry; while ((entry = readdir(dir)) != NULL) { if (entry->d_type != DT_DIR || strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { continue; } int name_len = strlen(entry->d_name); memcpy(path_buf + path_len + 1, entry->d_name, name_len + 1); int subdir_id = walk_tree(path_len + 1 + name_len, table_get(watches, id), recursive, mounts); if (subdir_id < 0 && subdir_id != ERR_IGNORE) { rm_watch(id, true); id = subdir_id; break; } } closedir(dir); return id; }
static int handle_add_repo (SeafWTMonitor *monitor, const char *repo_id, const char *worktree) { HANDLE handle; handle = add_watch (monitor->priv, repo_id, worktree); if (handle == NULL || !add_handle_to_iocp(monitor, handle)) { return -1; } return 0; }
static int handle_add_repo (SeafWTMonitorPriv *priv, const char *repo_id, long *handle) { int inotify_fd; g_assert (handle != NULL); inotify_fd = add_watch (repo_id); if (inotify_fd < 0) return -1; FD_SET (inotify_fd, &priv->read_fds); priv->maxfd = MAX (inotify_fd, priv->maxfd); *handle = (long)inotify_fd; return 0; }
int evfilt_vnode_knote_create(struct filter *filt, struct knote *kn) { struct stat sb; if (fstat(kn->kev.ident, &sb) < 0) { dbg_puts("fstat failed"); return (-1); } kn->data.vnode.nlink = sb.st_nlink; kn->data.vnode.size = sb.st_size; kn->kev.data = -1; return (add_watch(filt, kn)); }
static int add_watch(int fd, char *indir, unsigned int mask) { int wd = inotify_add_watch(fd, indir, mask); if (wd == -1) { LOG(vfs_sig_log, LOG_ERROR, "add %s to inotify watch err %m\n", indir); return -1; } if (wd >= MAX_WATCH) { LOG(vfs_sig_log, LOG_ERROR, "too many wd %d add to inotify!\n", wd); return -1; } snprintf(watch_dirs[wd], sizeof(watch_dirs[wd]), "%s", indir); DIR *dp; struct dirent *dirp; if ((dp = opendir(indir)) == NULL) { LOG(vfs_sig_log, LOG_ERROR, "add inotify watch opendir %s err %m\n", indir); return -1; } char file[256] = {0x0}; struct stat filestat; while((dirp = readdir(dp)) != NULL) { if (dirp->d_name[0] == '.') continue; snprintf(file, sizeof(file), "%s/%s", indir, dirp->d_name); if (stat(file, &filestat)) { LOG(vfs_sig_log, LOG_ERROR, "add inotify watch get file stat %s err %m\n", file); continue; } if (S_ISDIR(filestat.st_mode)) { if (add_watch(fd, file, mask)) return -1; } } closedir(dp); LOG(vfs_sig_log, LOG_TRACE, "add inotify watch %s ok\n", indir); return 0; }
void inotify_monitor::scan(const string &path, const bool accept_non_dirs) { struct stat fd_stat; if (!stat_path(path, fd_stat)) return; /* * When watching a directory the inotify API will return change events of * first-level children. Therefore, we do not need to manually add a watch * for a child unless it is a directory. By default, accept_non_dirs is * true to allow watching a file when first invoked on a node. */ if (!accept_non_dirs && !S_ISDIR(fd_stat.st_mode)) return; else if (follow_symlinks && S_ISLNK(fd_stat.st_mode)) { string link_path; if (read_link_path(path, link_path)) scan(link_path/*, fn */, accept_non_dirs); return; } if (!S_ISDIR(fd_stat.st_mode) && !accept_path(path)) return; if (!add_watch(path, fd_stat /*, fn */)) return; if (!recursive || !S_ISDIR(fd_stat.st_mode)) return; vector<string> children; get_directory_children(path, children); for (const string &child : children) { if (child.compare(".") == 0 || child.compare("..") == 0) continue; /* * Scan children but only watch directories. */ scan(path + "/" + child /*, fn */, false); } }
static void inotify_event_handler(struct inotify_event *event) { int wd = event->wd; char *filename = event->name; if(filename == NULL ) { LOG(vfs_sig_log, LOG_DEBUG, "inotify event has no filename, go next!\n"); return; } LOG(vfs_sig_log, LOG_DEBUG, "inotify event filename [%s]!\n", filename); if(filename[0] == '.') { LOG(vfs_sig_log, LOG_TRACE, "tmpfile [%s] , i dont care!\n", filename); return; } char path[256] = {0x0}; strcpy(path, watch_dirs[wd]); strcat(path, "/"); strcat(path, filename); if (event->mask & IN_CREATE) { struct stat filestat; if (stat(path, &filestat)) { LOG(vfs_sig_log, LOG_ERROR, "get file stat %s err %m\n", path); return; } if (S_ISDIR(filestat.st_mode)) { LOG(vfs_sig_log, LOG_NORMAL, "new dir %s\n", path); add_watch(inotify_fd, path, mask); } else LOG(vfs_sig_log, LOG_NORMAL, "file %s be create, ignore it\n", path); return; } t_task_base task; memset(&task, 0, sizeof(task)); snprintf(task.filename, sizeof(task.filename), "%s", path); if((event->mask & IN_CLOSE_WRITE) || (event->mask & IN_MOVED_TO)) { if (get_localfile_stat(&task) != LOCALFILE_OK) { LOG(vfs_sig_log, LOG_ERROR, "get_localfile_stat err %s %m\n", task.filename); return; } task.type = TASK_ADDFILE; } if((event->mask & IN_DELETE) || (event->mask & IN_MOVED_FROM)) { LOG(vfs_sig_log, LOG_DEBUG, "inotify file delete or move away %s\n", path); task.type = TASK_DELFILE; } t_vfs_tasklist *vfs_task; int ret = vfs_get_task(&vfs_task, TASK_HOME); if(ret != GET_TASK_OK) { LOG(vfs_sig_log, LOG_ERROR, "inotify get task_home error %s:%d:%d\n", ID, FUNC, LN); return; } memset(&(vfs_task->task), 0, sizeof(t_vfs_taskinfo)); memcpy(&(vfs_task->task.base), &task, sizeof(task)); vfs_set_task(vfs_task, TASK_WAIT); LOG(vfs_sig_log, LOG_DEBUG, "inotify add task to task_wait filepath %s, task type %d\n", task.filename, task.type); return; }
static void start_inotify_thread(void * arg) { #ifndef PR_SET_NAME #define PR_SET_NAME 15 #endif memset(watch_dirs, 0, sizeof(watch_dirs)); prctl(PR_SET_NAME, "fcs_inotify", 0, 0, 0); pthread_detach(pthread_self()); inotify_fd = inotify_init(); if(inotify_fd < 0) { stop = 1; LOG(vfs_sig_log, LOG_ERROR, "inotify thread init error!\n"); return ; } char *flvdir = myconfig_get_value("vfs_src_datadir"); if(!flvdir) { flvdir = "/flvdata"; } FD_ZERO(&fds); FD_SET(inotify_fd, &fds); int ret = add_watch(inotify_fd, flvdir, mask); if(ret != 0) { stop = 1; LOG(vfs_sig_log, LOG_ERROR, "inotify add watch dir error!\n"); return ; } LOG(vfs_sig_log, LOG_DEBUG, "start to inotify watch dir\n"); struct timeval tv; //Ñ»·¼ì²éʼþ while(1) { tv.tv_sec = 20; tv.tv_usec = 0; if (select(inotify_fd + 1, &fds, NULL, NULL, &tv) > 0) { while (1) { int len, index = 0; unsigned char buf[1024] = {0}; len = read(inotify_fd, &buf, sizeof(buf)); if (len <= 0) break; while (index < len) { struct inotify_event *event = (struct inotify_event *)(buf + index); inotify_event_handler(event); index += sizeof(struct inotify_event) + event->len; } } } FD_ZERO(&fds); FD_SET(inotify_fd, &fds); } }
int handle_monitor (int argc, gchar *argv[], gboolean do_help) { GOptionContext *context; gchar *param; GError *error = NULL; GFileMonitorFlags flags; guint total = 0; guint i; g_set_prgname ("gio monitor"); /* Translators: commandline placeholder */ param = g_strdup_printf ("[%s...]", _("LOCATION")); context = g_option_context_new (param); g_free (param); g_option_context_set_help_enabled (context, FALSE); g_option_context_set_summary (context, _("Monitor files or directories for changes.")); g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); if (do_help) { show_help (context, NULL); return 0; } if (!g_option_context_parse (context, &argc, &argv, &error)) { show_help (context, error->message); g_error_free (error); return 1; } g_option_context_free (context); flags = (no_moves ? 0 : G_FILE_MONITOR_WATCH_MOVES) | (mounts ? G_FILE_MONITOR_WATCH_MOUNTS : 0); if (watch_dirs) { for (i = 0; watch_dirs[i]; i++) if (!add_watch (watch_dirs[i], WATCH_DIR, flags, TRUE)) return 1; total++; } if (watch_files) { for (i = 0; watch_files[i]; i++) if (!add_watch (watch_files[i], WATCH_FILE, flags, TRUE)) return 1; total++; } if (watch_direct) { for (i = 0; watch_direct[i]; i++) if (!add_watch (watch_direct[i], WATCH_FILE, flags | G_FILE_MONITOR_WATCH_HARD_LINKS, TRUE)) return 1; total++; } if (watch_silent) { for (i = 0; watch_silent[i]; i++) if (!add_watch (watch_silent[i], WATCH_FILE, flags | G_FILE_MONITOR_WATCH_HARD_LINKS, FALSE)) return 1; total++; } if (watch_default) { for (i = 0; watch_default[i]; i++) if (!add_watch (watch_default[i], WATCH_AUTO, flags, TRUE)) return 1; total++; } if (!total) { g_printerr ("gio: Must give at least one file to monitor\n"); return 1; } while (TRUE) g_main_context_iteration (NULL, TRUE); return 0; }
int main(int argc, char *argv[]) { struct itimerspec its; sigset_t mask; std::unordered_map<int, std::string> inotify_watch_map; std::unordered_map<int, fd::socket> conn_map; struct epoll_event events[MAX_EVENTS]; /* setup inotify */ auto inotify = fd::inotify(); for (int i = 0; i < argc; ++i) { int wd = inotify.add_watch(argv[i], IN_OPEN | IN_MODIFY | IN_ACCESS); inotify_watch_map[wd] = std::string(argv[i]); } /* setup timerfd */ its.it_value.tv_sec = 1; its.it_value.tv_nsec = 0; its.it_interval.tv_sec = 10; its.it_interval.tv_nsec = 0; auto timerfd = fd::timerfd(); timerfd.settime(its); /* setup signalfd */ sigfillset(&mask); int err = sigprocmask(SIG_BLOCK, &mask, nullptr); if (err < 0) throw std::system_error(errno, std::system_category(), "sigprocmask()"); auto sfd = fd::signalfd(mask); /* setup socket */ unlink("/tmp/.epoll_test.sock"); auto server = fd::easy::unix_socket::server("/tmp/.epoll_test.sock"); /* setup epoll */ auto epoll = fd::epoll(); epoll.add(inotify, EPOLLIN, inotify); epoll.add(timerfd, EPOLLIN, timerfd); epoll.add(sfd, EPOLLIN, sfd); epoll.add(server, EPOLLIN, server); std::cout << "Use: \"Hello, World!\" | ncat -U /tmp/.epoll_test.sock\n" << "Press CTRL + c to exit\n"; bool loop = true; while (loop) { auto nfds = epoll.wait(events, MAX_EVENTS); for (int i = 0; i < nfds; ++i) { if (events[i].data.fd == inotify) { struct inotify_event *event; char buffer[4096]; std::cout << "**INOTIFY: "; auto n = inotify.read(buffer, sizeof(buffer)); FOR_EACH_INOTIFY_EVENT(buffer, n, event) { if (event->len > 0) std::cout << event->name << " "; else std::cout << inotify_watch_map[event->wd] << " "; if (event->mask & IN_ACCESS) std::cout << "IN_ACCESS "; if (event->mask & IN_MODIFY) std::cout << "IN_MODIFY "; if (event->mask & IN_OPEN) std::cout << "IN_OPEN "; std::cout << '\n'; } } else if (events[i].data.fd == timerfd) { /* * Clear data on file descriptor, otherwise epoll will * trigger again. */ (void) timerfd.read(); std::cout << "**TIMERFD: timeout\n"; } else if (events[i].data.fd == sfd) { struct signalfd_siginfo info; sfd.read(info); std::cout << "**SIGNALFD: received " << strsignal(info.ssi_signo) << '\n'; if (info.ssi_signo == SIGTERM || info.ssi_signo == SIGINT) loop = false; } else if (events[i].data.fd == server) { auto sock = server.accept(); epoll.add(sock, EPOLLIN, sock); /* * Notice how std::make_pair() can't make use of the cast * operator, therefore we can use the socket::fd() function */ conn_map.insert(std::make_pair(sock.fd(), std::move(sock))); std::cout << "**SERVER SOCKET: new connection\n"; } else { char buf[128]; auto it = conn_map.find(events[i].data.fd); std::cout << "**UNIX_CONNECTION: received: "; while (1) { auto n = it->second.recv(buf, sizeof(buf), MSG_NOSIGNAL); if (n == 0) break; std::cout << std::string(buf, n); } conn_map.erase(it); } } }
int evfilt_vnode_knote_enable(struct filter *filt, struct knote *kn) { return add_watch(filt, kn); }
CmdResult Handle (const std::vector<std::string> ¶meters, User *user) { if (parameters.empty()) { watchlist* wl = ext.get(user); if (wl) { for (watchlist::iterator q = wl->begin(); q != wl->end(); q++) { if (!q->second.empty()) user->WriteNumeric(604, "%s %s :is online", q->first.c_str(), q->second.c_str()); } } user->WriteNumeric(607, ":End of WATCH list"); } else if (parameters.size() > 0) { for (int x = 0; x < (int)parameters.size(); x++) { const char *nick = parameters[x].c_str(); if (!strcasecmp(nick,"C")) { // watch clear watchlist* wl = ext.get(user); if (wl) { for (watchlist::iterator i = wl->begin(); i != wl->end(); i++) { watchentries::iterator i2 = whos_watching_me->find(i->first); if (i2 != whos_watching_me->end()) { /* People are watching this user, am i one of them? */ std::deque<User*>::iterator n = std::find(i2->second.begin(), i2->second.end(), user); if (n != i2->second.end()) /* I'm no longer watching you... */ i2->second.erase(n); if (i2->second.empty()) /* nobody else is, either. */ whos_watching_me->erase(i2); } } ext.unset(user); } } else if (!strcasecmp(nick,"L")) { watchlist* wl = ext.get(user); if (wl) { for (watchlist::iterator q = wl->begin(); q != wl->end(); q++) { if (!q->second.empty()) { user->WriteNumeric(604, "%s %s :is online", q->first.c_str(), q->second.c_str()); User *targ = ServerInstance->FindNick(q->first.c_str()); if (targ->IsAway()) { user->WriteNumeric(609, "%s %s %s %lu :is away", targ->nick.c_str(), targ->ident.c_str(), targ->dhost.c_str(), (unsigned long) targ->awaytime); } } else user->WriteNumeric(605, "%s * * 0 :is offline", q->first.c_str()); } } user->WriteNumeric(607, ":End of WATCH list"); } else if (!strcasecmp(nick,"S")) { watchlist* wl = ext.get(user); int you_have = 0; int youre_on = 0; std::string list; if (wl) { for (watchlist::iterator q = wl->begin(); q != wl->end(); q++) list.append(q->first.c_str()).append(" "); you_have = wl->size(); } watchentries::iterator i2 = whos_watching_me->find(user->nick.c_str()); if (i2 != whos_watching_me->end()) youre_on = i2->second.size(); user->WriteNumeric(603, ":You have %d and are on %d WATCH entries", you_have, youre_on); user->WriteNumeric(606, ":%s", list.c_str()); user->WriteNumeric(607, ":End of WATCH S"); } else if (nick[0] == '-') { nick++; remove_watch(user, nick); } else if (nick[0] == '+') { nick++; add_watch(user, nick); } } } return CMD_SUCCESS; }
axa_json_res_t axa_body_to_json(axa_emsg_t *emsg, nmsg_input_t nmsg_input, axa_p_hdr_t *hdr, axa_p_body_t *body, size_t body_len, char **out) { struct axa_strbuf *sb = NULL, *sb_tmp = NULL; axa_json_res_t res; yajl_gen g = NULL; int yajl_rc; char op_str[AXA_P_OP_STRLEN]; char addr_str[INET6_ADDRSTRLEN]; axa_p_direction_t dir; uint8_t *p, *q; uint16_t user_objs_cnt, an_objs_cnt; _axa_p_stats_sys_t *sys; char time_buf[30]; struct tm *tm_info; time_t t; runits_t ru; _axa_p_stats_user_t *user_obj; _axa_p_stats_user_rad_an_t *an_obj; switch(AXA_P2H16(hdr->op)) { case AXA_P_OP_MISSED_RAD: case AXA_P_OP_AHIT: case AXA_P_OP_ALIST: dir = AXA_P_FROM_RAD; break; case AXA_P_OP_USER: case AXA_P_OP_JOIN: case AXA_P_OP_PAUSE: case AXA_P_OP_GO: case AXA_P_OP_WATCH: case AXA_P_OP_WGET: case AXA_P_OP_STOP: case AXA_P_OP_ALL_STOP: case AXA_P_OP_CHANNEL: case AXA_P_OP_CGET: case AXA_P_OP_ACCT: case _AXA_P_OP_KILL_REQ: case _AXA_P_OP_STATS_REQ: dir = AXA_P_TO_SRA; break; case AXA_P_OP_ANOM: case AXA_P_OP_AGET: case AXA_P_OP_RADU: dir = AXA_P_TO_RAD; break; default: dir = AXA_P_FROM_SRA; break; } /* switch */ if (axa_ck_hdr(emsg, hdr, "json", dir) == false) return (AXA_JSON_RES_FAILURE); if (AXA_P2H32(hdr->len) - sizeof(axa_p_hdr_t) != body_len) { axa_pemsg(emsg, "body length mismatch %zu != %zu", AXA_P2H32(hdr->len) - sizeof(axa_p_hdr_t), body_len); return (AXA_JSON_RES_FAILURE); } if (axa_ck_body(emsg, hdr->op, body, body_len) == false) return (AXA_JSON_RES_FAILURE); sb = axa_strbuf_init(); if (sb == NULL) { axa_pemsg(emsg, "could not allocate axa_strbuf"); return (AXA_JSON_RES_MEMFAIL); } sb_tmp = axa_strbuf_init(); if (sb_tmp == NULL) { axa_pemsg(emsg, "could not allocate axa_strbuf"); axa_strbuf_destroy(&sb); res = AXA_JSON_RES_MEMFAIL; goto err; } g = yajl_gen_alloc(NULL); AXA_ASSERT (g != NULL); yajl_rc = yajl_gen_config(g, yajl_gen_print_callback, _callback_print_yajl_axa_strbuf, sb); AXA_ASSERT(yajl_rc != 0); add_yajl_map(g); add_yajl_string(g, "tag"); if (AXA_P2H16(hdr->tag) == AXA_TAG_NONE) add_yajl_string(g, "*"); else add_yajl_integer(g, AXA_P2H16(hdr->tag)); add_yajl_string(g, "op"); axa_op_to_str(op_str, sizeof(op_str), hdr->op); add_yajl_string(g, op_str); switch ((axa_p_op_t)hdr->op) { case AXA_P_OP_NOP: break; case AXA_P_OP_HELLO: add_yajl_string(g, "id"); add_yajl_number(g, sb_tmp, AXA_P2H64(body->hello.id)); add_yajl_string(g, "pvers_min"); add_yajl_integer(g, body->hello.pvers_min); add_yajl_string(g, "pvers_max"); add_yajl_integer(g, body->hello.pvers_max); add_yajl_string(g, "str"); add_yajl_string(g, body->hello.str); break; case AXA_P_OP_OK: case AXA_P_OP_ERROR: add_yajl_string(g, "orig_op"); axa_op_to_str(op_str, sizeof(op_str), body->result.orig_op); add_yajl_string(g, op_str); add_yajl_string(g, "str"); add_yajl_string(g, body->result.str); break; case AXA_P_OP_MISSED: add_yajl_string(g, "missed"); add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed.missed)); add_yajl_string(g, "dropped"); add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed.dropped)); add_yajl_string(g, "rlimit"); add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed.rlimit)); add_yajl_string(g, "filtered"); add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed.filtered)); add_yajl_string(g, "last_report"); add_yajl_integer(g, AXA_P2H32(body->missed.last_report)); break; case AXA_P_OP_MISSED_RAD: add_yajl_string(g, "sra_missed"); add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed_rad.sra_missed)); add_yajl_string(g, "sra_dropped"); add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed_rad.sra_dropped)); add_yajl_string(g, "sra_rlimit"); add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed_rad.sra_rlimit)); add_yajl_string(g, "sra_filtered"); add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed_rad.sra_filtered)); add_yajl_string(g, "dropped"); add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed_rad.dropped)); add_yajl_string(g, "rlimit"); add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed_rad.rlimit)); add_yajl_string(g, "filtered"); add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed_rad.filtered)); add_yajl_string(g, "last_report"); add_yajl_integer(g, AXA_P2H32(body->missed_rad.last_report)); break; case AXA_P_OP_WHIT: res = add_whit(emsg, g, sb, nmsg_input, &(body->whit), body_len); if (res != AXA_JSON_RES_SUCCESS) goto err; break; case AXA_P_OP_WATCH: add_watch(g, &(body->watch), body_len); break; case AXA_P_OP_ANOM: { bool print_parms; print_parms = body_len > offsetof(axa_p_anom_t, parms) && body->anom.parms[0] != '\0'; add_anom(g, body->anom, print_parms); break; } case AXA_P_OP_CHANNEL: res = add_channel(emsg, g, body->channel.ch); if (res != AXA_JSON_RES_SUCCESS) goto err; add_yajl_string(g, "on"); add_yajl_bool(g, body->channel.on != 0); break; case AXA_P_OP_WLIST: add_yajl_string(g, "cur_tag"); add_yajl_integer(g, AXA_P2H16(body->wlist.cur_tag)); add_watch(g, &(body->wlist.w), body_len - offsetof(axa_p_wlist_t, w)); break; case AXA_P_OP_AHIT: add_yajl_string(g, "an"); add_yajl_string(g, body->ahit.an.c); res = add_whit(emsg, g, sb, nmsg_input, &(body->ahit.whit), body_len - offsetof(axa_p_ahit_t, whit)); if (res != AXA_JSON_RES_SUCCESS) goto err; break; case AXA_P_OP_ALIST: { bool print_parms; add_yajl_string(g, "cur_tag"); add_yajl_integer(g, AXA_P2H16(body->alist.cur_tag)); print_parms = body_len > offsetof(axa_p_alist_t, anom) + offsetof(axa_p_anom_t, parms) && body->alist.anom.parms[0] != '\0'; add_anom(g, body->alist.anom, print_parms); break; } case AXA_P_OP_CLIST: res = add_channel(emsg, g, body->clist.ch); if (res != AXA_JSON_RES_SUCCESS) goto err; add_yajl_string(g, "on"); add_yajl_bool(g, body->clist.on != 0); add_yajl_string(g, "spec"); add_yajl_string(g, body->clist.spec.c); break; case AXA_P_OP_USER: add_yajl_string(g, "name"); add_yajl_string(g, body->user.name); break; case AXA_P_OP_OPT: { char buf[AXA_P_OP_STRLEN]; add_yajl_string(g, "type"); add_yajl_string(g, axa_opt_to_str(buf, sizeof(buf), AXA_P2H64(body->opt.type))); switch((axa_p_opt_type_t)body->opt.type) { case AXA_P_OPT_TRACE: { add_yajl_string(g, "trace"); if (AXA_P2H64(body->opt.u.trace) != AXA_P_OPT_TRACE_REQ) { add_yajl_number(g, sb_tmp, AXA_P2H64(body->opt.u.trace)); } else { add_yajl_string(g, "REQUEST TRACE VALUE"); } break; } case AXA_P_OPT_RLIMIT: add_yajl_string(g, "max_pkts_per_sec"); res = add_rlimit_count(emsg, g, body->opt.u.rlimit.max_pkts_per_sec); if (res != AXA_JSON_RES_SUCCESS) goto err; add_yajl_string(g, "cur_pkts_per_sec"); add_yajl_number(g, sb_tmp, AXA_P2H64(body->opt.u.rlimit.cur_pkts_per_sec)); add_yajl_string(g, "report_secs"); res = add_rlimit_count(emsg, g, body->opt.u.rlimit.report_secs); if (res != AXA_JSON_RES_SUCCESS) goto err; break; case AXA_P_OPT_SAMPLE: add_yajl_string(g, "sample"); if (AXA_P2H64(body->opt.u.sample) == 0) { add_yajl_string(g, "requested"); } else { axa_strbuf_reset(sb_tmp); axa_strbuf_append(sb_tmp, "%0.6f", ((double)AXA_P2H64(body->opt.u.sample)) / AXA_P_OPT_SAMPLE_MAX); add_yajl_number_sb(g, sb_tmp); } break; case AXA_P_OPT_SNDBUF: add_yajl_string(g, "bufsize"); add_yajl_number(g, sb_tmp, AXA_P2H64(body->opt.u.bufsize)); break; } /* switch */ break; } case AXA_P_OP_JOIN: add_yajl_string(g, "id"); add_yajl_number(g, sb_tmp, AXA_P2H64(body->join.id)); break; case _AXA_P_OP_STATS_REQ: if (body->stats_req.version != _AXA_STATS_VERSION_ONE) { res = AXA_JSON_RES_FAILURE; goto err; } add_yajl_string(g, "version"); add_yajl_integer(g, body->stats_req.version); add_yajl_string(g, "type"); switch (body->stats_req.type) { case AXA_P_STATS_M_M_SUM: add_yajl_string(g, "summary"); break; case AXA_P_STATS_M_M_ALL: add_yajl_string(g, "all"); break; case AXA_P_STATS_M_M_SN: add_yajl_string(g, "serial number"); break; case AXA_P_STATS_M_M_U: add_yajl_string(g, "user name"); break; default: add_yajl_string(g, "unknown"); } if (body->stats_req.type == AXA_P_STATS_M_M_SN) { add_yajl_string(g, "serial number"); add_yajl_integer(g, body->stats_req.sn); } if (body->stats_req.type == AXA_P_STATS_M_M_U) { add_yajl_string(g, "user name"); add_yajl_string(g, body->stats_req.user.name); } break; case _AXA_P_OP_STATS_RSP: if (body->stats_rsp.version != _AXA_STATS_VERSION_ONE) { res = AXA_JSON_RES_FAILURE; goto err; } add_yajl_string(g, "version"); add_yajl_integer(g, body->stats_rsp.version); if (body->stats_rsp.sys_objs_cnt > 1) { res = AXA_JSON_RES_FAILURE; goto err; } add_yajl_string(g, "result"); switch (body->stats_rsp.result) { case AXA_P_STATS_R_SUCCESS: add_yajl_string(g, "success"); break; case AXA_P_STATS_R_FAIL_NF: add_yajl_string(g, "failed: user not found"); break; case AXA_P_STATS_R_FAIL_UNK: default: add_yajl_string(g, "failed: unknown reason"); } if (body->stats_rsp.sys_objs_cnt == 1) { p = (uint8_t *)&body->stats_rsp; sys = (_axa_p_stats_sys_t *)(p + sizeof (_axa_p_stats_rsp_t)); if (sys->type != _AXA_P_STATS_TYPE_SYS) { res = AXA_JSON_RES_FAILURE; goto err; } add_yajl_string(g, "load"); add_yajl_array(g); add_yajl_integer(g, AXA_P2H32(sys->load[0])); add_yajl_integer(g, AXA_P2H32(sys->load[1])); add_yajl_integer(g, AXA_P2H32(sys->load[2])); close_yajl_array(g); add_yajl_string(g, "cpu_usage"); add_yajl_integer(g, AXA_P2H32(sys->cpu_usage)); add_yajl_string(g, "uptime"); add_yajl_integer(g, AXA_P2H32(sys->uptime)); add_yajl_string(g, "starttime"); add_yajl_integer(g, AXA_P2H32(sys->starttime)); add_yajl_string(g, "vmsize"); add_yajl_number(g, sb_tmp, AXA_P2H64(sys->vmsize)); add_yajl_string(g, "vmrss"); add_yajl_number(g, sb_tmp, AXA_P2H64(sys->vmrss)); add_yajl_string(g, "thread_cnt"); add_yajl_integer(g, AXA_P2H32(sys->thread_cnt)); add_yajl_string(g, "user_cnt"); add_yajl_integer(g, AXA_P2H32(sys->user_cnt)); switch (sys->server_type) { case _AXA_STATS_SRVR_TYPE_SRA: add_yajl_string(g, "server_type"); add_yajl_string(g, "sra"); add_yajl_string(g, "fd_sockets"); add_yajl_integer(g, AXA_P2H32(sys->fd_sockets)); add_yajl_string(g, "fd_pipes"); add_yajl_integer(g, AXA_P2H32(sys->fd_pipes)); add_yajl_string(g, "fd_anon_inodes"); add_yajl_integer(g, AXA_P2H32(sys->fd_anon_inodes)); add_yajl_string(g, "fd_other"); add_yajl_integer(g, AXA_P2H32(sys->fd_other)); add_yajl_string(g, "rchar"); add_yajl_number(g, sb_tmp, AXA_P2H64(sys->rchar)); add_yajl_string(g, "wchar"); add_yajl_number(g, sb_tmp, AXA_P2H64(sys->wchar)); add_yajl_string(g, "sra_ipv4_watch_cnt"); add_yajl_integer(g, AXA_P2H32(sys->srvr.sra.watches.ipv4_cnt)); add_yajl_string(g, "sra_ipv6_watch_cnt"); add_yajl_integer(g, AXA_P2H32(sys->srvr.sra.watches.ipv6_cnt)); add_yajl_string(g, "sra_dns_watch_cnt"); add_yajl_integer(g, AXA_P2H32(sys->srvr.sra.watches.dns_cnt)); add_yajl_string(g, "sra_ch_watch_cnt"); add_yajl_integer(g, AXA_P2H32(sys->srvr.sra.watches.ch_cnt)); add_yajl_string(g, "sra_err_watch_cnt"); add_yajl_integer(g, AXA_P2H32(sys->srvr.sra.watches.err_cnt)); add_yajl_string(g, "sra_channels"); add_yajl_array(g); for (int j = 0; j <= AXA_NMSG_CH_MAX; j++) { if (axa_get_bitwords(sys->srvr.sra.ch_mask.m, j)) { axa_strbuf_reset(sb_tmp); axa_strbuf_append(sb_tmp, "ch%d", (j)); add_yajl_string(g, (const char*)sb_tmp->data); } } close_yajl_array(g); break; case _AXA_STATS_SRVR_TYPE_RAD: add_yajl_string(g, "server_type"); add_yajl_string(g, "rad"); add_yajl_string(g, "rad_anomaly_cnt"); add_yajl_integer(g, AXA_P2H32(sys->srvr.rad.an_cnt)); break; default: res = AXA_JSON_RES_FAILURE; goto err; } } user_objs_cnt = body->stats_rsp.user_objs_cnt; p = (uint8_t *)&body->stats_rsp + sizeof (_axa_p_stats_rsp_t) + body->stats_rsp.sys_objs_cnt * sizeof (_axa_p_stats_sys_t); if (user_objs_cnt > 0) { add_yajl_string(g, "users"); add_yajl_array(g); user_obj = (_axa_p_stats_user_t *)p; for (; user_objs_cnt; user_objs_cnt--, user_obj++) { add_yajl_string(g, "user_obj"); add_yajl_map(g); add_yajl_string(g, "server_type"); switch (user_obj->server_type) { case _AXA_STATS_SRVR_TYPE_SRA: add_yajl_string(g, "sra"); break; case _AXA_STATS_SRVR_TYPE_RAD: add_yajl_string(g, "rad"); break; default: add_yajl_string(g, "unkwn"); break; } add_yajl_string(g, "user"); add_yajl_string(g, user_obj->user.name); add_yajl_string(g, "is_admin"); add_yajl_bool(g, user_obj->is_admin == 1 ? true : false); add_yajl_string(g, "io_type"); switch (user_obj->io_type) { case AXA_IO_TYPE_UNIX: add_yajl_string(g, AXA_IO_TYPE_UNIX_STR); break; case AXA_IO_TYPE_TCP: add_yajl_string(g, AXA_IO_TYPE_TCP_STR); break; case AXA_IO_TYPE_SSH: add_yajl_string(g, AXA_IO_TYPE_SSH_STR); break; case AXA_IO_TYPE_TLS: add_yajl_string(g, AXA_IO_TYPE_TLS_STR); break; case AXA_IO_TYPE_APIKEY: add_yajl_string(g, AXA_IO_TYPE_APIKEY_STR); break; case AXA_IO_TYPE_UNKN: default: add_yajl_string(g, "unknown"); break; } add_yajl_string(g, "address"); switch (user_obj->addr_type) { case AXA_AF_INET: inet_ntop(AF_INET, &user_obj->ip.ipv4, addr_str, sizeof(addr_str)); break; case AXA_AF_INET6: inet_ntop(AF_INET6, &user_obj->ip.ipv6, addr_str, sizeof(addr_str)); break; case AXA_AF_UNKNOWN: strlcpy(addr_str, "unknown", sizeof(addr_str)); break; } add_yajl_string(g, addr_str); add_yajl_string(g, "sn"); add_yajl_integer(g, user_obj->sn); add_yajl_string(g, "connected_since"); t = AXA_P2H32(user_obj->connected_since.tv_sec); tm_info = gmtime(&t); strftime(time_buf, sizeof (time_buf), "%Y-%m-%dT%H:%M:%SZ", tm_info); add_yajl_string(g, time_buf); add_yajl_string(g, "ratelimit"); if (AXA_P2H64(user_obj->ratelimit) == AXA_RLIMIT_OFF) { add_yajl_integer(g, 0); } else { add_yajl_integer(g, AXA_P2H64(user_obj->ratelimit)); } add_yajl_string(g, "sample"); axa_strbuf_reset(sb_tmp); axa_strbuf_append(sb_tmp, "%0.2f", ((double)AXA_P2H64(user_obj->sample))); add_yajl_number_sb(g, sb_tmp); add_yajl_string(g, "last_count_update"); t = AXA_P2H32(user_obj->last_cnt_update.tv_sec); tm_info = gmtime(&t); strftime(time_buf, sizeof (time_buf), "%Y-%m-%dT%H:%M:%SZ", tm_info); add_yajl_string(g, time_buf); add_yajl_string(g, "filtered"); add_yajl_integer(g, user_obj->filtered); add_yajl_string(g, "missed"); add_yajl_integer(g, user_obj->missed); add_yajl_string(g, "collected"); add_yajl_integer(g, user_obj->collected); add_yajl_string(g, "sent"); add_yajl_integer(g, user_obj->sent); add_yajl_string(g, "rlimit"); add_yajl_integer(g, user_obj->rlimit); add_yajl_string(g, "congested"); add_yajl_integer(g, user_obj->congested); switch (user_obj->server_type) { case _AXA_STATS_SRVR_TYPE_SRA: add_yajl_string(g, "ipv4_watch_cnt"); add_yajl_integer(g, AXA_P2H32(user_obj->srvr.sra.watches.ipv4_cnt)); add_yajl_string(g, "ipv6_watch_cnt"); add_yajl_integer(g, AXA_P2H32(user_obj->srvr.sra.watches.ipv6_cnt)); add_yajl_string(g, "dns_watch_cnt"); add_yajl_integer(g, AXA_P2H32(user_obj->srvr.sra.watches.dns_cnt)); add_yajl_string(g, "ch_watch_cnt"); add_yajl_integer(g, AXA_P2H32(user_obj->srvr.sra.watches.ch_cnt)); add_yajl_string(g, "err_watch_cnt"); add_yajl_integer(g, AXA_P2H32(user_obj->srvr.sra.watches.err_cnt)); add_yajl_string(g, "channels"); add_yajl_array(g); for (int j = 0; j <= AXA_NMSG_CH_MAX; j++) { if (axa_get_bitwords(user_obj->srvr.sra.ch_mask.m, j)) { axa_strbuf_reset(sb_tmp); axa_strbuf_append(sb_tmp, "ch%d", (j)); add_yajl_string(g, (const char*)sb_tmp->data); } } close_yajl_array(g); break; case _AXA_STATS_SRVR_TYPE_RAD: add_yajl_string(g, "anomaly_count_in_flight"); add_yajl_integer(g, AXA_P2H32(user_obj->srvr.rad.an_obj_cnt)); add_yajl_string(g, "anomaly_count_total"); add_yajl_integer(g, AXA_P2H32(user_obj->srvr.rad.an_obj_cnt_total)); an_objs_cnt = user_obj->srvr.rad.an_obj_cnt; q = (uint8_t *)&body->stats_rsp + sizeof (_axa_p_stats_rsp_t) + body->stats_rsp.sys_objs_cnt * sizeof (_axa_p_stats_sys_t) + sizeof (_axa_p_stats_user_t); if (an_objs_cnt > 0) { add_yajl_string(g, "anomalies"); add_yajl_array(g); an_obj = (_axa_p_stats_user_rad_an_t *)q; for ( ; an_objs_cnt; an_objs_cnt--, an_obj++) { add_yajl_string(g, "an_obj"); add_yajl_map(g); add_yajl_string(g, "name"); add_yajl_string(g, an_obj->name); add_yajl_string(g, "options"); add_yajl_string(g, an_obj->opt); add_yajl_string(g, "ru_original"); ru = AXA_P2H32(an_obj->ru_original); if (ru == INT_MAX) add_yajl_string(g, "unlimited"); else add_yajl_integer(g, AXA_P2H32(an_obj->ru_original)); add_yajl_string(g, "ru_current"); ru = AXA_P2H32(an_obj->ru_current); if (ru == INT_MAX) add_yajl_string(g, "unlimited"); else add_yajl_integer(g, AXA_P2H32(an_obj->ru_current)); add_yajl_string(g, "ru_cost"); add_yajl_integer(g, AXA_P2H32(an_obj->ru_cost)); add_yajl_string(g, "channels"); add_yajl_array(g); for (int j = 0; j <= AXA_NMSG_CH_MAX; j++) { if (axa_get_bitwords(an_obj->ch_mask.m, j)) { axa_strbuf_reset(sb_tmp); axa_strbuf_append(sb_tmp, "ch%d", (j)); add_yajl_string(g, (const char*)sb_tmp->data); } } close_yajl_array(g); close_yajl_map(g); } close_yajl_array(g); } break; default: res = AXA_JSON_RES_FAILURE; goto err; } /* switch (user_obj->server_type) */ close_yajl_map(g); } /* for (; user_objs_cnt; user_objs_cnt--, ... */ close_yajl_array(g); } /* if (user_objs_cnt > 0) */ break; case _AXA_P_OP_KILL_REQ: case _AXA_P_OP_KILL_RSP: add_yajl_string(g, "mode"); add_yajl_integer(g, body->kill.mode); add_yajl_string(g, "user"); add_yajl_string(g, body->kill.user.name); add_yajl_string(g, "sn"); add_yajl_integer(g, AXA_P2H32(body->kill.sn)); add_yajl_string(g, "result"); add_yajl_integer(g, body->kill.result); break; case AXA_P_OP_PAUSE: case AXA_P_OP_GO: case AXA_P_OP_WGET: case AXA_P_OP_AGET: case AXA_P_OP_STOP: case AXA_P_OP_ALL_STOP: case AXA_P_OP_CGET: case AXA_P_OP_ACCT: case AXA_P_OP_RADU: break; case AXA_P_OP_MGMT_GETRSP: case AXA_P_OP_MGMT_GET: add_yajl_string(g, "mgmt is deprecated; please upgrade and use \"stats\""); break; } /* switch */ close_yajl_map(g); yajl_gen_reset(g, ""); yajl_gen_free(g); *out = sb->data; free(sb); axa_strbuf_destroy(&sb_tmp); return (AXA_JSON_RES_SUCCESS); err: if (g != NULL) yajl_gen_free(g); axa_strbuf_destroy(&sb); axa_strbuf_destroy(&sb_tmp); return (res); }