diff options
Diffstat (limited to 'source3/printing/printing.c')
-rw-r--r-- | source3/printing/printing.c | 81 |
1 files changed, 52 insertions, 29 deletions
diff --git a/source3/printing/printing.c b/source3/printing/printing.c index 208da5b78b..0344d44d61 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -382,9 +382,13 @@ static uint32 sysjob_to_jobid_value; static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA data, void *state) { - struct printjob *pjob = (struct printjob *)data.dptr; + struct printjob *pjob; int *sysjob = (int *)state; + if (!data.dptr || data.dsize == 0) + return 0; + + pjob = (struct printjob *)data.dptr; if (key.dsize != sizeof(uint32)) return 0; @@ -1408,6 +1412,7 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DE int njobs = 0; const char *printername = lp_const_servicename(snum); struct tdb_print_db *pdb = get_print_db_byname(printername); + BOOL pdb_locked = False; errno = 0; @@ -1457,37 +1462,15 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DE return (uint32)-1; } - /* create the database entry */ - - ZERO_STRUCT(pjob); - - pjob.pid = local_pid; - pjob.sysjob = -1; - pjob.fd = -1; - pjob.starttime = time(NULL); - pjob.status = LPQ_SPOOLING; - pjob.size = 0; - pjob.spooled = False; - pjob.smbjob = True; - pjob.nt_devmode = nt_devmode; - - fstrcpy(pjob.jobname, jobname); - - if ((vuser = get_valid_user_struct(user->vuid)) != NULL) { - fstrcpy(pjob.user, vuser->user.smb_name); - } else { - fstrcpy(pjob.user, uidtoname(user->uid)); - } - - fstrcpy(pjob.queuename, lp_const_servicename(snum)); - - /* lock the database */ + /* Lock the database */ if (tdb_lock_bystring(pdb->tdb, "INFO/nextjob") == -1) { DEBUG(0,("print_job_start: failed to lock printing database %s\n", printername )); release_print_db(pdb); return (uint32)-1; } + pdb_locked = True; + next_jobid = tdb_fetch_int32(pdb->tdb, "INFO/nextjob"); if (next_jobid == -1) next_jobid = 1; @@ -1496,13 +1479,27 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DE if (!print_job_exists(snum, jobid)) break; } - if (jobid == next_jobid || !pjob_store(snum, jobid, &pjob)) { - DEBUG(3, ("print_job_start: either jobid (%d)==next_jobid(%d) or pjob_store failed.\n", + + if (jobid == next_jobid) { + DEBUG(3, ("print_job_start: jobid (%d)==next_jobid(%d).\n", jobid, next_jobid )); jobid = -1; goto fail; } + /* Store a dummy placeholder. This must be quick as we have the lock. */ + { + TDB_DATA dum; + dum.dptr = NULL; + dum.dsize = 0; + if (tdb_store(pdb->tdb, print_key(jobid), dum, TDB_INSERT) == -1) { + DEBUG(3, ("print_job_start: jobid (%d) failed to store placeholder.\n", + jobid )); + jobid = -1; + goto fail; + } + } + if (tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid)==-1) { DEBUG(3, ("print_job_start: failed to store INFO/nextjob.\n")); jobid = -1; @@ -1511,6 +1508,31 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DE /* We've finished with the INFO/nextjob lock. */ tdb_unlock_bystring(pdb->tdb, "INFO/nextjob"); + pdb_locked = False; + + /* create the database entry */ + + ZERO_STRUCT(pjob); + + pjob.pid = local_pid; + pjob.sysjob = -1; + pjob.fd = -1; + pjob.starttime = time(NULL); + pjob.status = LPQ_SPOOLING; + pjob.size = 0; + pjob.spooled = False; + pjob.smbjob = True; + pjob.nt_devmode = nt_devmode; + + fstrcpy(pjob.jobname, jobname); + + if ((vuser = get_valid_user_struct(user->vuid)) != NULL) { + fstrcpy(pjob.user, vuser->user.smb_name); + } else { + fstrcpy(pjob.user, uidtoname(user->uid)); + } + + fstrcpy(pjob.queuename, lp_const_servicename(snum)); /* we have a job entry - now create the spool file */ slprintf(pjob.filename, sizeof(pjob.filename)-1, "%s/%s%.8u.XXXXXX", @@ -1551,7 +1573,8 @@ to open spool file %s.\n", pjob.filename)); if (jobid != -1) pjob_delete(snum, jobid); - tdb_unlock_bystring(pdb->tdb, "INFO/nextjob"); + if (pdb_locked) + tdb_unlock_bystring(pdb->tdb, "INFO/nextjob"); release_print_db(pdb); DEBUG(3, ("print_job_start: returning fail. Error = %s\n", strerror(errno) )); |