initial commit with v2.6.9
[linux-2.6.9-moxart.git] / arch / um / kernel / umid.c
blob78c8dc45c61eaf62a0ebef5bd74d9d5bf27b076a
1 /*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
6 #include <stdio.h>
7 #include <unistd.h>
8 #include <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"
18 #include "os.h"
19 #include "user_util.h"
20 #include "choose-mode.h"
22 #define UMID_LEN 64
23 #define UML_DIR "~/.uml/"
25 /* Changed by set_umid and make_umid, which are run early in boot */
26 static char umid[UMID_LEN] = { 0 };
28 /* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
29 static char *uml_dir = UML_DIR;
31 /* Changed by set_umid */
32 static int umid_is_random = 1;
33 static int umid_inited = 0;
35 static int make_umid(int (*printer)(const char *fmt, ...));
37 static int __init set_umid(char *name, int is_random,
38 int (*printer)(const char *fmt, ...))
40 if(umid_inited){
41 (*printer)("Unique machine name can't be set twice\n");
42 return(-1);
45 if(strlen(name) > UMID_LEN - 1)
46 (*printer)("Unique machine name is being truncated to %d "
47 "characters\n", UMID_LEN);
48 strlcpy(umid, name, sizeof(umid));
50 umid_is_random = is_random;
51 umid_inited = 1;
52 return 0;
55 static int __init set_umid_arg(char *name, int *add)
57 return(set_umid(name, 0, printf));
60 __uml_setup("umid=", set_umid_arg,
61 "umid=<name>\n"
62 " This is used to assign a unique identity to this UML machine and\n"
63 " is used for naming the pid file and management console socket.\n\n"
66 int __init umid_file_name(char *name, char *buf, int len)
68 int n;
70 if(!umid_inited && make_umid(printk)) return(-1);
72 n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1;
73 if(n > len){
74 printk("umid_file_name : buffer too short\n");
75 return(-1);
78 sprintf(buf, "%s%s/%s", uml_dir, umid, name);
79 return(0);
82 extern int tracing_pid;
84 static int __init create_pid_file(void)
86 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
87 char pid[sizeof("nnnnn\0")];
88 int fd, n;
90 if(umid_file_name("pid", file, sizeof(file))) return 0;
92 fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))),
93 0644);
94 if(fd < 0){
95 printf("Open of machine pid file \"%s\" failed - "
96 "err = %d\n", file, -fd);
97 return 0;
100 sprintf(pid, "%d\n", os_getpid());
101 n = os_write_file(fd, pid, strlen(pid));
102 if(n != strlen(pid))
103 printf("Write of pid file failed - err = %d\n", -n);
104 os_close_file(fd);
105 return 0;
108 static int actually_do_remove(char *dir)
110 DIR *directory;
111 struct dirent *ent;
112 int len;
113 char file[256];
115 directory = opendir(dir);
116 if(directory == NULL){
117 printk("actually_do_remove : couldn't open directory '%s', "
118 "errno = %d\n", dir, errno);
119 return(1);
121 while((ent = readdir(directory)) != NULL){
122 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
123 continue;
124 len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1;
125 if(len > sizeof(file)){
126 printk("Not deleting '%s' from '%s' - name too long\n",
127 ent->d_name, dir);
128 continue;
130 sprintf(file, "%s/%s", dir, ent->d_name);
131 if(unlink(file) < 0){
132 printk("actually_do_remove : couldn't remove '%s' "
133 "from '%s', errno = %d\n", ent->d_name, dir,
134 errno);
135 return(1);
138 if(rmdir(dir) < 0){
139 printk("actually_do_remove : couldn't rmdir '%s', "
140 "errno = %d\n", dir, errno);
141 return(1);
143 return(0);
146 void remove_umid_dir(void)
148 char dir[strlen(uml_dir) + UMID_LEN + 1];
149 if(!umid_inited) return;
151 sprintf(dir, "%s%s", uml_dir, umid);
152 actually_do_remove(dir);
155 char *get_umid(int only_if_set)
157 if(only_if_set && umid_is_random) return(NULL);
158 return(umid);
161 int not_dead_yet(char *dir)
163 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
164 char pid[sizeof("nnnnn\0")], *end;
165 int dead, fd, p, n;
167 sprintf(file, "%s/pid", dir);
168 dead = 0;
169 fd = os_open_file(file, of_read(OPENFLAGS()), 0);
170 if(fd < 0){
171 if(fd != -ENOENT){
172 printk("not_dead_yet : couldn't open pid file '%s', "
173 "err = %d\n", file, -fd);
174 return(1);
176 dead = 1;
178 if(fd > 0){
179 n = os_read_file(fd, pid, sizeof(pid));
180 if(n < 0){
181 printk("not_dead_yet : couldn't read pid file '%s', "
182 "err = %d\n", file, -n);
183 return(1);
185 p = strtoul(pid, &end, 0);
186 if(end == pid){
187 printk("not_dead_yet : couldn't parse pid file '%s', "
188 "errno = %d\n", file, errno);
189 dead = 1;
191 if(((kill(p, 0) < 0) && (errno == ESRCH)) ||
192 (p == CHOOSE_MODE(tracing_pid, os_getpid())))
193 dead = 1;
195 if(!dead) return(1);
196 return(actually_do_remove(dir));
199 static int __init set_uml_dir(char *name, int *add)
201 if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){
202 uml_dir = malloc(strlen(name) + 2);
203 if(uml_dir == NULL){
204 printf("Failed to malloc uml_dir - error = %d\n",
205 errno);
206 uml_dir = name;
207 /* Return 0 here because do_initcalls doesn't look at
208 * the return value.
210 return(0);
212 sprintf(uml_dir, "%s/", name);
214 else uml_dir = name;
215 return(0);
218 static int __init make_uml_dir(void)
220 char dir[MAXPATHLEN + 1] = { '\0' };
221 int len;
223 if(*uml_dir == '~'){
224 char *home = getenv("HOME");
226 if(home == NULL){
227 printf("make_uml_dir : no value in environment for "
228 "$HOME\n");
229 exit(1);
231 strlcpy(dir, home, sizeof(dir));
232 uml_dir++;
234 len = strlen(dir);
235 strncat(dir, uml_dir, sizeof(dir) - len);
236 len = strlen(dir);
237 if((len > 0) && (len < sizeof(dir) - 1) && (dir[len - 1] != '/')){
238 dir[len] = '/';
239 dir[len + 1] = '\0';
242 uml_dir = malloc(strlen(dir) + 1);
243 if(uml_dir == NULL){
244 printf("make_uml_dir : malloc failed, errno = %d\n", errno);
245 exit(1);
247 strcpy(uml_dir, dir);
249 if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
250 printf("Failed to mkdir %s - errno = %i\n", uml_dir, errno);
251 return(-1);
253 return 0;
256 static int __init make_umid(int (*printer)(const char *fmt, ...))
258 int fd, err;
259 char tmp[strlen(uml_dir) + UMID_LEN + 1];
261 strlcpy(tmp, uml_dir, sizeof(tmp));
263 if(!umid_inited){
264 strcat(tmp, "XXXXXX");
265 fd = mkstemp(tmp);
266 if(fd < 0){
267 (*printer)("make_umid - mkstemp failed, errno = %d\n",
268 errno);
269 return(1);
272 os_close_file(fd);
273 /* There's a nice tiny little race between this unlink and
274 * the mkdir below. It'd be nice if there were a mkstemp
275 * for directories.
277 unlink(tmp);
278 set_umid(&tmp[strlen(uml_dir)], 1, printer);
281 sprintf(tmp, "%s%s", uml_dir, umid);
283 err = mkdir(tmp, 0777);
284 if(err < 0){
285 if(errno == EEXIST){
286 if(not_dead_yet(tmp)){
287 (*printer)("umid '%s' is in use\n", umid);
288 return(-1);
290 err = mkdir(tmp, 0777);
293 if(err < 0){
294 (*printer)("Failed to create %s - errno = %d\n", umid, errno);
295 return(-1);
298 return(0);
301 __uml_setup("uml_dir=", set_uml_dir,
302 "uml_dir=<directory>\n"
303 " The location to place the pid and umid files.\n\n"
306 __uml_postsetup(make_uml_dir);
308 static int __init make_umid_setup(void)
310 return(make_umid(printf));
313 __uml_postsetup(make_umid_setup);
314 __uml_postsetup(create_pid_file);
317 * Overrides for Emacs so that we follow Linus's tabbing style.
318 * Emacs will notice this stuff at the end of the file and automatically
319 * adjust the settings for this buffer only. This must remain at the end
320 * of the file.
321 * ---------------------------------------------------------------------------
322 * Local variables:
323 * c-file-style: "linux"
324 * End: