_q_static int q_vdb_foreach_pkg_sorted(q_vdb_pkg_cb callback, void *priv) { q_vdb_ctx *ctx; q_vdb_cat_ctx *cat_ctx; q_vdb_pkg_ctx *pkg_ctx; int ret = 0; int c, p, cat_cnt, pkg_cnt; struct dirent **cat_de, **pkg_de; ctx = q_vdb_open(); if (!ctx) return EXIT_FAILURE; cat_cnt = scandirat(ctx->vdb_fd, ".", &cat_de, q_vdb_filter_cat, alphasort); for (c = 0; c < cat_cnt; ++c) { cat_ctx = q_vdb_open_cat(ctx, cat_de[c]->d_name); if (!cat_ctx) continue; pkg_cnt = scandirat(ctx->vdb_fd, cat_de[c]->d_name, &pkg_de, q_vdb_filter_pkg, alphasort); for (p = 0; p < pkg_cnt; ++p) { if (pkg_de[p]->d_name[0] == '-') continue; pkg_ctx = q_vdb_open_pkg(cat_ctx, pkg_de[p]->d_name); if (!pkg_ctx) continue; ret |= callback(pkg_ctx, priv); q_vdb_close_pkg(pkg_ctx); } scandir_free(pkg_de, pkg_cnt); q_vdb_close_cat(cat_ctx); } scandir_free(cat_de, cat_cnt); q_vdb_close(ctx); return ret; }
static int __mnt_table_parse_dir(struct libmnt_table *tb, const char *dirname) { int n = 0, i; int dd; struct dirent **namelist = NULL; dd = open(dirname, O_RDONLY|O_CLOEXEC|O_DIRECTORY); if (dd < 0) return -errno; n = scandirat(dd, ".", &namelist, mnt_table_parse_dir_filter, versionsort); if (n <= 0) { close(dd); return 0; } for (i = 0; i < n; i++) { struct dirent *d = namelist[i]; struct stat st; FILE *f; if (fstat_at(dd, ".", d->d_name, &st, 0) || !S_ISREG(st.st_mode)) continue; f = fopen_at(dd, ".", d->d_name, O_RDONLY, "r"); if (f) { mnt_table_parse_stream(tb, f, d->d_name); fclose(f); } } for (i = 0; i < n; i++) free(namelist[i]); free(namelist); close(dd); return 0; }
// push as many available events from our filesystem buffer of events off to the monitor's socketpair. // the order is determined lexicographically (i.e. we assume that whatever is writing events is naming them in // a monotonically increasing order, such as e.g. the SEQNUM field) // return 0 on success // return -ENODATA if there are no events // return -EAGAIN if there are events, but we couldn't push any // return -errno if we can't re-watch the directory // NOTE: this method should only be used if the underlying filesystem holding the events can't help us preserve the order. // NOTE: not thread-safe int udev_monitor_fs_push_events( struct udev_monitor* monitor ) { char pathbuf[ PATH_MAX+1 ]; int dirfd = -1; int fd = -1; int rc = 0; int num_events = 0; int num_valid_events = 0; int num_sent = 0; struct dirent** events = NULL; // names of events to buffer int i = 0; // reset the watch on this directory, and ensure we're watching the right one. rc = udev_monitor_fs_watch_reset( monitor ); if( rc < 0 ) { log_error("Failed to re-watch '%s', rc = %d", monitor->events_dir, rc ); goto udev_monitor_fs_push_events_cleanup; } // find new events... dirfd = open( monitor->events_dir, O_DIRECTORY | O_CLOEXEC ); if( dirfd < 0 ) { rc = -errno; log_error("open('%s') rc = %d", monitor->events_dir, rc ); goto udev_monitor_fs_push_events_cleanup; } num_events = scandirat( dirfd, ".", &events, udev_monitor_fs_scandir_filter, alphasort ); if( num_events < 0 ) { rc = -errno; log_error("scandir('%s') rc = %d", monitor->events_dir, rc ); goto udev_monitor_fs_push_events_cleanup; } if( num_events == 0 ) { // got nothing rc = -ENODATA; goto udev_monitor_fs_push_events_cleanup; } num_valid_events = num_events; // send them all off! for( i = 0; i < num_events; i++ ) { snprintf( pathbuf, PATH_MAX, "%s/%s", monitor->events_dir, events[i]->d_name ); fd = open( pathbuf, O_RDONLY | O_CLOEXEC ); if( fd < 0 ) { rc = -errno; log_error("cannot open event: open('%s') rc = %d", pathbuf, rc ); // we consider it more important to preserve order and drop events // than to try to resend later. unlink( pathbuf ); } else { // propagate to the monitor's socket rc = udev_monitor_fs_push_event( fd, monitor ); // garbage-collect close( fd ); unlink( pathbuf ); if( rc == -EBADMSG || rc == -EMSGSIZE ) { // invalid message anyway rc = 0; num_valid_events--; continue; } else if( rc < 0 ) { if( rc != -EAGAIN ) { // socket-level error log_error("failed to push event '%s', rc = %d", pathbuf, rc ); break; } else { // sent as many as we could rc = 0; break; } } else if( rc == 0 ) { num_sent++; } } } udev_monitor_fs_push_events_cleanup: if( dirfd >= 0 ) { close( dirfd ); } if( events != NULL ) { for( i = 0; i < num_events; i++ ) { if( events[i] != NULL ) { free( events[i] ); events[i] = NULL; } } free( events ); } if( num_sent == 0 && num_valid_events > 0 ) { // there are pending events, but we couldn't push any. rc = -EAGAIN; } return rc; }