(root)/
glib-2.79.0/
gmodule/
gmodule-ar.c
       1  /* GMODULE - GLIB wrapper code for dynamic module loading
       2   * Copyright (C) 1998, 2000 Tim Janik
       3   *
       4   * SPDX-License-Identifier: LGPL-2.1-or-later
       5   *
       6   * This library is free software; you can redistribute it and/or
       7   * modify it under the terms of the GNU Lesser General Public
       8   * License as published by the Free Software Foundation; either
       9   * version 2.1 of the License, or (at your option) any later version.
      10   *
      11   * This library is distributed in the hope that it will be useful,
      12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
      14   * Lesser General Public License for more details.
      15   *
      16   * You should have received a copy of the GNU Lesser General Public
      17   * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      18   */
      19  
      20  /* 
      21   * MT safe
      22   */
      23  
      24  /* because we are compatible with archive format only since AIX 4.3 */
      25  
      26  #define __AR_BIG__
      27  
      28  #include "config.h"
      29  
      30  #include <ar.h>
      31  #include <stdlib.h>
      32  
      33  #include <dlfcn.h>
      34  
      35  /* --- functions --- */
      36  static gchar*
      37  fetch_dlerror (gboolean replace_null)
      38  {
      39    gchar *msg = dlerror ();
      40  
      41    /* make sure we always return an error message != NULL, if
      42     * expected to do so. */
      43  
      44    if (!msg && replace_null)
      45      return "unknown dl-error";
      46  
      47    return msg;
      48  }
      49  
      50  static gchar* _g_module_get_member(const gchar* file_name)
      51  {
      52    gchar* member = NULL;
      53    struct fl_hdr file_header;
      54    struct ar_hdr ar_header;
      55    long first_member;
      56    long name_len;
      57    int fd;
      58  
      59    fd = open(file_name, O_RDONLY);
      60    if (fd == -1)
      61      return NULL;
      62  
      63    if (read(fd, (void*)&file_header, FL_HSZ) != FL_HSZ)
      64      goto exit;
      65  
      66    if (strncmp(file_header.fl_magic, AIAMAGBIG, SAIAMAG) != 0)
      67      goto exit;
      68  
      69    /* read first archive file member header */
      70  
      71    first_member = atol(file_header.fl_fstmoff);
      72  
      73    if (lseek(fd, first_member, SEEK_SET) != first_member)
      74      goto exit;
      75  
      76    if (read(fd, (void*)&ar_header, AR_HSZ - 2) != AR_HSZ - 2)
      77      goto exit;
      78  
      79    /* read member name */
      80  
      81    name_len = atol(ar_header.ar_namlen);
      82  
      83    member = g_malloc(name_len+1);
      84    if (!member)
      85      goto exit;
      86  
      87    if (read(fd, (void*)member, name_len) != name_len)
      88      {
      89        g_free(member);
      90        member = NULL;
      91        goto exit;
      92      }
      93  
      94    member[name_len] = 0;
      95  
      96  exit:
      97    close(fd);
      98  
      99    return member;
     100  }
     101  
     102  static gpointer
     103  _g_module_open (const gchar *file_name,
     104  		gboolean     bind_lazy,
     105  		gboolean     bind_local,
     106                  GError     **error)
     107  {
     108    gpointer handle;
     109    gchar* member;
     110    gchar* full_name;
     111  
     112    /* extract name of first member of archive */
     113  
     114    member = _g_module_get_member (file_name);
     115    if (member != NULL)
     116      {
     117        full_name = g_strconcat (file_name, "(", member, ")", NULL);
     118        g_free (member);
     119      }
     120    else
     121      full_name = g_strdup (file_name);
     122    
     123    handle = dlopen (full_name, 
     124  		   (bind_local ? RTLD_LOCAL : RTLD_GLOBAL) | RTLD_MEMBER | (bind_lazy ? RTLD_LAZY : RTLD_NOW));
     125  
     126    g_free (full_name);
     127  
     128    if (!handle)
     129      {
     130        const gchar *message = fetch_dlerror (TRUE);
     131  
     132        g_module_set_error (message);
     133        g_set_error_literal (error, G_MODULE_ERROR, G_MODULE_ERROR_FAILED, message);
     134      }
     135    
     136    return handle;
     137  }
     138  
     139  static gpointer
     140  _g_module_self (void)
     141  {
     142    gpointer handle;
     143  
     144    handle = dlopen (NULL, RTLD_GLOBAL | RTLD_LAZY);
     145    if (!handle)
     146      g_module_set_error (fetch_dlerror (TRUE));
     147    
     148    return handle;
     149  }
     150  
     151  static void
     152  _g_module_close (gpointer handle)
     153  {
     154    if (dlclose (handle) != 0)
     155      g_module_set_error (fetch_dlerror (TRUE));
     156  }
     157  
     158  static gpointer
     159  _g_module_symbol (gpointer     handle,
     160  		  const gchar *symbol_name)
     161  {
     162    gpointer p;
     163    
     164    p = dlsym (handle, symbol_name);
     165    if (!p)
     166      g_module_set_error (fetch_dlerror (FALSE));
     167    
     168    return p;
     169  }