diff options
| author | Adam Spragg <adam@spra.gg> | 2022-05-17 17:31:48 +0100 | 
|---|---|---|
| committer | Adam Spragg <adam@spra.gg> | 2022-05-18 17:19:47 +0100 | 
| commit | 260fc47f01ef64368721ec93de4cbd988357b32b (patch) | |
| tree | 551213a3f0ecdff66f525cf4b0a59c349ee898dd /src/utils.c | |
| parent | b3c08670f56d7c5ee85dffa1a2faa5e03d2df5a1 (diff) | |
Add ability to read Format 1 metadata files
Diffstat (limited to 'src/utils.c')
| -rw-r--r-- | src/utils.c | 125 | 
1 files changed, 125 insertions, 0 deletions
diff --git a/src/utils.c b/src/utils.c index 5cdef6b..2247151 100644 --- a/src/utils.c +++ b/src/utils.c @@ -80,6 +80,18 @@ xmalloc(size_t size)          return result;  } +/* Ditto for realloc */ +void * +xrealloc(void *ptr, size_t size) +{ +        void *result = realloc(ptr, size); +        if (!result) { +                msg(MSG_CRITICAL, "Failed to realloc %zu bytes\n", size); +                exit(EXIT_FAILURE); +        } +        return result; +} +  /* Ditto for strdup */  char *  xstrdup(const char *s) @@ -143,6 +155,19 @@ write_string(const char *string, FILE *to)  	xfwrite(string, strlen(string) + 1, to);  } +/* Get the value of a hex digit */ +static int +xdigitval(int c) +{ +	if (c >= '0' && c <= '9') +		return c - '0'; +	if (c >= 'A' && c <= 'F') +		return 10 + c - 'A'; +	if (c >= 'a' && c <= 'f') +		return 10 + c - 'a'; +	return -1; +} +  /* Check if a character being put into a URL must be encoded */  static int  char_url_mustencode(int c) @@ -192,6 +217,15 @@ write_string_url(const char *string, FILE *to)  		write_char_url(c, to);  } +/* Reads a single char from a file */ +int +read_char(const char **from, const char *max) +{ +	if (*from >= max) +		return EOF; +	return *((*from)++); +} +  /* Reads an int from a file, using len bytes, in little-endian order */  uint64_t  read_int(const char **from, size_t len, const char *max) @@ -211,6 +245,27 @@ read_int(const char **from, size_t len, const char *max)  	return result;  } +/* Reads an int from a file, stored as an ASCII string, to the first non-digit */ +long +read_int_string(const char **from, const char *max, int base) +{ +	long result = 0; +	int sign = 1, i; + +	if (*from < max && **from == '-') { +		sign = -1; +		*from += 1; +	} + +	while (*from < max && (i = xdigitval(**from)) >= 0 && i < base) { +		result *= base; +		result += i; +		*from += 1; +	} + +	return result * sign; +} +  /* Reads a binary string from a file */  char *  read_binary_string(const char **from, size_t len, const char *max) @@ -229,6 +284,69 @@ read_binary_string(const char **from, size_t len, const char *max)  	return result;  } +/* Reads binary data from a file, which was stored URL-encoded */ +char * +read_binary_url(const char **pfrom, const char *max, ssize_t *plen) +{ +	const char *from; +	size_t bufsize, len; +	char * buf; +	int hi, lo; + +	from = *pfrom; +	bufsize = 32; +	buf = xmalloc(bufsize); +	len = 0; + +	while (from < max) { +		if (len == bufsize) { +			bufsize *= 2; +			buf = xrealloc(buf, bufsize); +		} + +		if (*from == '%' && (max - from) >= 3) { +			/* URL-encoded char - decode */ +			from++; +			hi = xdigitval(*from++); +			lo = xdigitval(*from++); +			if (hi < 0 || lo < 0) { +				/* Invalid encoding */ +				free(buf); +				*pfrom = from; +				return NULL; +			} +			if (hi == 0 && lo == 0 && !plen) { +				/* NUL in C string? Stop here */ +				break; +			} +			buf[len++] = (hi << 4) + lo; +		} +		else if (char_url_mustencode(*from)) { +			/* Un-encoded char. Stop here */ +			break; +		} +		else { +			buf[len++] = *from++; +		} +	} + +	if (plen) { +		/* plen is non-NULL means read binary data - return length */ +		*plen = len; +	} +	else { +		/* plen is NULL actually means read C string - NUL terminate */ +		if (len == bufsize) { +			bufsize *= 2; +			buf = xrealloc(buf, bufsize); +		} +		buf[len++] = '\0'; +	} + +	*pfrom = from; +	return buf; +} +  /* Reads a normal C string from a file */  char *  read_string(const char **from, const char *max) @@ -236,6 +354,13 @@ read_string(const char **from, const char *max)  	return read_binary_string(from, strlen(*from) + 1, max);  } +/* Reads a normal C string from a file, which was stored URL-encoded */ +char * +read_string_url(const char **from, const char *max) +{ +	return read_binary_url(from, max, NULL); +} +  /* For group caching */  static struct group *gtable = NULL;  | 
