Skip to content

Commit

Permalink
sd-device: make sd_device_enumerator_get_*_next() not destroy the list
Browse files Browse the repository at this point in the history
  • Loading branch information
yuwata committed Sep 10, 2018
1 parent 3c83f15 commit 0a16658
Showing 1 changed file with 55 additions and 39 deletions.
94 changes: 55 additions & 39 deletions src/libsystemd/sd-device/device-enumerator.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include "device-util.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "prioq.h"
#include "set.h"
#include "string-util.h"
#include "strv.h"
Expand All @@ -26,7 +25,8 @@ struct sd_device_enumerator {
unsigned n_ref;

DeviceEnumerationType type;
Prioq *devices;
sd_device **devices;
size_t n_devices, n_allocated, current_device_index;
bool scan_uptodate;

Set *match_subsystem;
Expand Down Expand Up @@ -60,15 +60,14 @@ _public_ int sd_device_enumerator_new(sd_device_enumerator **ret) {
}

static sd_device_enumerator *device_enumerator_free(sd_device_enumerator *enumerator) {
sd_device *device;
size_t i;

assert(enumerator);

while ((device = prioq_pop(enumerator->devices)))
sd_device_unref(device);

prioq_free(enumerator->devices);
for (i = 0; i < enumerator->n_devices; i++)
sd_device_unref(enumerator->devices[i]);

free(enumerator->devices);
set_free_free(enumerator->match_subsystem);
set_free_free(enumerator->nomatch_subsystem);
hashmap_free_free_free(enumerator->match_sysattr);
Expand Down Expand Up @@ -251,7 +250,7 @@ int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator)
}

static int device_compare(const void *_a, const void *_b) {
sd_device *a = (sd_device *)_a, *b = (sd_device *)_b;
sd_device *a = *(sd_device **)_a, *b = *(sd_device **)_b;
const char *devpath_a, *devpath_b, *sound_a;
bool delay_a, delay_b;

Expand Down Expand Up @@ -301,20 +300,13 @@ static int device_compare(const void *_a, const void *_b) {
}

int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *device) {
int r;

assert_return(enumerator, -EINVAL);
assert_return(device, -EINVAL);

r = prioq_ensure_allocated(&enumerator->devices, device_compare);
if (r < 0)
return r;

r = prioq_put(enumerator->devices, device, NULL);
if (r < 0)
return r;
if (!GREEDY_REALLOC(enumerator->devices, enumerator->n_allocated, enumerator->n_devices + 1))
return -ENOMEM;

sd_device_ref(device);
enumerator->devices[enumerator->n_devices++] = sd_device_ref(device);

return 0;
}
Expand Down Expand Up @@ -810,17 +802,19 @@ static int enumerator_scan_devices_all(sd_device_enumerator *enumerator) {
}

int device_enumerator_scan_devices(sd_device_enumerator *enumerator) {
sd_device *device;
int r = 0, k;
size_t i;

assert(enumerator);

if (enumerator->scan_uptodate &&
enumerator->type == DEVICE_ENUMERATION_TYPE_DEVICES)
return 0;

while ((device = prioq_pop(enumerator->devices)))
sd_device_unref(device);
for (i = 0; i < enumerator->n_devices; i++)
sd_device_unref(enumerator->devices[i]);

enumerator->n_devices = 0;

if (!set_isempty(enumerator->match_tag)) {
k = enumerator_scan_devices_tags(enumerator);
Expand All @@ -836,7 +830,10 @@ int device_enumerator_scan_devices(sd_device_enumerator *enumerator) {
r = k;
}

qsort(enumerator->devices, enumerator->n_devices, sizeof(sd_device *), device_compare);

enumerator->scan_uptodate = true;
enumerator->type = DEVICE_ENUMERATION_TYPE_DEVICES;

return r;
}
Expand All @@ -850,36 +847,40 @@ _public_ sd_device *sd_device_enumerator_get_device_first(sd_device_enumerator *
if (r < 0)
return NULL;

enumerator->type = DEVICE_ENUMERATION_TYPE_DEVICES;
enumerator->current_device_index = 0;

if (enumerator->n_devices == 0)
return NULL;

return prioq_peek(enumerator->devices);
return enumerator->devices[0];
}

_public_ sd_device *sd_device_enumerator_get_device_next(sd_device_enumerator *enumerator) {
assert_return(enumerator, NULL);

if (!enumerator->scan_uptodate ||
enumerator->type != DEVICE_ENUMERATION_TYPE_DEVICES)
enumerator->type != DEVICE_ENUMERATION_TYPE_DEVICES ||
enumerator->current_device_index + 1 >= enumerator->n_devices)
return NULL;

sd_device_unref(prioq_pop(enumerator->devices));

return prioq_peek(enumerator->devices);
return enumerator->devices[++enumerator->current_device_index];
}

int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) {
sd_device *device;
const char *subsysdir;
int r = 0, k;
size_t i;

assert(enumerator);

if (enumerator->scan_uptodate &&
enumerator->type == DEVICE_ENUMERATION_TYPE_SUBSYSTEMS)
return 0;

while ((device = prioq_pop(enumerator->devices)))
sd_device_unref(device);
for (i = 0; i < enumerator->n_devices; i++)
sd_device_unref(enumerator->devices[i]);

enumerator->n_devices = 0;

/* modules */
if (match_subsystem(enumerator, "module")) {
Expand Down Expand Up @@ -913,7 +914,10 @@ int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) {
}
}

qsort(enumerator->devices, enumerator->n_devices, sizeof(sd_device *), device_compare);

enumerator->scan_uptodate = true;
enumerator->type = DEVICE_ENUMERATION_TYPE_SUBSYSTEMS;

return r;
}
Expand All @@ -927,33 +931,45 @@ _public_ sd_device *sd_device_enumerator_get_subsystem_first(sd_device_enumerato
if (r < 0)
return NULL;

enumerator->type = DEVICE_ENUMERATION_TYPE_SUBSYSTEMS;
enumerator->current_device_index = 0;

if (enumerator->n_devices == 0)
return NULL;

return prioq_peek(enumerator->devices);
return enumerator->devices[0];
}

_public_ sd_device *sd_device_enumerator_get_subsystem_next(sd_device_enumerator *enumerator) {
assert_return(enumerator, NULL);

if (!enumerator->scan_uptodate ||
enumerator->type != DEVICE_ENUMERATION_TYPE_SUBSYSTEMS)
enumerator->type != DEVICE_ENUMERATION_TYPE_SUBSYSTEMS ||
enumerator->current_device_index + 1 >= enumerator->n_devices)
return NULL;

sd_device_unref(prioq_pop(enumerator->devices));

return prioq_peek(enumerator->devices);
return enumerator->devices[++enumerator->current_device_index];
}

sd_device *device_enumerator_get_first(sd_device_enumerator *enumerator) {
assert_return(enumerator, NULL);

return prioq_peek(enumerator->devices);
if (!enumerator->scan_uptodate)
return NULL;

enumerator->current_device_index = 0;

if (enumerator->n_devices == 0)
return NULL;

return enumerator->devices[0];
}

sd_device *device_enumerator_get_next(sd_device_enumerator *enumerator) {
assert_return(enumerator, NULL);

sd_device_unref(prioq_pop(enumerator->devices));
if (!enumerator->scan_uptodate ||
enumerator->current_device_index + 1 >= enumerator->n_devices)
return NULL;

return prioq_peek(enumerator->devices);
return enumerator->devices[++enumerator->current_device_index];
}

0 comments on commit 0a16658

Please sign in to comment.