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