| 
									
										
										
										
											2004-02-22 01:31:24 +00:00
										 |  |  | /* GMODULE - GLIB wrapper code for dynamic module loading
 | 
					
						
							|  |  |  |  * Copyright (C) 1998, 2000 Tim Janik | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2022-06-01 12:44:23 +01:00
										 |  |  |  * SPDX-License-Identifier: LGPL-2.1-or-later | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2004-02-22 01:31:24 +00:00
										 |  |  |  * This library is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							| 
									
										
										
										
											2017-01-05 13:53:32 +01:00
										 |  |  |  * version 2.1 of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2004-02-22 01:31:24 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser General Public | 
					
						
							| 
									
										
										
										
											2014-01-23 12:58:29 +01:00
										 |  |  |  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2004-02-22 01:31:24 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* 
 | 
					
						
							|  |  |  |  * MT safe | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* because we are compatible with archive format only since AIX 4.3 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define __AR_BIG__
 | 
					
						
							| 
									
										
										
										
											2007-11-08 03:43:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "config.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-02-22 01:31:24 +00:00
										 |  |  | #include <ar.h>
 | 
					
						
							| 
									
										
										
										
											2005-06-30 19:32:33 +00:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											2004-02-22 01:31:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <dlfcn.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* --- functions --- */ | 
					
						
							|  |  |  | static gchar* | 
					
						
							|  |  |  | fetch_dlerror (gboolean replace_null) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   gchar *msg = dlerror (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* make sure we always return an error message != NULL, if
 | 
					
						
							|  |  |  |    * expected to do so. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!msg && replace_null) | 
					
						
							|  |  |  |     return "unknown dl-error"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return msg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gchar* _g_module_get_member(const gchar* file_name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   gchar* member = NULL; | 
					
						
							|  |  |  |   struct fl_hdr file_header; | 
					
						
							|  |  |  |   struct ar_hdr ar_header; | 
					
						
							|  |  |  |   long first_member; | 
					
						
							|  |  |  |   long name_len; | 
					
						
							|  |  |  |   int fd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   fd = open(file_name, O_RDONLY); | 
					
						
							|  |  |  |   if (fd == -1) | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (read(fd, (void*)&file_header, FL_HSZ) != FL_HSZ) | 
					
						
							|  |  |  |     goto exit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (strncmp(file_header.fl_magic, AIAMAGBIG, SAIAMAG) != 0) | 
					
						
							|  |  |  |     goto exit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* read first archive file member header */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   first_member = atol(file_header.fl_fstmoff); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (lseek(fd, first_member, SEEK_SET) != first_member) | 
					
						
							|  |  |  |     goto exit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (read(fd, (void*)&ar_header, AR_HSZ - 2) != AR_HSZ - 2) | 
					
						
							|  |  |  |     goto exit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* read member name */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   name_len = atol(ar_header.ar_namlen); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   member = g_malloc(name_len+1); | 
					
						
							|  |  |  |   if (!member) | 
					
						
							|  |  |  |     goto exit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (read(fd, (void*)member, name_len) != name_len) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_free(member); | 
					
						
							|  |  |  |       member = NULL; | 
					
						
							|  |  |  |       goto exit; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   member[name_len] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | exit: | 
					
						
							|  |  |  |   close(fd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return member; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gpointer | 
					
						
							|  |  |  | _g_module_open (const gchar *file_name, | 
					
						
							| 
									
										
										
										
											2004-05-12 03:31:55 +00:00
										 |  |  | 		gboolean     bind_lazy, | 
					
						
							| 
									
										
										
										
											2021-06-23 23:33:31 +05:30
										 |  |  | 		gboolean     bind_local, | 
					
						
							|  |  |  |                 GError     **error) | 
					
						
							| 
									
										
										
										
											2004-02-22 01:31:24 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   gpointer handle; | 
					
						
							|  |  |  |   gchar* member; | 
					
						
							|  |  |  |   gchar* full_name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* extract name of first member of archive */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-12 03:31:55 +00:00
										 |  |  |   member = _g_module_get_member (file_name); | 
					
						
							| 
									
										
										
										
											2004-02-22 01:31:24 +00:00
										 |  |  |   if (member != NULL) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-05-12 03:31:55 +00:00
										 |  |  |       full_name = g_strconcat (file_name, "(", member, ")", NULL); | 
					
						
							|  |  |  |       g_free (member); | 
					
						
							| 
									
										
										
										
											2004-02-22 01:31:24 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							| 
									
										
										
										
											2004-05-12 03:31:55 +00:00
										 |  |  |     full_name = g_strdup (file_name); | 
					
						
							| 
									
										
										
										
											2004-02-22 01:31:24 +00:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2004-05-12 03:31:55 +00:00
										 |  |  |   handle = dlopen (full_name,  | 
					
						
							|  |  |  | 		   (bind_local ? RTLD_LOCAL : RTLD_GLOBAL) | RTLD_MEMBER | (bind_lazy ? RTLD_LAZY : RTLD_NOW)); | 
					
						
							| 
									
										
										
										
											2004-02-22 01:31:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-12 03:31:55 +00:00
										 |  |  |   g_free (full_name); | 
					
						
							| 
									
										
										
										
											2004-02-22 01:31:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (!handle) | 
					
						
							| 
									
										
										
										
											2021-06-23 23:33:31 +05:30
										 |  |  |     { | 
					
						
							|  |  |  |       const gchar *message = fetch_dlerror (TRUE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       g_module_set_error (message); | 
					
						
							|  |  |  |       g_set_error_literal (error, G_MODULE_ERROR, G_MODULE_ERROR_FAILED, message); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2004-02-22 01:31:24 +00:00
										 |  |  |    | 
					
						
							|  |  |  |   return handle; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gpointer | 
					
						
							|  |  |  | _g_module_self (void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   gpointer handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   handle = dlopen (NULL, RTLD_GLOBAL | RTLD_LAZY); | 
					
						
							|  |  |  |   if (!handle) | 
					
						
							|  |  |  |     g_module_set_error (fetch_dlerror (TRUE)); | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   return handle; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2018-09-14 10:32:54 +01:00
										 |  |  | _g_module_close (gpointer handle) | 
					
						
							| 
									
										
										
										
											2004-02-22 01:31:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-09-14 10:32:54 +01:00
										 |  |  |   if (dlclose (handle) != 0) | 
					
						
							|  |  |  |     g_module_set_error (fetch_dlerror (TRUE)); | 
					
						
							| 
									
										
										
										
											2004-02-22 01:31:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gpointer | 
					
						
							|  |  |  | _g_module_symbol (gpointer     handle, | 
					
						
							|  |  |  | 		  const gchar *symbol_name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   gpointer p; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   p = dlsym (handle, symbol_name); | 
					
						
							|  |  |  |   if (!p) | 
					
						
							|  |  |  |     g_module_set_error (fetch_dlerror (FALSE)); | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   return p; | 
					
						
							|  |  |  | } |