aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux/umid.c
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2006-01-06 03:18:59 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:33:47 -0500
commit2264c475e4bf7427e59921953c89a5693ecb506f (patch)
tree4ebf1fa766ee7487eeaf583f1ffe2b63e6e0af2c /arch/um/os-Linux/umid.c
parente4dcee8099802c71437a15b940f66106d9f88b2f (diff)
[PATCH] uml: separate libc-dependent umid code
I reworked Gennady's umid OS abstraction patch because the code shouldn't be moved entirely to os. As it turns out, I moved most of it anyway. This patch is the minimal one needed to move the code and have it work. It turns out that the concept of the umid is OS-independent, but almost everything else about the implementation is OS-dependent. This is code movement without cleanup - a follow-on patch tidies everything up without shuffling code around. Signed-off-by: Jeff Dike <jdike@addtoit.com> Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/um/os-Linux/umid.c')
-rw-r--r--arch/um/os-Linux/umid.c292
1 files changed, 292 insertions, 0 deletions
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
new file mode 100644
index 00000000000..77d69a348cf
--- /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 */
20char umid[UMID_LEN] = { 0 };
21
22/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
23static char *uml_dir = UML_DIR;
24
25static 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
60static 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
98extern int tracing_pid;
99
100static 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
139static 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
163int __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
173static int umid_setup = 0;
174
175int __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
222static int __init make_umid_init(void)
223{
224 make_umid(printk);
225
226 return(0);
227}
228
229__initcall(make_umid_init);
230
231int __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
251extern int umid_is_random;
252
253char *get_umid(int only_if_set)
254{
255 if(only_if_set && umid_is_random)
256 return NULL;
257 return umid;
258}
259
260static 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
284static 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);