]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/cups-driverd.cxx
Merge changes from CUPS 1.4svn-r8628.
[thirdparty/cups.git] / scheduler / cups-driverd.cxx
index 0be49aa18e9e35fccdbf9ef420f56ce22083238d..7383145cc04f7e7e34d2ecf55abb66b903163115 100644 (file)
@@ -3,9 +3,9 @@
  *
  *   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.
@@ -23,6 +23,7 @@
  *   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.
@@ -73,7 +74,8 @@ static const char * const ppd_types[] =       /* ppd-type values */
   "pdf",
   "raster",
   "fax",
-  "unknown"
+  "unknown",
+  "drv"
 };
 
 
@@ -113,7 +115,8 @@ typedef struct                              /**** In-memory record ****/
  * 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? */
 
@@ -132,6 +135,7 @@ static ppd_info_t   *add_ppd(const char *filename, const char *name,
 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,
@@ -659,6 +663,21 @@ cat_static(const char *name,               /* I - PPD name */
 }
 
 
+/*
+ * '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.
  */
@@ -838,6 +857,8 @@ list_ppds(int        request_id,    /* I - Request ID */
   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);
 
@@ -1101,8 +1122,9 @@ list_ppds(int        request_id,  /* I - Request ID */
       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;
@@ -1135,8 +1157,9 @@ list_ppds(int        request_id,  /* I - Request ID */
       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;
@@ -1146,8 +1169,9 @@ list_ppds(int        request_id,  /* I - Request ID */
       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;
@@ -1319,6 +1343,8 @@ load_ppds(const char *d,          /* I - Actual directory */
           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 */
@@ -1378,7 +1404,32 @@ load_ppds(const char *d,         /* I - Actual directory */
   };
 
 
-  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)
   {
@@ -1390,6 +1441,8 @@ load_ppds(const char *d,          /* I - Actual directory */
     return (0);
   }
 
+  fprintf(stderr, "DEBUG: [cups-driverd] Loading \"%s\"...\n", d);
+
   while ((dent = cupsDirRead(dir)) != NULL)
   {
    /*