1b163bf346528ae396d4e4e2998903f158f218a4
[bootmanager.git] / source / libc-opendir-hack.c
1 /*
2  * $Id$
3  * $URL$
4  */
5
6 #define _GNU_SOURCE 1
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <dlfcn.h>
11 #include <sys/types.h>
12 #include <fcntl.h>
13 #include <dirent.h>
14 #include <glob.h>
15 #include <stdarg.h>
16 #include <string.h>
17
18 #define INIT(x) real_ ## x = dlsym(RTLD_NEXT, #x); \
19                 if (!real_ ## x) { \
20                   fprintf(stderr, "Would the real " #x " please stand up? %s\n", dlerror()); \
21                   exit(1); \
22                 }
23
24 DIR *opendir(const char *name)
25 {
26   int fd = open(name, O_RDONLY|O_NDELAY|O_DIRECTORY|O_LARGEFILE);
27   if (fd == -1)
28     return NULL;
29   return fdopendir(fd);
30 }
31
32 DIR *__opendir(const char *name)
33 {
34   return opendir(name);
35 }
36
37 static int (*real_glob)(const char *pattern, int flags,
38          int (*errfunc) (const char *epath, int eerrno),
39          glob_t *pglob);
40
41 int glob(const char *pattern, int flags,
42          int (*errfunc) (const char *epath, int eerrno),
43          glob_t *pglob)
44 {
45   if (!(flags & GLOB_ALTDIRFUNC)) {
46     pglob->gl_closedir = closedir;
47     pglob->gl_readdir = readdir;
48     pglob->gl_opendir = opendir;
49     pglob->gl_lstat = lstat;
50     pglob->gl_stat = stat;
51     flags |= GLOB_ALTDIRFUNC;
52   }
53   if (!real_glob) {
54     INIT(glob)
55   }
56   return real_glob(pattern, flags, errfunc, pglob);
57 }
58
59 #define PWD_LOCKFILE "/etc/.pwd.lock"
60
61 static int lock_fd = -1;
62
63 /* FIXME: Ignores multi-thread issues.
64  *        Doesn't wait for the file to become lockable
65  */
66 int lckpwdf(void)
67 {
68   struct flock fl = { 0 };
69
70   /* This process already holds the lock */
71   if (lock_fd != -1)
72     return -1;
73
74   lock_fd = open(PWD_LOCKFILE, O_WRONLY|O_CREAT, 0600);
75   if (lock_fd == -1)
76     return -1;
77
78   if (fcntl(lock_fd, F_SETFD, fcntl(lock_fd, F_GETFD, 0) | FD_CLOEXEC) == -1) {
79     close(lock_fd);
80     return -1;
81   }
82
83   fl.l_type = F_WRLCK;
84   fl.l_whence = SEEK_SET;
85   return fcntl(lock_fd, F_SETLKW, &fl);
86 }
87
88 int ulckpwdf(void)
89 {
90   int result;
91
92   if (lock_fd == -1)
93     return -1;
94
95   result = close(lock_fd);
96   lock_fd = -1;
97   return result;
98 }
99
100 static (*real_open)(const char *name, int flags, ...);
101 int open(const char *name, int flags, ...)
102 {
103   mode_t mode;
104   if (flags & O_CREAT) {
105     va_list va;
106     va_start(va, flags);
107     mode = va_arg(va, mode_t);
108     va_end(va);
109   }
110   if (!real_open) {
111     INIT(open)
112   }
113   return real_open(name, flags, mode);
114 }
115
116 static FILE *(*real_fopen)(const char *name, const char *flags);
117 FILE *fopen(const char *name, const char *flags)
118 {
119   char *str, *ptr = strchr(flags, 'e');
120   FILE *ret;
121   if (ptr) {
122     str = strdup(flags);
123     ptr = (str + (ptr - flags));
124     strcpy(ptr, ptr + 1);
125   }
126   else
127     str = flags;
128   if (!real_fopen) {
129     INIT(fopen)
130   }
131   ret = real_fopen(name, str);
132   if (ptr)
133     free(str);
134   return ret;
135 }
136
137 static void _init() __attribute__((constructor));
138 static void _init()
139 {
140   INIT(glob)
141   INIT(open)
142   INIT(fopen)
143 }