diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h index 222da8f6a3..0eb763944c 100644 --- a/src/basic/hashmap.h +++ b/src/basic/hashmap.h @@ -329,6 +329,29 @@ static inline void *ordered_hashmap_first(OrderedHashmap *h) { return internal_hashmap_first(HASHMAP_BASE(h)); } +#define hashmap_clear_with_destructor(_s, _f) \ + ({ \ + void *_item; \ + while ((_item = hashmap_steal_first(_s))) \ + _f(_item); \ + }) +#define hashmap_free_with_destructor(_s, _f) \ + ({ \ + hashmap_clear_with_destructor(_s, _f); \ + hashmap_free(_s); \ + }) +#define ordered_hashmap_clear_with_destructor(_s, _f) \ + ({ \ + void *_item; \ + while ((_item = ordered_hashmap_steal_first(_s))) \ + _f(_item); \ + }) +#define ordered_hashmap_free_with_destructor(_s, _f) \ + ({ \ + ordered_hashmap_clear_with_destructor(_s, _f); \ + ordered_hashmap_free(_s); \ + }) + /* no hashmap_next */ void *ordered_hashmap_next(OrderedHashmap *h, const void *key); diff --git a/src/basic/set.h b/src/basic/set.h index e798d5fb35..156ab4b081 100644 --- a/src/basic/set.h +++ b/src/basic/set.h @@ -108,6 +108,18 @@ static inline void *set_steal_first(Set *s) { return internal_hashmap_steal_first(HASHMAP_BASE(s)); } +#define set_clear_with_destructor(_s, _f) \ + ({ \ + void *_item; \ + while ((_item = set_steal_first(_s))) \ + _f(_item); \ + }) +#define set_free_with_destructor(_s, _f) \ + ({ \ + set_clear_with_destructor(_s, _f); \ + set_free(_s); \ + }) + /* no set_steal_first_key */ /* no set_first_key */ diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c index 3b2b5f3fc2..44110b63f9 100644 --- a/src/busctl/busctl.c +++ b/src/busctl/busctl.c @@ -692,12 +692,7 @@ static void member_free(Member *m) { DEFINE_TRIVIAL_CLEANUP_FUNC(Member*, member_free); static void member_set_free(Set *s) { - Member *m; - - while ((m = set_steal_first(s))) - member_free(m); - - set_free(s); + set_free_with_destructor(s, member_free); } DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, member_set_free); diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index 8add7e73e4..fe339eb493 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -105,10 +105,7 @@ static void group_free(Group *g) { } static void group_hashmap_clear(Hashmap *h) { - Group *g; - - while ((g = hashmap_steal_first(h))) - group_free(g); + hashmap_clear_with_destructor(h, group_free); } static void group_hashmap_free(Hashmap *h) { diff --git a/src/coredump/coredump-vacuum.c b/src/coredump/coredump-vacuum.c index 5a9b7f38e7..aede180b43 100644 --- a/src/coredump/coredump-vacuum.c +++ b/src/coredump/coredump-vacuum.c @@ -52,16 +52,11 @@ static void vacuum_candidate_free(struct vacuum_candidate *c) { DEFINE_TRIVIAL_CLEANUP_FUNC(struct vacuum_candidate*, vacuum_candidate_free); -static void vacuum_candidate_hasmap_free(Hashmap *h) { - struct vacuum_candidate *c; - - while ((c = hashmap_steal_first(h))) - vacuum_candidate_free(c); - - hashmap_free(h); +static void vacuum_candidate_hashmap_free(Hashmap *h) { + hashmap_free_with_destructor(h, vacuum_candidate_free); } -DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, vacuum_candidate_hasmap_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, vacuum_candidate_hashmap_free); static int uid_from_file_name(const char *filename, uid_t *uid) { const char *p, *e, *u; @@ -160,7 +155,7 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) { } for (;;) { - _cleanup_(vacuum_candidate_hasmap_freep) Hashmap *h = NULL; + _cleanup_(vacuum_candidate_hashmap_freep) Hashmap *h = NULL; struct vacuum_candidate *worst = NULL; struct dirent *de; uint64_t sum = 0; diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 3f7222a8aa..d0be412625 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -219,18 +219,12 @@ static int create_disk( return 0; } -static void free_arg_disks(void) { - crypto_device *d; - - while ((d = hashmap_steal_first(arg_disks))) { - free(d->uuid); - free(d->keyfile); - free(d->name); - free(d->options); - free(d); - } - - hashmap_free(arg_disks); +static void crypt_device_free(crypto_device *d) { + free(d->uuid); + free(d->keyfile); + free(d->name); + free(d->options); + free(d); } static crypto_device *get_crypto_device(const char *uuid) { @@ -492,7 +486,7 @@ int main(int argc, char *argv[]) { r = 0; finish: - free_arg_disks(); + hashmap_free_with_destructor(arg_disks, crypt_device_free); free(arg_default_options); free(arg_default_keyfile); diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index 01a6543708..10dd3db270 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -1043,18 +1043,17 @@ static int remoteserver_init(RemoteServer *s, return 0; } +static void MHDDaemonWrapper_free(MHDDaemonWrapper *d) { + MHD_stop_daemon(d->daemon); + sd_event_source_unref(d->io_event); + sd_event_source_unref(d->timer_event); + free(d); +} + static void server_destroy(RemoteServer *s) { size_t i; - MHDDaemonWrapper *d; - while ((d = hashmap_steal_first(s->daemons))) { - MHD_stop_daemon(d->daemon); - sd_event_source_unref(d->io_event); - sd_event_source_unref(d->timer_event); - free(d); - } - - hashmap_free(s->daemons); + hashmap_free_with_destructor(s->daemons, MHDDaemonWrapper_free); assert(s->sources_size == 0 || s->sources); for (i = 0; i < s->sources_size; i++) diff --git a/src/journal/compress.c b/src/journal/compress.c index a659459e49..92eb3874fd 100644 --- a/src/journal/compress.c +++ b/src/journal/compress.c @@ -667,7 +667,7 @@ int decompress_stream_lz4(int in, int out, uint64_t max_bytes) { log_debug("LZ4 decompression finished (%zu -> %zu bytes, %.1f%%)", total_in, total_out, - (double) total_out / total_in * 100); + total_in > 0 ? (double) total_out / total_in * 100 : 0.0); cleanup: munmap(src, st.st_size); return r; diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index faa7e9bab6..9d2e6dbb1b 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -400,15 +400,6 @@ JournalFile* journal_file_close(JournalFile *f) { return mfree(f); } -void journal_file_close_set(Set *s) { - JournalFile *f; - - assert(s); - - while ((f = set_steal_first(s))) - (void) journal_file_close(f); -} - static int journal_file_init_header(JournalFile *f, JournalFile *template) { Header h = {}; ssize_t k; @@ -3371,8 +3362,7 @@ int journal_file_open( f->header = h; if (!newly_created) { - if (deferred_closes) - journal_file_close_set(deferred_closes); + set_clear_with_destructor(deferred_closes, journal_file_close); r = journal_file_verify_header(f); if (r < 0) diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index c652687c45..c5cfa3d878 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -161,7 +161,6 @@ int journal_file_open( int journal_file_set_offline(JournalFile *f, bool wait); bool journal_file_is_offlining(JournalFile *f); JournalFile* journal_file_close(JournalFile *j); -void journal_file_close_set(Set *s); int journal_file_open_reliably( const char *fname, diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 8a2ad13a6a..19ae529ba4 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -1899,13 +1899,9 @@ void server_maybe_append_tags(Server *s) { } void server_done(Server *s) { - JournalFile *f; assert(s); - if (s->deferred_closes) { - journal_file_close_set(s->deferred_closes); - set_free(s->deferred_closes); - } + set_free_with_destructor(s->deferred_closes, journal_file_close); while (s->stdout_streams) stdout_stream_free(s->stdout_streams); @@ -1918,10 +1914,7 @@ void server_done(Server *s) { if (s->runtime_journal) (void) journal_file_close(s->runtime_journal); - while ((f = ordered_hashmap_steal_first(s->user_journals))) - (void) journal_file_close(f); - - ordered_hashmap_free(s->user_journals); + ordered_hashmap_free_with_destructor(s->user_journals, journal_file_close); sd_event_source_unref(s->syslog_event_source); sd_event_source_unref(s->native_event_source); diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 0b6698782d..8a1b161d8f 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -1977,18 +1977,13 @@ fail: _public_ void sd_journal_close(sd_journal *j) { Directory *d; - JournalFile *f; - char *p; if (!j) return; sd_journal_flush_matches(j); - while ((f = ordered_hashmap_steal_first(j->files))) - (void) journal_file_close(f); - - ordered_hashmap_free(j->files); + ordered_hashmap_free_with_destructor(j->files, journal_file_close); while ((d = hashmap_first(j->directories_by_path))) remove_directory(j, d); @@ -2006,9 +2001,7 @@ _public_ void sd_journal_close(sd_journal *j) { mmap_cache_unref(j->mmap); } - while ((p = hashmap_steal_first(j->errors))) - free(p); - hashmap_free(j->errors); + hashmap_free_free(j->errors); free(j->path); free(j->prefix); diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 660358e857..63fb355e85 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -87,7 +87,6 @@ int sd_dhcp_server_configure_pool(sd_dhcp_server *server, struct in_addr *addres size = size_max; if (server->address != address->s_addr || server->netmask != netmask || server->pool_size != size || server->pool_offset != offset) { - DHCPLease *lease; free(server->bound_leases); server->bound_leases = new0(DHCPLease*, size); @@ -105,8 +104,7 @@ int sd_dhcp_server_configure_pool(sd_dhcp_server *server, struct in_addr *addres server->bound_leases[server_off - offset] = &server->invalid_lease; /* Drop any leases associated with the old address range */ - while ((lease = hashmap_steal_first(server->leases_by_client_id))) - dhcp_lease_free(lease); + hashmap_clear_with_destructor(server->leases_by_client_id, dhcp_lease_free); } return 0; diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c index 75930f33ba..5b55f304de 100644 --- a/src/libsystemd/sd-bus/bus-track.c +++ b/src/libsystemd/sd-bus/bus-track.c @@ -184,8 +184,6 @@ _public_ sd_bus_track* sd_bus_track_ref(sd_bus_track *track) { } _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { - struct track_item *i; - if (!track) return NULL; @@ -196,14 +194,11 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { return NULL; } - while ((i = hashmap_steal_first(track->names))) - track_item_free(i); - if (track->in_list) LIST_REMOVE(tracks, track->bus->tracks, track); bus_track_remove_from_queue(track); - hashmap_free(track->names); + hashmap_free_with_destructor(track->names, track_item_free); sd_bus_unref(track->bus); return mfree(track); } @@ -429,8 +424,6 @@ void bus_track_dispatch(sd_bus_track *track) { } void bus_track_close(sd_bus_track *track) { - struct track_item *i; - assert(track); /* Called whenever our bus connected is closed. If so, and our track object is non-empty, dispatch it @@ -448,8 +441,7 @@ void bus_track_close(sd_bus_track *track) { return; /* Let's flush out all names */ - while ((i = hashmap_steal_first(track->names))) - track_item_free(i); + hashmap_clear_with_destructor(track->names, track_item_free); /* Invoke handler */ if (track->handler) diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c index aebfc38863..10d1b06016 100644 --- a/src/machine/image-dbus.c +++ b/src/machine/image-dbus.c @@ -396,14 +396,11 @@ const sd_bus_vtable image_vtable[] = { static int image_flush_cache(sd_event_source *s, void *userdata) { Manager *m = userdata; - Image *i; assert(s); assert(m); - while ((i = hashmap_steal_first(m->image_cache))) - image_unref(i); - + hashmap_clear_with_destructor(m->image_cache, image_unref); return 0; } diff --git a/src/machine/machined.c b/src/machine/machined.c index 17142a68af..d481020893 100644 --- a/src/machine/machined.c +++ b/src/machine/machined.c @@ -68,7 +68,6 @@ Manager *manager_new(void) { void manager_free(Manager *m) { Machine *machine; - Image *i; assert(m); @@ -84,10 +83,7 @@ void manager_free(Manager *m) { hashmap_free(m->machine_units); hashmap_free(m->machine_leaders); - while ((i = hashmap_steal_first(m->image_cache))) - image_unref(i); - - hashmap_free(m->image_cache); + hashmap_free_with_destructor(m->image_cache, image_unref); sd_event_source_unref(m->image_cache_defer_event); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 478fc090b1..527d2623ca 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -1223,7 +1223,6 @@ int manager_new(Manager **ret, sd_event *event) { } void manager_free(Manager *m) { - RoutingPolicyRule *rule; Network *network; NetDev *netdev; Link *link; @@ -1253,10 +1252,7 @@ void manager_free(Manager *m) { set_free(m->rules); set_free(m->rules_foreign); - while ((rule = set_steal_first(m->rules_saved))) - free(rule); - - set_free(m->rules_saved); + set_free_with_destructor(m->rules_saved, routing_policy_rule_free); sd_netlink_unref(m->rtnl); sd_event_unref(m->event); diff --git a/src/network/test-routing-policy-rule.c b/src/network/test-routing-policy-rule.c index fc6eb5626d..c29d134de2 100644 --- a/src/network/test-routing-policy-rule.c +++ b/src/network/test-routing-policy-rule.c @@ -34,7 +34,7 @@ static void test_rule_serialization(const char *title, const char *ruleset, cons const char *cmd; int fd, fd2, fd3; _cleanup_fclose_ FILE *f = NULL, *f2 = NULL, *f3 = NULL; - _cleanup_set_free_free_ Set *rules = NULL; + Set *rules = NULL; _cleanup_free_ char *buf = NULL; size_t buf_size; @@ -64,6 +64,8 @@ static void test_rule_serialization(const char *title, const char *ruleset, cons cmd = strjoina("diff -u ", pattern3, " ", pattern2); log_info("$ %s", cmd); assert_se(system(cmd) == 0); + + set_free_with_destructor(rules, routing_policy_rule_free); } int main(int argc, char **argv) { diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 4be6040e39..a9071ee73e 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -103,8 +103,6 @@ static void dns_scope_abort_transactions(DnsScope *s) { } DnsScope* dns_scope_free(DnsScope *s) { - DnsResourceRecord *rr; - if (!s) return NULL; @@ -119,10 +117,7 @@ DnsScope* dns_scope_free(DnsScope *s) { hashmap_free(s->transactions_by_key); - while ((rr = ordered_hashmap_steal_first(s->conflict_queue))) - dns_resource_record_unref(rr); - - ordered_hashmap_free(s->conflict_queue); + ordered_hashmap_free_with_destructor(s->conflict_queue, dns_resource_record_unref); sd_event_source_unref(s->conflict_event_source); sd_event_source_unref(s->announce_event_source); diff --git a/src/resolve/resolved-dns-trust-anchor.c b/src/resolve/resolved-dns-trust-anchor.c index f2bd9ef7e4..c6e47ed0e9 100644 --- a/src/resolve/resolved-dns-trust-anchor.c +++ b/src/resolve/resolved-dns-trust-anchor.c @@ -542,19 +542,10 @@ int dns_trust_anchor_load(DnsTrustAnchor *d) { } void dns_trust_anchor_flush(DnsTrustAnchor *d) { - DnsAnswer *a; - DnsResourceRecord *rr; - assert(d); - while ((a = hashmap_steal_first(d->positive_by_key))) - dns_answer_unref(a); - d->positive_by_key = hashmap_free(d->positive_by_key); - - while ((rr = set_steal_first(d->revoked_by_rr))) - dns_resource_record_unref(rr); - d->revoked_by_rr = set_free(d->revoked_by_rr); - + d->positive_by_key = hashmap_free_with_destructor(d->positive_by_key, dns_answer_unref); + d->revoked_by_rr = set_free_with_destructor(d->revoked_by_rr, dns_resource_record_unref); d->negative_by_name = set_free_free(d->negative_by_name); } diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index c6844f5ec2..7d5ea0c0ac 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -554,12 +554,7 @@ int bus_verify_polkit_async( void bus_verify_polkit_async_registry_free(Hashmap *registry) { #if ENABLE_POLKIT - AsyncPolkitQuery *q; - - while ((q = hashmap_steal_first(registry))) - async_polkit_query_free(q); - - hashmap_free(registry); + hashmap_free_with_destructor(registry, async_polkit_query_free); #endif } diff --git a/src/shared/install.c b/src/shared/install.c index a75a045d43..05ccc586a9 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -992,23 +992,11 @@ static void install_info_free(UnitFileInstallInfo *i) { free(i); } -static OrderedHashmap* install_info_hashmap_free(OrderedHashmap *m) { - UnitFileInstallInfo *i; - - if (!m) - return NULL; - - while ((i = ordered_hashmap_steal_first(m))) - install_info_free(i); - - return ordered_hashmap_free(m); -} - static void install_context_done(InstallContext *c) { assert(c); - c->will_process = install_info_hashmap_free(c->will_process); - c->have_processed = install_info_hashmap_free(c->have_processed); + c->will_process = ordered_hashmap_free_with_destructor(c->will_process, install_info_free); + c->have_processed = ordered_hashmap_free_with_destructor(c->have_processed, install_info_free); } static UnitFileInstallInfo *install_info_find(InstallContext *c, const char *name) { @@ -3141,12 +3129,7 @@ static void unit_file_list_free_one(UnitFileList *f) { } Hashmap* unit_file_list_free(Hashmap *h) { - UnitFileList *i; - - while ((i = hashmap_steal_first(h))) - unit_file_list_free_one(i); - - return hashmap_free(h); + return hashmap_free_with_destructor(h, unit_file_list_free_one); } DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one); diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c index 5b6260cbb8..66eefb3036 100644 --- a/src/shared/machine-image.c +++ b/src/shared/machine-image.c @@ -457,15 +457,6 @@ int image_discover(Hashmap *h) { return 0; } -void image_hashmap_free(Hashmap *map) { - Image *i; - - while ((i = hashmap_steal_first(map))) - image_unref(i); - - hashmap_free(map); -} - int image_remove(Image *i) { _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT; _cleanup_strv_free_ char **settings = NULL; diff --git a/src/shared/machine-image.h b/src/shared/machine-image.h index 9573000a5a..3df9a29a24 100644 --- a/src/shared/machine-image.h +++ b/src/shared/machine-image.h @@ -64,7 +64,9 @@ typedef struct Image { } Image; Image *image_unref(Image *i); -void image_hashmap_free(Hashmap *map); +static inline Hashmap* image_hashmap_free(Hashmap *map) { + return hashmap_free_with_destructor(map, image_unref); +} DEFINE_TRIVIAL_CLEANUP_FUNC(Image*, image_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, image_hashmap_free); diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c index 8887e2f989..d4f401d996 100644 --- a/src/socket-proxy/socket-proxyd.c +++ b/src/socket-proxy/socket-proxyd.c @@ -92,19 +92,10 @@ static void connection_free(Connection *c) { } static void context_free(Context *context) { - sd_event_source *es; - Connection *c; - assert(context); - while ((es = set_steal_first(context->listen))) - sd_event_source_unref(es); - - while ((c = set_first(context->connections))) - connection_free(c); - - set_free(context->listen); - set_free(context->connections); + set_free_with_destructor(context->listen, sd_event_source_unref); + set_free_with_destructor(context->connections, connection_free); sd_event_unref(context->event); sd_resolve_unref(context->resolve); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 4fd9b10634..0d67905cdc 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -699,12 +699,7 @@ static int get_unit_list( } static void message_set_freep(Set **set) { - sd_bus_message *m; - - while ((m = set_steal_first(*set))) - sd_bus_message_unref(m); - - set_free(*set); + set_free_with_destructor(*set, sd_bus_message_unref); } static int get_unit_list_recursive( diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 909a4ca542..d8009458ee 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -1864,20 +1864,15 @@ int main(int argc, char *argv[]) { log_error_errno(r, "Failed to write files: %m"); finish: - while ((i = hashmap_steal_first(groups))) - item_free(i); - - while ((i = hashmap_steal_first(users))) - item_free(i); + hashmap_free_with_destructor(groups, item_free); + hashmap_free_with_destructor(users, item_free); while ((n = hashmap_first_key(members))) { strv_free(hashmap_steal_first(members)); free(n); } - - hashmap_free(groups); - hashmap_free(users); hashmap_free(members); + hashmap_free(todo_uids); hashmap_free(todo_gids); diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c index cfb34c8f0b..f59c277e13 100644 --- a/src/sysv-generator/sysv-generator.c +++ b/src/sysv-generator/sysv-generator.c @@ -95,12 +95,7 @@ static void free_sysvstub(SysvStub *s) { DEFINE_TRIVIAL_CLEANUP_FUNC(SysvStub*, free_sysvstub); static void free_sysvstub_hashmapp(Hashmap **h) { - SysvStub *stub; - - while ((stub = hashmap_steal_first(*h))) - free_sysvstub(stub); - - hashmap_free(*h); + hashmap_free_with_destructor(*h, free_sysvstub); } static int add_alias(const char *service, const char *alias) { diff --git a/src/test/test-hashmap.c b/src/test/test-hashmap.c index 6ea1780cf2..dd9195425e 100644 --- a/src/test/test-hashmap.c +++ b/src/test/test-hashmap.c @@ -38,6 +38,29 @@ static void test_ordered_hashmap_next(void) { assert_se(!ordered_hashmap_next(m, INT_TO_PTR(3))); } +typedef struct Item { + int seen; +} Item; +static void item_seen(Item *item) { + item->seen++; +} + +static void test_hashmap_free_with_destructor(void) { + Hashmap *m; + struct Item items[4] = {}; + unsigned i; + + assert_se(m = hashmap_new(NULL)); + for (i = 0; i < ELEMENTSOF(items) - 1; i++) + assert_se(hashmap_put(m, INT_TO_PTR(i), items + i) == 1); + + m = hashmap_free_with_destructor(m, item_seen); + assert_se(items[0].seen == 1); + assert_se(items[1].seen == 1); + assert_se(items[2].seen == 1); + assert_se(items[3].seen == 0); +} + static void test_uint64_compare_func(void) { const uint64_t a = 0x100, b = 0x101; @@ -62,6 +85,7 @@ int main(int argc, const char *argv[]) { test_ordered_hashmap_funcs(); test_ordered_hashmap_next(); + test_hashmap_free_with_destructor(); test_uint64_compare_func(); test_trivial_compare_func(); test_string_compare_func(); diff --git a/src/test/test-mount-util.c b/src/test/test-mount-util.c index 9582d6ceec..2aad7f387c 100644 --- a/src/test/test-mount-util.c +++ b/src/test/test-mount-util.c @@ -97,10 +97,7 @@ static void test_mnt_id(void) { assert_se(path_equal_ptr(hashmap_get(h, INT_TO_PTR(mnt_id2)), p)); } - while ((p = hashmap_steal_first(h))) - free(p); - - hashmap_free(h); + hashmap_free_free(h); } int main(int argc, char *argv[]) { diff --git a/src/test/test-set.c b/src/test/test-set.c index 7bae95bd2b..0a29a62621 100644 --- a/src/test/test-set.c +++ b/src/test/test-set.c @@ -40,6 +40,29 @@ static void test_set_steal_first(void) { assert_se(set_isempty(m)); } +typedef struct Item { + int seen; +} Item; +static void item_seen(Item *item) { + item->seen++; +} + +static void test_set_free_with_destructor(void) { + Set *m; + struct Item items[4] = {}; + unsigned i; + + assert_se(m = set_new(NULL)); + for (i = 0; i < ELEMENTSOF(items) - 1; i++) + assert_se(set_put(m, items + i) == 1); + + m = set_free_with_destructor(m, item_seen); + assert_se(items[0].seen == 1); + assert_se(items[1].seen == 1); + assert_se(items[2].seen == 1); + assert_se(items[3].seen == 0); +} + static void test_set_put(void) { _cleanup_set_free_ Set *m = NULL; @@ -102,6 +125,7 @@ static void test_set_make(void) { int main(int argc, const char *argv[]) { test_set_steal_first(); + test_set_free_with_destructor(); test_set_put(); test_set_make(); diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 970ea3b05f..ad89b46f01 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -2393,14 +2393,8 @@ int main(int argc, char *argv[]) { } finish: - while ((a = ordered_hashmap_steal_first(items))) - item_array_free(a); - - while ((a = ordered_hashmap_steal_first(globs))) - item_array_free(a); - - ordered_hashmap_free(items); - ordered_hashmap_free(globs); + ordered_hashmap_free_with_destructor(items, item_array_free); + ordered_hashmap_free_with_destructor(globs, item_array_free); free(arg_include_prefixes); free(arg_exclude_prefixes); diff --git a/src/udev/collect/collect.c b/src/udev/collect/collect.c index 17e6616634..14e97e6f48 100644 --- a/src/udev/collect/collect.c +++ b/src/udev/collect/collect.c @@ -135,7 +135,8 @@ static int prepare(char *dir, char *filename) static int checkout(int fd) { int len; - char *buf, *ptr, *word = NULL; + _cleanup_free_ char *buf = NULL; + char *ptr, *word = NULL; struct _mate *him; restart: @@ -155,7 +156,6 @@ static int checkout(int fd) bufsize = bufsize << 1; if (debug) fprintf(stderr, "ID overflow, restarting with size %zu\n", bufsize); - free(buf); lseek(fd, 0, SEEK_SET); goto restart; } @@ -168,13 +168,10 @@ static int checkout(int fd) if (debug) fprintf(stderr, "Found word %s\n", word); him = malloc(sizeof (struct _mate)); - if (!him) { - free(buf); + if (!him) return log_oom(); - } him->name = strdup(word); if (!him->name) { - free(buf); free(him); return log_oom(); } @@ -188,12 +185,9 @@ static int checkout(int fd) if (!ptr) ptr = word; - if (!ptr) - break; ptr -= len; } - free(buf); return 0; }