Switch to devel as the default dist branch
[glibc.git] / fedora / glibc_post_upgrade.c
blobe9bb0b82b960e0285a84ab75b56953eb3042b0c8
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 #ifdef __i386__
31 static int
32 is_ia64 (void)
34 unsigned int fl1, fl2;
36 /* See if we can use cpuid. */
37 __asm__ ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
38 "pushl %0; popfl; pushfl; popl %0; popfl"
39 : "=&r" (fl1), "=&r" (fl2)
40 : "i" (0x00200000));
41 if (((fl1 ^ fl2) & 0x00200000) == 0)
42 return 0;
44 /* Host supports cpuid. See if cpuid gives capabilities, try
45 CPUID(0). Preserve %ebx and %ecx; cpuid insn clobbers these, we
46 don't need their CPUID values here, and %ebx may be the PIC
47 register. */
48 __asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx"
49 : "=a" (fl1) : "0" (0) : "edx", "cc");
50 if (fl1 == 0)
51 return 0;
53 /* Invoke CPUID(1), return %edx; caller can examine bits to
54 determine what's supported. */
55 __asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx"
56 : "=d" (fl2), "=a" (fl1) : "1" (1) : "cc");
57 return (fl2 & (1 << 30)) != 0;
59 #else
60 #define is_ia64() 0
61 #endif
63 int
64 main (void)
66 char initpath[256];
68 char buffer[4096];
69 struct pref {
70 char *p;
71 int len;
72 } prefix[] = { { "libc-", 5 }, { "libm-", 5 },
73 { "librt-", 6 }, { "libpthread-", 11 },
74 { "librtkaio-", 10 }, { "libthread_db-", 13 } };
75 int i, j, fd;
76 off_t base;
77 ssize_t ret;
78 #ifdef __i386__
79 const char *remove_dirs[] = { "/lib/tls", "/lib/i686", "/lib/tls/i486", "/lib/tls/i586", "/lib/tls/i686" };
80 #else
81 #ifndef LIBTLS
82 #define LIBTLS "/lib/tls"
83 #endif
84 const char *remove_dirs[] = { LIBTLS };
85 #endif
86 for (j = 0; j < sizeof (remove_dirs) / sizeof (remove_dirs[0]); ++j)
88 size_t rmlen = strlen (remove_dirs[j]);
89 fd = open (remove_dirs[j], O_RDONLY);
90 if (fd >= 0
91 && (ret = getdirentries (fd, buffer, sizeof (buffer), &base))
92 >= (ssize_t) offsetof (struct dirent, d_name))
94 for (base = 0; base + offsetof (struct dirent, d_name) < ret; )
96 struct dirent *d = (struct dirent *) (buffer + base);
98 for (i = 0; i < sizeof (prefix) / sizeof (prefix[0]); i++)
99 if (! strncmp (d->d_name, prefix[i].p, prefix[i].len))
101 char *p = d->d_name + prefix[i].len;
103 while (*p == '.' || (*p >= '0' && *p <= '9')) p++;
104 if (p[0] == 's' && p[1] == 'o' && p[2] == '\0'
105 && p + 3 - d->d_name
106 < sizeof (initpath) - rmlen - 1)
108 memcpy (initpath, remove_dirs[j], rmlen);
109 initpath[rmlen] = '/';
110 strcpy (initpath + rmlen + 1, d->d_name);
111 unlink (initpath);
112 break;
115 base += d->d_reclen;
117 close (fd);
121 int ldsocfd = open (LD_SO_CONF, O_RDONLY);
122 struct stat ldsocst;
123 if (ldsocfd >= 0 && fstat (ldsocfd, &ldsocst) >= 0)
125 char p[ldsocst.st_size + 1];
126 if (read (ldsocfd, p, ldsocst.st_size) == ldsocst.st_size)
128 p[ldsocst.st_size] = '\0';
129 if (strstr (p, "include ld.so.conf.d/*.conf") == NULL)
131 close (ldsocfd);
132 ldsocfd = open (LD_SO_CONF, O_WRONLY | O_TRUNC);
133 if (ldsocfd >= 0)
135 size_t slen = strlen ("include ld.so.conf.d/*.conf\n");
136 if (write (ldsocfd, "include ld.so.conf.d/*.conf\n", slen)
137 != slen
138 || write (ldsocfd, p, ldsocst.st_size) != ldsocst.st_size)
139 _exit (109);
143 if (ldsocfd >= 0)
144 close (ldsocfd);
147 /* If installing bi-arch glibc, rpm sometimes doesn't unpack all files
148 before running one of the lib's %post scriptlet. /sbin/ldconfig will
149 then be run by the other arch's %post. */
150 if (! access ("/sbin/ldconfig", X_OK))
151 verbose_exec (110, "/sbin/ldconfig", "/sbin/ldconfig");
153 if (! utimes (GCONV_MODULES_DIR "/gconv-modules.cache", NULL))
155 #ifndef ICONVCONFIG
156 #define ICONVCONFIG "/usr/sbin/iconvconfig"
157 #endif
158 const char *iconv_cache = GCONV_MODULES_DIR"/gconv-modules.cache";
159 const char *iconv_dir = GCONV_MODULES_DIR;
160 if (is_ia64 ())
162 iconv_cache = "/emul/ia32-linux"GCONV_MODULES_DIR"/gconv-modules.cache";
163 iconv_dir = "/emul/ia32-linux"GCONV_MODULES_DIR;
165 verbose_exec (113, ICONVCONFIG, "/usr/sbin/iconvconfig",
166 "-o", iconv_cache,
167 "--nostdlib", iconv_dir);
170 /* Check if telinit is available and either SysVInit fifo,
171 or upstart telinit. */
172 if (access ("/sbin/telinit", X_OK)
173 || ((!!access ("/dev/initctl", F_OK))
174 ^ !access ("/sbin/initctl", X_OK)))
175 _exit (0);
176 /* Check if we are not inside of some chroot, because we'd just
177 timeout and leave /etc/initrunlvl. */
178 if (readlink ("/proc/1/exe", initpath, 256) <= 0 ||
179 readlink ("/proc/1/root", initpath, 256) <= 0)
180 _exit (0);
182 if (check_elf ("/proc/1/exe"))
183 verbose_exec (116, "/sbin/telinit", "/sbin/telinit", "u");
185 /* Check if we can safely condrestart sshd. */
186 if (access ("/sbin/service", X_OK) == 0
187 && access ("/usr/sbin/sshd", X_OK) == 0
188 && access ("/etc/rc.d/init.d/sshd", X_OK) == 0
189 && access ("/bin/bash", X_OK) == 0)
191 if (check_elf ("/usr/sbin/sshd"))
192 verbose_exec (-121, "/sbin/service", "/sbin/service", "sshd", "condrestart");
195 _exit(0);
198 #ifndef NO_SIZE_OPTIMIZATION
199 int __libc_multiple_threads __attribute__((nocommon));
200 int __libc_enable_asynccancel (void) { return 0; }
201 void __libc_disable_asynccancel (int x) { }
202 void __libc_csu_init (void) { }
203 void __libc_csu_fini (void) { }
204 pid_t __fork (void) { return -1; }
205 char thr_buf[65536];
207 # ifndef __powerpc__
209 __libc_start_main (int (*main) (void), int argc, char **argv,
210 void (*init) (void), void (*fini) (void),
211 void (*rtld_fini) (void), void * stack_end)
212 # else
213 struct startup_info
215 void *sda_base;
216 int (*main) (int, char **, char **, void *);
217 int (*init) (int, char **, char **, void *);
218 void (*fini) (void);
222 __libc_start_main (int argc, char **ubp_av, char **ubp_ev,
223 void *auxvec, void (*rtld_fini) (void),
224 struct startup_info *stinfo,
225 char **stack_on_entry)
226 # endif
228 #if defined __ia64__ || defined __powerpc64__
229 register void *r13 __asm ("r13") = thr_buf + 32768;
230 __asm ("" : : "r" (r13));
231 #elif defined __sparc__
232 register void *g6 __asm ("g6") = thr_buf + 32768;
233 # ifdef __arch64__
234 __thread_self = thr_buf + 32768;
235 # else
236 register void *__thread_self __asm ("g7") = thr_buf + 32768;
237 # endif
238 __asm ("" : : "r" (g6), "r" (__thread_self));
239 #elif defined __s390__ && !defined __s390x__
240 __asm ("sar %%a0,%0" : : "d" (thr_buf + 32768));
241 #elif defined __s390x__
242 __asm ("sar %%a1,%0; srlg 0,%0,32; sar %%a0,0" : : "d" (thr_buf + 32768) : "0");
243 #elif defined __powerpc__ && !defined __powerpc64__
244 register void *r2 __asm ("r2") = thr_buf + 32768;
245 __asm ("" : : "r" (r2));
246 #endif
247 main();
248 return 0;
250 #endif
252 void
253 vexec (int failcode, char *const path[])
255 pid_t pid;
256 int status, save_errno;
257 int devnull = 0;
259 if (failcode < 0)
261 devnull = 1;
262 failcode = -failcode;
264 pid = vfork ();
265 if (pid == 0)
267 int fd;
268 if (devnull && (fd = open ("/dev/null", O_WRONLY)) >= 0)
270 dup2 (fd, 1);
271 dup2 (fd, 2);
272 close (fd);
274 execv (path[0], path + 1);
275 save_errno = errno;
276 message (path);
277 says (" exec failed with errno ");
278 sayn (save_errno);
279 says ("\n");
280 _exit (failcode);
282 else if (pid < 0)
284 save_errno = errno;
285 message (path);
286 says (" fork failed with errno ");
287 sayn (save_errno);
288 says ("\n");
289 _exit (failcode + 1);
291 if (waitpid (0, &status, 0) != pid || !WIFEXITED (status))
293 message (path);
294 says (" child terminated abnormally\n");
295 _exit (failcode + 2);
297 if (WEXITSTATUS (status))
299 message (path);
300 says (" child exited with exit code ");
301 sayn (WEXITSTATUS (status));
302 says ("\n");
303 _exit (WEXITSTATUS (status));
307 void
308 says (const char *str)
310 write (1, str, strlen (str));
313 void
314 sayn (long num)
316 char string[sizeof (long) * 3 + 1];
317 char *p = string + sizeof (string) - 1;
319 *p = '\0';
320 if (num == 0)
321 *--p = '0';
322 else
323 while (num)
325 *--p = '0' + num % 10;
326 num = num / 10;
329 says (p);
332 void
333 message (char *const path[])
335 says ("/usr/sbin/glibc_post_upgrade: While trying to execute ");
336 says (path[0]);
340 check_elf (const char *name)
342 /* Play safe, if we can't open or read, assume it might be
343 ELF for the current arch. */
344 int ret = 1;
345 int fd = open (name, O_RDONLY);
346 if (fd >= 0)
348 Elf32_Ehdr ehdr;
349 if (read (fd, &ehdr, offsetof (Elf32_Ehdr, e_version))
350 == offsetof (Elf32_Ehdr, e_version))
352 ret = 0;
353 if (ehdr.e_ident[EI_CLASS]
354 == (sizeof (long) == 8 ? ELFCLASS64 : ELFCLASS32))
356 #if defined __i386__
357 ret = ehdr.e_machine == EM_386;
358 #elif defined __x86_64__
359 ret = ehdr.e_machine == EM_X86_64;
360 #elif defined __ia64__
361 ret = ehdr.e_machine == EM_IA_64;
362 #elif defined __powerpc64__
363 ret = ehdr.e_machine == EM_PPC64;
364 #elif defined __powerpc__
365 ret = ehdr.e_machine == EM_PPC;
366 #elif defined __s390__ || defined __s390x__
367 ret = ehdr.e_machine == EM_S390;
368 #elif defined __x86_64__
369 ret = ehdr.e_machine == EM_X86_64;
370 #elif defined __sparc__
371 if (sizeof (long) == 8)
372 ret = ehdr.e_machine == EM_SPARCV9;
373 else
374 ret = (ehdr.e_machine == EM_SPARC
375 || ehdr.e_machine == EM_SPARC32PLUS);
376 #else
377 ret = 1;
378 #endif
381 close (fd);
383 return ret;