File: util.h

package info (click to toggle)
swupdate 2025.12%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 10,004 kB
  • sloc: ansic: 66,621; python: 6,291; makefile: 791; sh: 538; javascript: 229
file content (347 lines) | stat: -rw-r--r-- 9,729 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
/*
 * (C) Copyright 2012-2023
 * Stefano Babic <stefano.babic@swupdate.org>
 *
 * SPDX-License-Identifier:     GPL-2.0-only
 */

#pragma once

#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <sys/time.h>
#if defined(__linux__)
#include <linux/types.h>
#endif
#include <sys/types.h>
#include "globals.h"
#include "swupdate_status.h"
#include "swupdate_dict.h"
#include "compat.h"
#include "swupdate_aes.h"

#define NOTIFY_BUF_SIZE 	2048
#define ENOMEM_ASPRINTF		-1

#define SWUPDATE_SHA_DIGEST_LENGTH	20
#define AES_BLK_SIZE	16
#define AES_128_KEY_LEN	16
#define AES_192_KEY_LEN	24
#define AES_256_KEY_LEN	32

#define HWID_REGEXP_PREFIX	"#RE:"

#define BOOTVAR_TRANSACTION "recovery_status"

struct img_type;
struct imglist;
struct hw_type;

extern int loglevel;
extern int exit_code;

typedef enum {
	SERVER_OK,
	SERVER_EERR,
	SERVER_EBADMSG,
	SERVER_EINIT,
	SERVER_EACCES,
	SERVER_EAGAIN,
	SERVER_UPDATE_AVAILABLE,
	SERVER_NO_UPDATE_AVAILABLE,
	SERVER_UPDATE_CANCELED,
	SERVER_ID_REQUESTED,
} server_op_res_t;

enum compression_type {
  COMPRESSED_FALSE,
  COMPRESSED_TRUE,
  COMPRESSED_ZLIB,
  COMPRESSED_XZ,
  COMPRESSED_ZSTD,
};

typedef int (*writeimage) (void *out, const void *buf, size_t len);

struct swupdate_copy {
	/* input: either fdin is set or fdin < 0 and inbuf */
	int fdin;
	unsigned char *inbuf;
	/* data handler callback and output argument.
	 * out must point to a fd if seeking */
	writeimage callback;
	void *out;
	/* amount of data to copy */
	size_t nbytes;
	/* pointer to offset within source, must be set for fd */
	unsigned long *offs;
	/* absolute offset to seek in output (*out) if non-zero */
	unsigned long long seek;
	/* skip callback: only verify input */
	int skip_file;
	/* decompression to use */
	enum compression_type compressed;
	/* cpio crc checksum */
	uint32_t *checksum;
	/* sw-description sha256 checksum */
	unsigned char *hash;
	/* encryption */
	bool encrypted;
	const char *imgivt;
	const char *imgaes;
	cipher_t cipher;
};

/*
 * loglevel is used into TRACE / ERROR
 * for values > LASTLOGLEVEL, it is an encoded field 
 * to inform the installer about a change in a subprocess
 */
typedef enum {
	OFF,
	ERRORLEVEL,
	WARNLEVEL,
	INFOLEVEL,
	TRACELEVEL,
	DEBUGLEVEL,
	LASTLOGLEVEL=DEBUGLEVEL
} LOGLEVEL;

/*
 * Following are used for notification from another process
 */

typedef enum {
	CANCELUPDATE=LASTLOGLEVEL + 1,
	CHANGE,
} NOTIFY_CAUSE;

enum {
	RECOVERY_NO_ERROR,
	RECOVERY_ERROR,
	RECOVERY_DWL,
};

typedef void (*notifier) (RECOVERY_STATUS status, int error, int level, const char *msg);

void notify(RECOVERY_STATUS status, int error, int level, const char *msg);
void notify_init(void);
void notifier_set_color(int level, char *col);

#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
#define swupdate_notify(status, format, level, arg...) do { \
	if (loglevel >= level) { \
		char tmpbuf[NOTIFY_BUF_SIZE]; \
		if (status == FAILURE) { \
			if (loglevel >= DEBUGLEVEL) \
				snprintf(tmpbuf, sizeof(tmpbuf), \
				     	"ERROR %s : %s : %d : " format, \
						__FILENAME__, \
					       	__func__, \
					       	__LINE__, \
						## arg); \
			else \
				snprintf(tmpbuf, sizeof(tmpbuf), \
					       	"ERROR : " format, ## arg); \
			notify(FAILURE, 0, level, tmpbuf); \
		} else {\
			snprintf(tmpbuf, sizeof(tmpbuf), \
				       	"[%s] : " format, __func__, ## arg); \
			notify(RUN, RECOVERY_NO_ERROR, level, tmpbuf); \
		} \
	} \
} while(0)

#define ERROR(format, arg...) \
	swupdate_notify(FAILURE, format, ERRORLEVEL, ## arg)

#define WARN(format, arg...) \
	swupdate_notify(RUN, format, WARNLEVEL, ## arg)

#define INFO(format, arg...) \
	swupdate_notify(RUN, format, INFOLEVEL, ## arg)

#define TRACE(format, arg...) \
	swupdate_notify(RUN, format, TRACELEVEL, ## arg)

#define DEBUG(format, arg...) \
	swupdate_notify(RUN, format, DEBUGLEVEL, ## arg)

#ifndef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif

#define STRINGIFY(...) #__VA_ARGS__
#define PREPROCVALUE(s) STRINGIFY(s)
#define SETSTRING(p, v) do { \
	if (p) \
		free(p); \
	p = strdup(v); \
} while (0)


#define IS_STR_EQUAL(s,s1) (s && s1 && !strcmp(s,s1))
#define UNUSED __attribute__((__unused__))

#define LG_16 4
#define FROM_HEX(f) from_ascii (f, sizeof f, LG_16)
uintmax_t
from_ascii (char const *where, size_t digs, unsigned logbase);
int ascii_to_hash(unsigned char *hash, const char *s);
int ascii_to_bin(unsigned char *dest, size_t dstlen, const char *src);
void hash_to_ascii(const unsigned char *hash, char *s);
int IsValidHash(const unsigned char *hash);
bool is_hex_str(const char *ascii);

#ifndef typeof
#define typeof __typeof__
#endif
#define max(a, b) ({\
		typeof(a) _a = a;\
		typeof(b) _b = b;\
		_a > _b ? _a : _b; })

#define min(a, b) ({\
		typeof(a) _a = a;\
		typeof(b) _b = b;\
		_a < _b ? _a : _b; })

#define min_t(type,x,y) \
	({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
#define max_t(type,x,y) \
	({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })

#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
#define ROUND_DOWN(N, S) (((N) / (S)) * (S))

/* According to linux kernel ENOTSUPP is not a standard error code and should
 * be avoided in new patches. EOPNOTSUPP should be used instead. Unfortunately
 * some drivers still return ENOTSUPP. Do not confuse with ENOTSUP! See also:
 * https://lists.gnu.org/archive/html/bug-glibc/2002-08/msg00017.html
 * https://linux-fsdevel.vger.kernel.narkive.com/pERNbmWG/kernel-glibc-eopnotsupp-vs-enotsup-vs-enotsupp-also-rfc-posix-acl-kernel-infrastructure
 */
#ifndef ENOTSUPP
#define ENOTSUPP 524 /* Operation is not supported */
UNUSED static inline const char *strerror_enotsupp(int code)
{
	if (code == ENOTSUPP)
		return "Operation is not supported";
	return strerror(code);
}
#define STRERROR(code) strerror_enotsupp(code)
#else
#define STRERROR(code) strerror(code)
#endif

UNUSED static inline bool is_not_supported(int code)
{
	return (code == EOPNOTSUPP) || (code == ENOTSUP) || (code == ENOTSUPP);
}

bool strtobool(const char *s);

/*
 * Function to extract / copy images
 */
void *saferealloc(void *ptr, size_t size);
int copy_write(void *out, const void *buf, size_t len);
#if defined(__FreeBSD__)
int copy_write_padded(void *out, const void *buf, size_t len);
#endif
#if defined(__linux__)
/* strlcpy was originally developped in FreeBSD, not present in glibc */
size_t
strlcpy(char *dst, const char * src, size_t size);
#endif
int copyfile(struct swupdate_copy *copy);
int copyimage(void *out, struct img_type *img, writeimage callback);
int openfileoutput(const char *filename);
int mkpath(char *dir, mode_t mode);
int swupdate_file_setnonblock(int fd, bool block);

int register_notifier(notifier client);
int syslog_init(void);

char **splitargs(char *args, int *argc);
char *mstrcat(const char **nodes, const char *delim);
char *swupdate_strcat(int n, ...);
char** string_split(const char* a_str, const char a_delim);
char *substring(const char *src, int first, int len);
char *string_tolower(char *s);
size_t snescape(char *dst, size_t n, const char *src);
void freeargs (char **argv);
int compare_versions(const char* left_version, const char* right_version);
int hwid_match(const char* rev, const char* hwrev);
int count_elem_list(struct imglist *list);
unsigned int count_string_array(const char **nodes);
void free_string_array(char **nodes);
int read_lines_notify(int fd, char *buf, int buf_size, int *buf_offset,
		      LOGLEVEL level);
long long get_output_size(struct img_type *img, bool strict);
bool img_check_free_space(struct img_type *img, int fd);
bool check_same_file(int fd1, int fd2);

/* location for libubootenv configuration file */
const char *get_fwenv_config(void);
void set_fwenv_config(const char *fname);

/* Decryption key functions */
int load_decryption_key(char *fname);
char *swupdate_get_decrypt_key(void);
char swupdate_get_decrypt_keylen(void);
unsigned char *get_aes_ivt(void);
int set_aes_key(const char *key, const char *ivt);
int set_filename_as_key(const char *fname, cipher_t cipher);
cipher_t swupdate_get_decrypt_cipher(void);

/* Getting global information */
int get_install_info(char *buf, size_t len);
sourcetype  get_install_source(void);
void get_install_swset(char *buf, size_t len);
void get_install_running_mode(char *buf, size_t len);
bool is_dryrun_install(void);
char *get_root_device(void);
char **parse_linux_cmdline(void);

/* Setting global information */
int set_version_range(const char *updatetype,
			const char *minversion,
			const char *maxversion,
			const char *current);

int size_delimiter_match(const char *size);
unsigned long long ustrtoull(const char *cp, char **endptr, unsigned int base);

const char* get_tmpdir(void);
const char* get_tmpdirscripts(void);

void swupdate_create_directory(const char* path);
#ifndef CONFIG_NOCLEANUP
int swupdate_remove_directory(const char* path);
#endif

int swupdate_mount(const char *device, const char *dir, const char *fstype);
int swupdate_umount(const char *dir);
char *swupdate_temporary_mount(tmp_mountpoint_t type, const char *device, const char *fstype);
int swupdate_temporary_umount(char *mountpoint);

/* Date / Time utilities */
char *swupdate_time_iso8601(struct timeval *tv);

/* eMMC functions */
int emmc_write_bootpart(int fd, int bootpart);
int emmc_get_active_bootpart(int fd);

/* used to compare if an attribute is set to enabled or disabled */

static inline bool is_enabled_or_disabled(const char *s) {
	return (!(strcmp(s, "enabled") && strcmp(s, "disabled")));
}
static inline bool is_enabled(const char *s) {
	return (!strcmp(s, "enabled"));
}