Back to index

glibc  2.9
Classes | Functions | Variables
charmap-dir.c File Reference
#include <dirent.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <libintl.h>
#include <spawn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include "localedef.h"
#include "charmap-dir.h"

Go to the source code of this file.

Classes

struct  charmap_dir

Functions

CHARMAP_DIR * charmap_opendir (const char *directory)
const char * charmap_readdir (CHARMAP_DIR *cdir)
int charmap_closedir (CHARMAP_DIR *cdir)
static FILEfopen_uncompressed (const char *pathname, const char *compressor)
FILEcharmap_open (const char *directory, const char *name)
char ** charmap_aliases (const char *directory, const char *name)
void charmap_free_aliases (char **aliases)

Variables

static char * empty [1]

Class Documentation

struct charmap_dir

Definition at line 35 of file charmap-dir.c.

Class Members
DIR * dir
char * directory
size_t directory_len
char * pathname
size_t pathname_size

Function Documentation

char** charmap_aliases ( const char *  directory,
const char *  name 
)

Definition at line 250 of file charmap-dir.c.

{
  FILE *stream;
  char **aliases;
  size_t naliases;

  stream = charmap_open (directory, name);
  if (stream == NULL)
    return empty;

  aliases = NULL;
  naliases = 0;

  while (!feof (stream))
    {
      char *alias = NULL;
      char junk[BUFSIZ];

      if (fscanf (stream, " <code_set_name> %ms", &alias) == 1
          || fscanf (stream, "%% alias %ms", &alias) == 1)
        {
          aliases = (char **) xrealloc (aliases,
                                        (naliases + 2) * sizeof (char *));
          aliases[naliases++] = alias;
        }

      /* Read the rest of the line.  */
      if (fgets (junk, sizeof junk, stream) != NULL)
        {
          if (strstr (junk, "CHARMAP") != NULL)
            /* We cannot expect more aliases from now on.  */
            break;

          while (strchr (junk, '\n') == NULL
                 && fgets (junk, sizeof junk, stream) != NULL)
            continue;
        }
    }

  fclose (stream);

  if (naliases == 0)
    return empty;

  aliases[naliases] = NULL;
  return aliases;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int charmap_closedir ( CHARMAP_DIR *  cdir)

Definition at line 151 of file charmap-dir.c.

{
  DIR *dir = cdir->dir;

  free (cdir->directory);
  free (cdir->pathname);
  free (cdir);
  return closedir (dir);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void charmap_free_aliases ( char **  aliases)

Definition at line 300 of file charmap-dir.c.

{
  if (aliases != empty)
    {
      char **p;

      for (p = aliases; *p; p++)
        free (*p);

      free (aliases);
    }
}

Here is the caller graph for this function:

FILE* charmap_open ( const char *  directory,
const char *  name 
)

Definition at line 212 of file charmap-dir.c.

{
  size_t dlen = strlen (directory);
  int add_slash = (dlen == 0 || directory[dlen - 1] != '/');
  size_t nlen = strlen (name);
  char *pathname;
  char *p;
  FILE *stream;

  pathname = alloca (dlen + add_slash + nlen + 5);
  p = stpcpy (pathname, directory);
  if (add_slash)
    *p++ = '/';
  p = stpcpy (p, name);

  stream = fopen (pathname, "rm");
  if (stream != NULL)
    return stream;

  memcpy (p, ".gz", 4);
  stream = fopen_uncompressed (pathname, "gzip");
  if (stream != NULL)
    return stream;

  memcpy (p, ".bz2", 5);
  stream = fopen_uncompressed (pathname, "bzip2");
  if (stream != NULL)
    return stream;

  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

CHARMAP_DIR* charmap_opendir ( const char *  directory)

Definition at line 49 of file charmap-dir.c.

{
  struct charmap_dir *cdir;
  DIR *dir;
  size_t len;
  int add_slash;

  dir = opendir (directory);
  if (dir == NULL)
    {
      WITH_CUR_LOCALE (error (1, errno, gettext ("\
cannot read character map directory `%s'"), directory));
      return NULL;
    }

  cdir = (struct charmap_dir *) xmalloc (sizeof (struct charmap_dir));
  cdir->dir = dir;

  len = strlen (directory);
  add_slash = (len == 0 || directory[len - 1] != '/');
  cdir->directory = (char *) xmalloc (len + add_slash + 1);
  memcpy (cdir->directory, directory, len);
  if (add_slash)
    cdir->directory[len] = '/';
  cdir->directory[len + add_slash] = '\0';
  cdir->directory_len = len + add_slash;

  cdir->pathname = NULL;
  cdir->pathname_size = 0;

  return cdir;
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* charmap_readdir ( CHARMAP_DIR *  cdir)

Definition at line 87 of file charmap-dir.c.

{
  for (;;)
    {
      struct dirent64 *dirent;
      size_t len;
      size_t size;
      char *filename;
      mode_t mode;

      dirent = readdir64 (cdir->dir);
      if (dirent == NULL)
        return NULL;
      if (strcmp (dirent->d_name, ".") == 0)
        continue;
      if (strcmp (dirent->d_name, "..") == 0)
        continue;

      len = strlen (dirent->d_name);

      size = cdir->directory_len + len + 1;
      if (size > cdir->pathname_size)
        {
          free (cdir->pathname);
          if (size < 2 * cdir->pathname_size)
            size = 2 * cdir->pathname_size;
          cdir->pathname = (char *) xmalloc (size);
          cdir->pathname_size = size;
        }

      stpcpy (stpcpy (cdir->pathname, cdir->directory), dirent->d_name);
      filename = cdir->pathname + cdir->directory_len;

#ifdef _DIRENT_HAVE_D_TYPE
      if (dirent->d_type != DT_UNKNOWN && dirent->d_type != DT_LNK)
        mode = DTTOIF (dirent->d_type);
      else
#endif
        {
          struct stat statbuf;

          if (stat (cdir->pathname, &statbuf) < 0)
            continue;

          mode = statbuf.st_mode;
        }

      if (!S_ISREG (mode))
        continue;

      /* For compressed charmaps, the canonical charmap name does not
         include the extension.  */
      if (len > 3 && memcmp (&filename[len - 3], ".gz", 3) == 0)
        filename[len - 3] = '\0';
      else if (len > 4 && memcmp (&filename[len - 4], ".bz2", 4) == 0)
        filename[len - 4] = '\0';

      return filename;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static FILE* fopen_uncompressed ( const char *  pathname,
const char *  compressor 
) [static]

Definition at line 165 of file charmap-dir.c.

{
  int pfd;

  pfd = open (pathname, O_RDONLY);
  if (pfd >= 0)
    {
      struct stat statbuf;
      int fd[2];

      if (fstat (pfd, &statbuf) >= 0
          && S_ISREG (statbuf.st_mode)
          && pipe (fd) >= 0)
        {
          char *argv[4]
           = { (char *) compressor, (char *) "-d", (char *) "-c", NULL };
          posix_spawn_file_actions_t actions;

          if (posix_spawn_file_actions_init (&actions) == 0)
            {
              if (posix_spawn_file_actions_adddup2 (&actions,
                                                    fd[1], STDOUT_FILENO) == 0
                  && posix_spawn_file_actions_addclose (&actions, fd[1]) == 0
                  && posix_spawn_file_actions_addclose (&actions, fd[0]) == 0
                  && posix_spawn_file_actions_adddup2 (&actions,
                                                       pfd, STDIN_FILENO) == 0
                  && posix_spawn_file_actions_addclose (&actions, pfd) == 0
                  && posix_spawnp (NULL, compressor, &actions, NULL,
                                   argv, environ) == 0)
                {
                  posix_spawn_file_actions_destroy (&actions);
                  close (fd[1]);
                  close (pfd);
                  return fdopen (fd[0], "r");
                }
              posix_spawn_file_actions_destroy (&actions);
            }
          close (fd[1]);
          close (fd[0]);
        }
      close (pfd);
    }
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

char* empty[1] [static]

Definition at line 246 of file charmap-dir.c.