196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi/*
296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * kmod - interface to kernel module operations
396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi *
496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * Copyright (C) 2011-2013  ProFUSION embedded systems
596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * Copyright (C) 2012  Lucas De Marchi <lucas.de.marchi@gmail.com>
696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * Copyright (C) 2013-2014  Intel Corporation. All rights reserved.
796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi *
896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * This library is free software; you can redistribute it and/or
996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * modify it under the terms of the GNU Lesser General Public
1096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * License as published by the Free Software Foundation; either
1196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * version 2.1 of the License, or (at your option) any later version.
1296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi *
1396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * This library is distributed in the hope that it will be useful,
1496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * but WITHOUT ANY WARRANTY; without even the implied warranty of
1596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * Lesser General Public License for more details.
1796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi *
1896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * You should have received a copy of the GNU Lesser General Public
19dea2dfee9b301da84dbb09cf510b8ebf2ef28fffLucas De Marchi * License along with this library; if not, see <http://www.gnu.org/licenses/>.
2096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi */
2196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
2296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi#include <assert.h>
23c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <ctype.h>
24c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <errno.h>
25c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <stdarg.h>
26c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <stddef.h>
2796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi#include <stdio.h>
2896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi#include <stdlib.h>
2996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi#include <string.h>
30c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <unistd.h>
3196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
32efb5bfaca938fa5991865c1e9a0c730dc919708cNatanael Copa#include <shared/missing.h>
3396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi#include <shared/util.h>
3496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
3596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi#define USEC_PER_SEC  1000000ULL
3696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi#define NSEC_PER_USEC 1000ULL
3796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
38f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchistatic const struct kmod_ext {
39f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	const char *ext;
40f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	size_t len;
41f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi} kmod_exts[] = {
42f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	{KMOD_EXTENSION_UNCOMPRESSED, sizeof(KMOD_EXTENSION_UNCOMPRESSED) - 1},
43f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi#ifdef ENABLE_ZLIB
44f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	{".ko.gz", sizeof(".ko.gz") - 1},
45f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi#endif
46f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi#ifdef ENABLE_XZ
47f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	{".ko.xz", sizeof(".ko.xz") - 1},
48f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi#endif
49f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	{ }
50f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi};
51f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi
52a6ede6c7ad46b5e2b8eddddca5590c0b745b045aLucas De Marchiassert_cc(EAGAIN == EWOULDBLOCK);
53a6ede6c7ad46b5e2b8eddddca5590c0b745b045aLucas De Marchi
5496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi/* string handling functions and memory allocations                         */
5596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi/* ************************************************************************ */
5696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
5796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchivoid *memdup(const void *p, size_t n)
5896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi{
5996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	void *r = malloc(n);
6096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
6196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	if (r == NULL)
6296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		return NULL;
6396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
6496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	return memcpy(r, p, n);
6596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi}
6696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
679a437531af61a59f5f0a96545288735f45ce6469Lucas De Marchichar *strchr_replace(char *s, char c, char r)
6896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi{
6996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	char *p;
7096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
7196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	for (p = s; *p != '\0'; p++) {
7296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		if (*p == c)
7396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			*p = r;
7496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	}
7596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
7696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	return s;
7796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi}
7896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
792b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi/* module-related functions                                                 */
802b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi/* ************************************************************************ */
812b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchiint alias_normalize(const char *alias, char buf[static PATH_MAX], size_t *len)
822b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi{
832b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi	size_t i;
842b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi
852b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi	for (i = 0; i < PATH_MAX - 1; i++) {
862b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi		const char c = alias[i];
872b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi		switch (c) {
882b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi		case '-':
892b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi			buf[i] = '_';
902b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi			break;
912b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi		case ']':
922b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi			return -EINVAL;
932b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi		case '[':
942b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi			while (alias[i] != ']' && alias[i] != '\0') {
952b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi				buf[i] = alias[i];
962b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi				i++;
972b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi			}
982b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi
992b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi			if (alias[i] != ']')
1002b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi				return -EINVAL;
1012b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi
1022b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi			buf[i] = alias[i];
1032b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi			break;
1042b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi		case '\0':
1052b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi			goto finish;
1062b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi		default:
1072b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi			buf[i] = c;
1082b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi		}
1092b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi	}
1102b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi
1112b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchifinish:
1122b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi	buf[i] = '\0';
1132b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi	if (len)
1142b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi		*len = i;
1152b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi
1162b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi	return 0;
1172b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi}
1182b0104fe3c47a9746b6296ed5646cd39e2ae010dLucas De Marchi
11952c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi/*
12052c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi * Replace dashes with underscores.
12152c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi * Dashes inside character range patterns (e.g. [0-9]) are left unchanged.
12252c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi *
12352c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi * For convenience, it returns error if @s is NULL
12452c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi */
12552c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchiint underscores(char *s)
12652c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi{
12752c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi	unsigned int i;
12852c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi
12952c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi	if (!s)
13052c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi		return -EINVAL;
13152c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi
13252c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi	for (i = 0; s[i]; i++) {
13352c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi		switch (s[i]) {
13452c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi		case '-':
13552c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			s[i] = '_';
13652c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			break;
13752c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi		case ']':
13852c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			return -EINVAL;
13952c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi		case '[':
14052c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			i += strcspn(&s[i], "]");
14152c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			if (!s[i])
14252c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi				return -EINVAL;
14352c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			break;
14452c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi		}
14552c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi	}
14652c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi
14752c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi	return 0;
14852c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi}
14952c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi
150f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchichar *modname_normalize(const char *modname, char buf[static PATH_MAX], size_t *len)
151f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi{
152f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	size_t s;
153f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi
154f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	for (s = 0; s < PATH_MAX - 1; s++) {
155f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi		const char c = modname[s];
156f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi		if (c == '-')
157f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi			buf[s] = '_';
158f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi		else if (c == '\0' || c == '.')
159f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi			break;
160f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi		else
161f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi			buf[s] = c;
162f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	}
163f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi
164f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	buf[s] = '\0';
165f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi
166f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	if (len)
167f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi		*len = s;
168f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi
169f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	return buf;
170f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi}
171f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi
172f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchichar *path_to_modname(const char *path, char buf[static PATH_MAX], size_t *len)
173f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi{
174f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	char *modname;
175f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi
176f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	modname = basename(path);
177f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	if (modname == NULL || modname[0] == '\0')
178f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi		return NULL;
179f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi
180f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	return modname_normalize(modname, buf, len);
181f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi}
182f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi
183f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchibool path_ends_with_kmod_ext(const char *path, size_t len)
184f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi{
185f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	const struct kmod_ext *eitr;
186f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi
187f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	for (eitr = kmod_exts; eitr->ext != NULL; eitr++) {
188f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi		if (len <= eitr->len)
189f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi			continue;
190f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi		if (streq(path + len - eitr->len, eitr->ext))
191f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi			return true;
192f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	}
193f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi
194f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi	return false;
195f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi}
196f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi
19796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi/* read-like and fread-like functions                                       */
19896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi/* ************************************************************************ */
19996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchissize_t read_str_safe(int fd, char *buf, size_t buflen)
20096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi{
20196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	size_t todo = buflen - 1;
20296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	size_t done = 0;
20396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
20496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	do {
20596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		ssize_t r = read(fd, buf + done, todo);
20696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
20796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		if (r == 0)
20896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			break;
20996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		else if (r > 0) {
21096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			todo -= r;
21196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			done += r;
21296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		} else {
213a6ede6c7ad46b5e2b8eddddca5590c0b745b045aLucas De Marchi			if (errno == EAGAIN || errno == EINTR)
21496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				continue;
21596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			else
21696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				return -errno;
21796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		}
21896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	} while (todo > 0);
21996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
22096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	buf[done] = '\0';
22196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	return done;
22296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi}
22396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
22496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchissize_t write_str_safe(int fd, const char *buf, size_t buflen)
22596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi{
22696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	size_t todo = buflen;
22796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	size_t done = 0;
22896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
22996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	do {
23096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		ssize_t r = write(fd, buf + done, todo);
23196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
23296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		if (r == 0)
23396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			break;
23496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		else if (r > 0) {
23596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			todo -= r;
23696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			done += r;
23796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		} else {
238a6ede6c7ad46b5e2b8eddddca5590c0b745b045aLucas De Marchi			if (errno == EAGAIN || errno == EINTR)
23996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				continue;
24096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			else
24196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				return -errno;
24296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		}
24396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	} while (todo > 0);
24496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
24596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	return done;
24696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi}
24796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
24896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchiint read_str_long(int fd, long *value, int base)
24996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi{
25096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	char buf[32], *end;
25196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	long v;
25296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	int err;
25396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
25496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	*value = 0;
25596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	err = read_str_safe(fd, buf, sizeof(buf));
25696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	if (err < 0)
25796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		return err;
25896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	errno = 0;
25996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	v = strtol(buf, &end, base);
26096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	if (end == buf || !isspace(*end))
26196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		return -EINVAL;
26296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
26396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	*value = v;
26496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	return 0;
26596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi}
26696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
26796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchiint read_str_ulong(int fd, unsigned long *value, int base)
26896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi{
26996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	char buf[32], *end;
27096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	long v;
27196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	int err;
27296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
27396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	*value = 0;
27496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	err = read_str_safe(fd, buf, sizeof(buf));
27596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	if (err < 0)
27696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		return err;
27796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	errno = 0;
27896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	v = strtoul(buf, &end, base);
27996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	if (end == buf || !isspace(*end))
28096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		return -EINVAL;
28196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	*value = v;
28296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	return 0;
28396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi}
28496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
28596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi/*
28696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * Read one logical line from a configuration file.
28796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi *
28896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * Line endings may be escaped with backslashes, to form one logical line from
28996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * several physical lines.  No end of line character(s) are included in the
29096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * result.
29196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi *
29296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * If linenum is not NULL, it is incremented by the number of physical lines
29396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi * which have been read.
29496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi */
295aafd38359adfd93b1f8c1e84b8bd7bc9e1b0b6cfLucas De Marchichar *freadline_wrapped(FILE *fp, unsigned int *linenum)
29696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi{
29796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	int size = 256;
29896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	int i = 0, n = 0;
29996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	_cleanup_free_ char *buf = malloc(size);
30096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
30196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	if (buf == NULL)
30296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		return NULL;
30396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
30496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	for(;;) {
30596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		int ch = getc_unlocked(fp);
30696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
30796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		switch(ch) {
30896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		case EOF:
30996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			if (i == 0)
31096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				return NULL;
31196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			/* else fall through */
31296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
31396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		case '\n':
31496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			n++;
31596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
31696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			{
31788f6ffe449fc1c92725615348b63c4b59bb50921Caio Marcelo de Oliveira Filho				char *ret = buf;
31896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				ret[i] = '\0';
31996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				buf = NULL;
32096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				if (linenum)
32196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi					*linenum += n;
32296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				return ret;
32396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			}
32496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
32596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		case '\\':
32696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			ch = getc_unlocked(fp);
32796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
32896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			if (ch == '\n') {
32996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				n++;
33096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				continue;
33196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			}
33296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			/* else fall through */
33396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
33496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		default:
33596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			buf[i++] = ch;
33696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
33796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			if (i == size) {
33896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				char *tmp;
33996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				size *= 2;
34096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				tmp = realloc(buf, size);
34196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				if (!tmp)
34296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi					return NULL;
34396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				buf = tmp;
34496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			}
34596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		}
34696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	}
34796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi}
34896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
34996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi/* path handling functions                                                  */
35096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi/* ************************************************************************ */
35196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
35296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchibool path_is_absolute(const char *p)
35396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi{
35496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	assert(p != NULL);
35596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
35696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	return p[0] == '/';
35796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi}
35896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
35996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchichar *path_make_absolute_cwd(const char *p)
36096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi{
36196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	_cleanup_free_ char *cwd = NULL;
36296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	size_t plen, cwdlen;
36396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	char *r;
36496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
36596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	if (path_is_absolute(p))
36696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		return strdup(p);
36796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
36896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	cwd = get_current_dir_name();
36996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	if (!cwd)
37096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		return NULL;
37196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
37296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	plen = strlen(p);
37396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	cwdlen = strlen(cwd);
37496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
37596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	/* cwd + '/' + p + '\0' */
37696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	r = realloc(cwd, cwdlen + 1 + plen + 1);
37796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	if (r == NULL)
37896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		return NULL;
37996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
38096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	cwd = NULL;
38196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	r[cwdlen] = '/';
38296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	memcpy(&r[cwdlen + 1], p, plen + 1);
38396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
38496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	return r;
38596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi}
38696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
38796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchistatic inline int is_dir(const char *path)
38896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi{
38996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	struct stat st;
39096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
39196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	if (stat(path, &st) >= 0)
39296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		return S_ISDIR(st.st_mode);
39396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
39496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	return -errno;
39596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi}
39696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
39796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchiint mkdir_p(const char *path, int len, mode_t mode)
39896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi{
39996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	char *start, *end;
40096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
40196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	start = strndupa(path, len);
40296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	end = start + len;
40396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
40496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	/*
40596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	 * scan backwards, replacing '/' with '\0' while the component doesn't
40696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	 * exist
40796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	 */
40896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	for (;;) {
40996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		int r = is_dir(start);
41096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		if (r > 0) {
41196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			end += strlen(end);
41296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
41396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			if (end == start + len)
41496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi				return 0;
41596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
41696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			/* end != start, since it would be caught on the first
41796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			 * iteration */
41896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			*end = '/';
41996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			break;
42096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		} else if (r == 0)
42196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			return -ENOTDIR;
42296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
42396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		if (end == start)
42496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			break;
42596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
42696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		*end = '\0';
42796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
42896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		/* Find the next component, backwards, discarding extra '/'*/
42996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		while (end > start && *end != '/')
43096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			end--;
43196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
43296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		while (end > start && *(end - 1) == '/')
43396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			end--;
43496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	}
43596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
43696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	for (; end < start + len;) {
43796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		if (mkdir(start, mode) < 0 && errno != EEXIST)
43896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi			return -errno;
43996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
44096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		end += strlen(end);
44196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		*end = '/';
44296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	}
44396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
44496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	return 0;
44596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi}
44696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
44796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchiint mkdir_parents(const char *path, mode_t mode)
44896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi{
44996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	char *end = strrchr(path, '/');
45096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
45196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	/* no parent directories */
45296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	if (end == NULL)
45396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi		return 0;
45496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
45596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	return mkdir_p(path, end - path, mode);
45696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi}
45796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
45896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchiunsigned long long ts_usec(const struct timespec *ts)
45996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi{
46096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	return (unsigned long long) ts->tv_sec * USEC_PER_SEC +
46196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	       (unsigned long long) ts->tv_nsec / NSEC_PER_USEC;
46296573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi}
46396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
46496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchiunsigned long long stat_mstamp(const struct stat *st)
46596573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi{
46696573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi#ifdef HAVE_STRUCT_STAT_ST_MTIM
46796573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	return ts_usec(&st->st_mtim);
46896573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi#else
46996573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi	return (unsigned long long) st->st_mtime;
47096573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi#endif
47196573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi}
472