*
* PPD/driver support for the Common UNIX Printing System (CUPS).
*
- * This program handles listing and installing both static PPD files
- * in CUPS_DATADIR/model and dynamically generated PPD files using
- * the driver helper programs in CUPS_SERVERBIN/driver.
+ * This program handles listing and installing static PPD files, PPD files
+ * created from driver information files, and dynamically generated PPD files
+ * using driver helper programs.
*
* Copyright 2007-2009 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products.
* cat_drv() - Generate a PPD from a driver info file.
* cat_ppd() - Copy a PPD file to stdout.
* copy_static() - Copy a static PPD file to stdout.
+ * compare_inodes() - Compare two inodes.
* compare_matches() - Compare PPD match scores for sorting.
* compare_names() - Compare PPD filenames for sorting.
* compare_ppds() - Compare PPD file make and model names for sorting.
"pdf",
"raster",
"fax",
- "unknown"
+ "unknown",
+ "drv"
};
* Globals...
*/
-cups_array_t *PPDsByName = NULL, /* PPD files sorted by filename and name */
+cups_array_t *Inodes = NULL, /* Inodes of directories we've visited */
+ *PPDsByName = NULL, /* PPD files sorted by filename and name */
*PPDsByMakeModel = NULL;/* PPD files sorted by make and model */
int ChangedPPD; /* Did we change the PPD database? */
static int cat_drv(const char *name, int request_id);
static int cat_ppd(const char *name, int request_id);
static int cat_static(const char *name, int request_id);
+static int compare_inodes(struct stat *a, struct stat *b);
static int compare_matches(const ppd_info_t *p0,
const ppd_info_t *p1);
static int compare_names(const ppd_info_t *p0,
}
+/*
+ * 'compare_inodes()' - Compare two inodes.
+ */
+
+static int /* O - Result of comparison */
+compare_inodes(struct stat *a, /* I - First inode */
+ struct stat *b) /* I - Second inode */
+{
+ if (a->st_dev != b->st_dev)
+ return (a->st_dev - b->st_dev);
+ else
+ return (a->st_ino - b->st_ino);
+}
+
+
/*
* 'compare_matches()' - Compare PPD match scores for sorting.
*/
if ((cups_datadir = getenv("CUPS_DATADIR")) == NULL)
cups_datadir = CUPS_DATADIR;
+ Inodes = cupsArrayNew((cups_array_func_t)compare_inodes, NULL);
+
snprintf(model, sizeof(model), "%s/model", cups_datadir);
load_ppds(model, "", 1);
if (language)
{
for (i = 0; i < PPD_MAX_LANG; i ++)
- if (!ppd->record.languages[i][0] ||
- !strcmp(ppd->record.languages[i], language))
+ if (!ppd->record.languages[i][0])
+ break;
+ else if (!strcmp(ppd->record.languages[i], language))
{
ppd->matches ++;
break;
if (product)
{
for (i = 0; i < PPD_MAX_PROD; i ++)
- if (!ppd->record.products[i][0] ||
- !strcasecmp(ppd->record.products[i], product))
+ if (!ppd->record.products[i][0])
+ break;
+ else if (!strcasecmp(ppd->record.products[i], product))
{
ppd->matches += 3;
break;
if (psversion)
{
for (i = 0; i < PPD_MAX_VERS; i ++)
- if (!ppd->record.psversions[i][0] ||
- !strcasecmp(ppd->record.psversions[i], psversion))
+ if (!ppd->record.psversions[i][0])
+ break;
+ else if (!strcasecmp(ppd->record.psversions[i], psversion))
{
ppd->matches ++;
break;
const char *p, /* I - Virtual path in name */
int descend) /* I - Descend into directories? */
{
+ struct stat dinfo, /* Directory information */
+ *dinfoptr; /* Pointer to match */
int i; /* Looping var */
cups_file_t *fp; /* Pointer to file */
cups_dir_t *dir; /* Directory pointer */
};
- fprintf(stderr, "DEBUG: [cups-driverd] Loading \"%s\"...\n", d);
+ /*
+ * See if we've loaded this directory before...
+ */
+
+ if (stat(d, &dinfo))
+ {
+ if (errno != ENOENT)
+ fprintf(stderr, "ERROR: [cups-driverd] Unable to stat \"%s\": %s\n", d,
+ strerror(errno));
+
+ return (0);
+ }
+ else if (cupsArrayFind(Inodes, &dinfo))
+ {
+ fprintf(stderr, "ERROR: [cups-driverd] Skipping \"%s\": loop detected!\n",
+ d);
+ return (0);
+ }
+
+ /*
+ * Nope, add it to the Inodes array and continue...
+ */
+
+ dinfoptr = (struct stat *)malloc(sizeof(struct stat));
+ memcpy(dinfoptr, &dinfo, sizeof(struct stat));
+ cupsArrayAdd(Inodes, dinfoptr);
if ((dir = cupsDirOpen(d)) == NULL)
{
return (0);
}
+ fprintf(stderr, "DEBUG: [cups-driverd] Loading \"%s\"...\n", d);
+
while ((dent = cupsDirRead(dir)) != NULL)
{
/*