xref: /aosp_15_r20/external/e2fsprogs/lib/ext2fs/atexit.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker  * atexit.c --- Clean things up when we exit normally.
3*6a54128fSAndroid Build Coastguard Worker  *
4*6a54128fSAndroid Build Coastguard Worker  * Copyright Oracle, 2014
5*6a54128fSAndroid Build Coastguard Worker  * Author Darrick J. Wong <[email protected]>
6*6a54128fSAndroid Build Coastguard Worker  *
7*6a54128fSAndroid Build Coastguard Worker  * %Begin-Header%
8*6a54128fSAndroid Build Coastguard Worker  * This file may be redistributed under the terms of the GNU Library
9*6a54128fSAndroid Build Coastguard Worker  * General Public License, version 2.
10*6a54128fSAndroid Build Coastguard Worker  * %End-Header%
11*6a54128fSAndroid Build Coastguard Worker  */
12*6a54128fSAndroid Build Coastguard Worker 
13*6a54128fSAndroid Build Coastguard Worker #ifndef _LARGEFILE_SOURCE
14*6a54128fSAndroid Build Coastguard Worker #define _LARGEFILE_SOURCE
15*6a54128fSAndroid Build Coastguard Worker #endif
16*6a54128fSAndroid Build Coastguard Worker #ifndef _LARGEFILE64_SOURCE
17*6a54128fSAndroid Build Coastguard Worker #define _LARGEFILE64_SOURCE
18*6a54128fSAndroid Build Coastguard Worker #endif
19*6a54128fSAndroid Build Coastguard Worker 
20*6a54128fSAndroid Build Coastguard Worker #include "config.h"
21*6a54128fSAndroid Build Coastguard Worker #include <stdlib.h>
22*6a54128fSAndroid Build Coastguard Worker 
23*6a54128fSAndroid Build Coastguard Worker #include "ext2_fs.h"
24*6a54128fSAndroid Build Coastguard Worker #include "ext2fs.h"
25*6a54128fSAndroid Build Coastguard Worker #include "ext2fsP.h"
26*6a54128fSAndroid Build Coastguard Worker 
27*6a54128fSAndroid Build Coastguard Worker struct exit_data {
28*6a54128fSAndroid Build Coastguard Worker 	ext2_exit_fn func;
29*6a54128fSAndroid Build Coastguard Worker 	void *data;
30*6a54128fSAndroid Build Coastguard Worker };
31*6a54128fSAndroid Build Coastguard Worker 
32*6a54128fSAndroid Build Coastguard Worker static struct exit_data *items;
33*6a54128fSAndroid Build Coastguard Worker static size_t nr_items;
34*6a54128fSAndroid Build Coastguard Worker 
handle_exit(void)35*6a54128fSAndroid Build Coastguard Worker static void handle_exit(void)
36*6a54128fSAndroid Build Coastguard Worker {
37*6a54128fSAndroid Build Coastguard Worker 	struct exit_data *ed;
38*6a54128fSAndroid Build Coastguard Worker 
39*6a54128fSAndroid Build Coastguard Worker 	for (ed = items + nr_items - 1; ed >= items; ed--) {
40*6a54128fSAndroid Build Coastguard Worker 		if (ed->func == NULL)
41*6a54128fSAndroid Build Coastguard Worker 			continue;
42*6a54128fSAndroid Build Coastguard Worker 		ed->func(ed->data);
43*6a54128fSAndroid Build Coastguard Worker 	}
44*6a54128fSAndroid Build Coastguard Worker 
45*6a54128fSAndroid Build Coastguard Worker 	ext2fs_free_mem(&items);
46*6a54128fSAndroid Build Coastguard Worker 	nr_items = 0;
47*6a54128fSAndroid Build Coastguard Worker }
48*6a54128fSAndroid Build Coastguard Worker 
49*6a54128fSAndroid Build Coastguard Worker /*
50*6a54128fSAndroid Build Coastguard Worker  * Schedule a function to be called at (normal) program termination.
51*6a54128fSAndroid Build Coastguard Worker  * If you want this to be called during a signal exit, you must capture
52*6a54128fSAndroid Build Coastguard Worker  * the signal and call exit() yourself!
53*6a54128fSAndroid Build Coastguard Worker  */
ext2fs_add_exit_fn(ext2_exit_fn func,void * data)54*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_add_exit_fn(ext2_exit_fn func, void *data)
55*6a54128fSAndroid Build Coastguard Worker {
56*6a54128fSAndroid Build Coastguard Worker 	struct exit_data *ed, *free_ed = NULL;
57*6a54128fSAndroid Build Coastguard Worker 	size_t x;
58*6a54128fSAndroid Build Coastguard Worker 	errcode_t ret;
59*6a54128fSAndroid Build Coastguard Worker 
60*6a54128fSAndroid Build Coastguard Worker 	if (func == NULL)
61*6a54128fSAndroid Build Coastguard Worker 		return EXT2_ET_INVALID_ARGUMENT;
62*6a54128fSAndroid Build Coastguard Worker 
63*6a54128fSAndroid Build Coastguard Worker 	for (x = 0, ed = items; x < nr_items; x++, ed++) {
64*6a54128fSAndroid Build Coastguard Worker 		if (ed->func == func && ed->data == data)
65*6a54128fSAndroid Build Coastguard Worker 			return EXT2_ET_FILE_EXISTS;
66*6a54128fSAndroid Build Coastguard Worker 		if (ed->func == NULL)
67*6a54128fSAndroid Build Coastguard Worker 			free_ed = ed;
68*6a54128fSAndroid Build Coastguard Worker 	}
69*6a54128fSAndroid Build Coastguard Worker 
70*6a54128fSAndroid Build Coastguard Worker 	if (free_ed) {
71*6a54128fSAndroid Build Coastguard Worker 		free_ed->func = func;
72*6a54128fSAndroid Build Coastguard Worker 		free_ed->data = data;
73*6a54128fSAndroid Build Coastguard Worker 		return 0;
74*6a54128fSAndroid Build Coastguard Worker 	}
75*6a54128fSAndroid Build Coastguard Worker 
76*6a54128fSAndroid Build Coastguard Worker 	if (nr_items == 0) {
77*6a54128fSAndroid Build Coastguard Worker 		ret = atexit(handle_exit);
78*6a54128fSAndroid Build Coastguard Worker 		if (ret)
79*6a54128fSAndroid Build Coastguard Worker 			return ret;
80*6a54128fSAndroid Build Coastguard Worker 	}
81*6a54128fSAndroid Build Coastguard Worker 
82*6a54128fSAndroid Build Coastguard Worker 	ret = ext2fs_resize_mem(0, (nr_items + 1) * sizeof(struct exit_data),
83*6a54128fSAndroid Build Coastguard Worker 				&items);
84*6a54128fSAndroid Build Coastguard Worker 	if (ret)
85*6a54128fSAndroid Build Coastguard Worker 		return ret;
86*6a54128fSAndroid Build Coastguard Worker 
87*6a54128fSAndroid Build Coastguard Worker 	items[nr_items].func = func;
88*6a54128fSAndroid Build Coastguard Worker 	items[nr_items].data = data;
89*6a54128fSAndroid Build Coastguard Worker 	nr_items++;
90*6a54128fSAndroid Build Coastguard Worker 
91*6a54128fSAndroid Build Coastguard Worker 	return 0;
92*6a54128fSAndroid Build Coastguard Worker }
93*6a54128fSAndroid Build Coastguard Worker 
94*6a54128fSAndroid Build Coastguard Worker /* Remove a function from the exit cleanup list. */
ext2fs_remove_exit_fn(ext2_exit_fn func,void * data)95*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_remove_exit_fn(ext2_exit_fn func, void *data)
96*6a54128fSAndroid Build Coastguard Worker {
97*6a54128fSAndroid Build Coastguard Worker 	struct exit_data *ed;
98*6a54128fSAndroid Build Coastguard Worker 	size_t x;
99*6a54128fSAndroid Build Coastguard Worker 
100*6a54128fSAndroid Build Coastguard Worker 	if (func == NULL)
101*6a54128fSAndroid Build Coastguard Worker 		return EXT2_ET_INVALID_ARGUMENT;
102*6a54128fSAndroid Build Coastguard Worker 
103*6a54128fSAndroid Build Coastguard Worker 	for (x = 0, ed = items; x < nr_items; x++, ed++) {
104*6a54128fSAndroid Build Coastguard Worker 		if (ed->func == NULL)
105*6a54128fSAndroid Build Coastguard Worker 			return 0;
106*6a54128fSAndroid Build Coastguard Worker 		if (ed->func == func && ed->data == data) {
107*6a54128fSAndroid Build Coastguard Worker 			size_t sz = (nr_items - (x + 1)) *
108*6a54128fSAndroid Build Coastguard Worker 				    sizeof(struct exit_data);
109*6a54128fSAndroid Build Coastguard Worker 			memmove(ed, ed + 1, sz);
110*6a54128fSAndroid Build Coastguard Worker 			memset(items + nr_items - 1, 0,
111*6a54128fSAndroid Build Coastguard Worker 			       sizeof(struct exit_data));
112*6a54128fSAndroid Build Coastguard Worker 		}
113*6a54128fSAndroid Build Coastguard Worker 	}
114*6a54128fSAndroid Build Coastguard Worker 
115*6a54128fSAndroid Build Coastguard Worker 	return 0;
116*6a54128fSAndroid Build Coastguard Worker }
117