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.12 2004/05/09 16:06:10 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 /*
00044  * Make a list of all modules in the search path.
00045  */
00046 stp_list_t *
00047 stp_path_search(stp_list_t *dirlist, /* List of directories to search */
00048                 const char *suffix)  /* Required filename suffix */
00049 {
00050   stp_list_t *findlist;              /* List of files to return */
00051   stp_list_item_t *diritem;          /* Current directory */
00052   struct dirent** module_dir;        /* Current directory contents */
00053   char *module_name;                 /* File name to check */
00054   int n;                             /* Number of directory entries */
00055 
00056   if (!dirlist)
00057     return NULL;
00058 
00059   path_check_suffix = suffix;
00060 
00061   findlist = stp_list_create();
00062   if (!findlist)
00063     return NULL;
00064   stp_list_set_freefunc(findlist, stp_list_node_free_data);
00065 
00066   diritem = stp_list_get_start(dirlist);
00067   while (diritem)
00068     {
00069       path_check_path = (const char *) stp_list_item_get_data(diritem);
00070       stp_deprintf(STP_DBG_PATH, "stp-path: directory: %s\n",
00071                    (const char *) stp_list_item_get_data(diritem));
00072       n = scandir ((const char *) stp_list_item_get_data(diritem),
00073                    &module_dir, stpi_path_check, alphasort);
00074       if (n >= 0)
00075         {
00076           int idx;
00077           for (idx = 0; idx < n; ++idx)
00078             {
00079               module_name = stpi_path_merge((const char *) stp_list_item_get_data(diritem),
00080                                            module_dir[idx]->d_name);
00081               stp_list_item_create(findlist, NULL, module_name);
00082               free (module_dir[idx]); /* Must use plain free() */
00083             }
00084           free (module_dir); /* Must use plain free() */
00085         }
00086       diritem = stp_list_item_next(diritem);
00087     }
00088   return findlist;
00089 }
00090 
00091 
00092 /*
00093  * scandir() callback.  Check the filename is sane, has the correct
00094  * mode bits and suffix.
00095  */
00096 static int
00097 stpi_path_check(const struct dirent *module) /* File to check */
00098 {
00099   int namelen;                              /* Filename length */
00100   int status = 0;                           /* Error status */
00101   int savederr;                             /* Saved errno */
00102   char *filename;                           /* Filename */
00103   struct stat modstat;                      /* stat() output */
00104 
00105   savederr = errno; /* since we are a callback, preserve scandir() state */
00106 
00107   filename = stpi_path_merge(path_check_path, module->d_name);
00108 
00109   namelen = strlen(filename);
00110   /* make sure we can take off suffix (e.g. .la)
00111      and still have a sane filename */
00112   if (namelen >= strlen(path_check_suffix) + 1) 
00113     {
00114       if (!stat (filename, &modstat))
00115         {
00116           /* check file exists, and is a regular file */
00117           if (S_ISREG(modstat.st_mode))
00118             status = 1;
00119           if (strncmp(filename + (namelen - strlen(path_check_suffix)),
00120                       path_check_suffix,
00121                       strlen(path_check_suffix)))
00122             {
00123               status = 0;
00124             }
00125         }
00126     }
00127 
00128   if (status)
00129     stp_deprintf(STP_DBG_PATH, "stp-path: file: `%s'\n", filename);
00130 
00131   stp_free(filename);
00132   filename = NULL;
00133 
00134   errno = savederr;
00135   return status;
00136 }
00137 
00138 
00139 /*
00140  * Join a path and filename together.
00141  */
00142 static char *
00143 stpi_path_merge(const char *path, /* Path */
00144                const char *file) /* Filename */
00145 {
00146   char *filename;                /* Filename to return */
00147   int namelen = strlen(path) + strlen(file) + 2;
00148   filename = (char *) stp_malloc(namelen * sizeof(char));
00149   strcpy (filename, path);
00150   strcat (filename, "/");
00151   strcat (filename, file);
00152   filename[namelen - 1] = '\0';
00153   return filename;
00154 }
00155 
00156 
00157 /*
00158  * Split a PATH-type string (colon-delimited) into separate
00159  * directories.
00160  */
00161 void
00162 stp_path_split(stp_list_t *list, /* List to add directories to */
00163                const char *path) /* Path to split */
00164 {
00165   const char *start = path;      /* Start of path name */
00166   const char *end = NULL;        /* End of path name */
00167   char *dir = NULL;              /* Path name */
00168   int len;                       /* Length of path name */
00169 
00170   while (start)
00171     {
00172       end = (const char *) strchr(start, ':');
00173       if (!end)
00174         len = strlen(start) + 1;
00175       else
00176         len = (end - start);
00177 
00178       if (len && !(len == 1 && !end))
00179         {
00180           dir = (char *) stp_malloc(len + 1);
00181           strncpy(dir, start, len);
00182           dir[len] = '\0';
00183           stp_list_item_create(list, NULL, dir);
00184         }
00185       if (!end)
00186         {
00187           start = NULL;
00188           break;
00189         }
00190       start = end + 1;
00191     }
00192 }

Generated on Wed May 12 20:21:29 2004 for libgimpprint API Reference by doxygen1.2.17