diff options
-rw-r--r-- | arch/um/include/kern.h | 13 | ||||
-rw-r--r-- | arch/um/include/os.h | 17 | ||||
-rw-r--r-- | arch/um/kernel/Makefile | 6 | ||||
-rw-r--r-- | arch/um/kernel/process_kern.c | 4 | ||||
-rw-r--r-- | arch/um/kernel/umid.c | 327 | ||||
-rw-r--r-- | arch/um/os-Linux/Makefile | 4 | ||||
-rw-r--r-- | arch/um/os-Linux/umid.c | 292 |
7 files changed, 324 insertions, 339 deletions
diff --git a/arch/um/include/kern.h b/arch/um/include/kern.h index 1e3170768b5c..7d223beccbc0 100644 --- a/arch/um/include/kern.h +++ b/arch/um/include/kern.h | |||
@@ -17,7 +17,7 @@ extern int errno; | |||
17 | 17 | ||
18 | extern int clone(int (*proc)(void *), void *sp, int flags, void *data); | 18 | extern int clone(int (*proc)(void *), void *sp, int flags, void *data); |
19 | extern int sleep(int); | 19 | extern int sleep(int); |
20 | extern int printf(char *fmt, ...); | 20 | extern int printf(const char *fmt, ...); |
21 | extern char *strerror(int errnum); | 21 | extern char *strerror(int errnum); |
22 | extern char *ptsname(int __fd); | 22 | extern char *ptsname(int __fd); |
23 | extern int munmap(void *, int); | 23 | extern int munmap(void *, int); |
@@ -35,15 +35,6 @@ extern int read(unsigned int, char *, int); | |||
35 | extern int pipe(int *); | 35 | extern int pipe(int *); |
36 | extern int sched_yield(void); | 36 | extern int sched_yield(void); |
37 | extern int ptrace(int op, int pid, long addr, long data); | 37 | extern int ptrace(int op, int pid, long addr, long data); |
38 | |||
38 | #endif | 39 | #endif |
39 | 40 | ||
40 | /* | ||
41 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
42 | * Emacs will notice this stuff at the end of the file and automatically | ||
43 | * adjust the settings for this buffer only. This must remain at the end | ||
44 | * of the file. | ||
45 | * --------------------------------------------------------------------------- | ||
46 | * Local variables: | ||
47 | * c-file-style: "linux" | ||
48 | * End: | ||
49 | */ | ||
diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 2cccfa5b8ab5..258444e5b9bc 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h | |||
@@ -213,15 +213,10 @@ extern int run_helper_thread(int (*proc)(void *), void *arg, | |||
213 | int stack_order); | 213 | int stack_order); |
214 | extern int helper_wait(int pid); | 214 | extern int helper_wait(int pid); |
215 | 215 | ||
216 | #endif | 216 | /* umid.c */ |
217 | 217 | ||
218 | /* | 218 | extern int umid_file_name(char *name, char *buf, int len); |
219 | * Overrides for Emacs so that we follow Linus's tabbing style. | 219 | extern int set_umid(char *name, int (*printer)(const char *fmt, ...)); |
220 | * Emacs will notice this stuff at the end of the file and automatically | 220 | extern char *get_umid(int only_if_set); |
221 | * adjust the settings for this buffer only. This must remain at the end | 221 | |
222 | * of the file. | 222 | #endif |
223 | * --------------------------------------------------------------------------- | ||
224 | * Local variables: | ||
225 | * c-file-style: "linux" | ||
226 | * End: | ||
227 | */ | ||
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 3de9d21e36bf..6f7700593a6f 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile | |||
@@ -10,8 +10,8 @@ obj-y = config.o exec_kern.o exitcode.o \ | |||
10 | init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \ | 10 | init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \ |
11 | process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ | 11 | process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ |
12 | signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \ | 12 | signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \ |
13 | time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \ | 13 | time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o umid.o \ |
14 | umid.o user_util.o | 14 | user_util.o |
15 | 15 | ||
16 | obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o | 16 | obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o |
17 | obj-$(CONFIG_GPROF) += gprof_syms.o | 17 | obj-$(CONFIG_GPROF) += gprof_syms.o |
@@ -24,7 +24,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/ | |||
24 | 24 | ||
25 | user-objs-$(CONFIG_TTY_LOG) += tty_log.o | 25 | user-objs-$(CONFIG_TTY_LOG) += tty_log.o |
26 | 26 | ||
27 | USER_OBJS := $(user-objs-y) config.o time.o tty_log.o umid.o user_util.o | 27 | USER_OBJS := $(user-objs-y) config.o time.o tty_log.o user_util.o |
28 | 28 | ||
29 | include arch/um/scripts/Makefile.rules | 29 | include arch/um/scripts/Makefile.rules |
30 | 30 | ||
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index 34b54a3e2132..651abf255bc5 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c | |||
@@ -324,10 +324,6 @@ int user_context(unsigned long sp) | |||
324 | return(stack != (unsigned long) current_thread); | 324 | return(stack != (unsigned long) current_thread); |
325 | } | 325 | } |
326 | 326 | ||
327 | extern void remove_umid_dir(void); | ||
328 | |||
329 | __uml_exitcall(remove_umid_dir); | ||
330 | |||
331 | extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; | 327 | extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; |
332 | 328 | ||
333 | void do_uml_exitcalls(void) | 329 | void do_uml_exitcalls(void) |
diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c index 0b21d59ba0cd..772c7cfbd8ec 100644 --- a/arch/um/kernel/umid.c +++ b/arch/um/kernel/umid.c | |||
@@ -3,61 +3,34 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdio.h> | 6 | #include "linux/stddef.h" |
7 | #include <unistd.h> | 7 | #include "linux/kernel.h" |
8 | #include <errno.h> | 8 | #include "asm/errno.h" |
9 | #include <string.h> | ||
10 | #include <stdlib.h> | ||
11 | #include <dirent.h> | ||
12 | #include <signal.h> | ||
13 | #include <sys/stat.h> | ||
14 | #include <sys/param.h> | ||
15 | #include "user.h" | ||
16 | #include "umid.h" | ||
17 | #include "init.h" | 9 | #include "init.h" |
18 | #include "os.h" | 10 | #include "os.h" |
19 | #include "user_util.h" | 11 | #include "kern.h" |
20 | #include "choose-mode.h" | ||
21 | 12 | ||
22 | #define UMID_LEN 64 | 13 | /* Changed by set_umid_arg and umid_file_name */ |
23 | #define UML_DIR "~/.uml/" | 14 | int umid_is_random = 0; |
24 | |||
25 | /* Changed by set_umid and make_umid, which are run early in boot */ | ||
26 | static char umid[UMID_LEN] = { 0 }; | ||
27 | |||
28 | /* Changed by set_uml_dir and make_uml_dir, which are run early in boot */ | ||
29 | static char *uml_dir = UML_DIR; | ||
30 | |||
31 | /* Changed by set_umid */ | ||
32 | static int umid_is_random = 1; | ||
33 | static int umid_inited = 0; | 15 | static int umid_inited = 0; |
34 | /* Have we created the files? Should we remove them? */ | ||
35 | static int umid_owned = 0; | ||
36 | 16 | ||
37 | static int make_umid(int (*printer)(const char *fmt, ...)); | 17 | static int __init set_umid_arg(char *name, int *add) |
38 | |||
39 | static int __init set_umid(char *name, int is_random, | ||
40 | int (*printer)(const char *fmt, ...)) | ||
41 | { | 18 | { |
42 | if(umid_inited){ | 19 | int err; |
43 | (*printer)("Unique machine name can't be set twice\n"); | ||
44 | return(-1); | ||
45 | } | ||
46 | 20 | ||
47 | if(strlen(name) > UMID_LEN - 1) | 21 | if(umid_inited) |
48 | (*printer)("Unique machine name is being truncated to %d " | 22 | return 0; |
49 | "characters\n", UMID_LEN); | ||
50 | strlcpy(umid, name, sizeof(umid)); | ||
51 | 23 | ||
52 | umid_is_random = is_random; | ||
53 | umid_inited = 1; | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static int __init set_umid_arg(char *name, int *add) | ||
58 | { | ||
59 | *add = 0; | 24 | *add = 0; |
60 | return(set_umid(name, 0, printf)); | 25 | err = set_umid(name, printf); |
26 | if(err == -EEXIST){ | ||
27 | printf("umid '%s' already in use\n", name); | ||
28 | umid_is_random = 1; | ||
29 | } | ||
30 | else if(!err) | ||
31 | umid_inited = 1; | ||
32 | |||
33 | return 0; | ||
61 | } | 34 | } |
62 | 35 | ||
63 | __uml_setup("umid=", set_umid_arg, | 36 | __uml_setup("umid=", set_umid_arg, |
@@ -66,265 +39,3 @@ __uml_setup("umid=", set_umid_arg, | |||
66 | " is used for naming the pid file and management console socket.\n\n" | 39 | " is used for naming the pid file and management console socket.\n\n" |
67 | ); | 40 | ); |
68 | 41 | ||
69 | int __init umid_file_name(char *name, char *buf, int len) | ||
70 | { | ||
71 | int n; | ||
72 | |||
73 | if(!umid_inited && make_umid(printk)) return(-1); | ||
74 | |||
75 | n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1; | ||
76 | if(n > len){ | ||
77 | printk("umid_file_name : buffer too short\n"); | ||
78 | return(-1); | ||
79 | } | ||
80 | |||
81 | sprintf(buf, "%s%s/%s", uml_dir, umid, name); | ||
82 | return(0); | ||
83 | } | ||
84 | |||
85 | extern int tracing_pid; | ||
86 | |||
87 | static void __init create_pid_file(void) | ||
88 | { | ||
89 | char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; | ||
90 | char pid[sizeof("nnnnn\0")]; | ||
91 | int fd, n; | ||
92 | |||
93 | if(umid_file_name("pid", file, sizeof(file))) | ||
94 | return; | ||
95 | |||
96 | fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), | ||
97 | 0644); | ||
98 | if(fd < 0){ | ||
99 | printf("Open of machine pid file \"%s\" failed: %s\n", | ||
100 | file, strerror(-fd)); | ||
101 | return; | ||
102 | } | ||
103 | |||
104 | sprintf(pid, "%d\n", os_getpid()); | ||
105 | n = os_write_file(fd, pid, strlen(pid)); | ||
106 | if(n != strlen(pid)) | ||
107 | printf("Write of pid file failed - err = %d\n", -n); | ||
108 | os_close_file(fd); | ||
109 | } | ||
110 | |||
111 | static int actually_do_remove(char *dir) | ||
112 | { | ||
113 | DIR *directory; | ||
114 | struct dirent *ent; | ||
115 | int len; | ||
116 | char file[256]; | ||
117 | |||
118 | directory = opendir(dir); | ||
119 | if(directory == NULL){ | ||
120 | printk("actually_do_remove : couldn't open directory '%s', " | ||
121 | "errno = %d\n", dir, errno); | ||
122 | return(1); | ||
123 | } | ||
124 | while((ent = readdir(directory)) != NULL){ | ||
125 | if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) | ||
126 | continue; | ||
127 | len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1; | ||
128 | if(len > sizeof(file)){ | ||
129 | printk("Not deleting '%s' from '%s' - name too long\n", | ||
130 | ent->d_name, dir); | ||
131 | continue; | ||
132 | } | ||
133 | sprintf(file, "%s/%s", dir, ent->d_name); | ||
134 | if(unlink(file) < 0){ | ||
135 | printk("actually_do_remove : couldn't remove '%s' " | ||
136 | "from '%s', errno = %d\n", ent->d_name, dir, | ||
137 | errno); | ||
138 | return(1); | ||
139 | } | ||
140 | } | ||
141 | if(rmdir(dir) < 0){ | ||
142 | printk("actually_do_remove : couldn't rmdir '%s', " | ||
143 | "errno = %d\n", dir, errno); | ||
144 | return(1); | ||
145 | } | ||
146 | return(0); | ||
147 | } | ||
148 | |||
149 | void remove_umid_dir(void) | ||
150 | { | ||
151 | char dir[strlen(uml_dir) + UMID_LEN + 1]; | ||
152 | if (!umid_owned) | ||
153 | return; | ||
154 | |||
155 | sprintf(dir, "%s%s", uml_dir, umid); | ||
156 | actually_do_remove(dir); | ||
157 | } | ||
158 | |||
159 | char *get_umid(int only_if_set) | ||
160 | { | ||
161 | if(only_if_set && umid_is_random) | ||
162 | return NULL; | ||
163 | return umid; | ||
164 | } | ||
165 | |||
166 | static int not_dead_yet(char *dir) | ||
167 | { | ||
168 | char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; | ||
169 | char pid[sizeof("nnnnn\0")], *end; | ||
170 | int dead, fd, p, n; | ||
171 | |||
172 | sprintf(file, "%s/pid", dir); | ||
173 | dead = 0; | ||
174 | fd = os_open_file(file, of_read(OPENFLAGS()), 0); | ||
175 | if(fd < 0){ | ||
176 | if(fd != -ENOENT){ | ||
177 | printk("not_dead_yet : couldn't open pid file '%s', " | ||
178 | "err = %d\n", file, -fd); | ||
179 | return(1); | ||
180 | } | ||
181 | dead = 1; | ||
182 | } | ||
183 | if(fd > 0){ | ||
184 | n = os_read_file(fd, pid, sizeof(pid)); | ||
185 | if(n < 0){ | ||
186 | printk("not_dead_yet : couldn't read pid file '%s', " | ||
187 | "err = %d\n", file, -n); | ||
188 | return(1); | ||
189 | } | ||
190 | p = strtoul(pid, &end, 0); | ||
191 | if(end == pid){ | ||
192 | printk("not_dead_yet : couldn't parse pid file '%s', " | ||
193 | "errno = %d\n", file, errno); | ||
194 | dead = 1; | ||
195 | } | ||
196 | if(((kill(p, 0) < 0) && (errno == ESRCH)) || | ||
197 | (p == CHOOSE_MODE(tracing_pid, os_getpid()))) | ||
198 | dead = 1; | ||
199 | } | ||
200 | if(!dead) | ||
201 | return(1); | ||
202 | return(actually_do_remove(dir)); | ||
203 | } | ||
204 | |||
205 | static int __init set_uml_dir(char *name, int *add) | ||
206 | { | ||
207 | if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){ | ||
208 | uml_dir = malloc(strlen(name) + 2); | ||
209 | if(uml_dir == NULL){ | ||
210 | printf("Failed to malloc uml_dir - error = %d\n", | ||
211 | errno); | ||
212 | uml_dir = name; | ||
213 | /* Return 0 here because do_initcalls doesn't look at | ||
214 | * the return value. | ||
215 | */ | ||
216 | return(0); | ||
217 | } | ||
218 | sprintf(uml_dir, "%s/", name); | ||
219 | } | ||
220 | else uml_dir = name; | ||
221 | return(0); | ||
222 | } | ||
223 | |||
224 | static int __init make_uml_dir(void) | ||
225 | { | ||
226 | char dir[MAXPATHLEN + 1] = { '\0' }; | ||
227 | int len; | ||
228 | |||
229 | if(*uml_dir == '~'){ | ||
230 | char *home = getenv("HOME"); | ||
231 | |||
232 | if(home == NULL){ | ||
233 | printf("make_uml_dir : no value in environment for " | ||
234 | "$HOME\n"); | ||
235 | exit(1); | ||
236 | } | ||
237 | strlcpy(dir, home, sizeof(dir)); | ||
238 | uml_dir++; | ||
239 | } | ||
240 | strlcat(dir, uml_dir, sizeof(dir)); | ||
241 | len = strlen(dir); | ||
242 | if (len > 0 && dir[len - 1] != '/') | ||
243 | strlcat(dir, "/", sizeof(dir)); | ||
244 | |||
245 | uml_dir = malloc(strlen(dir) + 1); | ||
246 | if (uml_dir == NULL) { | ||
247 | printf("make_uml_dir : malloc failed, errno = %d\n", errno); | ||
248 | exit(1); | ||
249 | } | ||
250 | strcpy(uml_dir, dir); | ||
251 | |||
252 | if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ | ||
253 | printf("Failed to mkdir %s: %s\n", uml_dir, strerror(errno)); | ||
254 | return(-1); | ||
255 | } | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int __init make_umid(int (*printer)(const char *fmt, ...)) | ||
260 | { | ||
261 | int fd, err; | ||
262 | char tmp[strlen(uml_dir) + UMID_LEN + 1]; | ||
263 | |||
264 | strlcpy(tmp, uml_dir, sizeof(tmp)); | ||
265 | |||
266 | if(!umid_inited){ | ||
267 | strcat(tmp, "XXXXXX"); | ||
268 | fd = mkstemp(tmp); | ||
269 | if(fd < 0){ | ||
270 | (*printer)("make_umid - mkstemp(%s) failed: %s\n", | ||
271 | tmp,strerror(errno)); | ||
272 | return(1); | ||
273 | } | ||
274 | |||
275 | os_close_file(fd); | ||
276 | /* There's a nice tiny little race between this unlink and | ||
277 | * the mkdir below. It'd be nice if there were a mkstemp | ||
278 | * for directories. | ||
279 | */ | ||
280 | unlink(tmp); | ||
281 | set_umid(&tmp[strlen(uml_dir)], 1, printer); | ||
282 | } | ||
283 | |||
284 | sprintf(tmp, "%s%s", uml_dir, umid); | ||
285 | |||
286 | err = mkdir(tmp, 0777); | ||
287 | if(err < 0){ | ||
288 | if(errno == EEXIST){ | ||
289 | if(not_dead_yet(tmp)){ | ||
290 | (*printer)("umid '%s' is in use\n", umid); | ||
291 | umid_owned = 0; | ||
292 | return(-1); | ||
293 | } | ||
294 | err = mkdir(tmp, 0777); | ||
295 | } | ||
296 | } | ||
297 | if(err < 0){ | ||
298 | (*printer)("Failed to create %s - errno = %d\n", umid, errno); | ||
299 | return(-1); | ||
300 | } | ||
301 | |||
302 | umid_owned = 1; | ||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | __uml_setup("uml_dir=", set_uml_dir, | ||
307 | "uml_dir=<directory>\n" | ||
308 | " The location to place the pid and umid files.\n\n" | ||
309 | ); | ||
310 | |||
311 | static int __init make_umid_setup(void) | ||
312 | { | ||
313 | /* one function with the ordering we need ... */ | ||
314 | make_uml_dir(); | ||
315 | make_umid(printf); | ||
316 | create_pid_file(); | ||
317 | return 0; | ||
318 | } | ||
319 | __uml_postsetup(make_umid_setup); | ||
320 | |||
321 | /* | ||
322 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
323 | * Emacs will notice this stuff at the end of the file and automatically | ||
324 | * adjust the settings for this buffer only. This must remain at the end | ||
325 | * of the file. | ||
326 | * --------------------------------------------------------------------------- | ||
327 | * Local variables: | ||
328 | * c-file-style: "linux" | ||
329 | * End: | ||
330 | */ | ||
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index b83ac8e21c35..11e30b13e318 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile | |||
@@ -4,11 +4,11 @@ | |||
4 | # | 4 | # |
5 | 5 | ||
6 | obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ | 6 | obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ |
7 | start_up.o time.o tt.o tty.o uaccess.o user_syms.o drivers/ \ | 7 | start_up.o time.o tt.o tty.o uaccess.o umid.o user_syms.o drivers/ \ |
8 | sys-$(SUBARCH)/ | 8 | sys-$(SUBARCH)/ |
9 | 9 | ||
10 | USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ | 10 | USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ |
11 | start_up.o time.o tt.o tty.o uaccess.o | 11 | start_up.o time.o tt.o tty.o uaccess.o umid.o |
12 | 12 | ||
13 | elf_aux.o: $(ARCH_DIR)/kernel-offsets.h | 13 | elf_aux.o: $(ARCH_DIR)/kernel-offsets.h |
14 | CFLAGS_elf_aux.o += -I$(objtree)/arch/um | 14 | CFLAGS_elf_aux.o += -I$(objtree)/arch/um |
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c new file mode 100644 index 000000000000..77d69a348cf4 --- /dev/null +++ b/arch/um/os-Linux/umid.c | |||
@@ -0,0 +1,292 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <unistd.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <string.h> | ||
5 | #include <errno.h> | ||
6 | #include <signal.h> | ||
7 | #include <dirent.h> | ||
8 | #include <sys/stat.h> | ||
9 | #include <sys/param.h> | ||
10 | #include "init.h" | ||
11 | #include "os.h" | ||
12 | #include "user.h" | ||
13 | #include "mode.h" | ||
14 | |||
15 | #define UML_DIR "~/.uml/" | ||
16 | |||
17 | #define UMID_LEN 64 | ||
18 | |||
19 | /* Changed by set_umid, which is run early in boot */ | ||
20 | char umid[UMID_LEN] = { 0 }; | ||
21 | |||
22 | /* Changed by set_uml_dir and make_uml_dir, which are run early in boot */ | ||
23 | static char *uml_dir = UML_DIR; | ||
24 | |||
25 | static int __init make_uml_dir(void) | ||
26 | { | ||
27 | char dir[512] = { '\0' }; | ||
28 | int len; | ||
29 | |||
30 | if(*uml_dir == '~'){ | ||
31 | char *home = getenv("HOME"); | ||
32 | |||
33 | if(home == NULL){ | ||
34 | printf("make_uml_dir : no value in environment for " | ||
35 | "$HOME\n"); | ||
36 | exit(1); | ||
37 | } | ||
38 | strlcpy(dir, home, sizeof(dir)); | ||
39 | uml_dir++; | ||
40 | } | ||
41 | strlcat(dir, uml_dir, sizeof(dir)); | ||
42 | len = strlen(dir); | ||
43 | if (len > 0 && dir[len - 1] != '/') | ||
44 | strlcat(dir, "/", sizeof(dir)); | ||
45 | |||
46 | uml_dir = malloc(strlen(dir) + 1); | ||
47 | if (uml_dir == NULL) { | ||
48 | printf("make_uml_dir : malloc failed, errno = %d\n", errno); | ||
49 | exit(1); | ||
50 | } | ||
51 | strcpy(uml_dir, dir); | ||
52 | |||
53 | if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ | ||
54 | printf("Failed to mkdir '%s': %s\n", uml_dir, strerror(errno)); | ||
55 | return(-1); | ||
56 | } | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static int actually_do_remove(char *dir) | ||
61 | { | ||
62 | DIR *directory; | ||
63 | struct dirent *ent; | ||
64 | int len; | ||
65 | char file[256]; | ||
66 | |||
67 | directory = opendir(dir); | ||
68 | if(directory == NULL){ | ||
69 | printk("actually_do_remove : couldn't open directory '%s', " | ||
70 | "errno = %d\n", dir, errno); | ||
71 | return(1); | ||
72 | } | ||
73 | while((ent = readdir(directory)) != NULL){ | ||
74 | if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) | ||
75 | continue; | ||
76 | len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1; | ||
77 | if(len > sizeof(file)){ | ||
78 | printk("Not deleting '%s' from '%s' - name too long\n", | ||
79 | ent->d_name, dir); | ||
80 | continue; | ||
81 | } | ||
82 | sprintf(file, "%s/%s", dir, ent->d_name); | ||
83 | if(unlink(file) < 0){ | ||
84 | printk("actually_do_remove : couldn't remove '%s' " | ||
85 | "from '%s', errno = %d\n", ent->d_name, dir, | ||
86 | errno); | ||
87 | return(1); | ||
88 | } | ||
89 | } | ||
90 | if(rmdir(dir) < 0){ | ||
91 | printk("actually_do_remove : couldn't rmdir '%s', " | ||
92 | "errno = %d\n", dir, errno); | ||
93 | return(1); | ||
94 | } | ||
95 | return(0); | ||
96 | } | ||
97 | |||
98 | extern int tracing_pid; | ||
99 | |||
100 | static int not_dead_yet(char *dir) | ||
101 | { | ||
102 | char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; | ||
103 | char pid[sizeof("nnnnn\0")], *end; | ||
104 | int dead, fd, p, n; | ||
105 | |||
106 | sprintf(file, "%s/pid", dir); | ||
107 | dead = 0; | ||
108 | fd = os_open_file(file, of_read(OPENFLAGS()), 0); | ||
109 | if(fd < 0){ | ||
110 | if(fd != -ENOENT){ | ||
111 | printk("not_dead_yet : couldn't open pid file '%s', " | ||
112 | "err = %d\n", file, -fd); | ||
113 | return(1); | ||
114 | } | ||
115 | dead = 1; | ||
116 | } | ||
117 | if(fd > 0){ | ||
118 | n = os_read_file(fd, pid, sizeof(pid)); | ||
119 | if(n < 0){ | ||
120 | printk("not_dead_yet : couldn't read pid file '%s', " | ||
121 | "err = %d\n", file, -n); | ||
122 | return(1); | ||
123 | } | ||
124 | p = strtoul(pid, &end, 0); | ||
125 | if(end == pid){ | ||
126 | printk("not_dead_yet : couldn't parse pid file '%s', " | ||
127 | "errno = %d\n", file, errno); | ||
128 | dead = 1; | ||
129 | } | ||
130 | if(((kill(p, 0) < 0) && (errno == ESRCH)) || | ||
131 | (p == CHOOSE_MODE(tracing_pid, os_getpid()))) | ||
132 | dead = 1; | ||
133 | } | ||
134 | if(!dead) | ||
135 | return(1); | ||
136 | return(actually_do_remove(dir)); | ||
137 | } | ||
138 | |||
139 | static void __init create_pid_file(void) | ||
140 | { | ||
141 | char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; | ||
142 | char pid[sizeof("nnnnn\0")]; | ||
143 | int fd, n; | ||
144 | |||
145 | if(umid_file_name("pid", file, sizeof(file))) | ||
146 | return; | ||
147 | |||
148 | fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), | ||
149 | 0644); | ||
150 | if(fd < 0){ | ||
151 | printf("Open of machine pid file \"%s\" failed: %s\n", | ||
152 | file, strerror(-fd)); | ||
153 | return; | ||
154 | } | ||
155 | |||
156 | sprintf(pid, "%d\n", os_getpid()); | ||
157 | n = os_write_file(fd, pid, strlen(pid)); | ||
158 | if(n != strlen(pid)) | ||
159 | printf("Write of pid file failed - err = %d\n", -n); | ||
160 | os_close_file(fd); | ||
161 | } | ||
162 | |||
163 | int __init set_umid(char *name, int (*printer)(const char *fmt, ...)) | ||
164 | { | ||
165 | if(strlen(name) > UMID_LEN - 1) | ||
166 | (*printer)("Unique machine name is being truncated to %d " | ||
167 | "characters\n", UMID_LEN); | ||
168 | strlcpy(umid, name, sizeof(umid)); | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static int umid_setup = 0; | ||
174 | |||
175 | int __init make_umid(int (*printer)(const char *fmt, ...)) | ||
176 | { | ||
177 | int fd, err; | ||
178 | char tmp[256]; | ||
179 | |||
180 | make_uml_dir(); | ||
181 | |||
182 | if(*umid == '\0'){ | ||
183 | strlcpy(tmp, uml_dir, sizeof(tmp)); | ||
184 | strcat(tmp, "XXXXXX"); | ||
185 | fd = mkstemp(tmp); | ||
186 | if(fd < 0){ | ||
187 | (*printer)("make_umid - mkstemp(%s) failed: %s\n", | ||
188 | tmp,strerror(errno)); | ||
189 | return(1); | ||
190 | } | ||
191 | |||
192 | os_close_file(fd); | ||
193 | /* There's a nice tiny little race between this unlink and | ||
194 | * the mkdir below. It'd be nice if there were a mkstemp | ||
195 | * for directories. | ||
196 | */ | ||
197 | unlink(tmp); | ||
198 | set_umid(&tmp[strlen(uml_dir)], printer); | ||
199 | } | ||
200 | |||
201 | sprintf(tmp, "%s%s", uml_dir, umid); | ||
202 | err = mkdir(tmp, 0777); | ||
203 | if(err < 0){ | ||
204 | if(errno == EEXIST){ | ||
205 | if(not_dead_yet(tmp)) | ||
206 | return -EEXIST; | ||
207 | err = mkdir(tmp, 0777); | ||
208 | } | ||
209 | } | ||
210 | if(err < 0){ | ||
211 | (*printer)("Failed to create %s - errno = %d\n", umid, errno); | ||
212 | return(-1); | ||
213 | } | ||
214 | |||
215 | umid_setup = 1; | ||
216 | |||
217 | create_pid_file(); | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | static int __init make_umid_init(void) | ||
223 | { | ||
224 | make_umid(printk); | ||
225 | |||
226 | return(0); | ||
227 | } | ||
228 | |||
229 | __initcall(make_umid_init); | ||
230 | |||
231 | int __init umid_file_name(char *name, char *buf, int len) | ||
232 | { | ||
233 | int n, err; | ||
234 | |||
235 | if(!umid_setup){ | ||
236 | err = make_umid(printk); | ||
237 | if(err) | ||
238 | return err; | ||
239 | } | ||
240 | |||
241 | n = strlen(uml_dir) + strlen(umid) + strlen("/") + strlen(name) + 1; | ||
242 | if(n > len){ | ||
243 | printk("umid_file_name : buffer too short\n"); | ||
244 | return(-1); | ||
245 | } | ||
246 | |||
247 | sprintf(buf, "%s%s/%s", uml_dir, umid, name); | ||
248 | return(0); | ||
249 | } | ||
250 | |||
251 | extern int umid_is_random; | ||
252 | |||
253 | char *get_umid(int only_if_set) | ||
254 | { | ||
255 | if(only_if_set && umid_is_random) | ||
256 | return NULL; | ||
257 | return umid; | ||
258 | } | ||
259 | |||
260 | static int __init set_uml_dir(char *name, int *add) | ||
261 | { | ||
262 | if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){ | ||
263 | uml_dir = malloc(strlen(name) + 2); | ||
264 | if(uml_dir == NULL){ | ||
265 | printf("Failed to malloc uml_dir - error = %d\n", | ||
266 | errno); | ||
267 | uml_dir = name; | ||
268 | /* Return 0 here because do_initcalls doesn't look at | ||
269 | * the return value. | ||
270 | */ | ||
271 | return(0); | ||
272 | } | ||
273 | sprintf(uml_dir, "%s/", name); | ||
274 | } | ||
275 | else uml_dir = name; | ||
276 | return(0); | ||
277 | } | ||
278 | |||
279 | __uml_setup("uml_dir=", set_uml_dir, | ||
280 | "uml_dir=<directory>\n" | ||
281 | " The location to place the pid and umid files.\n\n" | ||
282 | ); | ||
283 | |||
284 | static void remove_umid_dir(void) | ||
285 | { | ||
286 | char dir[strlen(uml_dir) + UMID_LEN + 1]; | ||
287 | |||
288 | sprintf(dir, "%s%s", uml_dir, umid); | ||
289 | actually_do_remove(dir); | ||
290 | } | ||
291 | |||
292 | __uml_exitcall(remove_umid_dir); | ||