int fdset_new_fill(FDSet **_s) { DIR *d; struct dirent *de; int r = 0; FDSet *s; assert(_s); /* Creates an fdset and fills in all currently open file * descriptors. */ d = opendir("/proc/self/fd"); if (!d) return -errno; s = fdset_new(); if (!s) { r = -ENOMEM; goto finish; } while ((de = readdir(d))) { int fd = -1; if (ignore_file(de->d_name)) continue; r = safe_atoi(de->d_name, &fd); if (r < 0) goto finish; if (fd < 3) continue; if (fd == dirfd(d)) continue; r = fdset_put(s, fd); if (r < 0) goto finish; } r = 0; *_s = s; s = NULL; finish: closedir(d); /* We won't close the fds here! */ if (s) set_free(MAKE_SET(s)); return r; }
static int add_locales_from_libdir (Set *locales) { _cleanup_closedir_ DIR *dir; struct dirent *entry; int r; dir = opendir("/usr/lib/locale"); if (!dir) { log_error("Failed to open locale directory: %m"); return -errno; } errno = 0; while ((entry = readdir(dir))) { char *z; if (entry->d_type != DT_DIR) continue; if (ignore_file(entry->d_name)) continue; z = strdup(entry->d_name); if (!z) return log_oom(); r = set_consume(locales, z); if (r < 0 && r != -EEXIST) { log_error("Failed to add locale: %s", strerror(-r)); return r; } errno = 0; } if (errno > 0) { log_error("Failed to read locale directory: %m"); return -errno; } return 0; }
int main(int argc, char **argv) { int i, c, ret = 0; int n_files; unsigned long n_units = DEFAULT_N_LINES; char forever = 0, mode = M_LINES; char **filenames; //struct file_struct *files = NULL; int event_cnt = 1; /* Set up logging */ openlog("AUDITD_BRO", 0, LOG_USER); au = auparse_init(AUSOURCE_FEED, 0); auparse_add_callback(au, auparse_callback, &event_cnt, NULL); if (au == NULL) { printf("Error - %s\n", strerror(errno)); return 1; } while ((c = getopt_long(argc, argv, "c:n:fvVh", long_opts, NULL)) != -1) { switch (c) { case 'c': mode = M_BYTES; /* fall through */ case 'n': if (*optarg == '+') { from_begin = 1; optarg++; } else if (*optarg == '-') optarg++; if (!is_digit(*optarg)) { fprintf(stderr, "Error: Invalid number of units: %s\n", optarg); exit(EXIT_FAILURE); } n_units = strtoul(optarg, NULL, 0); break; case 'f': forever = 1; break; case 'v': verbose = 1; break; case 'V': fprintf(stdout, "%s %s\n", PROGRAM_NAME, VERSION); exit(EXIT_SUCCESS); case 'h': usage(EXIT_SUCCESS); default: usage(EXIT_FAILURE); } } /* Do we have some files to read from? */ if (optind < argc) { n_files = argc - optind; filenames = argv + optind; } else { /* It must be stdin then */ static char *dummy_stdin = "-"; n_files = 1; filenames = &dummy_stdin; /* POSIX says that -f is ignored if no file operand is specified and standard input is a pipe. */ if (forever) { struct stat finfo; int rc = fstat(STDIN_FILENO, &finfo); if (unlikely(rc == -1)) { fprintf(stderr, "Error: Could not stat stdin (%s)\n", strerror(errno)); exit(EXIT_FAILURE); } if (rc == 0 && IS_PIPELIKE(finfo.st_mode)) forever = 0; } } // end stdin files = emalloc(n_files * sizeof(struct file_struct)); for (i = 0; i < n_files; i++) { files[i].name = filenames[i]; setup_file(&files[i]); ret = tail_file(&files[i], n_units, mode, forever); if (ret < 0) ignore_file(&files[i]); } if (forever) ret = watch_files(files, n_files); free(files); auparse_flush_feed(au); auparse_destroy(au); closelog(); return ret; }
static int watch_files(struct file_struct *_files, int n_files) { int ifd, i; char buf[n_files * INOTIFY_BUFLEN]; ifd = inotify_init(); if (errno == ENOSYS) { fprintf(stderr, "Error: inotify is not supported by the kernel you're currently running.\n"); exit(EXIT_FAILURE); } else if (unlikely(ifd < 0)) { fprintf(stderr, "Error: Could not initialize inotify (%s)\n", strerror(errno)); exit(EXIT_FAILURE); } for (i = 0; i < n_files; i++) { if (!_files[i].ignore) { _files[i].i_watch = inotify_add_watch(ifd, _files[i].name, IN_MODIFY|IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT); if (_files[i].i_watch < 0) { fprintf(stderr, "Error: Could not create inotify watch on file '%s' (%s)\n", _files[i].name, strerror(errno)); ignore_file(&_files[i]); } } } while (n_ignored < n_files) { ssize_t len; int ev_idx = 0; len = read(ifd, buf, (n_files * INOTIFY_BUFLEN)); if (unlikely(len < 0)) { /* Some signal, likely ^Z/fg's STOP and CONT interrupted the inotify read, retry */ if (errno == EINTR || errno == EAGAIN) continue; else { fprintf(stderr, "Error: Could not read inotify events (%s)\n", strerror(errno)); exit(EXIT_FAILURE); } } while (ev_idx < len) { struct inotify_event *inev; struct file_struct *f = NULL; inev = (struct inotify_event *) &buf[ev_idx]; /* Which file has produced the event? */ for (i = 0; i < n_files; i++) { if (!_files[i].ignore && _files[i].fd >= 0 && _files[i].i_watch == inev->wd) { f = &_files[i]; break; } } if (unlikely(!f)) break; if (handle_inotify_event(inev, f) < 0) break; ev_idx += sizeof(struct inotify_event) + inev->len; } } close(ifd); return -1; }
static int handle_inotify_event(struct inotify_event *inev, struct file_struct *f) { int ret = 0; if (inev->mask & IN_MODIFY) { char *fbuf; ssize_t rc; struct stat finfo; if (verbose) write_header(f->name); /* Seek to old file size */ if (lseek(f->fd, f->size, SEEK_SET) == (off_t) -1) { fprintf(stderr, "Error: Could not seek in file '%s' (%s)\n", f->name, strerror(errno)); ret = -1; goto ignore; } fbuf = emalloc(f->blksize); while ((rc = read(f->fd, fbuf, f->blksize)) != 0) { auparse_feed(au,fbuf, rc); } if (fstat(f->fd, &finfo) < 0) { fprintf(stderr, "Error: Could not stat file '%s' (%s)\n", f->name, strerror(errno)); ret = -1; free(fbuf); goto ignore; } f->size = finfo.st_size; free(fbuf); return ret; } else if (inev->mask & IN_DELETE_SELF) { fprintf(stderr, "File '%s' deleted.\n", f->name); } else if (inev->mask & IN_MOVE_SELF) { fprintf(stderr, "File '%s' moved.\n", f->name); // SCOTT close(f->fd); free(files); struct file_struct *new_files = NULL; new_files = emalloc( sizeof(struct file_struct) ); new_files[0].name = "/var/log/audit/audit.log"; setup_file(&new_files[0]); // Take a sec here to let the new file get // set up by the OS - there are problems with this // asking just a bit too soon. sleep(1); tail_file(new_files, DEFAULT_N_LINES, M_LINES, 1); watch_files(new_files, 1); return 0; } else if (inev->mask & IN_UNMOUNT) { fprintf(stderr, "Device containing file '%s' unmounted.\n", f->name); } ignore: ignore_file(f); return ret; }
static int tail_file(struct file_struct *f, unsigned long n_units, char mode, char forever) { ssize_t bytes_read = 0; off_t offset = 0; char *buf; struct stat finfo; if (strcmp(f->name, "-") == 0) f->fd = STDIN_FILENO; else { f->fd = open(f->name, O_RDONLY); if (unlikely(f->fd < 0)) { fprintf(stderr, "Error: Could not open file '%s' (%s)\n", f->name, strerror(errno)); ignore_file(f); return -1; } } if (fstat(f->fd, &finfo) < 0) { fprintf(stderr, "Error: Could not stat file '%s' (%s)\n", f->name, strerror(errno)); ignore_file(f); return -1; } if (!IS_TAILABLE(finfo.st_mode)) { fprintf(stderr, "Error: '%s' of unsupported file type (%s)\n", f->name, strerror(errno)); ignore_file(f); return -1; } /* Cannot seek on these */ if (IS_PIPELIKE(finfo.st_mode) || f->fd == STDIN_FILENO) return tail_pipe(f); f->size = finfo.st_size; f->blksize = finfo.st_blksize; /* TODO: Can this value be 0? */ if (mode == M_LINES) offset = lines_to_offset(f, n_units); else offset = bytes_to_offset(f, n_units); /* We only get negative offsets on errors */ if (unlikely(offset < 0)) { ignore_file(f); return -1; } if (verbose) write_header(f->name); if (lseek(f->fd, offset, SEEK_SET) == (off_t) -1) { fprintf(stderr, "Error: Could not seek in file '%s' (%s)\n", f->name, strerror(errno)); return -1; } buf = emalloc(f->blksize); while ((bytes_read = read(f->fd, buf, f->blksize)) > 0) { auparse_feed(au,buf, bytes_read); } if (!forever) { if (close(f->fd) < 0) { fprintf(stderr, "Error: Could not close file '%s' (%s)\n", f->name, strerror(errno)); free(buf); return -1; } } /* Let the fd open otherwise, we'll need it */ free(buf); return 0; }
static CamelFolderInfo * scan_dir (CamelStore *store, GHashTable *visited, CamelFolderInfo *parent, const gchar *root, const gchar *name, guint32 flags, GError **error) { CamelFolderInfo *folders, *tail, *fi; GHashTable *folder_hash; const gchar *dent; GDir *dir; tail = folders = NULL; if (!(dir = g_dir_open (root, 0, NULL))) return NULL; folder_hash = g_hash_table_new (g_str_hash, g_str_equal); /* FIXME: it would be better if we queue'd up the recursive * scans till the end so that we can limit the number of * directory descriptors open at any given time... */ while ((dent = g_dir_read_name (dir))) { gchar *short_name, *full_name, *path, *ext; struct stat st; if (dent[0] == '.') continue; if (ignore_file (dent, FALSE)) continue; path = g_strdup_printf ("%s/%s", root, dent); if (g_stat (path, &st) == -1) { g_free (path); continue; } #ifndef G_OS_WIN32 if (S_ISDIR (st.st_mode)) { struct _inode in = { st.st_dev, st.st_ino }; if (g_hash_table_lookup (visited, &in)) { g_free (path); continue; } } #endif short_name = g_strdup (dent); if ((ext = strrchr (short_name, '.')) && !strcmp (ext, ".sbd")) *ext = '\0'; if (name != NULL) full_name = g_strdup_printf ("%s/%s", name, short_name); else full_name = g_strdup (short_name); if ((fi = g_hash_table_lookup (folder_hash, short_name)) != NULL) { g_free (short_name); g_free (full_name); if (S_ISDIR (st.st_mode)) { fi->flags = (fi->flags & ~CAMEL_FOLDER_NOCHILDREN) | CAMEL_FOLDER_CHILDREN; } else { fi->flags &= ~CAMEL_FOLDER_NOSELECT; } } else { fi = camel_folder_info_new (); fi->parent = parent; fi->full_name = full_name; fi->display_name = short_name; fi->unread = -1; fi->total = -1; if (S_ISDIR (st.st_mode)) fi->flags = CAMEL_FOLDER_NOSELECT; else fi->flags = CAMEL_FOLDER_NOCHILDREN; if (tail == NULL) folders = fi; else tail->next = fi; tail = fi; g_hash_table_insert (folder_hash, fi->display_name, fi); } if (!S_ISDIR (st.st_mode)) { fill_fi (store, fi, flags); } else if ((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE)) { struct _inode in = { st.st_dev, st.st_ino }; if (g_hash_table_lookup (visited, &in) == NULL) { #ifndef G_OS_WIN32 struct _inode *inew = g_new (struct _inode, 1); *inew = in; g_hash_table_insert (visited, inew, inew); #endif if ((fi->child = scan_dir (store, visited, fi, path, fi->full_name, flags, error))) fi->flags |= CAMEL_FOLDER_CHILDREN; else fi->flags = (fi->flags & ~CAMEL_FOLDER_CHILDREN) | CAMEL_FOLDER_NOCHILDREN; } } g_free (path); } g_dir_close (dir); g_hash_table_destroy (folder_hash); return folders; }