1 /* $OpenBSD: lp.c,v 1.3 2020/03/16 20:46:44 benno Exp $ */ 2 3 /* 4 * Copyright (c) 2017 Eric Faurot <eric@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/mount.h> 21 #include <sys/stat.h> 22 23 #include <ctype.h> 24 #include <dirent.h> 25 #include <errno.h> 26 #include <fcntl.h> 27 #include <limits.h> 28 #include <signal.h> 29 #include <stdarg.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <unistd.h> 33 34 #include "lp.h" 35 36 #include "log.h" 37 38 #define XXX_PID_MAX 99999 39 40 struct qentry { 41 char *name; 42 time_t mtime; 43 }; 44 45 static int readent(struct lp_printer *, char *); 46 static int qentrycmp(const void *, const void *); 47 static int fullpath(struct lp_printer *, const char *, char *, size_t); 48 static int checksize(struct lp_printer *, size_t); 49 50 static int scanning; 51 static char *db[] = { 52 _PATH_PRINTCAP, 53 NULL, 54 }; 55 56 /* 57 * Fill a printer structure from its /etc/printcap entry. 58 * Return 0 on success, or -1 on error. 59 */ 60 int 61 lp_getprinter(struct lp_printer *lp, const char *name) 62 { 63 char *buf = NULL; 64 int r; 65 66 memset(lp, 0, sizeof(*lp)); 67 68 r = cgetent(&buf, db, name); 69 if (r == 0) 70 r = readent(lp, buf); 71 free(buf); 72 73 switch (r) { 74 case -3: 75 log_warnx("%s: potential reference loop", name); 76 break; 77 case -2: 78 log_warn("%s", name); 79 break; 80 case -1: 81 log_warnx("%s: unknown printer", name); 82 break; 83 case 0: 84 return 0; 85 case 1: 86 log_warnx("%s: unresolved tc expansion", name); 87 break; 88 default: 89 log_warnx("%s: unexpected return value %d", name, r); 90 } 91 92 lp_clearprinter(lp); 93 return -1; 94 } 95 96 /* 97 * Iterate over /etc/printcap and fill the printer structure from the next 98 * entry, if any. 99 * 100 * Return 0 if no entry is found. 101 * 1 if a printer is filled. 102 * -1 on error, and set errno. 103 */ 104 int 105 lp_scanprinters(struct lp_printer *lp) 106 { 107 char *buf; 108 int r, saved_errno; 109 110 if (scanning++ == 0) 111 r = cgetfirst(&buf, db); 112 else 113 r = cgetnext(&buf, db); 114 115 if (r == 0) { 116 cgetclose(); 117 scanning = 0; 118 return 0; 119 } else if (r == 1) { 120 memset(lp, 0, sizeof(*lp)); 121 r = readent(lp, buf); 122 free(buf); 123 if (r == -2) 124 goto fail; 125 return 1; 126 } else if (r == -1) 127 fatal("cannot open %s", _PATH_PRINTCAP); 128 else if (r == -2) 129 errno = ELOOP; /* potential reference loop */ 130 131 fail: 132 saved_errno = errno; 133 lp_clearprinter(lp); 134 cgetclose(); 135 scanning = 0; 136 errno = saved_errno; 137 return -1; 138 } 139 140 static int 141 readent(struct lp_printer *lp, char *buf) 142 { 143 char *s; 144 145 s = strchr(buf, ':'); 146 if (s) 147 *s = '\0'; 148 lp->lp_name = strdup(buf); 149 if (s) 150 *s = ':'; 151 if (lp->lp_name == NULL) 152 return -2; 153 154 s = lp->lp_name; 155 while ((s = strchr(s, '|'))) { 156 *s++ = '\0'; 157 if (lp->lp_aliascount < LP_MAXALIASES) 158 lp->lp_aliases[lp->lp_aliascount++] = s; 159 } 160 161 #define CGETSTR(x) if (cgetstr(buf, #x, &(lp->lp_ ## x)) == -2) \ 162 goto fail 163 #define CGETNUM(x, d) if (cgetnum(buf, #x, &(lp->lp_ ## x)) == -1) \ 164 (lp->lp_ ## x) = d; 165 #define CGETBOOL(x) lp->lp_ ## x = cgetcap(buf, #x, ':') ? 1 : 0 166 167 CGETSTR(af); 168 CGETNUM(br, 0); 169 CGETSTR(cf); 170 CGETSTR(df); 171 CGETSTR(ff); 172 CGETBOOL(fo); 173 CGETSTR(gf); 174 CGETBOOL(hl); 175 CGETBOOL(ic); 176 CGETSTR(if); 177 CGETSTR(lf); 178 CGETSTR(lo); 179 CGETSTR(lp); 180 CGETNUM(mc, 0); 181 CGETSTR(ms); 182 CGETNUM(mx, 0); 183 CGETSTR(nd); 184 CGETSTR(nf); 185 CGETSTR(of); 186 CGETNUM(pc, DEFAULT_PC); 187 CGETNUM(pl, DEFAULT_PL); 188 CGETNUM(pw, DEFAULT_PW); 189 CGETNUM(px, 0); 190 CGETNUM(py, 0); 191 CGETSTR(rf); 192 CGETSTR(rg); 193 CGETSTR(rm); 194 CGETSTR(rp); 195 CGETBOOL(rs); 196 CGETBOOL(rw); 197 CGETBOOL(sb); 198 CGETBOOL(sc); 199 CGETSTR(sd); 200 CGETBOOL(sf); 201 CGETBOOL(sh); 202 CGETSTR(st); 203 CGETSTR(tf); 204 CGETSTR(tr); 205 CGETSTR(vf); 206 207 if (lp->lp_rm && lp->lp_rm[0]) { 208 lp->lp_type = PRN_LPR; 209 lp->lp_host = lp->lp_rm; 210 lp->lp_port = NULL; 211 } 212 else if (strchr(LP_LP(lp), '@')) { 213 lp->lp_type = PRN_NET; 214 lp->lp_port = strdup(LP_LP(lp)); 215 lp->lp_host = strchr(lp->lp_port, '@'); 216 *lp->lp_host++ = '\0'; 217 } 218 else { 219 lp->lp_type = PRN_LOCAL; 220 } 221 222 return 0; 223 fail: 224 return -2; 225 } 226 227 void 228 lp_clearprinter(struct lp_printer *lp) 229 { 230 free(lp->lp_name); 231 free(lp->lp_port); 232 if (lp->lp_lock) 233 fclose(lp->lp_lock); 234 free(lp->lp_af); 235 free(lp->lp_cf); 236 free(lp->lp_df); 237 free(lp->lp_ff); 238 free(lp->lp_gf); 239 free(lp->lp_if); 240 free(lp->lp_lf); 241 free(lp->lp_lo); 242 free(lp->lp_lp); 243 free(lp->lp_ms); 244 free(lp->lp_nd); 245 free(lp->lp_nf); 246 free(lp->lp_of); 247 free(lp->lp_rf); 248 free(lp->lp_rg); 249 free(lp->lp_rm); 250 free(lp->lp_rp); 251 free(lp->lp_sd); 252 free(lp->lp_st); 253 free(lp->lp_tf); 254 free(lp->lp_tr); 255 free(lp->lp_vf); 256 memset(lp, 0, sizeof(*lp)); 257 } 258 259 static int 260 qentrycmp(const void *aa, const void *bb) 261 { 262 const struct qentry *a = aa, *b = bb; 263 264 if (a->mtime < b->mtime) 265 return -1; 266 if (a->mtime > b->mtime) 267 return 1; 268 269 return strcmp(a->name, b->name); 270 } 271 272 /* 273 * Read the printer queue content. 274 * Return the task count, or -1 on error. 275 */ 276 int 277 lp_readqueue(struct lp_printer *lp, struct lp_queue *q) 278 { 279 struct qentry *qe = NULL, *tqe; 280 struct dirent *d; 281 struct stat st; 282 size_t len, sz, nqi, nqe = 0, nqa = 0, n, i; 283 char path[PATH_MAX], *end; 284 DIR *dp= NULL; 285 286 len = strlcpy(path, LP_SD(lp), sizeof(path)); 287 if (len == 0 || len >= sizeof(path)) { 288 log_warn("%s: %s: invalid spool directory name", 289 __func__, LP_SD(lp)); 290 goto fail; 291 } 292 293 if ((dp = opendir(path)) == NULL) { 294 log_warn("%s: opendir", __func__); 295 goto fail; 296 } 297 298 if (fstat(dirfd(dp), &st) == -1) { 299 log_warn("%s: fstat", __func__); 300 goto fail; 301 } 302 /* Assume half the files are cf files. */ 303 nqi = st.st_nlink / 2; 304 305 if (path[len-1] != '/') { 306 len = strlcat(path, "/", sizeof(path)); 307 if (len >= sizeof(path)) { 308 errno = ENAMETOOLONG; 309 log_warn("%s: strlcat", __func__); 310 goto fail; 311 } 312 } 313 end = path + len; 314 sz = sizeof(path) - len; 315 316 errno = 0; 317 while ((d = readdir(dp))) { 318 if (d->d_name[0] != 'c' || d->d_name[1] != 'f') 319 continue; 320 321 if (strlen(d->d_name) < 7) 322 continue; 323 324 if (!isdigit((unsigned char)d->d_name[3]) || 325 !isdigit((unsigned char)d->d_name[4]) || 326 !isdigit((unsigned char)d->d_name[5])) 327 continue; 328 329 if (strlcpy(end, d->d_name, sz) >= sz) { 330 errno = ENAMETOOLONG; 331 log_warn("%s: strlcat", __func__); 332 goto fail; 333 } 334 335 if (stat(path, &st) == -1) { 336 log_warn("%s: stat", __func__); 337 goto fail; 338 } 339 340 if (nqe == nqa) { 341 n = nqa ? (nqa + 5) : nqi; 342 tqe = recallocarray(qe, nqa, n, sizeof(*qe)); 343 if (tqe == NULL) { 344 log_warn("%s: recallocarray", __func__); 345 goto fail; 346 } 347 qe = tqe; 348 nqa = n; 349 } 350 351 if ((qe[nqe].name = strdup(d->d_name)) == NULL) { 352 log_warn("%s: strdup", __func__); 353 goto fail; 354 } 355 qe[nqe].mtime = st.st_mtime; 356 nqe++; 357 } 358 if (errno) { 359 log_warn("%s: readdir", __func__); 360 goto fail; 361 } 362 closedir(dp); 363 dp = NULL; 364 365 qsort(qe, nqe, sizeof(*qe), qentrycmp); 366 367 q->count = nqe; 368 q->cfname = calloc(nqe, sizeof(*q->cfname)); 369 if (q->cfname == NULL) { 370 log_warn("%s: calloc", __func__); 371 goto fail; 372 } 373 for (i = 0; i < nqe; i++) 374 q->cfname[i] = qe[i].name; 375 376 free(qe); 377 return nqe; 378 379 fail: 380 if (dp) 381 closedir(dp); 382 for (i = 0; i < nqe; i++) 383 free(qe[i].name); 384 free(qe); 385 lp_clearqueue(q); 386 return -1; 387 } 388 389 void 390 lp_clearqueue(struct lp_queue *q) 391 { 392 int i; 393 394 for (i = 0; i < q->count; i++) 395 free(q->cfname[i]); 396 free(q->cfname); 397 } 398 399 static int 400 fullpath(struct lp_printer *lp, const char *fname, char *dst, size_t sz) 401 { 402 int r; 403 404 r = snprintf(dst, sz, "%s/%s", LP_SD(lp), fname); 405 if (r < 0 || (size_t)r >= sz) { 406 errno = ENAMETOOLONG; 407 return -1; 408 } 409 410 return 0; 411 } 412 413 /* 414 * fopen(3) a file in the printer spooldir for reading. 415 */ 416 FILE * 417 lp_fopen(struct lp_printer *lp, const char *fname) 418 { 419 char path[PATH_MAX]; 420 421 if (fullpath(lp, fname, path, sizeof(path)) == -1) 422 return NULL; 423 424 return fopen(path, "r"); 425 } 426 427 /* 428 * unlink(2) a file in the printer spooldir. 429 */ 430 int 431 lp_unlink(struct lp_printer *lp, const char *fname) 432 { 433 char path[PATH_MAX]; 434 435 if (fullpath(lp, fname, path, sizeof(path)) == -1) 436 return -1; 437 438 return unlink(path); 439 } 440 441 /* 442 * stat(2) a file in the printer spooldir. 443 */ 444 int 445 lp_stat(struct lp_printer *lp, const char *fname, struct stat *st) 446 { 447 char path[PATH_MAX]; 448 449 if (fullpath(lp, fname, path, sizeof(path)) == -1) 450 return -1; 451 452 return stat(path, st); 453 } 454 455 /* 456 * Grab the lockfile for this printer, and associate it to the printer. 457 * Return -1 on error or 0 otherwise. 458 */ 459 int 460 lp_lock(struct lp_printer *lp) 461 { 462 char path[PATH_MAX]; 463 struct stat st; 464 int fd, saved_errno; 465 466 if (lp->lp_lock) { 467 errno = EWOULDBLOCK; 468 return -1; 469 } 470 471 if (fullpath(lp, LP_LO(lp), path, sizeof(path)) == -1) { 472 log_warn("%s: %s", __func__, LP_LO(lp)); 473 return -1; 474 } 475 476 fd = open(path, O_WRONLY|O_CREAT|O_NOFOLLOW|O_NONBLOCK|O_EXLOCK|O_TRUNC, 477 0640); 478 if (fd == -1) { 479 if (errno != EWOULDBLOCK) 480 log_warn("%s: open", __func__); 481 return -1; 482 } 483 484 if (fstat(fd, &st) == -1) { 485 log_warn("%s: fstat", __func__); 486 saved_errno = errno; 487 (void)close(fd); 488 errno = saved_errno; 489 return -1; 490 } 491 492 if (!S_ISREG(st.st_mode)) { 493 errno = EFTYPE; 494 log_warnx("%s: %s: Not a regular file", __func__, path); 495 (void)close(fd); 496 return -1; 497 } 498 499 if ((lp->lp_lock = fdopen(fd, "w")) == NULL) { 500 log_warn("%s: fdopen", __func__); 501 saved_errno = errno; 502 (void)close(fd); 503 errno = saved_errno; 504 return -1; 505 } 506 507 lp_setcurrtask(lp, NULL); 508 509 return 0; 510 } 511 512 /* 513 * Truncate the lock file and close it. 514 */ 515 void 516 lp_unlock(struct lp_printer *lp) 517 { 518 if (ftruncate(fileno(lp->lp_lock), 0) == -1) 519 log_warn("%s: ftruncate", __func__); 520 if (fclose(lp->lp_lock) == EOF) 521 log_warn("%s: fclose", __func__); 522 lp->lp_lock = NULL; 523 } 524 525 int 526 lp_getqueuestate(struct lp_printer *lp, int reset, int *qstate) 527 { 528 FILE *fp; 529 struct stat st; 530 int saved_errno; 531 532 *qstate = 0; 533 534 fp = lp->lp_lock; 535 if (lp->lp_lock == NULL) { 536 fp = lp_fopen(lp, LP_LO(lp)); 537 if (fp == NULL) { 538 if (errno == ENOENT) 539 return 0; 540 log_warn("%s: lp_fopen", __func__); 541 return -1; 542 } 543 } 544 545 if (fstat(fileno(fp), &st) == -1) { 546 log_warn("%s: fstat", __func__); 547 if (lp->lp_lock == NULL) { 548 saved_errno = errno; 549 (void)fclose(fp); 550 errno = saved_errno; 551 } 552 return -1; 553 } 554 555 if (st.st_mode & S_IXUSR) 556 *qstate |= LPQ_PRINTER_DOWN; 557 if (st.st_mode & S_IXGRP) 558 *qstate |= LPQ_QUEUE_OFF; 559 if (st.st_mode & S_IXOTH) { 560 *qstate |= LPQ_QUEUE_UPDATED; 561 if (reset) { 562 st.st_mode &= ~S_IXOTH & 0777; 563 if (fchmod(fileno(lp->lp_lock), st.st_mode) == -1) 564 log_warn("%s: fchmod", __func__); 565 } 566 } 567 568 if (lp->lp_lock == NULL) 569 fclose(fp); 570 571 return 0; 572 } 573 574 /* 575 * Update the current task description in the lock file. 576 * The lock file must be opened. 577 */ 578 void 579 lp_setcurrtask(struct lp_printer *lp, const char *cfile) 580 { 581 int r; 582 583 if (ftruncate(fileno(lp->lp_lock), 0) == -1) 584 log_warn("%s: ftruncate", __func__); 585 586 if (cfile) 587 r = fprintf(lp->lp_lock, "%d\n%s\n", (int)getpid(), cfile); 588 else 589 r = fprintf(lp->lp_lock, "%d\n", (int)getpid()); 590 if (r < 0) 591 log_warn("%s: fprintf", __func__); 592 593 if (fflush(lp->lp_lock) != 0) 594 log_warn("%s: fflush", __func__); 595 } 596 597 /* 598 * Find the pid of the running process if any, and the task being printed. 599 * 600 * Returns -1 on error (errno set). 601 * 0 if no process is running. 602 * 1 if a printer process is up. 603 * 2 if a printer process is up and a file is being printed. 604 */ 605 int 606 lp_getcurrtask(struct lp_printer *lp, pid_t *ppid, char *dst, size_t dstsz) 607 { 608 FILE *fp; 609 const char *errstr; 610 char *line = NULL; 611 size_t linesz = 0; 612 ssize_t len; 613 pid_t pid; 614 int r, saved_errno; 615 616 pid = *ppid = 0; 617 dst[0] = '\0'; 618 r = -1; 619 620 fp = lp_fopen(lp, LP_LO(lp)); 621 if (fp == NULL) { 622 if (errno == ENOENT) 623 return 0; 624 log_warn("%s: lp_fopen", __func__); 625 return -1; 626 } 627 628 while ((len = getline(&line, &linesz, fp)) != -1) { 629 if (line[len-1] == '\n') 630 line[len-1] = '\0'; 631 632 /* Read filename. */ 633 if (pid) { 634 (void)strlcpy(dst, line, dstsz); 635 break; 636 } 637 638 pid = strtonum(line, 2, XXX_PID_MAX, &errstr); 639 if (errstr) { 640 log_warn("%s: strtonum", __func__); 641 goto done; 642 } 643 } 644 645 if ((errno = ferror(fp))) { 646 log_warn("%s: getline", __func__); 647 goto done; 648 } 649 650 r = 0; 651 if (pid == 0) 652 goto done; 653 654 if (kill(pid, 0) == -1 && errno != EPERM) { 655 if (errno != ESRCH) 656 log_warn("%s: kill", __func__); 657 goto done; 658 } 659 660 *ppid = pid; 661 r = dst[0] ? 2 : 1; 662 663 done: 664 free(line); 665 saved_errno = errno; 666 (void)fclose(fp); 667 errno = saved_errno; 668 return r; 669 } 670 671 /* 672 * Read the current printer status file. 673 * Return -1 on error, 0 on success. 674 */ 675 int 676 lp_getstatus(struct lp_printer *lp, char *buf, size_t bufsz) 677 { 678 size_t len; 679 char *line; 680 FILE *fp; 681 int saved_errno; 682 683 buf[0] = '\0'; 684 685 fp = lp_fopen(lp, LP_ST(lp)); 686 if (fp == NULL) { 687 if (errno == ENOENT) 688 return 0; 689 log_warn("%s: lp_fopen", __func__); 690 return -1; 691 } 692 693 line = fgetln(fp, &len); 694 if (line) { 695 if (len >= bufsz) 696 len = bufsz - 1; 697 else if (line[len - 1] == '\n') 698 len--; 699 memmove(buf, line, len); 700 buf[len] = '\0'; 701 } 702 else if ((errno = ferror(fp))) { 703 log_warn("%s: fgetln", __func__); 704 saved_errno = errno; 705 (void)fclose(fp); 706 errno = saved_errno; 707 return -1; 708 } 709 710 (void)fclose(fp); 711 return 0; 712 } 713 714 /* 715 * Update the current printer status. 716 */ 717 void 718 lp_setstatus(struct lp_printer *lp, const char *fmt, ...) 719 { 720 va_list ap; 721 FILE *fp; 722 char path[PATH_MAX], *s; 723 int fd = -1, r, saved_errno; 724 725 va_start(ap, fmt); 726 r = vasprintf(&s, fmt, ap); 727 va_end(ap); 728 729 if (r == -1) { 730 log_warn("%s: vasprintf", __func__); 731 return; 732 } 733 734 if (fullpath(lp, LP_ST(lp), path, sizeof(path)) == -1) { 735 log_warn("%s: fullpath", __func__); 736 free(s); 737 return; 738 } 739 740 fd = open(path, O_WRONLY|O_CREAT|O_NOFOLLOW|O_EXLOCK|O_TRUNC, 0660); 741 if (fd == -1) { 742 log_warn("%s: open", __func__); 743 free(s); 744 return; 745 } 746 747 fp = fdopen(fd, "w"); 748 if (fp == NULL) { 749 log_warn("%s: fdopen", __func__); 750 saved_errno = errno; 751 (void)close(fd); 752 free(s); 753 errno = saved_errno; 754 return; 755 } 756 757 r = fprintf(fp, "%s\n", s); 758 759 if (r <= 0) { 760 log_warn("%s: fprintf", __func__); 761 saved_errno = errno; 762 (void)fclose(fp); 763 free(s); 764 errno = saved_errno; 765 return; 766 } 767 768 (void)fclose(fp); 769 free(s); 770 } 771 772 /* 773 * Check that the given string is a valid filename for the spooler. 774 */ 775 int 776 lp_validfilename(const char *fname, int cf) 777 { 778 size_t len, i; 779 780 len = strlen(fname); 781 if (len <= 6) /* strlen("cfA000") */ 782 return 0; 783 784 if (fname[0] != (cf ? 'c' : 'd') || 785 fname[1] != 'f' || 786 fname[2] < 'A' || 787 fname[2] > 'Z' || 788 !isdigit((unsigned char)fname[3]) || 789 !isdigit((unsigned char)fname[4]) || 790 !isdigit((unsigned char)fname[5])) 791 return 0; 792 793 for (i = 6; i < len; i++) 794 if (!isalpha((unsigned char)fname[i]) && 795 !isdigit((unsigned char)fname[i]) && 796 strchr("-_.", (unsigned char)fname[i]) == NULL) 797 return 0; 798 799 return 1; 800 } 801 802 /* 803 * Create a new control or data file in the printer spooldir. 804 * Control files have there name changed to a temporary name. They are renamed 805 * to their final name by lp_commit(). 806 */ 807 int 808 lp_create(struct lp_printer *lp, int cf, size_t sz, const char *fname) 809 { 810 struct stat st; 811 char path[PATH_MAX]; 812 int fd; 813 814 /* Make sure the file size is acceptable. */ 815 if (checksize(lp, sz) == -1) 816 return -1; 817 818 if (fullpath(lp, fname, path, sizeof(path)) == -1) { 819 log_warn("%s: %s", __func__, fname); 820 return -1; 821 } 822 823 if (cf) { 824 /* 825 * Create a temporay file, but we want to avoid 826 * a collision with the final cf filename. 827 */ 828 /* XXX this would require a lock on .seq */ 829 path[strlen(LP_SD(lp)) + 1] = 'c'; 830 if (stat(path, &st) == 0) { 831 errno = EEXIST; 832 log_warn("%s: %s", __func__, fname); 833 return -1; 834 } 835 path[strlen(LP_SD(lp)) + 1] = 't'; 836 } 837 838 fd = open(path, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, 0660); 839 if (fd == -1) 840 log_warn("%s: open", __func__); 841 842 return fd; 843 } 844 845 /* 846 * Commit the job given by its temporary CF name. 847 * This is done by renaming the temporay CF file name to its final name. 848 * The functions return 0 on success, or -1 on error and set errno. 849 */ 850 int 851 lp_commit(struct lp_printer *lp, const char *cf) 852 { 853 char ipath[PATH_MAX], opath[PATH_MAX]; 854 855 if (fullpath(lp, cf, ipath, sizeof(ipath)) == -1 || 856 fullpath(lp, cf, opath, sizeof(opath)) == -1) 857 return -1; 858 859 ipath[strlen(LP_SD(lp)) + 1] = 't'; 860 opath[strlen(LP_SD(lp)) + 1] = 'c'; 861 862 return rename(ipath, opath); 863 } 864 865 /* 866 * Check if a file size is acceptable. 867 * Return -1 on error or if false (EFBIG or ENOSPC), 0 otherwise. 868 */ 869 static int 870 checksize(struct lp_printer *lp, size_t sz) 871 { 872 struct statfs st; 873 ssize_t len; 874 size_t linesz = 0; 875 off_t req, avail, minfree; 876 char *line = NULL; 877 const char *errstr; 878 FILE *fp; 879 int saved_errno; 880 881 if (sz == 0) { 882 errno = EINVAL; 883 return -1; 884 } 885 886 /* Check printer limit. */ 887 if (lp->lp_mx && sz > (size_t)lp->lp_mx) { 888 errno = EFBIG; 889 return -1; 890 } 891 892 /* 893 * Check for minfree. Note that it does not really guarantee the 894 * directory will not be filled up anyway, since it's not taking 895 * other incoming files into account. 896 */ 897 fp = lp_fopen(lp, "minfree"); 898 if (fp == NULL) { 899 if (errno == ENOENT) 900 return 0; 901 log_warn("%s: lp_fopen", __func__); 902 return -1; 903 } 904 905 len = getline(&line, &linesz, fp); 906 saved_errno = errno; 907 (void)fclose(fp); 908 if (len == -1) { 909 errno = saved_errno; 910 return 0; 911 } 912 913 if (line[len - 1] == '\n') 914 line[len - 1] = '\0'; 915 minfree = strtonum(line, 0, INT_MAX, &errstr); 916 free(line); 917 918 if (errstr) 919 return 0; 920 921 if (statfs(LP_SD(lp), &st) == -1) 922 return 0; 923 924 req = sz / 512 + (sz % 512) ? 1 : 0; 925 avail = st.f_bavail * (st.f_bsize / 512); 926 if (avail < minfree || (avail - minfree) < req) { 927 errno = ENOSPC; 928 return -1; 929 } 930 931 return 0; 932 } 933