Page MenuHomeFreeBSD

D55399.id172382.diff
No OneTemporary

D55399.id172382.diff

diff --git a/usr.sbin/lpr/lpd/recvjob.c b/usr.sbin/lpr/lpd/recvjob.c
--- a/usr.sbin/lpr/lpd/recvjob.c
+++ b/usr.sbin/lpr/lpd/recvjob.c
@@ -39,22 +39,25 @@
#include <sys/mount.h>
#include <sys/stat.h>
-#include <unistd.h>
-#include <signal.h>
-#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
-#include <syslog.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdckdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
#include "lp.h"
#include "lp.local.h"
#include "ctlinfo.h"
#include "extern.h"
#include "pathnames.h"
-#define ack() (void) write(STDOUT_FILENO, sp, (size_t)1)
+#define digit(ch) ((ch) >= '0' && (ch) <= '9')
/*
* The buffer size to use when reading/writing spool files.
@@ -62,15 +65,16 @@
#define SPL_BUFSIZ BUFSIZ
static char dfname[NAME_MAX]; /* data files */
-static int minfree; /* keep at least minfree blocks available */
-static const char *sp = "";
+static size_t minfree; /* keep at least minfree blocks available */
static char tfname[NAME_MAX]; /* tmp copy of cf before linking */
-static int chksize(int _size);
+static void ack(struct printer *_pp);
+static void nak(struct printer *_pp);
+static int chksize(size_t _size);
static void frecverr(const char *_msg, ...) __printf0like(1, 2);
static int noresponse(void);
static void rcleanup(int _signo);
-static int read_number(const char *_fn);
+static void read_minfree(void);
static int readfile(struct printer *_pp, char *_file, size_t _size);
static int readjob(struct printer *_pp);
@@ -118,7 +122,7 @@
} else if (stat(pp->spool_dir, &stb) < 0)
frecverr("%s: stat(%s): %s", pp->printer, pp->spool_dir,
strerror(errno));
- minfree = 2 * read_number("minfree"); /* scale KB to 512 blocks */
+ read_minfree();
signal(SIGTERM, rcleanup);
signal(SIGPIPE, rcleanup);
@@ -133,12 +137,13 @@
static int
readjob(struct printer *pp)
{
- register int size;
+ ssize_t rlen;
+ size_t len, size;
int cfcnt, dfcnt;
- char *cp, *clastp, *errmsg;
+ char *cp, *clastp, *errmsg, *sep;
char givenid[32], givenhost[MAXHOSTNAMELEN];
- ack();
+ ack(pp);
cfcnt = 0;
dfcnt = 0;
for (;;) {
@@ -148,16 +153,16 @@
cp = line;
clastp = line + sizeof(line) - 1;
do {
- size = read(STDOUT_FILENO, cp, (size_t)1);
- if (size != (ssize_t)1) {
- if (size < (ssize_t)0) {
+ rlen = read(STDOUT_FILENO, cp, 1);
+ if (rlen != 1) {
+ if (rlen < 0) {
frecverr("%s: lost connection",
pp->printer);
/*NOTREACHED*/
}
return (cfcnt);
}
- } while ((*cp++ != '\n') && (cp <= clastp));
+ } while (*cp++ != '\n' && cp <= clastp);
if (cp > clastp) {
frecverr("%s: readjob overflow", pp->printer);
/*NOTREACHED*/
@@ -165,37 +170,38 @@
*--cp = '\0';
cp = line;
switch (*cp++) {
- case '\1': /* cleanup because data sent was bad */
+ case '\1': /* abort print job */
rcleanup(0);
continue;
- case '\2': /* read cf file */
- size = 0;
+ case '\2': /* read control file */
dfcnt = 0;
- while (*cp >= '0' && *cp <= '9')
- size = size * 10 + (*cp++ - '0');
+ for (size = 0; digit(*cp); cp++) {
+ if (ckd_mul(&size, size, 10) ||
+ ckd_add(&size, size, *cp - '0'))
+ break;
+ }
if (*cp++ != ' ')
break;
/*
- * host name has been authenticated, we use our
- * view of the host name since we may be passed
- * something different than what gethostbyaddr()
- * returns
+ * The next six bytes must be "cfA" followed by a
+ * three-digit job number. The rest of the line
+ * is the client host name, but we substitute the
+ * host name we've already authenticated.
*/
- strlcpy(cp + 6, from_host, sizeof(line)
- + (size_t)(line - cp - 6));
- if (strchr(cp, '/')) {
- frecverr("readjob: %s: illegal path name", cp);
- /*NOTREACHED*/
- }
- strlcpy(tfname, cp, sizeof(tfname));
- tfname[sizeof (tfname) - 1] = '\0';
+ if (cp[0] != 'c' || cp[1] != 'f' || cp[2] != 'A' ||
+ !digit(cp[3]) || !digit(cp[4]) || !digit(cp[5]))
+ break;
+ len = snprintf(tfname, sizeof(tfname), "%.6s%s", cp,
+ from_host);
+ if (len >= sizeof(tfname))
+ break;
tfname[0] = 't';
if (!chksize(size)) {
- (void) write(STDOUT_FILENO, "\2", (size_t)1);
+ nak(pp);
continue;
}
- if (!readfile(pp, tfname, (size_t)size)) {
+ if (!readfile(pp, tfname, size)) {
rcleanup(0);
continue;
}
@@ -208,27 +214,37 @@
cfcnt++;
continue;
- case '\3': /* read df file */
+ case '\3': /* read data file */
*givenid = '\0';
*givenhost = '\0';
- size = 0;
- while (*cp >= '0' && *cp <= '9')
- size = size * 10 + (*cp++ - '0');
+ for (size = 0; digit(*cp); cp++) {
+ if (ckd_mul(&size, size, 10) ||
+ ckd_add(&size, size, *cp - '0'))
+ break;
+ }
if (*cp++ != ' ')
break;
- if (strchr(cp, '/')) {
- frecverr("readjob: %s: illegal path name", cp);
- /*NOTREACHED*/
- }
+ /*
+ * The next six bytes must be "dfA" followed by a
+ * three-digit job number. The rest of the line
+ * is the client host name, but we substitute the
+ * host name we've already authenticated.
+ */
+ if (cp[0] != 'd' || cp[1] != 'f' || cp[2] != 'A' ||
+ !digit(cp[3]) || !digit(cp[4]) || !digit(cp[5]))
+ break;
+ len = snprintf(dfname, sizeof(dfname), "%.6s%s", cp,
+ from_host);
+ if (len >= sizeof(dfname))
+ break;
if (!chksize(size)) {
- (void) write(STDOUT_FILENO, "\2", (size_t)1);
+ nak(pp);
continue;
}
- strlcpy(dfname, cp, sizeof(dfname));
dfcnt++;
trstat_init(pp, dfname, dfcnt);
- (void) readfile(pp, dfname, (size_t)size);
- trstat_write(pp, TR_RECVING, (size_t)size, givenid,
+ (void) readfile(pp, dfname, size);
+ trstat_write(pp, TR_RECVING, size, givenid,
from_host, givenhost);
continue;
}
@@ -243,52 +259,55 @@
static int
readfile(struct printer *pp, char *file, size_t size)
{
- register char *cp;
char buf[SPL_BUFSIZ];
- size_t amt, i;
- int err, fd, j;
+ ssize_t rlen, wlen;
+ int err, f0, fd, j;
fd = open(file, O_CREAT|O_EXCL|O_WRONLY, FILMOD);
if (fd < 0) {
- frecverr("%s: readfile: error on open(%s): %s",
- pp->printer, file, strerror(errno));
+ /*
+ * We need to pass the file name to frecverr() so it can
+ * log an error, but frecverr() will then call rcleanup()
+ * which will delete the file if we don't zero out the
+ * first character.
+ */
+ f0 = file[0];
+ file[0] = '\0';
+ frecverr("%s: readfile: error on open(%c%s): %s",
+ pp->printer, f0, file + 1, strerror(errno));
/*NOTREACHED*/
}
- ack();
- err = 0;
- for (i = 0; i < size; i += SPL_BUFSIZ) {
- amt = SPL_BUFSIZ;
- cp = buf;
- if (i + amt > size)
- amt = size - i;
- do {
- j = read(STDOUT_FILENO, cp, amt);
- if (j <= 0) {
- frecverr("%s: lost connection", pp->printer);
+ ack(pp);
+ while (size > 0) {
+ rlen = read(STDOUT_FILENO, buf, MIN(SPL_BUFSIZ, size));
+ if (rlen < 0 && errno == EINTR)
+ continue;
+ if (rlen <= 0) {
+ frecverr("%s: lost connection", pp->printer);
+ /*NOTREACHED*/
+ }
+ size -= rlen;
+ while (rlen > 0) {
+ wlen = write(fd, buf, rlen);
+ if (wlen < 0 && errno == EINTR)
+ continue;
+ if (wlen <= 0) {
+ frecverr("%s: write error on write(%s)",
+ pp->printer, file);
/*NOTREACHED*/
}
- amt -= j;
- cp += j;
- } while (amt > 0);
- amt = SPL_BUFSIZ;
- if (i + amt > size)
- amt = size - i;
- if (write(fd, buf, amt) != (ssize_t)amt) {
- err++;
- break;
+ rlen -= wlen;
}
}
- (void) close(fd);
- if (err) {
+ if (close(fd) != 0) {
frecverr("%s: write error on close(%s)", pp->printer, file);
/*NOTREACHED*/
}
if (noresponse()) { /* file sent had bad data in it */
- if (strchr(file, '/') == NULL)
- (void) unlink(file);
+ (void) unlink(file);
return (0);
}
- ack();
+ ack(pp);
return (1);
}
@@ -297,13 +316,13 @@
{
char resp;
- if (read(STDOUT_FILENO, &resp, (size_t)1) != 1) {
+ if (read(STDOUT_FILENO, &resp, 1) != 1) {
frecverr("lost connection in noresponse()");
/*NOTREACHED*/
}
if (resp == '\0')
return(0);
- return(1);
+ return (1);
}
/*
@@ -311,36 +330,42 @@
* 1 == OK, 0 == Not OK.
*/
static int
-chksize(int size)
+chksize(size_t size)
{
- int64_t spacefree;
struct statfs sfb;
+ size_t avail;
if (statfs(".", &sfb) < 0) {
syslog(LOG_ERR, "%s: %m", "statfs(\".\")");
return (1);
}
- spacefree = sfb.f_bavail * (sfb.f_bsize / 512);
- size = (size + 511) / 512;
- if (minfree + size > spacefree)
- return(0);
- return(1);
+ /* more free space than we can count; possible on 32-bit */
+ if (ckd_mul(&avail, sfb.f_bavail, (sfb.f_bsize / 512)))
+ return (1);
+ /* already at or below minfree */
+ if (avail <= minfree)
+ return (0);
+ /* not enough space */
+ if (avail - minfree <= size / 512)
+ return (0);
+ return (1);
}
-static int
-read_number(const char *fn)
+static void
+read_minfree(void)
{
- char lin[80];
- register FILE *fp;
+ FILE *fp;
- if ((fp = fopen(fn, "r")) == NULL)
- return (0);
- if (fgets(lin, sizeof(lin), fp) == NULL) {
+ minfree = 0;
+ /* read from disk */
+ if ((fp = fopen("minfree", "r")) != NULL) {
+ if (fscanf(fp, "%zu", &minfree) != 1)
+ minfree = 0;
fclose(fp);
- return (0);
}
- fclose(fp);
- return (atoi(lin));
+ /* scale kB to 512-byte blocks */
+ if (ckd_mul(&minfree, minfree, 2))
+ minfree = SIZE_MAX;
}
/*
@@ -351,19 +376,11 @@
{
if (tfname[0] && strchr(tfname, '/') == NULL)
(void) unlink(tfname);
- if (dfname[0] && strchr(dfname, '/') == NULL) {
- do {
- do
- (void) unlink(dfname);
- while (dfname[2]-- != 'A');
- dfname[2] = 'z';
- } while (dfname[0]-- != 'd');
- }
+ if (dfname[0] && strchr(dfname, '/') == NULL)
+ (void) unlink(dfname);
dfname[0] = '\0';
}
-#include <stdarg.h>
-
static void
frecverr(const char *msg, ...)
{
@@ -391,3 +408,17 @@
putchar('\1'); /* return error code */
exit(1);
}
+
+static void
+ack(struct printer *pp)
+{
+ if (write(STDOUT_FILENO, "\0", 1) != 1)
+ frecverr("%s: write error on ack", pp->printer);
+}
+
+static void
+nak(struct printer *pp)
+{
+ if (write(STDOUT_FILENO, "\2", 1) != 1)
+ frecverr("%s: write error on nak", pp->printer);
+}

File Metadata

Mime Type
text/plain
Expires
Thu, May 21, 12:34 PM (13 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28938332
Default Alt Text
D55399.id172382.diff (10 KB)

Event Timeline