add .%%{_target_cpu} to glibc_post_upgrade, only run telinit u
[glibc.git] / fedora / glibc_post_upgrade.c
blobe0d0d082f226c73ca1863602ab7d7b4b565ce35f
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 int rerun_ldconfig = 0, rerun_cnt = 0;
34 char initpath[256];
36 #ifdef __i386__
37 char buffer[4096];
38 struct pref {
39 char *p;
40 int len;
41 } prefix[] = { { "libc-", 5 }, { "libm-", 5 },
42 { "librt-", 6 }, { "libpthread-", 11 },
43 { "librtkaio-", 10 }, { "libthread_db-", 13 } };
44 int i, j, fd;
45 off_t base;
46 ssize_t ret;
47 #ifdef ARCH_386
48 const char *remove_dirs[] = { "/lib/i686", "/lib/tls" };
49 #else
50 const char *remove_dirs[] = { "/lib/tls/i686" };
51 #endif
52 for (j = 0; j < sizeof (remove_dirs) / sizeof (remove_dirs[0]); ++j)
54 size_t rmlen = strlen (remove_dirs[j]);
55 fd = open (remove_dirs[j], O_RDONLY);
56 if (fd >= 0
57 && (ret = getdirentries (fd, buffer, sizeof (buffer), &base))
58 >= (ssize_t) offsetof (struct dirent, d_name))
60 for (base = 0; base + offsetof (struct dirent, d_name) < ret; )
62 struct dirent *d = (struct dirent *) (buffer + base);
64 for (i = 0; i < sizeof (prefix) / sizeof (prefix[0]); i++)
65 if (! strncmp (d->d_name, prefix[i].p, prefix[i].len))
67 char *p = d->d_name + prefix[i].len;
69 while (*p == '.' || (*p >= '0' && *p <= '9')) p++;
70 if (p[0] == 's' && p[1] == 'o' && p[2] == '\0'
71 && p + 3 - d->d_name
72 < sizeof (initpath) - rmlen - 1)
74 memcpy (initpath, remove_dirs[j], rmlen);
75 initpath[rmlen] = '/';
76 strcpy (initpath + rmlen + 1, d->d_name);
77 unlink (initpath);
78 break;
81 base += d->d_reclen;
83 close (fd);
86 #endif
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);
116 char linkbuf[64], *linkp;
117 int linklen;
119 verbose_exec (110, "/sbin/ldconfig", "/sbin/ldconfig");
121 rerun_ldconfig = 0;
122 #ifdef LIBTLS
123 linkp = linkbuf + strlen (LIBTLS);
124 linklen = readlink (LIBTLS "librt.so.1", linkp,
125 sizeof (linkbuf) - 1 - strlen (LIBTLS));
126 if (linklen == strlen ("librtkaio-2.3.X.so")
127 && memcmp (linkp, "librtkaio-2.3.", 14) == 0
128 && strchr ("23", linkp[14])
129 && memcmp (linkp + 15, ".so", 4) == 0)
131 memcpy (linkbuf, LIBTLS, strlen (LIBTLS));
132 unlink (linkbuf);
133 rerun_ldconfig = 1;
135 #endif
137 #ifdef __i386__
138 linkp = linkbuf + strlen ("/lib/i686/");
139 linklen = readlink ("/lib/i686/librt.so.1", linkp,
140 sizeof (linkbuf) - 1 - strlen ("/lib/i686/"));
141 if (linklen == strlen ("librtkaio-2.3.X.so")
142 && memcmp (linkp, "librtkaio-2.3.", 14) == 0
143 && strchr ("23", linkp[14])
144 && memcmp (linkp + 15, ".so", 4) == 0)
146 memcpy (linkbuf, "/lib/i686/", strlen ("/lib/i686/"));
147 unlink (linkbuf);
148 rerun_ldconfig = 1;
150 #endif
152 while (rerun_ldconfig && ++rerun_cnt < 2);
154 if (! utimes (GCONV_MODULES_CACHE, NULL))
156 verbose_exec (113, "/usr/sbin/iconvconfig", "/usr/sbin/iconvconfig");
159 /* Check if telinit is available and the init fifo as well. */
160 if (access ("/sbin/telinit", X_OK) || access ("/dev/initctl", F_OK))
161 _exit (0);
162 /* Check if we are not inside of some chroot, because we'd just
163 timeout and leave /etc/initrunlvl. */
164 if (readlink ("/proc/1/exe", initpath, 256) <= 0 ||
165 readlink ("/proc/1/root", initpath, 256) <= 0)
166 _exit (0);
168 if (check_elf ("/proc/1/exe"))
169 verbose_exec (116, "/sbin/telinit", "/sbin/telinit", "u");
171 /* Check if we can safely condrestart sshd. */
172 if (access ("/sbin/service", X_OK) == 0
173 && access ("/usr/sbin/sshd", X_OK) == 0
174 && access ("/bin/bash", X_OK) == 0)
176 if (check_elf ("/usr/sbin/sshd"))
177 verbose_exec (121, "/sbin/service", "/sbin/service", "sshd", "condrestart");
180 _exit(0);
183 int __libc_multiple_threads __attribute__((nocommon));
184 int __libc_enable_asynccancel (void) { return 0; }
185 void __libc_disable_asynccancel (int x) { }
186 void __libc_csu_init (void) { }
187 void __libc_csu_fini (void) { }
188 pid_t __fork (void) { return -1; }
189 char thr_buf[65536];
191 #ifndef __powerpc__
193 __libc_start_main (int (*main) (void), int argc, char **argv,
194 void (*init) (void), void (*fini) (void),
195 void (*rtld_fini) (void), void * stack_end)
196 #else
197 struct startup_info
199 void *sda_base;
200 int (*main) (int, char **, char **, void *);
201 int (*init) (int, char **, char **, void *);
202 void (*fini) (void);
206 __libc_start_main (int argc, char **ubp_av, char **ubp_ev,
207 void *auxvec, void (*rtld_fini) (void),
208 struct startup_info *stinfo,
209 char **stack_on_entry)
210 #endif
212 #if defined __ia64__ || defined __powerpc64__
213 register void *r13 __asm ("r13") = thr_buf + 32768;
214 __asm ("" : : "r" (r13));
215 #elif defined __sparc__
216 register void *g6 __asm ("g6") = thr_buf + 32768;
217 # ifdef __arch64__
218 __thread_self = thr_buf + 32768;
219 # else
220 register void *__thread_self __asm ("g7") = thr_buf + 32768;
221 # endif
222 __asm ("" : : "r" (g6), "r" (__thread_self));
223 #elif defined __s390__ && !defined __s390x__
224 __asm ("sar %%a0,%0" : : "d" (thr_buf + 32768));
225 #elif defined __s390x__
226 __asm ("sar %%a1,%0; srlg 0,%0,32; sar %%a0,0" : : "d" (thr_buf + 32768) : "0");
227 #elif defined __powerpc__ && !defined __powerpc64__
228 register void *r2 __asm ("r2") = thr_buf + 32768;
229 __asm ("" : : "r" (r2));
230 #endif
231 main();
232 return 0;
235 void
236 vexec (int failcode, char *const path[])
238 pid_t pid;
239 int status, save_errno;
241 pid = vfork ();
242 if (pid == 0)
244 execv (path[0], path + 1);
245 save_errno = errno;
246 message (path);
247 says (" exec failed with errno ");
248 sayn (save_errno);
249 says ("\n");
250 _exit (failcode);
252 else if (pid < 0)
254 save_errno = errno;
255 message (path);
256 says (" fork failed with errno ");
257 sayn (save_errno);
258 says ("\n");
259 _exit (failcode + 1);
261 if (waitpid (0, &status, 0) != pid || !WIFEXITED (status))
263 message (path);
264 says (" child terminated abnormally\n");
265 _exit (failcode + 2);
267 if (WEXITSTATUS (status))
269 message (path);
270 says (" child exited with exit code ");
271 sayn (WEXITSTATUS (status));
272 says ("\n");
273 _exit (WEXITSTATUS (status));
277 void
278 says (const char *str)
280 write (1, str, strlen (str));
283 void
284 sayn (long num)
286 char string[sizeof (long) * 3 + 1];
287 char *p = string + sizeof (string) - 1;
289 *p = '\0';
290 if (num == 0)
291 *--p = '0';
292 else
293 while (num)
295 *--p = '0' + num % 10;
296 num = num / 10;
299 says (p);
302 void
303 message (char *const path[])
305 says ("/usr/sbin/glibc_post_upgrade: While trying to execute ");
306 says (path[0]);
310 check_elf (const char *name)
312 /* Play safe, if we can't open or read, assume it might be
313 ELF for the current arch. */
314 int ret = 1;
315 int fd = open (name, O_RDONLY);
316 if (fd >= 0)
318 Elf32_Ehdr ehdr;
319 if (read (fd, &ehdr, offsetof (Elf32_Ehdr, e_version))
320 == offsetof (Elf32_Ehdr, e_version))
322 ret = 0;
323 if (ehdr.e_ident[EI_CLASS]
324 == (sizeof (long) == 8 ? ELFCLASS64 : ELFCLASS32))
326 #if defined __i386__
327 ret = ehdr.e_machine == EM_386;
328 #elif defined __x86_64__
329 ret = ehdr.e_machine == EM_X86_64;
330 #elif defined __ia64__
331 ret = ehdr.e_machine == EM_IA_64;
332 #elif defined __powerpc64__
333 ret = ehdr.e_machine == EM_PPC64;
334 #elif defined __powerpc__
335 ret = ehdr.e_machine == EM_PPC;
336 #elif defined __s390__ || defined __s390x__
337 ret = ehdr.e_machine == EM_S390;
338 #elif defined __x86_64__
339 ret = ehdr.e_machine == EM_X86_64;
340 #elif defined __sparc__
341 if (sizeof (long) == 8)
342 ret = ehdr.e_machine == EM_SPARCV9;
343 else
344 ret = (ehdr.e_machine == EM_SPARC
345 || ehdr.e_machine == EM_SPARC32PLUS);
346 #else
347 ret = 1;
348 #endif
351 close (fd);
353 return ret;