do not provide /usr/lib/locale
[platform/upstream/glibc.git] / packaging / glibc_post_upgrade.c
1 /* skeleton based on version from Fedora Core 3 */
2
3 #define _GNU_SOURCE
4
5 #include <sys/types.h>
6 #include <sys/wait.h>
7 #include <stdio.h>
8 #include <errno.h>
9 #include <unistd.h>
10 #include <sys/time.h>
11 #include <dirent.h>
12 #include <stddef.h>
13 #include <fcntl.h>
14 #include <string.h>
15 #include <sys/stat.h>
16 #include <elf.h>
17
18 #define verbose_exec(failcode, fail_ok, path...)                \
19   do                                                    \
20     {                                                   \
21       char *const arr[] = { path, NULL };               \
22       vexec (failcode, fail_ok, arr);                   \
23     } while (0)
24
25 __attribute__((noinline)) void vexec (int failcode, int fail_ok, char *const path[]);
26 __attribute__((noinline)) void says (const char *str);
27 __attribute__((noinline)) void sayn (long num);
28 __attribute__((noinline)) void message (char *const path[]);
29 __attribute__((noinline)) int check_elf (const char *name);
30
31 int
32 main (void)
33 {
34   char initpath[256];
35   struct stat root, init_root;
36
37   /* First, get rid of platform-optimized libraries. We remove any we have
38      ever built, since otherwise we might end up using some old leftover
39      libraries when new ones aren't installed in their place anymore. */
40 #ifdef REMOVE_TLS_DIRS
41   const char *library[] = {"libc.so.6", "libc.so.6.1", "libm.so.6",
42                            "libm.so.6.1", "librt.so.1", "librtkaio.so.1",
43                            "libpthread.so.0", "libthread_db.so.1"};
44   const char *remove_dir[] = {
45 #ifdef __i386__
46         "/lib/i686/",
47 #endif
48 #ifdef __powerpc64__
49 #ifdef REMOVE_PPC_OPTIMIZE_POWER4
50         "/lib64/power4/",
51         "/lib64/ppc970/",
52 #endif
53 #ifdef REMOVE_PPC_OPTIMIZE_POWER5
54         "/lib64/power5/",
55         "/lib64/power5+/",
56 #endif
57 #ifdef REMOVE_PPC_OPTIMIZE_POWER6
58         "/lib64/power6/",
59         "/lib64/power6x/",
60 #endif
61 #ifdef REMOVE_PPC_OPTIMIZE_POWER7
62         "/lib64/power7/",
63 #endif
64 #ifdef REMOVE_PPC_OPTIMIZE_CELL
65         "/lib64/ppc-cell-be/",
66 #endif
67 #endif /* __powerpc64__ */
68 #ifdef __powerpc__
69 #ifdef REMOVE_PPC_OPTIMIZE_POWER4
70         "/lib/power4/",
71         "/lib/ppc970/",
72 #endif
73 #ifdef REMOVE_PPC_OPTIMIZE_POWER5
74         "/lib/power5/",
75         "/lib/power5+/",
76 #endif
77 #ifdef REMOVE_PPC_OPTIMIZE_POWER6
78         "/lib/power6/",
79         "/lib/power6x/",
80 #endif
81 #ifdef REMOVE_PPC_OPTIMIZE_POWER7
82         "/lib/power7/",
83 #endif
84 #ifdef REMOVE_PPC_OPTIMIZE_CELL
85         "/lib/ppc-cell-be/",
86 #endif
87 #endif /* __powerpc__ */
88         LIBDIR"/tls/" };
89   int i, j;
90
91   for (i = 0; i < sizeof (remove_dir) / sizeof (remove_dir[0]); ++i)
92     for (j = 0; j < sizeof (library) / sizeof (library[0]); j++)
93       {
94         char buf[strlen (remove_dir[i]) + strlen (library[j]) + 1];
95         char readlink_buf[(strlen (remove_dir[i]) + strlen (library[j])) * 2 + 30];
96         ssize_t len;
97         char *cp;
98
99         cp = stpcpy (buf, remove_dir[i]);
100         strcpy (cp, library[j]);
101         /* This file could be a symlink to library-%{version}.so, so check
102            this and don't remove only the link, but also the library itself. */
103         cp = stpcpy (readlink_buf, remove_dir[i]);
104         if ((len = readlink (buf, cp, (sizeof (readlink_buf)
105                                        - (cp - readlink_buf) - 1))) > 0)
106           {
107             cp[len] = '\0';
108             if (cp[0] != '/') cp = readlink_buf;
109             unlink (cp);
110           }
111         unlink (buf);
112       }
113 #endif
114
115   /* If installing bi-arch glibc, rpm sometimes doesn't unpack all files
116      before running one of the lib's %post scriptlet.  /sbin/ldconfig will
117      then be run by the other arch's %post.  */
118   if (access ("/sbin/ldconfig", X_OK) == 0)
119     verbose_exec (110, 0, "/sbin/ldconfig", "/sbin/ldconfig", "-X");
120
121   if (utimes (GCONV_MODULES_DIR "/gconv-modules.cache", NULL) == 0)
122     {
123 #ifndef ICONVCONFIG
124 #define ICONVCONFIG "/usr/sbin/iconvconfig"
125 #endif
126       verbose_exec (113, 0, ICONVCONFIG, "/usr/sbin/iconvconfig",
127                     "-o", GCONV_MODULES_DIR"/gconv-modules.cache",
128                     "--nostdlib", GCONV_MODULES_DIR);
129     }
130
131   /* Implement %set_permissions %{_libexecdir}/pt_chown.  */
132   if (access ("/usr/bin/chkstat", X_OK) == 0)
133     verbose_exec (114, 1, "/usr/bin/chkstat", "/usr/bin/chkstat",
134                   "-n",  "--set", "--system", "/usr/lib/pt_chown");
135
136   /* Check if telinit is available and the init fifo as well.  */
137   if (access ("/sbin/telinit", X_OK) || access ("/dev/initctl", F_OK))
138     _exit (0);
139   /* Check if we are not inside of some chroot, because we'd just
140      timeout and leave /etc/initrunlvl.  */
141   if (readlink ("/proc/1/exe", initpath, 256) <= 0 ||
142       readlink ("/proc/1/root", initpath, 256) <= 0 ||
143       stat ("/proc/1/root", &init_root) < 0 ||
144       stat ("/.buildenv", &init_root) < 0 || /* XEN build */
145       stat ("/", &root) < 0 ||
146       init_root.st_dev != root.st_dev || init_root.st_ino != root.st_ino)
147     _exit (0);
148
149   if (check_elf ("/proc/1/exe"))
150     verbose_exec (116, 0, "/sbin/telinit", "/sbin/telinit", "u");
151
152 #if 0
153   /* Check if we can safely condrestart sshd.  */
154   if (access ("/sbin/service", X_OK) == 0
155       && access ("/usr/sbin/sshd", X_OK) == 0
156       && access ("/bin/bash", X_OK) == 0)
157     {
158       if (check_elf ("/usr/sbin/sshd"))
159         verbose_exec (121, 0, "/sbin/service", "/sbin/service", "sshd", "condrestart");
160     }
161 #endif
162
163   _exit(0);
164 }
165
166 void
167 vexec (int failcode, int fail_ok, char *const path[])
168 {
169   pid_t pid;
170   int status, save_errno;
171
172   pid = vfork ();
173   if (pid == 0)
174     {
175       execv (path[0], path + 1);
176       save_errno = errno;
177       message (path);
178       says (" exec failed with errno ");
179       sayn (save_errno);
180       says ("\n");
181       _exit (failcode);
182     }
183   else if (pid < 0)
184     {
185       save_errno = errno;
186       message (path);
187       says (" fork failed with errno ");
188       sayn (save_errno);
189       says ("\n");
190       _exit (failcode + 1);
191     }
192   if (waitpid (0, &status, 0) != pid || !WIFEXITED (status))
193     {
194       message (path);
195       says (" child terminated abnormally\n");
196       _exit (failcode + 2);
197     }
198   if (WEXITSTATUS (status))
199     {
200       message (path);
201       says (" child exited with exit code ");
202       sayn (WEXITSTATUS (status));
203       if (fail_ok)
204         {
205           says (" (ignored) \n");
206         }
207       else
208         {
209           says ("\n");
210           _exit (WEXITSTATUS (status));
211         }
212     }
213 }
214
215 void
216 says (const char *str)
217 {
218   write (1, str, strlen (str));
219 }
220
221 void
222 sayn (long num)
223 {
224   char string[sizeof (long) * 3 + 1];
225   char *p = string + sizeof (string) - 1;
226
227   *p = '\0';
228   if (num == 0)
229     *--p = '0';
230   else
231     while (num)
232       {
233         *--p = '0' + num % 10;
234         num = num / 10;
235       }
236
237   says (p);
238 }
239
240 void
241 message (char *const path[])
242 {
243   says ("/usr/sbin/glibc_post_upgrade: While trying to execute ");
244   says (path[0]);
245 }
246
247 int
248 check_elf (const char *name)
249 {
250   /* Play safe, if we can't open or read, assume it might be
251      ELF for the current arch.  */
252   int ret = 1;
253   int fd = open (name, O_RDONLY);
254   if (fd >= 0)
255     {
256       Elf32_Ehdr ehdr;
257       if (read (fd, &ehdr, offsetof (Elf32_Ehdr, e_version))
258           == offsetof (Elf32_Ehdr, e_version))
259         {
260           ret = 0;
261           if (ehdr.e_ident[EI_CLASS]
262               == (sizeof (long) == 8 ? ELFCLASS64 : ELFCLASS32))
263             {
264 #if defined __i386__
265               ret = ehdr.e_machine == EM_386;
266 #elif defined __x86_64__
267               ret = ehdr.e_machine == EM_X86_64;
268 #elif defined __ia64__
269               ret = ehdr.e_machine == EM_IA_64;
270 #elif defined __powerpc64__
271               ret = ehdr.e_machine == EM_PPC64;
272 #elif defined __powerpc__
273               ret = ehdr.e_machine == EM_PPC;
274 #elif defined __s390__ || defined __s390x__
275               ret = ehdr.e_machine == EM_S390;
276 #elif defined __x86_64__
277               ret = ehdr.e_machine == EM_X86_64;
278 #elif defined __sparc__
279               if (sizeof (long) == 8)
280                 ret = ehdr.e_machine == EM_SPARCV9;
281               else
282                 ret = (ehdr.e_machine == EM_SPARC
283                        || ehdr.e_machine == EM_SPARC32PLUS);
284 #else
285               ret = 1;
286 #endif
287             }
288         }
289       close (fd);
290     }
291   return ret;
292 }
293
294 #ifdef SMALL_BINARY
295
296 int __libc_multiple_threads __attribute__((nocommon));
297 int __libc_enable_asynccancel (void) { return 0; }
298 void __libc_disable_asynccancel (int x) { }
299 void __libc_csu_init (void) { }
300 void __libc_csu_fini (void) { }
301 pid_t __fork (void) { return -1; }
302 char thr_buf[65536];
303
304 #ifndef __powerpc__
305 int
306 __libc_start_main (int (*main) (void), int argc, char **argv,
307                    void (*init) (void), void (*fini) (void),
308                    void (*rtld_fini) (void), void * stack_end)
309 #else
310 struct startup_info
311 {
312   void *sda_base;
313   int (*main) (int, char **, char **, void *);
314   int (*init) (int, char **, char **, void *);
315   void (*fini) (void);
316 };
317
318 int
319 __libc_start_main (int argc, char **ubp_av, char **ubp_ev,
320                    void *auxvec, void (*rtld_fini) (void),
321                    struct startup_info *stinfo,
322                    char **stack_on_entry)
323 #endif
324 {
325 #if defined __ia64__ || defined __powerpc64__
326   register void *r13 __asm ("r13") = thr_buf + 32768;
327   __asm ("" : : "r" (r13));
328 #elif defined __sparc__
329   register void *g6 __asm ("g6") = thr_buf + 32768;
330 # ifdef __arch64__
331   __thread_self = thr_buf + 32768;
332 # else
333   register void *__thread_self __asm ("g7") = thr_buf + 32768;
334 # endif
335   __asm ("" : : "r" (g6), "r" (__thread_self));
336 #elif defined __s390__ && !defined __s390x__
337   __asm ("sar %%a0,%0" : : "d" (thr_buf + 32768));
338 #elif defined __s390x__
339   __asm ("sar %%a1,%0; srlg 0,%0,32; sar %%a0,0" : : "d" (thr_buf + 32768) : "0");
340 #elif defined __powerpc__ && !defined __powerpc64__
341   register void *r2 __asm ("r2") = thr_buf + 32768;
342   __asm ("" : : "r" (r2));
343 #endif
344   main();
345   return 0;
346 }
347
348 #endif