From 880fec09182a500b7e19b5b1c73189040cf3421a Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Thu, 20 Nov 2014 12:13:02 -0600 Subject: Greatly increase database generation speed from compressed PPDs where possible --- tdeprint/cups/make_driver_db_cups.cpp | 351 ++++++++++++++++++++++++++++++++++ 1 file changed, 351 insertions(+) create mode 100644 tdeprint/cups/make_driver_db_cups.cpp (limited to 'tdeprint/cups/make_driver_db_cups.cpp') diff --git a/tdeprint/cups/make_driver_db_cups.cpp b/tdeprint/cups/make_driver_db_cups.cpp new file mode 100644 index 000000000..021c77b95 --- /dev/null +++ b/tdeprint/cups/make_driver_db_cups.cpp @@ -0,0 +1,351 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001 Michael Goffioul + * Copyright (c) 2014 Timothy Pearson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +extern "C" { + #include "driverparse.h" +} + +#define PROCESS_PPD_FILE_CONTENTS \ + memset(value,0,256); \ + c1 = strchr(line,':'); \ + if (c1) \ + { \ + c2 = strchr(c1,'"'); \ + if (c2) \ + { \ + c2++; \ + c1 = strchr(c2,'"'); \ + if (c1) strlcpy(value,c2,c1-c2+1); \ + } \ + else \ + { \ + c1++; \ + while (*c1 && isspace(*c1)) \ + c1++; \ + if (!*c1) \ + continue; \ + c2 = line+strlen(line)-1; /* point to \n */ \ + while (*c2 && isspace(*c2)) \ + c2--; \ + strlcpy(value,c1,c2-c1+2); \ + } \ + } \ + count++; \ + if (strncmp(line,"*Manufacturer:",14) == 0) fprintf(output_file,"MANUFACTURER=%s\n",value); \ + else if (strncmp(line,"*ShortNickName:",15) == 0) fprintf(output_file,"MODEL=%s\n",value); \ + else if (strncmp(line,"*ModelName:",11) == 0) fprintf(output_file,"MODELNAME=%s\n",value); \ + else if (strncmp(line,"*NickName:",10) == 0) strncat(desc,value,255-strlen(desc)); \ + else if (strncmp(line,"*pnpManufacturer:",17) == 0) fprintf(output_file,"PNPMANUFACTURER=%s\n",value); \ + else if (strncmp(line,"*pnpModel:",10) == 0) fprintf(output_file,"PNPMODEL=%s\n",value); \ + else if (strncmp(line,"*LanguageVersion:",17) == 0) strncat(langver,value,63-strlen(langver)); \ + else count--; \ + /* Either we got everything we needed, or we encountered an "OpenUI" directive \ + * and it's reasonable to assume that there's no needed info further in the file, \ + * just stop here */ \ + if (count >= 7 || strncmp(line, "*OpenUI", 7) == 0) \ + { \ + if (strlen(langver) > 0) \ + { \ + strncat(desc, " [", 255-strlen(desc)); \ + strncat(desc, langver, 255-strlen(desc)); \ + strncat(desc, "]", 255-strlen(desc)); \ + } \ + if (strlen(desc) > 0) \ + fprintf(output_file, "DESCRIPTION=%s\n", desc); \ + break; \ + } + +void initPpd(const char *dirname) +{ + struct stat stat_res; + if (stat(dirname, &stat_res) == -1) { + fprintf(stderr, "Can't open drivers directory : %s\n", dirname); + return; + } + + if (S_ISDIR(stat_res.st_mode)) { + DIR *dir = opendir(dirname); + struct dirent *entry; + char buffer[4096] = {0}; + char drFile[256]; + int len = strlen(dirname); + + if (dir == NULL) + { + fprintf(stderr, "Can't open drivers directory : %s\n", dirname); + return; + } + while ((entry=readdir(dir)) != NULL) + { + if (strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0) + { + continue; + } + if (len+strlen(entry->d_name)+1 < 4096) + { + struct stat st; + + strcpy(buffer,dirname); + strcat(buffer,"/"); + strcat(buffer,entry->d_name); + if (stat(buffer,&st) == 0) + { + if (S_ISDIR(st.st_mode)) + { + initPpd(buffer); + } + else if (S_ISREG(st.st_mode)) + { + char *c = strrchr(buffer,'.'); + snprintf(drFile, 255, "ppd:%s", buffer); + if (c && strncmp(c,".ppd",4) == 0) + { + addFile(drFile, "", ""); + } + else if (c && strncmp(c, ".gz", 3) == 0) + { /* keep also compressed driver files */ + while (c != buffer) + { + if (*(--c) == '.') break; + } + if (*c == '.' && strncmp(c, ".ppd",4) == 0) + { + addFile(drFile, "", ""); + } + } + } + } + } + } + closedir(dir); + } + else if (access(dirname, X_OK) != -1) { + char *filename; + int n = strlen(dirname)+strlen(" list"); + filename = (char*)malloc(n*sizeof(char)+1); + memset(filename,0,n); + strcat(filename, dirname); + strcat(filename, " list"); + + FILE* file = popen(filename, "r"); + if (file) { + char * line = NULL; + size_t len = 0; + ssize_t read; + while ((read = getline(&line, &len, file)) != -1) { + char * pos1 = strstr(line, "\""); + if (pos1 != NULL) { + char * pos2 = strstr(pos1 + 1, "\""); + if (pos2 != NULL) { + *pos2 = 0; + char * pos3 = strstr(pos1 + 1, ":"); + if (pos3 != NULL) { + char *ppduri; + int n2 = strlen("compressed-ppd:")+strlen(pos3+1); + ppduri = (char*)malloc(n2*sizeof(char)+1); + memset(ppduri,0,n2); + strcat(ppduri, "compressed-ppd:"); + strcat(ppduri, pos3+1); + addFile(ppduri, dirname, pos2+1); + free(ppduri); + ppduri = NULL; + } + } + } + } + if (line) { + free(line); + } + + pclose(file); + } + else { + fprintf(stderr, "Can't execute compressed driver handler : %s\n", dirname); + } + + free(filename); + filename = NULL; + } + else { + fprintf(stderr, "Can't open drivers directory : %s\n", dirname); + return; + } +} + +int parsePpdFile(const char *filename, const char *origin, const char *metadata, FILE *output_file) +{ + gzFile ppd_file; + char line[4096], value[256], langver[64] = {0}, desc[256] = {0}; + char *c1, *c2; + int count = 0; + + ppd_file = gzopen(filename,"r"); + if (ppd_file == NULL) + { + fprintf(stderr, "Can't open driver file : %s\n", filename); + return 0; + } + fprintf(output_file,"FILE=ppd:%s\n",filename); + + while (gzgets(ppd_file,line,4095) != Z_NULL) + { + PROCESS_PPD_FILE_CONTENTS + } + fprintf(output_file,"\n"); + + gzclose(ppd_file); + return 1; +} + +int parseCompressedPpdFile(const char *ppdfilename, const char *origin, const char *metadata, FILE *output_file) +{ + char value[256], langver[64] = {0}, desc[256] = {0}; + char *c1, *c2; + int count = 0; + + bool useFallbackExtractionMethod = false; + + if (strlen(metadata) > 0) { + TQString metadataProcessed(metadata); + metadataProcessed = metadataProcessed.stripWhiteSpace(); + TQStringList metadataList = TQStringList::split(" ", metadataProcessed, TRUE); + TQLocale ppdLanguage(metadataList[0]); + TQString languageVersion = TQLocale::languageToString(ppdLanguage.language()); + metadataList = TQStringList::split("\" \"", metadataProcessed, TRUE); + TQString description = metadataList[1]; + + int pos = metadataProcessed.find("MFG:"); + if (pos < 0) { + pos = metadataProcessed.find("MANUFACTURER:"); + } + if (pos >= 0) { + TQString manufacturer; + TQString model; + TQString modelName; + TQString pnpManufacturer; + TQString pnpModel; + TQString driver; + TQStringList metadataList = TQStringList::split(";", metadataProcessed.mid(pos), TRUE); + for (TQStringList::Iterator it = metadataList.begin(); it != metadataList.end(); ++it) { + TQStringList kvPair = TQStringList::split(":", *it, TRUE); + if ((kvPair[0].upper() == "MFG") || (kvPair[0].upper() == "MANUFACTURER")) { + manufacturer = kvPair[1]; + } + else if ((kvPair[0].upper() == "MDL") ||(kvPair[0].upper() == "MODEL")) { + modelName = kvPair[1]; + } +// else if (kvPair[0].upper() == "PNPMANUFACTURER") { +// pnpManufacturer = kvPair[1]; +// } +// else if (kvPair[0].upper() == "PNPMODEL") { +// pnpModel = kvPair[1]; +// } + else if ((kvPair[0].upper() == "DRV") || (kvPair[0].upper() == "DRIVER")) { + driver = kvPair[1]; + } + } + + TQStringList driverList = TQStringList::split(",", driver, TRUE); + driver = driverList[0]; + if (driver.startsWith("D")) { + driver = driver.mid(1); + } + model = manufacturer + " " + modelName + " " + driver; + description = description + " [" + languageVersion + "]"; + + fprintf(output_file,"FILE=compressed-ppd:%s:%s\n", origin, ppdfilename); + + fprintf(output_file,"MANUFACTURER=%s\n",manufacturer.ascii()); + fprintf(output_file,"MODELNAME=%s\n",modelName.ascii()); + fprintf(output_file,"MODEL=%s\n",model.ascii()); + if (pnpManufacturer.length() > 0) { + fprintf(output_file,"PNPMANUFACTURER=%s\n",pnpManufacturer.ascii()); + } + if (pnpModel.length() > 0) { + fprintf(output_file,"PNPMODEL=%s\n",pnpModel.ascii()); + } + if (description.length() > 0) { + fprintf(output_file,"DESCRIPTION=%s\n",description.ascii()); + } + } + else { + useFallbackExtractionMethod = true; + } + } + + if (useFallbackExtractionMethod) { + char *filename; + int n = strlen(origin)+strlen(" cat ")+strlen(ppdfilename); + filename = (char*)malloc(n*sizeof(char)+1); + memset(filename,0,n); + strcat(filename, origin); + strcat(filename, " cat "); + strcat(filename, ppdfilename); + + FILE* file = popen(filename, "r"); + if (file) { + char * line = NULL; + size_t len = 0; + ssize_t read; + + fprintf(output_file,"FILE=compressed-ppd:%s:%s\n", origin, ppdfilename); + + while ((read = getline(&line, &len, file)) != -1) { + PROCESS_PPD_FILE_CONTENTS + } + if (line) { + free(line); + } + + pclose(file); + } + else { + fprintf(stderr, "Can't open driver file : %s\n", ppdfilename); + return 0; + } + + free(filename); + filename = NULL; + } + + return 1; +} + +int main(int argc, char *argv[]) +{ + registerHandler("ppd:", initPpd, parsePpdFile); + registerHandler("compressed-ppd:", initPpd, parseCompressedPpdFile); + initFoomatic(); + return execute(argc, argv); +} -- cgit v1.2.1