patches and low-level development discussion
 help / color / mirror / code / Atom feed
blob ab33c91eb3c23a4efd31d415c8f892a71722a739 1906 bytes (raw)
name: tools/resolve_in_root/resolve_in_root.c 	 # note: path name is non-authoritative(*)

 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
 
// SPDX-License-Identifier: EUPL-1.2+
// SPDX-FileCopyrightText: 2022 Alyssa Ross <hi@alyssa.is>

#include <assert.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <sys/syscall.h>

#include <linux/openat2.h>

#define STRINGIZE(x) STRINGIZE2(x)
#define STRINGIZE2(x) #x

[[gnu::malloc]] [[gnu::nonnull]] char *areadlink(const char *pathname)
{
	char *target = NULL;
	size_t link_size, target_size = 4096;

	for (;;) {
		free(target);
		if (!(target = malloc(target_size)))
			return NULL;
		if ((link_size = readlink(pathname, target, target_size)) == -1)
			return NULL;
		if (link_size < target_size)
			break;
		if (target_size > (((size_t)-1) >> 1)) {
			errno = ENOMEM;
			return NULL;
		}
		target_size <<= 1;
	}
	target[link_size] = '\0';

	return target;
}

int main(int argc, char **argv)
{
	// -1 because both paths include a null terminator.
	char fdpath[sizeof "/proc/self/fd/" + sizeof(STRINGIZE(INT_MAX)) - 1];

	char *target;
	int rootfd, targetfd;
	struct open_how how = { .flags = O_PATH };

	// Ensure INT_MAX is actually defined, because otherwise
	// sizeof("INT_MAX") will silently be used instead in fdpath's
	// size.
	(void) INT_MAX;

	if (argc != 3) {
		fprintf(stderr, "Usage: %s root dir\n", argc ? argv[0] : "resolve_in_root");
		return 1;
	}

	if ((rootfd = syscall(SYS_openat2, AT_FDCWD, argv[1], &how, sizeof how)) == -1)
		err(EXIT_FAILURE, "opening %s", argv[1]);

	how.resolve = RESOLVE_IN_ROOT | RESOLVE_NO_MAGICLINKS | RESOLVE_NO_XDEV;
	if ((targetfd = syscall(SYS_openat2, rootfd, argv[2], &how, sizeof how)) == -1)
		err(EXIT_FAILURE, "opening %s with %s:/", argv[2], argv[1]);

	assert(snprintf(fdpath, sizeof fdpath, "/proc/self/fd/%d", targetfd) < sizeof fdpath);

	target = areadlink(fdpath);
	if (!target)
		err(EXIT_FAILURE, "reading %s", fdpath);
	puts(target);
}

debug log:

solving ab33c91 ...
found ab33c91 in https://inbox.spectrum-os.org/spectrum-devel/20221010232909.1953738-17-hi@alyssa.is/

applying [1/1] https://inbox.spectrum-os.org/spectrum-devel/20221010232909.1953738-17-hi@alyssa.is/
diff --git a/tools/resolve_in_root/resolve_in_root.c b/tools/resolve_in_root/resolve_in_root.c
new file mode 100644
index 0000000..ab33c91

Checking patch tools/resolve_in_root/resolve_in_root.c...
Applied patch tools/resolve_in_root/resolve_in_root.c cleanly.

index at:
100644 ab33c91eb3c23a4efd31d415c8f892a71722a739	tools/resolve_in_root/resolve_in_root.c

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this public inbox

	https://spectrum-os.org/git/crosvm
	https://spectrum-os.org/git/doc
	https://spectrum-os.org/git/mktuntap
	https://spectrum-os.org/git/nixpkgs
	https://spectrum-os.org/git/spectrum
	https://spectrum-os.org/git/ucspi-vsock
	https://spectrum-os.org/git/www

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).