static gboolean do_read_run (GLnxDirFdIterator *dfd_iter, guint *out_n_read, GError **error) { guint nattrs = 0; while (TRUE) { struct dirent *dent; if (!glnx_dirfd_iterator_next_dent (dfd_iter, &dent, NULL, error)) return FALSE; if (!dent) break; glnx_autofd int fd = -1; if (!glnx_openat_rdonly (dfd_iter->fd, dent->d_name, FALSE, &fd, error)) return FALSE; g_autoptr(GVariant) current_xattrs = NULL; if (!glnx_fd_get_all_xattrs (fd, ¤t_xattrs, NULL, error)) return FALSE; /* We don't actually care about the values, just use the variable * to avoid compiler warnings. */ nattrs += g_variant_n_children (current_xattrs); } *out_n_read = nattrs; return TRUE; }
/** * gs_fd_get_all_xattrs: * @fd: a file descriptor * @out_xattrs: (out): A new #GVariant containing the extended attributes * @cancellable: Cancellable * @error: Error * * Read all extended attributes from @fd in a canonical sorted order, and * set @out_xattrs with the result. * * If the filesystem does not support extended attributes, @out_xattrs * will have 0 elements, and this function will return successfully. */ gboolean gs_fd_get_all_xattrs (int fd, GVariant **out_xattrs, GCancellable *cancellable, GError **error) { return glnx_fd_get_all_xattrs (fd, out_xattrs, cancellable, error); }
static gboolean do_write_run (GLnxDirFdIterator *dfd_iter, GError **error) { WriteType wtype = g_random_int () % 2; if (wtype == WRITE_RUN_CREATE) { guint32 randname_v = g_random_int (); g_autofree char *randname = g_strdup_printf ("file%u", randname_v); glnx_autofd int fd = -1; again: fd = openat (dfd_iter->fd, randname, O_CREAT | O_EXCL, 0644); if (fd < 0) { if (errno == EEXIST) { g_printerr ("Congratulations! I suggest purchasing a lottery ticket today!\n"); goto again; } else { glnx_set_error_from_errno (error); return FALSE; } } if (!add_random_xattrs (fd, error)) return FALSE; } else if (wtype == WRITE_RUN_MUTATE) { while (TRUE) { struct dirent *dent; if (!glnx_dirfd_iterator_next_dent (dfd_iter, &dent, NULL, error)) return FALSE; if (!dent) break; glnx_autofd int fd = -1; if (!glnx_openat_rdonly (dfd_iter->fd, dent->d_name, FALSE, &fd, error)) return FALSE; g_autoptr(GVariant) current_xattrs = NULL; if (!glnx_fd_get_all_xattrs (fd, ¤t_xattrs, NULL, error)) return FALSE; for (int i = 0; i < g_variant_n_children (current_xattrs); i++) { const char *name, *value; g_variant_get_child (current_xattrs, i, "(^&ay^&ay)", &name, &value); /* We don't want to potentially test/change xattrs like security.selinux * that were injected by the system. */ if (!g_str_has_prefix (name, "user.test")) continue; if (!set_random_xattr_value (fd, name, error)) return FALSE; } } } else g_assert_not_reached (); return TRUE; }