Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
open_tempdir: add a new function
Baptiste Daroussin committed 3 years ago
commit 3fbc61c930a99ced93a23b31ca6c590ff1d6d245
parent e04d9e6
3 files changed +95 -0
modified libpkg/private/utils.h
@@ -55,6 +55,14 @@ struct hardlink {
	dev_t dev;
};

+
struct tempdir {
+
	char name[MAXHOSTNAMELEN];
+
	char temp[MAXHOSTNAMELEN];
+
	size_t len;
+
	int fd;
+
};
+
typedef tll(struct tempdir *) tempdirs_t;
+

struct dns_srvinfo {
	unsigned int type;
	unsigned int class;
@@ -117,5 +125,6 @@ bool copy_file(int from, int to);
void hidden_tempfile(char *buf, int buflen, const char *path);
void append_random_suffix(char *buf, int buflen, int suffixlen);
char *json_escape(const char *str);
+
struct tempdir *open_tempdir(int rootfd, const char *path);

#endif
modified libpkg/utils.c
@@ -1001,3 +1001,50 @@ json_escape(const char *str)
	return (xstring_get(buf));
}

+

+
struct tempdir *
+
open_tempdir(int rootfd, const char *path)
+
{
+
	struct stat st;
+
	char walk[MAXPATHLEN];
+
	char *dir;
+
	size_t cnt = 0;
+
	
+
	strlcpy(walk, path, sizeof(walk));
+
	while ((dir = strrchr(walk, '/')) != NULL) {
+
		struct tempdir *t;
+
		*dir = '\0';
+
		cnt++;
+
		/* accept symlinks pointing to directories */
+
		if (strlen(walk) == 0 && cnt == 1)
+
			break;
+
		if (strlen(walk) > 0) {
+
			if (fstatat(rootfd, RELATIVE_PATH(walk), &st, 0) == -1) 
+
				continue;
+
			if (S_ISDIR(st.st_mode) && cnt == 1)
+
				break;
+
			if (!S_ISDIR(st.st_mode))
+
				continue;
+
		}
+
		*dir = '/';
+
		t = xcalloc(1, sizeof(*t));
+
		hidden_tempfile(t->temp, sizeof(t->temp), walk);
+
		if (mkdirat(rootfd, RELATIVE_PATH(t->temp), 0755) == -1) {
+
			pkg_errno("Fail to create temporary directory: %s", t->temp);
+
			free(t);
+
			return (NULL);
+
		}
+

+
		strlcpy(t->name, walk, sizeof(t->name));
+
		t->len = strlen(t->name);
+
		t->fd = openat(rootfd, RELATIVE_PATH(t->temp), O_DIRECTORY);
+
		if (t->fd == -1) {
+
			pkg_errno("Fail to open directory %s", t->temp);
+
			free(t);
+
			return (NULL);
+
		}
+
		return (t);
+
	}
+
	errno = 0;
+
	return (NULL);
+
}
modified tests/lib/utils.c
@@ -25,11 +25,13 @@

#include <atf-c.h>
#include <err.h>
+
#include <fcntl.h>
#include <private/utils.h>

ATF_TC_WITHOUT_HEAD(hidden_tempfile);
ATF_TC_WITHOUT_HEAD(random_suffix);
ATF_TC_WITHOUT_HEAD(json_escape);
+
ATF_TC_WITHOUT_HEAD(open_tempdir);

ATF_TC_BODY(hidden_tempfile, tc) {
	const char *filename = "plop";
@@ -67,11 +69,48 @@ ATF_TC_BODY(json_escape, tc) {
	ATF_REQUIRE_STREQ_MSG(m, "entry1\\\"\\\"\\\\ ", "Invalid escaping");
}

+
ATF_TC_BODY(open_tempdir, tc) {
+
	struct tempdir *t;
+
	int rootfd = open(getenv("TMPDIR"), O_DIRECTORY);
+
	ATF_REQUIRE_MSG(rootfd  != -1, "impossible to open TMPDIR");
+
	t = open_tempdir(rootfd, "/plop");
+
	ATF_REQUIRE(t == NULL);
+
	mkdirat(rootfd, "usr", 0755);
+
	t = open_tempdir(rootfd, "/usr/local/directory");
+
	ATF_REQUIRE(t != NULL);
+
	ATF_REQUIRE_STREQ(t->name, "/usr/local");
+
	ATF_REQUIRE_EQ(t->len, strlen("/usr/local"));
+
	ATF_REQUIRE(strncmp(t->temp, "/usr/.pkgtemp.", 14) == 0);
+
	ATF_REQUIRE(t->fd != -1);
+
	close(t->fd);
+
	free(t);
+
	t = open_tempdir(rootfd, "/nousr/local/directory");
+
	ATF_REQUIRE(t != NULL);
+
	ATF_REQUIRE_STREQ(t->name, "/nousr");
+
	ATF_REQUIRE_EQ(t->len, strlen("/nousr"));
+
	ATF_REQUIRE(strncmp(t->temp, "/.pkgtemp.", 10) == 0);
+
	ATF_REQUIRE(t->fd != -1);
+
	close(t->fd);
+
	free(t);
+
	mkdirat(rootfd, "dir", 0755);
+
	/* a file in the path */
+
	close(open(rootfd, "dir/file1", O_CREAT|O_WRONLY, 0644));
+
	t = open_tempdir(rootfd, "/dir/file1/test");
+
	ATF_REQUIRE(t != NULL);
+
	ATF_REQUIRE_STREQ(t->name, "/dir/file1");
+
	ATF_REQUIRE_EQ(t->len, strlen("/dir/file1"));
+
	ATF_REQUIRE(strncmp(t->temp, "/dir/.pkgtemp.", 14) == 0);
+
	ATF_REQUIRE(t->fd != -1);
+
	close(t->fd);
+
	free(t);
+
}
+

ATF_TP_ADD_TCS(tp)
{
	ATF_TP_ADD_TC(tp, hidden_tempfile);
	ATF_TP_ADD_TC(tp, random_suffix);
	ATF_TP_ADD_TC(tp, json_escape);
+
	ATF_TP_ADD_TC(tp, open_tempdir);

	return (atf_no_error());
}