From 38b9a80a9d1c1e061e6ffccdddb9d72d9345a61e Mon Sep 17 00:00:00 2001 From: Tim Waugh Date: Aug 20 2014 16:26:01 +0000 Subject: Merge branch 'f21' Conflicts: cups.spec --- diff --git a/cups-str2913.patch b/cups-str2913.patch new file mode 100644 index 0000000..0de987e --- /dev/null +++ b/cups-str2913.patch @@ -0,0 +1,399 @@ +diff -up cups-1.7.5/scheduler/ipp.c.str2913 cups-1.7.5/scheduler/ipp.c +--- cups-1.7.5/scheduler/ipp.c.str2913 2014-08-20 17:19:25.216908923 +0100 ++++ cups-1.7.5/scheduler/ipp.c 2014-08-20 17:21:45.641812985 +0100 +@@ -1531,8 +1531,7 @@ add_job(cupsd_client_t *con, /* I - Cl + } + + if ((attr = ippFindAttribute(con->request, "job-name", IPP_TAG_ZERO)) == NULL) +- ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL, +- "Untitled"); ++ ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL, "Untitled"); + else if ((attr->value_tag != IPP_TAG_NAME && + attr->value_tag != IPP_TAG_NAMELANG) || + attr->num_values != 1) +@@ -1612,6 +1611,9 @@ add_job(cupsd_client_t *con, /* I - Cl + ippDeleteAttribute(job->attrs, auth_info); + } + ++ if ((attr = ippFindAttribute(con->request, "job-name", IPP_TAG_NAME)) != NULL) ++ cupsdSetString(&(job->name), attr->values[0].string.text); ++ + if ((attr = ippFindAttribute(job->attrs, "job-originating-host-name", + IPP_TAG_ZERO)) != NULL) + { +@@ -1706,8 +1708,7 @@ add_job(cupsd_client_t *con, /* I - Cl + ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri", NULL, + printer->uri); + +- if ((attr = ippFindAttribute(job->attrs, "job-k-octets", +- IPP_TAG_INTEGER)) != NULL) ++ if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL) + attr->values[0].integer = 0; + else + ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-k-octets", 0); +@@ -4357,8 +4358,9 @@ copy_banner(cupsd_client_t *con, /* I - + + kbytes = (cupsFileTell(out) + 1023) / 1024; + +- if ((attr = ippFindAttribute(job->attrs, "job-k-octets", +- IPP_TAG_INTEGER)) != NULL) ++ job->koctets += kbytes; ++ ++ if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL) + attr->values[0].integer += kbytes; + + cupsFileClose(out); +@@ -4780,7 +4782,55 @@ copy_job_attrs(cupsd_client_t *con, /* I + "job-uri", NULL, job_uri); + } + +- copy_attrs(con->response, job->attrs, ra, IPP_TAG_JOB, 0, exclude); ++ if (job->attrs) ++ { ++ copy_attrs(con->response, job->attrs, ra, IPP_TAG_JOB, 0, exclude); ++ } ++ else ++ { ++ /* ++ * Generate attributes from the job structure... ++ */ ++ ++ if (!ra || cupsArrayFind(ra, "job-id")) ++ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job->id); ++ ++ if (!ra || cupsArrayFind(ra, "job-k-octets")) ++ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-k-octets", job->koctets); ++ ++ if (job->name && (!ra || cupsArrayFind(ra, "job-name"))) ++ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL, job->name); ++ ++ if (job->username && (!ra || cupsArrayFind(ra, "job-originating-user-name"))) ++ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_NAME, "job-originating-user-name", NULL, job->username); ++ ++ if (!ra || cupsArrayFind(ra, "job-state")) ++ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_ENUM, "job-state", (int)job->state_value); ++ ++ if (!ra || cupsArrayFind(ra, "job-state-reasons")) ++ { ++ switch (job->state_value) ++ { ++ default : /* Should never get here for processing, pending, held, or stopped jobs since they don't get unloaded... */ ++ break; ++ case IPP_JSTATE_ABORTED : ++ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-aborted-by-system"); ++ break; ++ case IPP_JSTATE_CANCELED : ++ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-canceled-by-user"); ++ break; ++ case IPP_JSTATE_COMPLETED : ++ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-completed-successfully"); ++ break; ++ } ++ } ++ ++ if (job->completed_time && (!ra || cupsArrayFind(ra, "time-at-completed"))) ++ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-completed", (int)job->completed_time); ++ ++ if (job->completed_time && (!ra || cupsArrayFind(ra, "time-at-creation"))) ++ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-creation", (int)job->creation_time); ++ } + } + + +@@ -6133,9 +6183,13 @@ get_jobs(cupsd_client_t *con, /* I - C + int port; /* Port portion of URI */ + int job_comparison; /* Job comparison */ + ipp_jstate_t job_state; /* job-state value */ +- int first_job_id; /* First job ID */ +- int limit; /* Maximum number of jobs to return */ ++ int first_job_id = 1, /* First job ID */ ++ first_index = 1, /* First index */ ++ current_index = 0; /* Current index */ ++ int limit = 0; /* Maximum number of jobs to return */ + int count; /* Number of jobs that match */ ++ int need_load_job = 0; /* Do we need to load the job? */ ++ const char *job_attr; /* Job attribute requested */ + ipp_attribute_t *job_ids; /* job-ids attribute */ + cupsd_job_t *job; /* Current job pointer */ + cupsd_printer_t *printer; /* Printer */ +@@ -6301,8 +6355,7 @@ get_jobs(cupsd_client_t *con, /* I - C + * See if they want to limit the number of jobs reported... + */ + +- if ((attr = ippFindAttribute(con->request, "limit", +- IPP_TAG_INTEGER)) != NULL) ++ if ((attr = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER)) != NULL) + { + if (job_ids) + { +@@ -6314,11 +6367,20 @@ get_jobs(cupsd_client_t *con, /* I - C + + limit = attr->values[0].integer; + } +- else +- limit = 0; + +- if ((attr = ippFindAttribute(con->request, "first-job-id", +- IPP_TAG_INTEGER)) != NULL) ++ if ((attr = ippFindAttribute(con->request, "first-index", IPP_TAG_INTEGER)) != NULL) ++ { ++ if (job_ids) ++ { ++ send_ipp_status(con, IPP_CONFLICT, ++ _("The %s attribute cannot be provided with job-ids."), ++ "first-index"); ++ return; ++ } ++ ++ first_index = attr->values[0].integer; ++ } ++ else if ((attr = ippFindAttribute(con->request, "first-job-id", IPP_TAG_INTEGER)) != NULL) + { + if (job_ids) + { +@@ -6330,15 +6392,12 @@ get_jobs(cupsd_client_t *con, /* I - C + + first_job_id = attr->values[0].integer; + } +- else +- first_job_id = 1; + + /* + * See if we only want to see jobs for a specific user... + */ + +- if ((attr = ippFindAttribute(con->request, "my-jobs", +- IPP_TAG_BOOLEAN)) != NULL && job_ids) ++ if ((attr = ippFindAttribute(con->request, "my-jobs", IPP_TAG_BOOLEAN)) != NULL && job_ids) + { + send_ipp_status(con, IPP_CONFLICT, + _("The %s attribute cannot be provided with job-ids."), +@@ -6351,6 +6410,43 @@ get_jobs(cupsd_client_t *con, /* I - C + username[0] = '\0'; + + ra = create_requested_array(con->request); ++ for (job_attr = (char *)cupsArrayFirst(ra); job_attr; job_attr = (char *)cupsArrayNext(ra)) ++ if (strcmp(job_attr, "job-id") && ++ strcmp(job_attr, "job-k-octets") && ++ strcmp(job_attr, "job-media-progress") && ++ strcmp(job_attr, "job-more-info") && ++ strcmp(job_attr, "job-name") && ++ strcmp(job_attr, "job-originating-user-name") && ++ strcmp(job_attr, "job-preserved") && ++ strcmp(job_attr, "job-printer-up-time") && ++ strcmp(job_attr, "job-printer-uri") && ++ strcmp(job_attr, "job-state") && ++ strcmp(job_attr, "job-state-reasons") && ++ strcmp(job_attr, "job-uri") && ++ strcmp(job_attr, "time-at-completed") && ++ strcmp(job_attr, "time-at-creation") && ++ strcmp(job_attr, "number-of-documents")) ++ { ++ need_load_job = 1; ++ break; ++ } ++ ++ if (need_load_job && (limit == 0 || limit > 500) && (list == Jobs || delete_list)) ++ { ++ /* ++ * Limit expensive Get-Jobs for job history to 500 jobs... ++ */ ++ ++ ippAddInteger(con->response, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "limit", 500); ++ ++ if (limit) ++ ippAddInteger(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_INTEGER, "limit", limit); ++ ++ limit = 500; ++ ++ cupsdLogMessage(CUPSD_LOG_INFO, ++ "Limiting Get-Jobs response to %d jobs.", limit); ++ } + + /* + * OK, build a list of jobs for this printer... +@@ -6377,13 +6473,15 @@ get_jobs(cupsd_client_t *con, /* I - C + { + job = cupsdFindJob(job_ids->values[i].integer); + +- cupsdLoadJob(job); +- +- if (!job->attrs) ++ if (need_load_job && !job->attrs) + { +- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: No attributes for job %d", +- job->id); +- continue; ++ cupsdLoadJob(job); ++ ++ if (!job->attrs) ++ { ++ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: No attributes for job %d", job->id); ++ continue; ++ } + } + + if (i > 0) +@@ -6433,13 +6531,19 @@ get_jobs(cupsd_client_t *con, /* I - C + if (job->id < first_job_id) + continue; + +- cupsdLoadJob(job); ++ current_index ++; ++ if (current_index < first_index) ++ continue; + +- if (!job->attrs) ++ if (need_load_job && !job->attrs) + { +- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: No attributes for job %d", +- job->id); +- continue; ++ cupsdLoadJob(job); ++ ++ if (!job->attrs) ++ { ++ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: No attributes for job %d", job->id); ++ continue; ++ } + } + + if (username[0] && _cups_strcasecmp(username, job->username)) +@@ -8173,8 +8277,9 @@ print_job(cupsd_client_t *con, /* I - + + cupsdUpdateQuota(printer, job->username, 0, kbytes); + +- if ((attr = ippFindAttribute(job->attrs, "job-k-octets", +- IPP_TAG_INTEGER)) != NULL) ++ job->koctets += kbytes; ++ ++ if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL) + attr->values[0].integer += kbytes; + + /* +@@ -9410,8 +9515,9 @@ send_document(cupsd_client_t *con, /* I + + cupsdUpdateQuota(printer, job->username, 0, kbytes); + +- if ((attr = ippFindAttribute(job->attrs, "job-k-octets", +- IPP_TAG_INTEGER)) != NULL) ++ job->koctets += kbytes; ++ ++ if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL) + attr->values[0].integer += kbytes; + + snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, job->id, +diff -up cups-1.7.5/scheduler/job.c.str2913 cups-1.7.5/scheduler/job.c +--- cups-1.7.5/scheduler/job.c.str2913 2014-08-20 17:19:25.261909213 +0100 ++++ cups-1.7.5/scheduler/job.c 2014-08-20 17:19:25.272909284 +0100 +@@ -1707,9 +1707,10 @@ cupsdLoadJob(cupsd_job_t *job) /* I - J + job->file_time = 0; + job->history_time = 0; + +- if (job->state_value >= IPP_JOB_CANCELED && +- (attr = ippFindAttribute(job->attrs, "time-at-completed", +- IPP_TAG_INTEGER)) != NULL) ++ if ((attr = ippFindAttribute(job->attrs, "time-at-creation", IPP_TAG_INTEGER)) != NULL) ++ job->creation_time = attr->values[0].integer; ++ ++ if (job->state_value >= IPP_JOB_CANCELED && (attr = ippFindAttribute(job->attrs, "time-at-completed", IPP_TAG_INTEGER)) != NULL) + { + job->completed_time = attr->values[0].integer; + +@@ -1858,6 +1859,12 @@ cupsdLoadJob(cupsd_job_t *job) /* I - J + cupsdSetString(&job->username, attr->values[0].string.text); + } + ++ if (!job->name) ++ { ++ if ((attr = ippFindAttribute(job->attrs, "job-name", IPP_TAG_NAME)) != NULL) ++ cupsdSetString(&job->name, attr->values[0].string.text); ++ } ++ + /* + * Set the job hold-until time and state... + */ +@@ -1882,6 +1889,9 @@ cupsdLoadJob(cupsd_job_t *job) /* I - J + job->state_value = IPP_JOB_PENDING; + } + ++ if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL) ++ job->koctets = attr->values[0].integer; ++ + if (!job->num_files) + { + /* +@@ -2190,14 +2200,18 @@ cupsdSaveAllJobs(void) + { + cupsFilePrintf(fp, "\n", job->id); + cupsFilePrintf(fp, "State %d\n", job->state_value); ++ cupsFilePrintf(fp, "Created %ld\n", (long)job->creation_time); + if (job->completed_time) + cupsFilePrintf(fp, "Completed %ld\n", (long)job->completed_time); + cupsFilePrintf(fp, "Priority %d\n", job->priority); + if (job->hold_until) + cupsFilePrintf(fp, "HoldUntil %ld\n", (long)job->hold_until); + cupsFilePrintf(fp, "Username %s\n", job->username); ++ if (job->name) ++ cupsFilePutConf(fp, "Name", job->name); + cupsFilePrintf(fp, "Destination %s\n", job->dest); + cupsFilePrintf(fp, "DestType %d\n", job->dtype); ++ cupsFilePrintf(fp, "KOctets %d\n", job->koctets); + cupsFilePrintf(fp, "NumFiles %d\n", job->num_files); + for (i = 0; i < job->num_files; i ++) + cupsFilePrintf(fp, "File %d %s/%s %d\n", i + 1, job->filetypes[i]->super, +@@ -4138,7 +4152,7 @@ load_job_cache(const char *filename) /* + cupsArrayAdd(ActiveJobs, job); + else if (job->state_value > IPP_JOB_STOPPED) + { +- if (!job->completed_time) ++ if (!job->completed_time || !job->creation_time || !job->name || !job->koctets) + { + cupsdLoadJob(job); + unload_job(job); +@@ -4161,6 +4175,14 @@ load_job_cache(const char *filename) /* + else if (job->state_value > IPP_JOB_COMPLETED) + job->state_value = IPP_JOB_COMPLETED; + } ++ else if (!_cups_strcasecmp(line, "Name")) ++ { ++ cupsdSetString(&(job->name), value); ++ } ++ else if (!_cups_strcasecmp(line, "Created")) ++ { ++ job->creation_time = strtol(value, NULL, 10); ++ } + else if (!_cups_strcasecmp(line, "Completed")) + { + job->completed_time = strtol(value, NULL, 10); +@@ -4185,6 +4207,10 @@ load_job_cache(const char *filename) /* + { + job->dtype = (cups_ptype_t)atoi(value); + } ++ else if (!_cups_strcasecmp(line, "KOctets")) ++ { ++ job->koctets = atoi(value); ++ } + else if (!_cups_strcasecmp(line, "NumFiles")) + { + job->num_files = atoi(value); +diff -up cups-1.7.5/scheduler/job.h.str2913 cups-1.7.5/scheduler/job.h +--- cups-1.7.5/scheduler/job.h.str2913 2014-08-20 17:19:25.196908795 +0100 ++++ cups-1.7.5/scheduler/job.h 2014-08-20 17:19:25.273909291 +0100 +@@ -39,6 +39,8 @@ struct cupsd_job_s /**** Job request * + * waiting on files */ + char *username; /* Printing user */ + char *dest; /* Destination printer or class */ ++ char *name; /* Job name/title */ ++ int koctets; /* job-k-octets */ + cups_ptype_t dtype; /* Destination type */ + cupsd_printer_t *printer; /* Printer this job is assigned to */ + int num_files; /* Number of files in job */ +@@ -47,6 +49,7 @@ struct cupsd_job_s /**** Job request * + ipp_attribute_t *sheets; /* job-media-sheets-completed */ + time_t access_time, /* Last access time */ + cancel_time, /* When to cancel/send SIGTERM */ ++ creation_time, /* When job was created */ + completed_time, /* When job was completed (0 if not) */ + file_time, /* Job file retain time */ + history_time, /* Job history retain time */ diff --git a/cups-str4396.patch b/cups-str4396.patch new file mode 100644 index 0000000..d399eda --- /dev/null +++ b/cups-str4396.patch @@ -0,0 +1,271 @@ +diff -up cups-1.7.5/CHANGES.txt.str4396 cups-1.7.5/CHANGES.txt +diff -up cups-1.7.5/scheduler/ipp.c.str4396 cups-1.7.5/scheduler/ipp.c +--- cups-1.7.5/scheduler/ipp.c.str4396 2014-08-20 16:56:29.012022421 +0100 ++++ cups-1.7.5/scheduler/ipp.c 2014-08-20 16:56:38.535084011 +0100 +@@ -6595,6 +6595,7 @@ get_jobs(cupsd_client_t *con, /* I - C + cupsd_job_t *job; /* Current job pointer */ + cupsd_printer_t *printer; /* Printer */ + cups_array_t *list; /* Which job list... */ ++ int delete_list = 0; /* Delete the list afterwards? */ + cups_array_t *ra, /* Requested attributes array */ + *exclude; /* Private attributes array */ + cupsd_policy_t *policy; /* Current policy */ +@@ -6694,13 +6695,15 @@ get_jobs(cupsd_client_t *con, /* I - C + { + job_comparison = 1; + job_state = IPP_JOB_CANCELED; +- list = Jobs; ++ list = cupsdGetCompletedJobs(printer); ++ delete_list = 1; + } + else if (!strcmp(attr->values[0].string.text, "aborted")) + { + job_comparison = 0; + job_state = IPP_JOB_ABORTED; +- list = Jobs; ++ list = cupsdGetCompletedJobs(printer); ++ delete_list = 1; + } + else if (!strcmp(attr->values[0].string.text, "all")) + { +@@ -6712,7 +6715,8 @@ get_jobs(cupsd_client_t *con, /* I - C + { + job_comparison = 0; + job_state = IPP_JOB_CANCELED; +- list = Jobs; ++ list = cupsdGetCompletedJobs(printer); ++ delete_list = 1; + } + else if (!strcmp(attr->values[0].string.text, "pending")) + { +@@ -6919,6 +6923,9 @@ get_jobs(cupsd_client_t *con, /* I - C + + cupsArrayDelete(ra); + ++ if (delete_list) ++ cupsArrayDelete(list); ++ + con->response->request.status.status_code = IPP_OK; + } + +diff -up cups-1.7.5/scheduler/job.c.str4396 cups-1.7.5/scheduler/job.c +--- cups-1.7.5/scheduler/job.c.str4396 2014-08-20 16:56:29.013022427 +0100 ++++ cups-1.7.5/scheduler/job.c 2014-08-20 16:56:38.537084024 +0100 +@@ -130,6 +130,7 @@ static mime_filter_t gziptoany_filter = + */ + + static int compare_active_jobs(void *first, void *second, void *data); ++static int compare_completed_jobs(void *first, void *second, void *data); + static int compare_jobs(void *first, void *second, void *data); + static void dump_job_history(cupsd_job_t *job); + static void finalize_job(cupsd_job_t *job, int set_job_state); +@@ -1568,6 +1569,30 @@ cupsdFindJob(int id) /* I - Job ID */ + + + /* ++ * 'cupsdGetCompletedJobs()'- Generate a completed jobs list. ++ */ ++ ++cups_array_t * /* O - Array of jobs */ ++cupsdGetCompletedJobs( ++ cupsd_printer_t *p) /* I - Printer */ ++{ ++ cups_array_t *list; /* Array of jobs */ ++ cupsd_job_t *job; /* Current job */ ++ ++ ++ list = cupsArrayNew(compare_completed_jobs, NULL); ++ ++ for (job = (cupsd_job_t *)cupsArrayFirst(Jobs); ++ job; ++ job = (cupsd_job_t *)cupsArrayNext(Jobs)) ++ if ((!p || !_cups_strcasecmp(p->name, job->dest)) && job->state_value >= IPP_JOB_STOPPED && job->completed_time) ++ cupsArrayAdd(list, job); ++ ++ return (list); ++} ++ ++ ++/* + * 'cupsdGetPrinterJobCount()' - Get the number of pending, processing, + * or held jobs in a printer or class. + */ +@@ -1766,6 +1791,8 @@ cupsdLoadJob(cupsd_job_t *job) /* I - J + (attr = ippFindAttribute(job->attrs, "time-at-completed", + IPP_TAG_INTEGER)) != NULL) + { ++ job->completed_time = attr->values[0].integer; ++ + if (JobHistory < INT_MAX) + job->history_time = attr->values[0].integer + JobHistory; + else +@@ -2257,8 +2284,11 @@ cupsdSaveAllJobs(void) + { + cupsFilePrintf(fp, "\n", job->id); + cupsFilePrintf(fp, "State %d\n", job->state_value); ++ if (job->completed_time) ++ cupsFilePrintf(fp, "Completed %ld\n", (long)job->completed_time); + cupsFilePrintf(fp, "Priority %d\n", job->priority); +- cupsFilePrintf(fp, "HoldUntil %d\n", (int)job->hold_until); ++ if (job->hold_until) ++ cupsFilePrintf(fp, "HoldUntil %ld\n", (long)job->hold_until); + cupsFilePrintf(fp, "Username %s\n", job->username); + cupsFilePrintf(fp, "Destination %s\n", job->dest); + cupsFilePrintf(fp, "DestType %d\n", job->dtype); +@@ -2993,6 +3023,28 @@ compare_active_jobs(void *first, /* I - + + + /* ++ * 'compare_completed_jobs()' - Compare the job IDs and completion times of two jobs. ++ */ ++ ++static int /* O - Difference */ ++compare_completed_jobs(void *first, /* I - First job */ ++ void *second, /* I - Second job */ ++ void *data) /* I - App data (not used) */ ++{ ++ int diff; /* Difference */ ++ ++ ++ (void)data; ++ ++ if ((diff = ((cupsd_job_t *)second)->completed_time - ++ ((cupsd_job_t *)first)->completed_time) != 0) ++ return (diff); ++ else ++ return (((cupsd_job_t *)first)->id - ((cupsd_job_t *)second)->id); ++} ++ ++ ++/* + * 'compare_jobs()' - Compare the job IDs of two jobs. + */ + +@@ -4268,6 +4320,14 @@ load_job_cache(const char *filename) /* + + if (job->state_value <= IPP_JOB_STOPPED && cupsdLoadJob(job)) + cupsArrayAdd(ActiveJobs, job); ++ else if (job->state_value > IPP_JOB_STOPPED) ++ { ++ if (!job->completed_time) ++ { ++ cupsdLoadJob(job); ++ unload_job(job); ++ } ++ } + + job = NULL; + } +@@ -4285,9 +4345,13 @@ load_job_cache(const char *filename) /* + else if (job->state_value > IPP_JOB_COMPLETED) + job->state_value = IPP_JOB_COMPLETED; + } ++ else if (!_cups_strcasecmp(line, "Completed")) ++ { ++ job->completed_time = strtol(value, NULL, 10); ++ } + else if (!_cups_strcasecmp(line, "HoldUntil")) + { +- job->hold_until = atoi(value); ++ job->hold_until = strtol(value, NULL, 10); + } + else if (!_cups_strcasecmp(line, "Priority")) + { +@@ -4625,6 +4689,8 @@ set_time(cupsd_job_t *job, /* I - Job t + + if (!strcmp(name, "time-at-completed")) + { ++ job->completed_time = curtime; ++ + if (JobHistory < INT_MAX && attr) + job->history_time = attr->values[0].integer + JobHistory; + else +diff -up cups-1.7.5/scheduler/job.h.str4396 cups-1.7.5/scheduler/job.h +--- cups-1.7.5/scheduler/job.h.str4396 2014-08-20 16:56:29.013022427 +0100 ++++ cups-1.7.5/scheduler/job.h 2014-08-20 16:56:38.538084031 +0100 +@@ -54,6 +54,7 @@ struct cupsd_job_s /**** Job request * + ipp_attribute_t *sheets; /* job-media-sheets-completed */ + time_t access_time, /* Last access time */ + cancel_time, /* When to cancel/send SIGTERM */ ++ completed_time, /* When job was completed (0 if not) */ + file_time, /* Job file retain time */ + history_time, /* Job history retain time */ + hold_until, /* Hold expiration date/time */ +@@ -156,6 +157,7 @@ extern void cupsdDeleteJob(cupsd_job_t + cupsd_jobaction_t action); + extern cupsd_job_t *cupsdFindJob(int id); + extern void cupsdFreeAllJobs(void); ++extern cups_array_t *cupsdGetCompletedJobs(cupsd_printer_t *p); + extern int cupsdGetPrinterJobCount(const char *dest); + extern int cupsdGetUserJobCount(const char *username); + extern void cupsdLoadAllJobs(void); +diff -up cups-1.7.5/systemv/lpstat.c.str4396 cups-1.7.5/systemv/lpstat.c +--- cups-1.7.5/systemv/lpstat.c.str4396 2014-05-22 14:59:21.000000000 +0100 ++++ cups-1.7.5/systemv/lpstat.c 2014-08-20 16:56:38.539084037 +0100 +@@ -1316,7 +1316,8 @@ show_jobs(const char *dests, /* I - Des + const char *dest, /* Pointer into job-printer-uri */ + *username, /* Pointer to job-originating-user-name */ + *title, /* Pointer to job-name */ +- *message; /* Pointer to job-printer-state-message */ ++ *message, /* Pointer to job-printer-state-message */ ++ *time_at; /* time-at-xxx attribute name to use */ + int rank, /* Rank in queue */ + jobid, /* job-id */ + size; /* job-k-octets */ +@@ -1332,7 +1333,8 @@ show_jobs(const char *dests, /* I - Des + "job-printer-state-message", + "job-printer-uri", + "job-state-reasons", +- "time-at-creation" ++ "time-at-creation", ++ "time-at-completed" + }; + + +@@ -1398,6 +1400,13 @@ show_jobs(const char *dests, /* I - Des + * Loop through the job list and display them... + */ + ++ if (!strcmp(which, "aborted") || ++ !strcmp(which, "canceled") || ++ !strcmp(which, "completed")) ++ time_at = "time-at-completed"; ++ else ++ time_at = "time-at-creation"; ++ + rank = -1; + + for (attr = response->attrs; attr != NULL; attr = attr->next) +@@ -1433,8 +1442,7 @@ show_jobs(const char *dests, /* I - Des + else if (!strcmp(attr->name, "job-k-octets") && + attr->value_tag == IPP_TAG_INTEGER) + size = attr->values[0].integer; +- else if (!strcmp(attr->name, "time-at-creation") && +- attr->value_tag == IPP_TAG_INTEGER) ++ else if (!strcmp(attr->name, time_at) && attr->value_tag == IPP_TAG_INTEGER) + jobtime = attr->values[0].integer; + else if (!strcmp(attr->name, "job-printer-state-message") && + attr->value_tag == IPP_TAG_TEXT) +diff -up cups-1.7.5/test/5.5-lp.sh.str4396 cups-1.7.5/test/5.5-lp.sh +--- cups-1.7.5/test/5.5-lp.sh.str4396 2013-11-06 20:09:03.000000000 +0000 ++++ cups-1.7.5/test/5.5-lp.sh 2014-08-20 16:56:38.540084044 +0100 +@@ -79,6 +79,19 @@ echo "" + + ./waitjobs.sh + ++echo "LPSTAT Completed Jobs Order Test" ++echo "" ++echo " lpstat -W completed -o" ++$VALGRIND ../systemv/lpstat -W completed -o | tee $BASE/lpstat-completed.txt ++if test "`uniq -d $BASE/lpstat-completed.txt`" != ""; then ++ echo " FAILED" ++ exit 1 ++else ++ echo " PASSED" ++fi ++echo "" ++ ++ + # + # End of "$Id: 5.5-lp.sh 11396 2013-11-06 20:09:03Z msweet $". + # diff --git a/cups.spec b/cups.spec index 0c80efb..fd3b5da 100644 --- a/cups.spec +++ b/cups.spec @@ -30,6 +30,7 @@ Source8: macros.cups Patch1: cups-no-gzip-man.patch Patch2: cups-system-auth.patch Patch3: cups-multilib.patch +Patch4: cups-str4396.patch Patch5: cups-banners.patch Patch6: cups-serverbin-compat.patch Patch7: cups-no-export-ssllibs.patch @@ -66,6 +67,7 @@ Patch37: cups-final-content-type.patch Patch38: cups-journal.patch Patch39: cups-synconclose.patch Patch40: cups-str4461.patch +Patch41: cups-str2913.patch Patch100: cups-lspp.patch @@ -193,6 +195,8 @@ Sends IPP requests to the specified URI and tests and/or displays the results. %patch2 -p1 -b .system-auth # Prevent multilib conflict in cups-config script. %patch3 -p1 -b .multilib +# Upstream patch for STR #4396, pre-requisite for STR #2913 patch. +%patch4 -p1 -b .str4396 # Ignore rpm save/new files in the banners directory. %patch5 -p1 -b .banners # Use compatibility fallback path for ServerBin. @@ -267,6 +271,9 @@ Sends IPP requests to the specified URI and tests and/or displays the results. %patch39 -p1 -b .synconclose # Fix conf/log file reading for authenticated users (STR #4461). %patch40 -p1 -b .str4461 +# Upstream patch for STR #2913 to limit Get-Jobs replies to 500 jobs +# (bug #421671). +%patch41 -p1 -b .str2913 %if %lspp # LSPP support. @@ -672,6 +679,9 @@ rm -f %{cups_serverbin}/backend/smb - Removed old one-off trigger now it's no longer needed. - Run systemd postun script for path and socket unit files as well as the main service unit file. +- Upstream patch for STR #4396, pre-requisite for STR #2913 patch. +- Upstream patch for STR #2913 to limit Get-Jobs replies to 500 jobs + (bug #421671). * Sat Aug 16 2014 Fedora Release Engineering - 1:1.7.5-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild