2.5-18.1
[glibc.git] / fedora / glibc_post_upgrade.c
blobcde931bde38753d22ae0c8a3b83c8a39343905be
1 #if defined __sparc__ && defined __arch64__
2 register void *__thread_self __asm ("g7");
3 #endif
4 #include <sys/types.h>
5 #include <sys/wait.h>
6 #include <stdio.h>
7 #include <errno.h>
8 #include <unistd.h>
9 #include <sys/time.h>
10 #include <dirent.h>
11 #include <stddef.h>
12 #include <fcntl.h>
13 #include <string.h>
14 #include <sys/stat.h>
15 #include <elf.h>
17 #define verbose_exec(failcode, path...) \
18 do \
19 { \
20 char *const arr[] = { path, NULL }; \
21 vexec (failcode, arr); \
22 } while (0)
24 __attribute__((noinline)) void vexec (int failcode, char *const path[]);
25 __attribute__((noinline)) void says (const char *str);
26 __attribute__((noinline)) void sayn (long num);
27 __attribute__((noinline)) void message (char *const path[]);
28 __attribute__((noinline)) int check_elf (const char *name);
30 int
31 main (void)
33 char initpath[256];
35 char buffer[4096];
36 struct pref {
37 char *p;
38 int len;
39 } prefix[] = { { "libc-", 5 }, { "libm-", 5 },
40 { "librt-", 6 }, { "libpthread-", 11 },
41 { "librtkaio-", 10 }, { "libthread_db-", 13 } };
42 int i, j, fd;
43 off_t base;
44 ssize_t ret;
45 #ifdef __i386__
46 const char *remove_dirs[] = { "/lib/tls", "/lib/i686", "/lib/tls/i486", "/lib/tls/i586", "/lib/tls/i686" };
47 #else
48 #ifndef LIBTLS
49 #define LIBTLS "/lib/tls"
50 #endif
51 const char *remove_dirs[] = { LIBTLS };
52 #endif
53 for (j = 0; j < sizeof (remove_dirs) / sizeof (remove_dirs[0]); ++j)
55 size_t rmlen = strlen (remove_dirs[j]);
56 fd = open (remove_dirs[j], O_RDONLY);
57 if (fd >= 0
58 && (ret = getdirentries (fd, buffer, sizeof (buffer), &base))
59 >= (ssize_t) offsetof (struct dirent, d_name))
61 for (base = 0; base + offsetof (struct dirent, d_name) < ret; )
63 struct dirent *d = (struct dirent *) (buffer + base);
65 for (i = 0; i < sizeof (prefix) / sizeof (prefix[0]); i++)
66 if (! strncmp (d->d_name, prefix[i].p, prefix[i].len))
68 char *p = d->d_name + prefix[i].len;
70 while (*p == '.' || (*p >= '0' && *p <= '9')) p++;
71 if (p[0] == 's' && p[1] == 'o' && p[2] == '\0'
72 && p + 3 - d->d_name
73 < sizeof (initpath) - rmlen - 1)
75 memcpy (initpath, remove_dirs[j], rmlen);
76 initpath[rmlen] = '/';
77 strcpy (initpath + rmlen + 1, d->d_name);
78 unlink (initpath);
79 break;
82 base += d->d_reclen;
84 close (fd);
88 int ldsocfd = open (LD_SO_CONF, O_RDONLY);
89 struct stat ldsocst;
90 if (ldsocfd >= 0 && fstat (ldsocfd, &ldsocst) >= 0)
92 char p[ldsocst.st_size + 1];
93 if (read (ldsocfd, p, ldsocst.st_size) == ldsocst.st_size)
95 p[ldsocst.st_size] = '\0';
96 if (strstr (p, "include ld.so.conf.d/*.conf") == NULL)
98 close (ldsocfd);
99 ldsocfd = open (LD_SO_CONF, O_WRONLY | O_TRUNC);
100 if (ldsocfd >= 0)
102 size_t slen = strlen ("include ld.so.conf.d/*.conf\n");
103 if (write (ldsocfd, "include ld.so.conf.d/*.conf\n", slen)
104 != slen
105 || write (ldsocfd, p, ldsocst.st_size) != ldsocst.st_size)
106 _exit (109);
110 if (ldsocfd >= 0)
111 close (ldsocfd);
114 /* If installing bi-arch glibc, rpm sometimes doesn't unpack all files
115 before running one of the lib's %post scriptlet. /sbin/ldconfig will
116 then be run by the other arch's %post. */
117 if (! access ("/sbin/ldconfig", X_OK))
118 verbose_exec (110, "/sbin/ldconfig", "/sbin/ldconfig");
120 if (! utimes (GCONV_MODULES_DIR "/gconv-modules.cache", NULL))
122 #ifndef ICONVCONFIG
123 #define ICONVCONFIG "/usr/sbin/iconvconfig"
124 #endif
125 verbose_exec (113, ICONVCONFIG, "/usr/sbin/iconvconfig",
126 "-o", GCONV_MODULES_DIR"/gconv-modules.cache",
127 "--nostdlib", GCONV_MODULES_DIR);
130 /* Check if telinit is available and the init fifo as well. */
131 if (access ("/sbin/telinit", X_OK) || access ("/dev/initctl", F_OK))
132 _exit (0);
133 /* Check if we are not inside of some chroot, because we'd just
134 timeout and leave /etc/initrunlvl. */
135 if (readlink ("/proc/1/exe", initpath, 256) <= 0 ||
136 readlink ("/proc/1/root", initpath, 256) <= 0)
137 _exit (0);
139 if (check_elf ("/proc/1/exe"))
140 verbose_exec (116, "/sbin/telinit", "/sbin/telinit", "u");
142 /* Check if we can safely condrestart sshd. */
143 if (access ("/sbin/service", X_OK) == 0
144 && access ("/usr/sbin/sshd", X_OK) == 0
145 && access ("/bin/bash", X_OK) == 0)
147 if (check_elf ("/usr/sbin/sshd"))
148 verbose_exec (-121, "/sbin/service", "/sbin/service", "sshd", "condrestart");
151 _exit(0);
154 #ifndef NO_SIZE_OPTIMIZATION
155 int __libc_multiple_threads __attribute__((nocommon));
156 int __libc_enable_asynccancel (void) { return 0; }
157 void __libc_disable_asynccancel (int x) { }
158 void __libc_csu_init (void) { }
159 void __libc_csu_fini (void) { }
160 pid_t __fork (void) { return -1; }
161 char thr_buf[65536];
163 # ifndef __powerpc__
165 __libc_start_main (int (*main) (void), int argc, char **argv,
166 void (*init) (void), void (*fini) (void),
167 void (*rtld_fini) (void), void * stack_end)
168 # else
169 struct startup_info
171 void *sda_base;
172 int (*main) (int, char **, char **, void *);
173 int (*init) (int, char **, char **, void *);
174 void (*fini) (void);
178 __libc_start_main (int argc, char **ubp_av, char **ubp_ev,
179 void *auxvec, void (*rtld_fini) (void),
180 struct startup_info *stinfo,
181 char **stack_on_entry)
182 # endif
184 #if defined __ia64__ || defined __powerpc64__
185 register void *r13 __asm ("r13") = thr_buf + 32768;
186 __asm ("" : : "r" (r13));
187 #elif defined __sparc__
188 register void *g6 __asm ("g6") = thr_buf + 32768;
189 # ifdef __arch64__
190 __thread_self = thr_buf + 32768;
191 # else
192 register void *__thread_self __asm ("g7") = thr_buf + 32768;
193 # endif
194 __asm ("" : : "r" (g6), "r" (__thread_self));
195 #elif defined __s390__ && !defined __s390x__
196 __asm ("sar %%a0,%0" : : "d" (thr_buf + 32768));
197 #elif defined __s390x__
198 __asm ("sar %%a1,%0; srlg 0,%0,32; sar %%a0,0" : : "d" (thr_buf + 32768) : "0");
199 #elif defined __powerpc__ && !defined __powerpc64__
200 register void *r2 __asm ("r2") = thr_buf + 32768;
201 __asm ("" : : "r" (r2));
202 #endif
203 main();
204 return 0;
206 #endif
208 void
209 vexec (int failcode, char *const path[])
211 pid_t pid;
212 int status, save_errno;
213 int devnull = 0;
215 if (failcode < 0)
217 devnull = 1;
218 failcode = -failcode;
220 pid = vfork ();
221 if (pid == 0)
223 int fd;
224 if (devnull && (fd = open ("/dev/null", O_WRONLY)) >= 0)
226 dup2 (fd, 1);
227 dup2 (fd, 2);
228 close (fd);
230 execv (path[0], path + 1);
231 save_errno = errno;
232 message (path);
233 says (" exec failed with errno ");
234 sayn (save_errno);
235 says ("\n");
236 _exit (failcode);
238 else if (pid < 0)
240 save_errno = errno;
241 message (path);
242 says (" fork failed with errno ");
243 sayn (save_errno);
244 says ("\n");
245 _exit (failcode + 1);
247 if (waitpid (0, &status, 0) != pid || !WIFEXITED (status))
249 message (path);
250 says (" child terminated abnormally\n");
251 _exit (failcode + 2);
253 if (WEXITSTATUS (status))
255 message (path);
256 says (" child exited with exit code ");
257 sayn (WEXITSTATUS (status));
258 says ("\n");
259 _exit (WEXITSTATUS (status));
263 void
264 says (const char *str)
266 write (1, str, strlen (str));
269 void
270 sayn (long num)
272 char string[sizeof (long) * 3 + 1];
273 char *p = string + sizeof (string) - 1;
275 *p = '\0';
276 if (num == 0)
277 *--p = '0';
278 else
279 while (num)
281 *--p = '0' + num % 10;
282 num = num / 10;
285 says (p);
288 void
289 message (char *const path[])
291 says ("/usr/sbin/glibc_post_upgrade: While trying to execute ");
292 says (path[0]);
296 check_elf (const char *name)
298 /* Play safe, if we can't open or read, assume it might be
299 ELF for the current arch. */
300 int ret = 1;
301 int fd = open (name, O_RDONLY);
302 if (fd >= 0)
304 Elf32_Ehdr ehdr;
305 if (read (fd, &ehdr, offsetof (Elf32_Ehdr, e_version))
306 == offsetof (Elf32_Ehdr, e_version))
308 ret = 0;
309 if (ehdr.e_ident[EI_CLASS]
310 == (sizeof (long) == 8 ? ELFCLASS64 : ELFCLASS32))
312 #if defined __i386__
313 ret = ehdr.e_machine == EM_386;
314 #elif defined __x86_64__
315 ret = ehdr.e_machine == EM_X86_64;
316 #elif defined __ia64__
317 ret = ehdr.e_machine == EM_IA_64;
318 #elif defined __powerpc64__
319 ret = ehdr.e_machine == EM_PPC64;
320 #elif defined __powerpc__
321 ret = ehdr.e_machine == EM_PPC;
322 #elif defined __s390__ || defined __s390x__
323 ret = ehdr.e_machine == EM_S390;
324 #elif defined __x86_64__
325 ret = ehdr.e_machine == EM_X86_64;
326 #elif defined __sparc__
327 if (sizeof (long) == 8)
328 ret = ehdr.e_machine == EM_SPARCV9;
329 else
330 ret = (ehdr.e_machine == EM_SPARC
331 || ehdr.e_machine == EM_SPARC32PLUS);
332 #else
333 ret = 1;
334 #endif
337 close (fd);
339 return ret;