xref: /openbmc/linux/arch/um/os-Linux/umid.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
197870c34SAlex Dewar // SPDX-License-Identifier: GPL-2.0
2ba180fd4SJeff Dike /*
3ba180fd4SJeff Dike  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
4ba180fd4SJeff Dike  */
5ba180fd4SJeff Dike 
62264c475SJeff Dike #include <stdio.h>
72264c475SJeff Dike #include <stdlib.h>
82264c475SJeff Dike #include <dirent.h>
9ba180fd4SJeff Dike #include <errno.h>
10ba180fd4SJeff Dike #include <fcntl.h>
11ba180fd4SJeff Dike #include <signal.h>
12ba180fd4SJeff Dike #include <string.h>
13ba180fd4SJeff Dike #include <unistd.h>
142264c475SJeff Dike #include <sys/stat.h>
1537185b33SAl Viro #include <init.h>
1637185b33SAl Viro #include <os.h>
172264c475SJeff Dike 
182264c475SJeff Dike #define UML_DIR "~/.uml/"
192264c475SJeff Dike 
202264c475SJeff Dike #define UMID_LEN 64
212264c475SJeff Dike 
222264c475SJeff Dike /* Changed by set_umid, which is run early in boot */
23de5fe76eSJeff Dike static char umid[UMID_LEN] = { 0 };
242264c475SJeff Dike 
252264c475SJeff Dike /* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
262264c475SJeff Dike static char *uml_dir = UML_DIR;
272264c475SJeff Dike 
make_uml_dir(void)282264c475SJeff Dike static int __init make_uml_dir(void)
292264c475SJeff Dike {
302264c475SJeff Dike 	char dir[512] = { '\0' };
317eebe8a9SJeff Dike 	int len, err;
322264c475SJeff Dike 
332264c475SJeff Dike 	if (*uml_dir == '~') {
342264c475SJeff Dike 		char *home = getenv("HOME");
352264c475SJeff Dike 
367eebe8a9SJeff Dike 		err = -ENOENT;
372264c475SJeff Dike 		if (home == NULL) {
38e03c78acSMasami Hiramatsu 			printk(UM_KERN_ERR
39e03c78acSMasami Hiramatsu 				"%s: no value in environment for $HOME\n",
40e03c78acSMasami Hiramatsu 				__func__);
417eebe8a9SJeff Dike 			goto err;
422264c475SJeff Dike 		}
43*61ce78f2SAzeem Shaikh 		strscpy(dir, home, sizeof(dir));
442264c475SJeff Dike 		uml_dir++;
452264c475SJeff Dike 	}
462264c475SJeff Dike 	strlcat(dir, uml_dir, sizeof(dir));
472264c475SJeff Dike 	len = strlen(dir);
482264c475SJeff Dike 	if (len > 0 && dir[len - 1] != '/')
492264c475SJeff Dike 		strlcat(dir, "/", sizeof(dir));
502264c475SJeff Dike 
517eebe8a9SJeff Dike 	err = -ENOMEM;
522264c475SJeff Dike 	uml_dir = malloc(strlen(dir) + 1);
532264c475SJeff Dike 	if (uml_dir == NULL) {
54e03c78acSMasami Hiramatsu 		printk(UM_KERN_ERR "%s : malloc failed, errno = %d\n",
55e03c78acSMasami Hiramatsu 			__func__, errno);
567eebe8a9SJeff Dike 		goto err;
572264c475SJeff Dike 	}
582264c475SJeff Dike 	strcpy(uml_dir, dir);
592264c475SJeff Dike 
602264c475SJeff Dike 	if ((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)) {
61e03c78acSMasami Hiramatsu 		printk(UM_KERN_ERR "Failed to mkdir '%s': %s\n",
62e03c78acSMasami Hiramatsu 			uml_dir, strerror(errno));
637eebe8a9SJeff Dike 		err = -errno;
647eebe8a9SJeff Dike 		goto err_free;
652264c475SJeff Dike 	}
662264c475SJeff Dike 	return 0;
677eebe8a9SJeff Dike 
687eebe8a9SJeff Dike err_free:
697eebe8a9SJeff Dike 	free(uml_dir);
707eebe8a9SJeff Dike err:
717eebe8a9SJeff Dike 	uml_dir = NULL;
727eebe8a9SJeff Dike 	return err;
732264c475SJeff Dike }
742264c475SJeff Dike 
75eb28931eSPaolo 'Blaisorblade' Giarrusso /*
76eb28931eSPaolo 'Blaisorblade' Giarrusso  * Unlinks the files contained in @dir and then removes @dir.
77eb28931eSPaolo 'Blaisorblade' Giarrusso  * Doesn't handle directory trees, so it's not like rm -rf, but almost such. We
78ba180fd4SJeff Dike  * ignore ENOENT errors for anything (they happen, strangely enough - possibly
79ba180fd4SJeff Dike  * due to races between multiple dying UML threads).
80eb28931eSPaolo 'Blaisorblade' Giarrusso  */
remove_files_and_dir(char * dir)81eb28931eSPaolo 'Blaisorblade' Giarrusso static int remove_files_and_dir(char *dir)
822264c475SJeff Dike {
832264c475SJeff Dike 	DIR *directory;
842264c475SJeff Dike 	struct dirent *ent;
852264c475SJeff Dike 	int len;
862264c475SJeff Dike 	char file[256];
87eb28931eSPaolo 'Blaisorblade' Giarrusso 	int ret;
882264c475SJeff Dike 
892264c475SJeff Dike 	directory = opendir(dir);
90eb28931eSPaolo 'Blaisorblade' Giarrusso 	if (directory == NULL) {
91eb28931eSPaolo 'Blaisorblade' Giarrusso 		if (errno != ENOENT)
927eebe8a9SJeff Dike 			return -errno;
93eb28931eSPaolo 'Blaisorblade' Giarrusso 		else
94eb28931eSPaolo 'Blaisorblade' Giarrusso 			return 0;
95eb28931eSPaolo 'Blaisorblade' Giarrusso 	}
967eebe8a9SJeff Dike 
972264c475SJeff Dike 	while ((ent = readdir(directory)) != NULL) {
982264c475SJeff Dike 		if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
992264c475SJeff Dike 			continue;
100e8a58591SMaciej Żenczykowski 		len = strlen(dir) + strlen("/") + strlen(ent->d_name) + 1;
101eb28931eSPaolo 'Blaisorblade' Giarrusso 		if (len > sizeof(file)) {
102eb28931eSPaolo 'Blaisorblade' Giarrusso 			ret = -E2BIG;
103eb28931eSPaolo 'Blaisorblade' Giarrusso 			goto out;
104eb28931eSPaolo 'Blaisorblade' Giarrusso 		}
1057eebe8a9SJeff Dike 
1062264c475SJeff Dike 		sprintf(file, "%s/%s", dir, ent->d_name);
107eb28931eSPaolo 'Blaisorblade' Giarrusso 		if (unlink(file) < 0 && errno != ENOENT) {
108eb28931eSPaolo 'Blaisorblade' Giarrusso 			ret = -errno;
109eb28931eSPaolo 'Blaisorblade' Giarrusso 			goto out;
1102264c475SJeff Dike 		}
111eb28931eSPaolo 'Blaisorblade' Giarrusso 	}
1127eebe8a9SJeff Dike 
113eb28931eSPaolo 'Blaisorblade' Giarrusso 	if (rmdir(dir) < 0 && errno != ENOENT) {
114eb28931eSPaolo 'Blaisorblade' Giarrusso 		ret = -errno;
115eb28931eSPaolo 'Blaisorblade' Giarrusso 		goto out;
116eb28931eSPaolo 'Blaisorblade' Giarrusso 	}
117eb28931eSPaolo 'Blaisorblade' Giarrusso 
118eb28931eSPaolo 'Blaisorblade' Giarrusso 	ret = 0;
119eb28931eSPaolo 'Blaisorblade' Giarrusso out:
120eb28931eSPaolo 'Blaisorblade' Giarrusso 	closedir(directory);
121eb28931eSPaolo 'Blaisorblade' Giarrusso 	return ret;
1222264c475SJeff Dike }
1232264c475SJeff Dike 
124ba180fd4SJeff Dike /*
125ba180fd4SJeff Dike  * This says that there isn't already a user of the specified directory even if
1267eebe8a9SJeff Dike  * there are errors during the checking.  This is because if these errors
1277eebe8a9SJeff Dike  * happen, the directory is unusable by the pre-existing UML, so we might as
1287eebe8a9SJeff Dike  * well take it over.  This could happen either by
1297eebe8a9SJeff Dike  * 	the existing UML somehow corrupting its umid directory
1307eebe8a9SJeff Dike  * 	something other than UML sticking stuff in the directory
1317eebe8a9SJeff Dike  *	this boot racing with a shutdown of the other UML
1327eebe8a9SJeff Dike  * In any of these cases, the directory isn't useful for anything else.
133912ad922SPaolo 'Blaisorblade' Giarrusso  *
134912ad922SPaolo 'Blaisorblade' Giarrusso  * Boolean return: 1 if in use, 0 otherwise.
1357eebe8a9SJeff Dike  */
is_umdir_used(char * dir)136912ad922SPaolo 'Blaisorblade' Giarrusso static inline int is_umdir_used(char *dir)
1372264c475SJeff Dike {
138e8a58591SMaciej Żenczykowski 	char pid[sizeof("nnnnnnnnn")], *end, *file;
1396e12adccSHaowen Bai 	int fd, p, n, err;
14097be7ceaSAnton Ivanov 	size_t filelen = strlen(dir) + sizeof("/pid") + 1;
1412264c475SJeff Dike 
14297be7ceaSAnton Ivanov 	file = malloc(filelen);
14397be7ceaSAnton Ivanov 	if (!file)
14497be7ceaSAnton Ivanov 		return -ENOMEM;
1450d4e5ac7SBartosz Golaszewski 
14697be7ceaSAnton Ivanov 	snprintf(file, filelen, "%s/pid", dir);
1477eebe8a9SJeff Dike 
1487eebe8a9SJeff Dike 	fd = open(file, O_RDONLY);
1492264c475SJeff Dike 	if (fd < 0) {
150d84a19ceSPaolo 'Blaisorblade' Giarrusso 		fd = -errno;
1512264c475SJeff Dike 		if (fd != -ENOENT) {
152ba180fd4SJeff Dike 			printk(UM_KERN_ERR "is_umdir_used : couldn't open pid "
153ba180fd4SJeff Dike 			       "file '%s', err = %d\n", file, -fd);
1542264c475SJeff Dike 		}
1557eebe8a9SJeff Dike 		goto out;
1562264c475SJeff Dike 	}
1577eebe8a9SJeff Dike 
1587eebe8a9SJeff Dike 	err = 0;
1597eebe8a9SJeff Dike 	n = read(fd, pid, sizeof(pid));
160d84a19ceSPaolo 'Blaisorblade' Giarrusso 	if (n < 0) {
161ba180fd4SJeff Dike 		printk(UM_KERN_ERR "is_umdir_used : couldn't read pid file "
162ba180fd4SJeff Dike 		       "'%s', err = %d\n", file, errno);
163d84a19ceSPaolo 'Blaisorblade' Giarrusso 		goto out_close;
164d84a19ceSPaolo 'Blaisorblade' Giarrusso 	} else if (n == 0) {
165ba180fd4SJeff Dike 		printk(UM_KERN_ERR "is_umdir_used : couldn't read pid file "
166ba180fd4SJeff Dike 		       "'%s', 0-byte read\n", file);
1677eebe8a9SJeff Dike 		goto out_close;
1682264c475SJeff Dike 	}
1697eebe8a9SJeff Dike 
1702264c475SJeff Dike 	p = strtoul(pid, &end, 0);
1712264c475SJeff Dike 	if (end == pid) {
172ba180fd4SJeff Dike 		printk(UM_KERN_ERR "is_umdir_used : couldn't parse pid file "
173ba180fd4SJeff Dike 		       "'%s', errno = %d\n", file, errno);
1747eebe8a9SJeff Dike 		goto out_close;
1752264c475SJeff Dike 	}
1767eebe8a9SJeff Dike 
1771fbbd684SJeff Dike 	if ((kill(p, 0) == 0) || (errno != ESRCH)) {
178ba180fd4SJeff Dike 		printk(UM_KERN_ERR "umid \"%s\" is already in use by pid %d\n",
179ba180fd4SJeff Dike 		       umid, p);
1807eebe8a9SJeff Dike 		return 1;
1811fbbd684SJeff Dike 	}
1827eebe8a9SJeff Dike 
1837eebe8a9SJeff Dike out_close:
1847eebe8a9SJeff Dike 	close(fd);
1857eebe8a9SJeff Dike out:
1860d4e5ac7SBartosz Golaszewski 	free(file);
1877eebe8a9SJeff Dike 	return 0;
1882264c475SJeff Dike }
1892264c475SJeff Dike 
190912ad922SPaolo 'Blaisorblade' Giarrusso /*
191912ad922SPaolo 'Blaisorblade' Giarrusso  * Try to remove the directory @dir unless it's in use.
192912ad922SPaolo 'Blaisorblade' Giarrusso  * Precondition: @dir exists.
193912ad922SPaolo 'Blaisorblade' Giarrusso  * Returns 0 for success, < 0 for failure in removal or if the directory is in
194912ad922SPaolo 'Blaisorblade' Giarrusso  * use.
195912ad922SPaolo 'Blaisorblade' Giarrusso  */
umdir_take_if_dead(char * dir)196912ad922SPaolo 'Blaisorblade' Giarrusso static int umdir_take_if_dead(char *dir)
197912ad922SPaolo 'Blaisorblade' Giarrusso {
198912ad922SPaolo 'Blaisorblade' Giarrusso 	int ret;
199912ad922SPaolo 'Blaisorblade' Giarrusso 	if (is_umdir_used(dir))
200912ad922SPaolo 'Blaisorblade' Giarrusso 		return -EEXIST;
201912ad922SPaolo 'Blaisorblade' Giarrusso 
202eb28931eSPaolo 'Blaisorblade' Giarrusso 	ret = remove_files_and_dir(dir);
203912ad922SPaolo 'Blaisorblade' Giarrusso 	if (ret) {
204ba180fd4SJeff Dike 		printk(UM_KERN_ERR "is_umdir_used - remove_files_and_dir "
205ba180fd4SJeff Dike 		       "failed with err = %d\n", ret);
206912ad922SPaolo 'Blaisorblade' Giarrusso 	}
207912ad922SPaolo 'Blaisorblade' Giarrusso 	return ret;
208912ad922SPaolo 'Blaisorblade' Giarrusso }
209912ad922SPaolo 'Blaisorblade' Giarrusso 
create_pid_file(void)2102264c475SJeff Dike static void __init create_pid_file(void)
2112264c475SJeff Dike {
212e8a58591SMaciej Żenczykowski 	char pid[sizeof("nnnnnnnnn")], *file;
2132264c475SJeff Dike 	int fd, n;
2142264c475SJeff Dike 
215e8a58591SMaciej Żenczykowski 	n = strlen(uml_dir) + UMID_LEN + sizeof("/pid");
216ba758cfcSWen Yang 	file = malloc(n);
2170d4e5ac7SBartosz Golaszewski 	if (!file)
2182264c475SJeff Dike 		return;
2192264c475SJeff Dike 
220ba758cfcSWen Yang 	if (umid_file_name("pid", file, n))
2210d4e5ac7SBartosz Golaszewski 		goto out;
2220d4e5ac7SBartosz Golaszewski 
2237eebe8a9SJeff Dike 	fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644);
2242264c475SJeff Dike 	if (fd < 0) {
225ba180fd4SJeff Dike 		printk(UM_KERN_ERR "Open of machine pid file \"%s\" failed: "
226ba180fd4SJeff Dike 		       "%s\n", file, strerror(errno));
2270d4e5ac7SBartosz Golaszewski 		goto out;
2282264c475SJeff Dike 	}
2292264c475SJeff Dike 
2307eebe8a9SJeff Dike 	snprintf(pid, sizeof(pid), "%d\n", getpid());
2317eebe8a9SJeff Dike 	n = write(fd, pid, strlen(pid));
2322264c475SJeff Dike 	if (n != strlen(pid))
233ba180fd4SJeff Dike 		printk(UM_KERN_ERR "Write of pid file failed - err = %d\n",
234ba180fd4SJeff Dike 		       errno);
2357eebe8a9SJeff Dike 
2367eebe8a9SJeff Dike 	close(fd);
2370d4e5ac7SBartosz Golaszewski out:
2380d4e5ac7SBartosz Golaszewski 	free(file);
2392264c475SJeff Dike }
2402264c475SJeff Dike 
set_umid(char * name)2417eebe8a9SJeff Dike int __init set_umid(char *name)
2422264c475SJeff Dike {
2432264c475SJeff Dike 	if (strlen(name) > UMID_LEN - 1)
2447eebe8a9SJeff Dike 		return -E2BIG;
2457eebe8a9SJeff Dike 
246*61ce78f2SAzeem Shaikh 	strscpy(umid, name, sizeof(umid));
2472264c475SJeff Dike 
2482264c475SJeff Dike 	return 0;
2492264c475SJeff Dike }
2502264c475SJeff Dike 
251de5fe76eSJeff Dike /* Changed in make_umid, which is called during early boot */
2522264c475SJeff Dike static int umid_setup = 0;
2532264c475SJeff Dike 
make_umid(void)25499764fa4SWANG Cong static int __init make_umid(void)
2552264c475SJeff Dike {
2562264c475SJeff Dike 	int fd, err;
2572264c475SJeff Dike 	char tmp[256];
2582264c475SJeff Dike 
2597eebe8a9SJeff Dike 	if (umid_setup)
2607eebe8a9SJeff Dike 		return 0;
2617eebe8a9SJeff Dike 
2622264c475SJeff Dike 	make_uml_dir();
2632264c475SJeff Dike 
2642264c475SJeff Dike 	if (*umid == '\0') {
265*61ce78f2SAzeem Shaikh 		strscpy(tmp, uml_dir, sizeof(tmp));
2667eebe8a9SJeff Dike 		strlcat(tmp, "XXXXXX", sizeof(tmp));
2672264c475SJeff Dike 		fd = mkstemp(tmp);
2682264c475SJeff Dike 		if (fd < 0) {
269ba180fd4SJeff Dike 			printk(UM_KERN_ERR "make_umid - mkstemp(%s) failed: "
270ba180fd4SJeff Dike 			       "%s\n", tmp, strerror(errno));
2717eebe8a9SJeff Dike 			err = -errno;
2727eebe8a9SJeff Dike 			goto err;
2732264c475SJeff Dike 		}
2742264c475SJeff Dike 
2757eebe8a9SJeff Dike 		close(fd);
2767eebe8a9SJeff Dike 
2777eebe8a9SJeff Dike 		set_umid(&tmp[strlen(uml_dir)]);
2787eebe8a9SJeff Dike 
279ba180fd4SJeff Dike 		/*
280ba180fd4SJeff Dike 		 * There's a nice tiny little race between this unlink and
2812264c475SJeff Dike 		 * the mkdir below.  It'd be nice if there were a mkstemp
2822264c475SJeff Dike 		 * for directories.
2832264c475SJeff Dike 		 */
2847eebe8a9SJeff Dike 		if (unlink(tmp)) {
2857eebe8a9SJeff Dike 			err = -errno;
2867eebe8a9SJeff Dike 			goto err;
2877eebe8a9SJeff Dike 		}
2882264c475SJeff Dike 	}
2892264c475SJeff Dike 
2907eebe8a9SJeff Dike 	snprintf(tmp, sizeof(tmp), "%s%s", uml_dir, umid);
2912264c475SJeff Dike 	err = mkdir(tmp, 0777);
2922264c475SJeff Dike 	if (err < 0) {
2937eebe8a9SJeff Dike 		err = -errno;
2941fbbd684SJeff Dike 		if (err != -EEXIST)
2957eebe8a9SJeff Dike 			goto err;
2967eebe8a9SJeff Dike 
297912ad922SPaolo 'Blaisorblade' Giarrusso 		if (umdir_take_if_dead(tmp) < 0)
2987eebe8a9SJeff Dike 			goto err;
2997eebe8a9SJeff Dike 
3002264c475SJeff Dike 		err = mkdir(tmp, 0777);
3012264c475SJeff Dike 	}
3021fbbd684SJeff Dike 	if (err) {
3031fbbd684SJeff Dike 		err = -errno;
304ba180fd4SJeff Dike 		printk(UM_KERN_ERR "Failed to create '%s' - err = %d\n", umid,
305ba180fd4SJeff Dike 		       errno);
3061fbbd684SJeff Dike 		goto err;
3072264c475SJeff Dike 	}
3082264c475SJeff Dike 
3092264c475SJeff Dike 	umid_setup = 1;
3102264c475SJeff Dike 
3112264c475SJeff Dike 	create_pid_file();
3122264c475SJeff Dike 
3131fbbd684SJeff Dike 	err = 0;
3147eebe8a9SJeff Dike  err:
3157eebe8a9SJeff Dike 	return err;
3162264c475SJeff Dike }
3172264c475SJeff Dike 
make_umid_init(void)3182264c475SJeff Dike static int __init make_umid_init(void)
3192264c475SJeff Dike {
3201fbbd684SJeff Dike 	if (!make_umid())
3211fbbd684SJeff Dike 		return 0;
3221fbbd684SJeff Dike 
323ba180fd4SJeff Dike 	/*
324ba180fd4SJeff Dike 	 * If initializing with the given umid failed, then try again with
3251fbbd684SJeff Dike 	 * a random one.
3261fbbd684SJeff Dike 	 */
327ba180fd4SJeff Dike 	printk(UM_KERN_ERR "Failed to initialize umid \"%s\", trying with a "
328ba180fd4SJeff Dike 	       "random umid\n", umid);
3291fbbd684SJeff Dike 	*umid = '\0';
3307eebe8a9SJeff Dike 	make_umid();
3312264c475SJeff Dike 
3327eebe8a9SJeff Dike 	return 0;
3332264c475SJeff Dike }
3342264c475SJeff Dike 
3352264c475SJeff Dike __initcall(make_umid_init);
3362264c475SJeff Dike 
umid_file_name(char * name,char * buf,int len)3372264c475SJeff Dike int __init umid_file_name(char *name, char *buf, int len)
3382264c475SJeff Dike {
3392264c475SJeff Dike 	int n, err;
3402264c475SJeff Dike 
3417eebe8a9SJeff Dike 	err = make_umid();
3422264c475SJeff Dike 	if (err)
3432264c475SJeff Dike 		return err;
3442264c475SJeff Dike 
3457eebe8a9SJeff Dike 	n = snprintf(buf, len, "%s%s/%s", uml_dir, umid, name);
3467eebe8a9SJeff Dike 	if (n >= len) {
347ba180fd4SJeff Dike 		printk(UM_KERN_ERR "umid_file_name : buffer too short\n");
3487eebe8a9SJeff Dike 		return -E2BIG;
3492264c475SJeff Dike 	}
3502264c475SJeff Dike 
3517eebe8a9SJeff Dike 	return 0;
3522264c475SJeff Dike }
3532264c475SJeff Dike 
get_umid(void)3547eebe8a9SJeff Dike char *get_umid(void)
3552264c475SJeff Dike {
3562264c475SJeff Dike 	return umid;
3572264c475SJeff Dike }
3582264c475SJeff Dike 
set_uml_dir(char * name,int * add)3592264c475SJeff Dike static int __init set_uml_dir(char *name, int *add)
3602264c475SJeff Dike {
3617eebe8a9SJeff Dike 	if (*name == '\0') {
3620936d4f3SMasami Hiramatsu 		os_warn("uml_dir can't be an empty string\n");
3637eebe8a9SJeff Dike 		return 0;
3647eebe8a9SJeff Dike 	}
3657eebe8a9SJeff Dike 
3667eebe8a9SJeff Dike 	if (name[strlen(name) - 1] == '/') {
3677eebe8a9SJeff Dike 		uml_dir = name;
3687eebe8a9SJeff Dike 		return 0;
3697eebe8a9SJeff Dike 	}
3707eebe8a9SJeff Dike 
3712264c475SJeff Dike 	uml_dir = malloc(strlen(name) + 2);
3722264c475SJeff Dike 	if (uml_dir == NULL) {
3730936d4f3SMasami Hiramatsu 		os_warn("Failed to malloc uml_dir - error = %d\n", errno);
3747eebe8a9SJeff Dike 
375ba180fd4SJeff Dike 		/*
376ba180fd4SJeff Dike 		 * Return 0 here because do_initcalls doesn't look at
3772264c475SJeff Dike 		 * the return value.
3782264c475SJeff Dike 		 */
3797eebe8a9SJeff Dike 		return 0;
3802264c475SJeff Dike 	}
3812264c475SJeff Dike 	sprintf(uml_dir, "%s/", name);
3827eebe8a9SJeff Dike 
3837eebe8a9SJeff Dike 	return 0;
3842264c475SJeff Dike }
3852264c475SJeff Dike 
3862264c475SJeff Dike __uml_setup("uml_dir=", set_uml_dir,
3872264c475SJeff Dike "uml_dir=<directory>\n"
3882264c475SJeff Dike "    The location to place the pid and umid files.\n\n"
3892264c475SJeff Dike );
3902264c475SJeff Dike 
remove_umid_dir(void)3912264c475SJeff Dike static void remove_umid_dir(void)
3922264c475SJeff Dike {
3930d4e5ac7SBartosz Golaszewski 	char *dir, err;
3940d4e5ac7SBartosz Golaszewski 
3950d4e5ac7SBartosz Golaszewski 	dir = malloc(strlen(uml_dir) + UMID_LEN + 1);
3960d4e5ac7SBartosz Golaszewski 	if (!dir)
3970d4e5ac7SBartosz Golaszewski 		return;
3982264c475SJeff Dike 
3992264c475SJeff Dike 	sprintf(dir, "%s%s", uml_dir, umid);
400eb28931eSPaolo 'Blaisorblade' Giarrusso 	err = remove_files_and_dir(dir);
4017eebe8a9SJeff Dike 	if (err)
4020936d4f3SMasami Hiramatsu 		os_warn("%s - remove_files_and_dir failed with err = %d\n",
4030936d4f3SMasami Hiramatsu 			__func__, err);
4040d4e5ac7SBartosz Golaszewski 
4050d4e5ac7SBartosz Golaszewski 	free(dir);
4062264c475SJeff Dike }
4072264c475SJeff Dike 
4082264c475SJeff Dike __uml_exitcall(remove_umid_dir);
409