xref: /aosp_15_r20/external/trace-cmd/tracecmd/trace-setup-guest.c (revision 58e6ee5f017f6a8912852c892d18457e4bafb554)
1*58e6ee5fSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0
2*58e6ee5fSAndroid Build Coastguard Worker /*
3*58e6ee5fSAndroid Build Coastguard Worker  * Copyright (C) 2019 VMware Inc, Slavomir Kaslev <[email protected]>
4*58e6ee5fSAndroid Build Coastguard Worker  *
5*58e6ee5fSAndroid Build Coastguard Worker  */
6*58e6ee5fSAndroid Build Coastguard Worker 
7*58e6ee5fSAndroid Build Coastguard Worker #include <errno.h>
8*58e6ee5fSAndroid Build Coastguard Worker #include <fcntl.h>
9*58e6ee5fSAndroid Build Coastguard Worker #include <getopt.h>
10*58e6ee5fSAndroid Build Coastguard Worker #include <grp.h>
11*58e6ee5fSAndroid Build Coastguard Worker #include <stdio.h>
12*58e6ee5fSAndroid Build Coastguard Worker #include <stdlib.h>
13*58e6ee5fSAndroid Build Coastguard Worker #include <string.h>
14*58e6ee5fSAndroid Build Coastguard Worker #include <sys/stat.h>
15*58e6ee5fSAndroid Build Coastguard Worker #include <unistd.h>
16*58e6ee5fSAndroid Build Coastguard Worker 
17*58e6ee5fSAndroid Build Coastguard Worker #include "trace-local.h"
18*58e6ee5fSAndroid Build Coastguard Worker #include "trace-msg.h"
19*58e6ee5fSAndroid Build Coastguard Worker 
make_dir(const char * path,mode_t mode)20*58e6ee5fSAndroid Build Coastguard Worker static int make_dir(const char *path, mode_t mode)
21*58e6ee5fSAndroid Build Coastguard Worker {
22*58e6ee5fSAndroid Build Coastguard Worker 	char buf[PATH_MAX+2], *p;
23*58e6ee5fSAndroid Build Coastguard Worker 
24*58e6ee5fSAndroid Build Coastguard Worker 	strncpy(buf, path, sizeof(buf));
25*58e6ee5fSAndroid Build Coastguard Worker 	if (buf[PATH_MAX])
26*58e6ee5fSAndroid Build Coastguard Worker 		return -E2BIG;
27*58e6ee5fSAndroid Build Coastguard Worker 
28*58e6ee5fSAndroid Build Coastguard Worker 	for (p = buf; *p; p++) {
29*58e6ee5fSAndroid Build Coastguard Worker 		p += strspn(p, "/");
30*58e6ee5fSAndroid Build Coastguard Worker 		p += strcspn(p, "/");
31*58e6ee5fSAndroid Build Coastguard Worker 		*p = '\0';
32*58e6ee5fSAndroid Build Coastguard Worker 		if (mkdir(buf, mode) < 0 && errno != EEXIST)
33*58e6ee5fSAndroid Build Coastguard Worker 			return -errno;
34*58e6ee5fSAndroid Build Coastguard Worker 		*p = '/';
35*58e6ee5fSAndroid Build Coastguard Worker 	}
36*58e6ee5fSAndroid Build Coastguard Worker 
37*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
38*58e6ee5fSAndroid Build Coastguard Worker }
39*58e6ee5fSAndroid Build Coastguard Worker 
make_fifo(const char * path,mode_t mode)40*58e6ee5fSAndroid Build Coastguard Worker static int make_fifo(const char *path, mode_t mode)
41*58e6ee5fSAndroid Build Coastguard Worker {
42*58e6ee5fSAndroid Build Coastguard Worker 	struct stat st;
43*58e6ee5fSAndroid Build Coastguard Worker 
44*58e6ee5fSAndroid Build Coastguard Worker 	if (!stat(path, &st)) {
45*58e6ee5fSAndroid Build Coastguard Worker 		if (S_ISFIFO(st.st_mode))
46*58e6ee5fSAndroid Build Coastguard Worker 			return 0;
47*58e6ee5fSAndroid Build Coastguard Worker 		return -EEXIST;
48*58e6ee5fSAndroid Build Coastguard Worker 	}
49*58e6ee5fSAndroid Build Coastguard Worker 
50*58e6ee5fSAndroid Build Coastguard Worker 	if (mkfifo(path, mode))
51*58e6ee5fSAndroid Build Coastguard Worker 		return -errno;
52*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
53*58e6ee5fSAndroid Build Coastguard Worker }
54*58e6ee5fSAndroid Build Coastguard Worker 
make_guest_dir(const char * guest)55*58e6ee5fSAndroid Build Coastguard Worker static int make_guest_dir(const char *guest)
56*58e6ee5fSAndroid Build Coastguard Worker {
57*58e6ee5fSAndroid Build Coastguard Worker 	char path[PATH_MAX];
58*58e6ee5fSAndroid Build Coastguard Worker 
59*58e6ee5fSAndroid Build Coastguard Worker 	snprintf(path, sizeof(path), GUEST_DIR_FMT, guest);
60*58e6ee5fSAndroid Build Coastguard Worker 	return make_dir(path, 0750);
61*58e6ee5fSAndroid Build Coastguard Worker }
62*58e6ee5fSAndroid Build Coastguard Worker 
make_guest_fifo(const char * guest,int cpu,mode_t mode)63*58e6ee5fSAndroid Build Coastguard Worker static int make_guest_fifo(const char *guest, int cpu, mode_t mode)
64*58e6ee5fSAndroid Build Coastguard Worker {
65*58e6ee5fSAndroid Build Coastguard Worker 	static const char *exts[] = {".in", ".out"};
66*58e6ee5fSAndroid Build Coastguard Worker 	char path[PATH_MAX];
67*58e6ee5fSAndroid Build Coastguard Worker 	int i, ret = 0;
68*58e6ee5fSAndroid Build Coastguard Worker 
69*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(exts); i++) {
70*58e6ee5fSAndroid Build Coastguard Worker 		snprintf(path, sizeof(path), GUEST_FIFO_FMT "%s",
71*58e6ee5fSAndroid Build Coastguard Worker 			 guest, cpu, exts[i]);
72*58e6ee5fSAndroid Build Coastguard Worker 		ret = make_fifo(path, mode);
73*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
74*58e6ee5fSAndroid Build Coastguard Worker 			break;
75*58e6ee5fSAndroid Build Coastguard Worker 	}
76*58e6ee5fSAndroid Build Coastguard Worker 
77*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
78*58e6ee5fSAndroid Build Coastguard Worker }
79*58e6ee5fSAndroid Build Coastguard Worker 
make_guest_fifos(const char * guest,int nr_cpus,mode_t mode)80*58e6ee5fSAndroid Build Coastguard Worker static int make_guest_fifos(const char *guest, int nr_cpus, mode_t mode)
81*58e6ee5fSAndroid Build Coastguard Worker {
82*58e6ee5fSAndroid Build Coastguard Worker 	int i, ret = 0;
83*58e6ee5fSAndroid Build Coastguard Worker 	mode_t mask;
84*58e6ee5fSAndroid Build Coastguard Worker 
85*58e6ee5fSAndroid Build Coastguard Worker 	mask = umask(0);
86*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < nr_cpus; i++) {
87*58e6ee5fSAndroid Build Coastguard Worker 		ret = make_guest_fifo(guest, i, mode);
88*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
89*58e6ee5fSAndroid Build Coastguard Worker 			break;
90*58e6ee5fSAndroid Build Coastguard Worker 	}
91*58e6ee5fSAndroid Build Coastguard Worker 	umask(mask);
92*58e6ee5fSAndroid Build Coastguard Worker 
93*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
94*58e6ee5fSAndroid Build Coastguard Worker }
95*58e6ee5fSAndroid Build Coastguard Worker 
get_guest_cpu_count(const char * guest)96*58e6ee5fSAndroid Build Coastguard Worker static int get_guest_cpu_count(const char *guest)
97*58e6ee5fSAndroid Build Coastguard Worker {
98*58e6ee5fSAndroid Build Coastguard Worker 	const char *cmd_fmt = "virsh vcpucount --maximum '%s' 2>/dev/null";
99*58e6ee5fSAndroid Build Coastguard Worker 	int nr_cpus = -1;
100*58e6ee5fSAndroid Build Coastguard Worker 	char cmd[1024];
101*58e6ee5fSAndroid Build Coastguard Worker 	FILE *f;
102*58e6ee5fSAndroid Build Coastguard Worker 
103*58e6ee5fSAndroid Build Coastguard Worker 	snprintf(cmd, sizeof(cmd), cmd_fmt, guest);
104*58e6ee5fSAndroid Build Coastguard Worker 	f = popen(cmd, "r");
105*58e6ee5fSAndroid Build Coastguard Worker 	if (!f)
106*58e6ee5fSAndroid Build Coastguard Worker 		return -errno;
107*58e6ee5fSAndroid Build Coastguard Worker 
108*58e6ee5fSAndroid Build Coastguard Worker 	fscanf(f, "%d", &nr_cpus);
109*58e6ee5fSAndroid Build Coastguard Worker 	pclose(f);
110*58e6ee5fSAndroid Build Coastguard Worker 
111*58e6ee5fSAndroid Build Coastguard Worker 	return nr_cpus;
112*58e6ee5fSAndroid Build Coastguard Worker }
113*58e6ee5fSAndroid Build Coastguard Worker 
attach_guest_fifos(const char * guest,int nr_cpus)114*58e6ee5fSAndroid Build Coastguard Worker static int attach_guest_fifos(const char *guest, int nr_cpus)
115*58e6ee5fSAndroid Build Coastguard Worker {
116*58e6ee5fSAndroid Build Coastguard Worker 	const char *cmd_fmt =
117*58e6ee5fSAndroid Build Coastguard Worker 		"virsh attach-device --config '%s' '%s' >/dev/null 2>/dev/null";
118*58e6ee5fSAndroid Build Coastguard Worker 	const char *xml_fmt =
119*58e6ee5fSAndroid Build Coastguard Worker 		"<channel type='pipe'>\n"
120*58e6ee5fSAndroid Build Coastguard Worker 		"  <source path='%s'/>\n"
121*58e6ee5fSAndroid Build Coastguard Worker 		"  <target type='virtio' name='%s%d'/>\n"
122*58e6ee5fSAndroid Build Coastguard Worker 		"</channel>";
123*58e6ee5fSAndroid Build Coastguard Worker 	char tmp_path[PATH_MAX], path[PATH_MAX];
124*58e6ee5fSAndroid Build Coastguard Worker 	char cmd[PATH_MAX], xml[PATH_MAX];
125*58e6ee5fSAndroid Build Coastguard Worker 	int i, fd, ret = 0;
126*58e6ee5fSAndroid Build Coastguard Worker 
127*58e6ee5fSAndroid Build Coastguard Worker #ifdef __ANDROID__
128*58e6ee5fSAndroid Build Coastguard Worker 	strcpy(tmp_path, "/data/local/tmp/pipexmlXXXXXX");
129*58e6ee5fSAndroid Build Coastguard Worker #else	/* !__ANDROID__ */
130*58e6ee5fSAndroid Build Coastguard Worker 	strcpy(tmp_path, "/tmp/pipexmlXXXXXX");
131*58e6ee5fSAndroid Build Coastguard Worker #endif	/* __ANDROID__ */
132*58e6ee5fSAndroid Build Coastguard Worker 
133*58e6ee5fSAndroid Build Coastguard Worker 	fd = mkstemp(tmp_path);
134*58e6ee5fSAndroid Build Coastguard Worker 	if (fd < 0)
135*58e6ee5fSAndroid Build Coastguard Worker 		return fd;
136*58e6ee5fSAndroid Build Coastguard Worker 
137*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < nr_cpus; i++) {
138*58e6ee5fSAndroid Build Coastguard Worker 		snprintf(path, sizeof(path), GUEST_FIFO_FMT, guest, i);
139*58e6ee5fSAndroid Build Coastguard Worker 		snprintf(xml, sizeof(xml), xml_fmt, path, GUEST_PIPE_NAME, i);
140*58e6ee5fSAndroid Build Coastguard Worker 		pwrite(fd, xml, strlen(xml), 0);
141*58e6ee5fSAndroid Build Coastguard Worker 
142*58e6ee5fSAndroid Build Coastguard Worker 		snprintf(cmd, sizeof(cmd), cmd_fmt, guest, tmp_path);
143*58e6ee5fSAndroid Build Coastguard Worker 		errno = 0;
144*58e6ee5fSAndroid Build Coastguard Worker 		if (system(cmd) != 0) {
145*58e6ee5fSAndroid Build Coastguard Worker 			ret = -errno;
146*58e6ee5fSAndroid Build Coastguard Worker 			break;
147*58e6ee5fSAndroid Build Coastguard Worker 		}
148*58e6ee5fSAndroid Build Coastguard Worker 	}
149*58e6ee5fSAndroid Build Coastguard Worker 
150*58e6ee5fSAndroid Build Coastguard Worker 	close(fd);
151*58e6ee5fSAndroid Build Coastguard Worker 	unlink(tmp_path);
152*58e6ee5fSAndroid Build Coastguard Worker 
153*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
154*58e6ee5fSAndroid Build Coastguard Worker }
155*58e6ee5fSAndroid Build Coastguard Worker 
do_setup_guest(const char * guest,int nr_cpus,mode_t mode,gid_t gid,bool attach)156*58e6ee5fSAndroid Build Coastguard Worker static void do_setup_guest(const char *guest, int nr_cpus,
157*58e6ee5fSAndroid Build Coastguard Worker 			   mode_t mode, gid_t gid, bool attach)
158*58e6ee5fSAndroid Build Coastguard Worker {
159*58e6ee5fSAndroid Build Coastguard Worker 	gid_t save_egid;
160*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
161*58e6ee5fSAndroid Build Coastguard Worker 
162*58e6ee5fSAndroid Build Coastguard Worker 	if (gid != -1) {
163*58e6ee5fSAndroid Build Coastguard Worker 		save_egid = getegid();
164*58e6ee5fSAndroid Build Coastguard Worker 		ret = setegid(gid);
165*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
166*58e6ee5fSAndroid Build Coastguard Worker 			die("failed to set effective group ID");
167*58e6ee5fSAndroid Build Coastguard Worker 	}
168*58e6ee5fSAndroid Build Coastguard Worker 
169*58e6ee5fSAndroid Build Coastguard Worker 	ret = make_guest_dir(guest);
170*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
171*58e6ee5fSAndroid Build Coastguard Worker 		die("failed to create guest directory for %s", guest);
172*58e6ee5fSAndroid Build Coastguard Worker 
173*58e6ee5fSAndroid Build Coastguard Worker 	ret = make_guest_fifos(guest, nr_cpus, mode);
174*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
175*58e6ee5fSAndroid Build Coastguard Worker 		die("failed to create FIFOs for %s", guest);
176*58e6ee5fSAndroid Build Coastguard Worker 
177*58e6ee5fSAndroid Build Coastguard Worker 	if (attach) {
178*58e6ee5fSAndroid Build Coastguard Worker 		ret = attach_guest_fifos(guest, nr_cpus);
179*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
180*58e6ee5fSAndroid Build Coastguard Worker 			die("failed to attach FIFOs to %s", guest);
181*58e6ee5fSAndroid Build Coastguard Worker 	}
182*58e6ee5fSAndroid Build Coastguard Worker 
183*58e6ee5fSAndroid Build Coastguard Worker 	if (gid != -1) {
184*58e6ee5fSAndroid Build Coastguard Worker 		ret = setegid(save_egid);
185*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
186*58e6ee5fSAndroid Build Coastguard Worker 			die("failed to restore effective group ID");
187*58e6ee5fSAndroid Build Coastguard Worker 	}
188*58e6ee5fSAndroid Build Coastguard Worker }
189*58e6ee5fSAndroid Build Coastguard Worker 
trace_setup_guest(int argc,char ** argv)190*58e6ee5fSAndroid Build Coastguard Worker void trace_setup_guest(int argc, char **argv)
191*58e6ee5fSAndroid Build Coastguard Worker {
192*58e6ee5fSAndroid Build Coastguard Worker 	bool attach = false;
193*58e6ee5fSAndroid Build Coastguard Worker 	struct group *group;
194*58e6ee5fSAndroid Build Coastguard Worker 	mode_t mode = 0660;
195*58e6ee5fSAndroid Build Coastguard Worker 	int nr_cpus = -1;
196*58e6ee5fSAndroid Build Coastguard Worker 	gid_t gid = -1;
197*58e6ee5fSAndroid Build Coastguard Worker 	char *guest;
198*58e6ee5fSAndroid Build Coastguard Worker 
199*58e6ee5fSAndroid Build Coastguard Worker 	if (argc < 2)
200*58e6ee5fSAndroid Build Coastguard Worker 		usage(argv);
201*58e6ee5fSAndroid Build Coastguard Worker 
202*58e6ee5fSAndroid Build Coastguard Worker 	if (strcmp(argv[1], "setup-guest") != 0)
203*58e6ee5fSAndroid Build Coastguard Worker 		usage(argv);
204*58e6ee5fSAndroid Build Coastguard Worker 
205*58e6ee5fSAndroid Build Coastguard Worker 	for (;;) {
206*58e6ee5fSAndroid Build Coastguard Worker 		int c, option_index = 0;
207*58e6ee5fSAndroid Build Coastguard Worker 		static struct option long_options[] = {
208*58e6ee5fSAndroid Build Coastguard Worker 			{"help", no_argument, NULL, '?'},
209*58e6ee5fSAndroid Build Coastguard Worker 			{NULL, 0, NULL, 0}
210*58e6ee5fSAndroid Build Coastguard Worker 		};
211*58e6ee5fSAndroid Build Coastguard Worker 
212*58e6ee5fSAndroid Build Coastguard Worker 		c = getopt_long(argc-1, argv+1, "+hc:p:g:a",
213*58e6ee5fSAndroid Build Coastguard Worker 				long_options, &option_index);
214*58e6ee5fSAndroid Build Coastguard Worker 		if (c == -1)
215*58e6ee5fSAndroid Build Coastguard Worker 			break;
216*58e6ee5fSAndroid Build Coastguard Worker 		switch (c) {
217*58e6ee5fSAndroid Build Coastguard Worker 		case 'h':
218*58e6ee5fSAndroid Build Coastguard Worker 			usage(argv);
219*58e6ee5fSAndroid Build Coastguard Worker 			break;
220*58e6ee5fSAndroid Build Coastguard Worker 		case 'c':
221*58e6ee5fSAndroid Build Coastguard Worker 			nr_cpus = atoi(optarg);
222*58e6ee5fSAndroid Build Coastguard Worker 			break;
223*58e6ee5fSAndroid Build Coastguard Worker 		case 'p':
224*58e6ee5fSAndroid Build Coastguard Worker 			mode = strtol(optarg, NULL, 8);
225*58e6ee5fSAndroid Build Coastguard Worker 			break;
226*58e6ee5fSAndroid Build Coastguard Worker 		case 'g':
227*58e6ee5fSAndroid Build Coastguard Worker 			group = getgrnam(optarg);
228*58e6ee5fSAndroid Build Coastguard Worker 			if (!group)
229*58e6ee5fSAndroid Build Coastguard Worker 				die("group %s does not exist", optarg);
230*58e6ee5fSAndroid Build Coastguard Worker 			gid = group->gr_gid;
231*58e6ee5fSAndroid Build Coastguard Worker 			break;
232*58e6ee5fSAndroid Build Coastguard Worker 		case 'a':
233*58e6ee5fSAndroid Build Coastguard Worker 			attach = true;
234*58e6ee5fSAndroid Build Coastguard Worker 			break;
235*58e6ee5fSAndroid Build Coastguard Worker 		default:
236*58e6ee5fSAndroid Build Coastguard Worker 			usage(argv);
237*58e6ee5fSAndroid Build Coastguard Worker 		}
238*58e6ee5fSAndroid Build Coastguard Worker 	}
239*58e6ee5fSAndroid Build Coastguard Worker 
240*58e6ee5fSAndroid Build Coastguard Worker 	if (optind != argc-2)
241*58e6ee5fSAndroid Build Coastguard Worker 		usage(argv);
242*58e6ee5fSAndroid Build Coastguard Worker 
243*58e6ee5fSAndroid Build Coastguard Worker 	guest = argv[optind+1];
244*58e6ee5fSAndroid Build Coastguard Worker 
245*58e6ee5fSAndroid Build Coastguard Worker 	if (nr_cpus <= 0)
246*58e6ee5fSAndroid Build Coastguard Worker 		nr_cpus = get_guest_cpu_count(guest);
247*58e6ee5fSAndroid Build Coastguard Worker 
248*58e6ee5fSAndroid Build Coastguard Worker 	if (nr_cpus <= 0)
249*58e6ee5fSAndroid Build Coastguard Worker 		die("invalid number of cpus for guest %s", guest);
250*58e6ee5fSAndroid Build Coastguard Worker 
251*58e6ee5fSAndroid Build Coastguard Worker 	do_setup_guest(guest, nr_cpus, mode, gid, attach);
252*58e6ee5fSAndroid Build Coastguard Worker }
253