Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals  

src/main/path.c

Go to the documentation of this file.
00001 /*
00002  * "$Id: path.c,v 1.13 2004/05/26 22:32:54 rleigh Exp $"
00003  *
00004  *   libgimpprint path functions - split and search paths.
00005  *
00006  *   Copyright 2002 Roger Leigh (rleigh@debian.org)
00007  *
00008  *   This program is free software; you can redistribute it and/or modify it
00009  *   under the terms of the GNU General Public License as published by the Free
00010  *   Software Foundation; either version 2 of the License, or (at your option)
00011  *   any later version.
00012  *
00013  *   This program is distributed in the hope that it will be useful, but
00014  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00015  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016  *   for more details.
00017  *
00018  *   You should have received a copy of the GNU General Public License
00019  *   along with this program; if not, write to the Free Software
00020  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00023 #include <gimp-print/gimp-print.h>
00024 #include "gimp-print-internal.h"
00025 #include <gimp-print/gimp-print-intl-internal.h>
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <errno.h>
00030 #include <dirent.h>
00031 #include <sys/types.h>
00032 #include <sys/stat.h>
00033 #include <unistd.h>
00034 
00035 static int stpi_path_check(const struct dirent *module);
00036 static char *stpi_path_merge(const char *path, const char *file);
00037 
00038 /* WARNING: This is not thread safe! -- rlk 20030721 */
00039 static const char *path_check_path;   /* Path for scandir() callback */
00040 static const char *path_check_suffix; /* Suffix for scandir() callback */
00041 
00042 
00043 static int
00044 dirent_sort(const void *a,
00045             const void *b)
00046 {
00047   return strcoll ((*(const struct dirent **) a)->d_name,
00048                   (*(const struct dirent **) b)->d_name);
00049 }
00050 
00051 
00052 /*
00053  * Make a list of all modules in the search path.
00054  */
00055 stp_list_t *
00056 stp_path_search(stp_list_t *dirlist, /* List of directories to search */
00057                 const char *suffix)  /* Required filename suffix */
00058 {
00059   stp_list_t *findlist;              /* List of files to return */
00060   stp_list_item_t *diritem;          /* Current directory */
00061   struct dirent** module_dir;        /* Current directory contents */
00062   char *module_name;                 /* File name to check */
00063   int n;                             /* Number of directory entries */
00064 
00065   if (!dirlist)
00066     return NULL;
00067 
00068   path_check_suffix = suffix;
00069 
00070   findlist = stp_list_create();
00071   if (!findlist)
00072     return NULL;
00073   stp_list_set_freefunc(findlist, stp_list_node_free_data);
00074 
00075   diritem = stp_list_get_start(dirlist);
00076   while (diritem)
00077     {
00078       path_check_path = (const char *) stp_list_item_get_data(diritem);
00079       stp_deprintf(STP_DBG_PATH, "stp-path: directory: %s\n",
00080                    (const char *) stp_list_item_get_data(diritem));
00081       n = scandir ((const char *) stp_list_item_get_data(diritem),
00082                    &module_dir, stpi_path_check, dirent_sort);
00083       if (n >= 0)
00084         {
00085           int idx;
00086           for (idx = 0; idx < n; ++idx)
00087             {
00088               module_name = stpi_path_merge((const char *) stp_list_item_get_data(diritem),
00089                                            module_dir[idx]->d_name);
00090               stp_list_item_create(findlist, NULL, module_name);
00091               free (module_dir[idx]); /* Must use plain free() */
00092             }
00093           free (module_dir); /* Must use plain free() */
00094         }
00095       diritem = stp_list_item_next(diritem);
00096     }
00097   return findlist;
00098 }
00099 
00100 
00101 /*
00102  * scandir() callback.  Check the filename is sane, has the correct
00103  * mode bits and suffix.
00104  */
00105 static int
00106 stpi_path_check(const struct dirent *module) /* File to check */
00107 {
00108   int namelen;                              /* Filename length */
00109   int status = 0;                           /* Error status */
00110   int savederr;                             /* Saved errno */
00111   char *filename;                           /* Filename */
00112   struct stat modstat;                      /* stat() output */
00113 
00114   savederr = errno; /* since we are a callback, preserve scandir() state */
00115 
00116   filename = stpi_path_merge(path_check_path, module->d_name);
00117 
00118   namelen = strlen(filename);
00119   /* make sure we can take off suffix (e.g. .la)
00120      and still have a sane filename */
00121   if (namelen >= strlen(path_check_suffix) + 1) 
00122     {
00123       if (!stat (filename, &modstat))
00124         {
00125           /* check file exists, and is a regular file */
00126           if (S_ISREG(modstat.st_mode))
00127             status = 1;
00128           if (strncmp(filename + (namelen - strlen(path_check_suffix)),
00129                       path_check_suffix,
00130                       strlen(path_check_suffix)))
00131             {
00132               status = 0;
00133             }
00134         }
00135     }
00136 
00137   if (status)
00138     stp_deprintf(STP_DBG_PATH, "stp-path: file: `%s'\n", filename);
00139 
00140   stp_free(filename);
00141   filename = NULL;
00142 
00143   errno = savederr;
00144   return status;
00145 }
00146 
00147 
00148 /*
00149  * Join a path and filename together.
00150  */
00151 static char *
00152 stpi_path_merge(const char *path, /* Path */
00153                const char *file) /* Filename */
00154 {
00155   char *filename;                /* Filename to return */
00156   int namelen = strlen(path) + strlen(file) + 2;
00157   filename = (char *) stp_malloc(namelen * sizeof(char));
00158   strcpy (filename, path);
00159   strcat (filename, "/");
00160   strcat (filename, file);
00161   filename[namelen - 1] = '\0';
00162   return filename;
00163 }
00164 
00165 
00166 /*
00167  * Split a PATH-type string (colon-delimited) into separate
00168  * directories.
00169  */
00170 void
00171 stp_path_split(stp_list_t *list, /* List to add directories to */
00172                const char *path) /* Path to split */
00173 {
00174   const char *start = path;      /* Start of path name */
00175   const char *end = NULL;        /* End of path name */
00176   char *dir = NULL;              /* Path name */
00177   int len;                       /* Length of path name */
00178 
00179   while (start)
00180     {
00181       end = (const char *) strchr(start, ':');
00182       if (!end)
00183         len = strlen(start) + 1;
00184       else
00185         len = (end - start);
00186 
00187       if (len && !(len == 1 && !end))
00188         {
00189           dir = (char *) stp_malloc(len + 1);
00190           strncpy(dir, start, len);
00191           dir[len] = '\0';
00192           stp_list_item_create(list, NULL, dir);
00193         }
00194       if (!end)
00195         {
00196           start = NULL;
00197           break;
00198         }
00199       start = end + 1;
00200     }
00201 }

Generated on Sat Jun 26 10:11:52 2004 for libgimpprint API Reference by doxygen1.2.17