Beispiel #1
0
_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;
}
Beispiel #2
0
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;
}
Beispiel #3
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;
}