usr.sbin/makefs: Sync with sys/vfs/hammer2
[dragonfly.git] / usr.bin / dsynth / subs.c
blob346b56ef3256c435453bff251d30017eedbbff55
1 /*
2 * Copyright (c) 2019-2020 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * This code uses concepts and configuration based on 'synth', by
8 * John R. Marino <draco@marino.st>, which was written in ada.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 * 3. Neither the name of The DragonFly Project nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific, prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
38 #include "dsynth.h"
40 struct logerrinfo {
41 struct logerrinfo *next;
42 char *logid;
43 pid_t pid;
44 long seq;
45 int exited;
48 buildenv_t *BuildEnv;
49 static buildenv_t **BuildEnvTail = &BuildEnv;
51 extern char **environ;
53 static void *dexec_logerr_thread(void *info);
55 #define EINFO_HSIZE 1024
56 #define EINFO_HMASK (EINFO_HSIZE - 1)
58 static struct logerrinfo *EInfo[EINFO_HSIZE];
59 static pthread_t ETid;
60 static int EFds[2];
61 static pthread_cond_t ECond;
63 static __inline
64 struct logerrinfo **
65 einfohash(pid_t pid)
67 return(&EInfo[pid & EINFO_HMASK]);
70 __dead2 void
71 _dfatal(const char *file __unused, int line __unused, const char *func,
72 int do_errno, const char *ctl, ...)
74 va_list va;
76 fprintf(stderr, "%s: ", func);
77 va_start(va, ctl);
78 vfprintf(stderr, ctl, va);
79 va_end(va);
80 if (do_errno & 1)
81 fprintf(stderr, ": %s", strerror(errno));
82 fprintf(stderr, "\n");
83 fflush(stderr);
85 if (do_errno & 2)
86 kill(getpid(), SIGQUIT);
87 exit(1);
90 void
91 _ddprintf(int tab, const char *ctl, ...)
93 va_list va;
95 if (tab)
96 printf("%*.*s", tab, tab, "");
97 va_start(va, ctl);
98 vfprintf(stdout, ctl, va);
99 va_end(va);
102 char *
103 strdup_or_null(char *str)
105 if (str && str[0])
106 return(strdup(str));
107 return NULL;
110 static const char *DLogNames[] = {
111 "00_last_results.log",
112 "01_success_list.log",
113 "02_failure_list.log",
114 "03_ignored_list.log",
115 "04_skipped_list.log",
116 "05_abnormal_command_output.log",
117 "06_obsolete_packages.log",
118 "07_debug.log",
121 static int DLogFd[DLOG_COUNT];
122 static pthread_mutex_t DLogFdMutex;
124 #define arysize(ary) (sizeof((ary)) / sizeof((ary)[0]))
126 static int
127 dlogfd(int which, int modes)
129 char *path;
130 int fd;
132 which &= DLOG_MASK;
133 if ((fd = DLogFd[which]) > 0)
134 return fd;
135 pthread_mutex_lock(&DLogFdMutex);
136 if ((fd = DLogFd[which]) <= 0) {
137 asprintf(&path, "%s/%s", LogsPath, DLogNames[which]);
138 fd = open(path, modes, 0666);
139 DLogFd[which] = fd;
140 free(path);
142 pthread_mutex_unlock(&DLogFdMutex);
144 return fd;
148 void
149 dlogreset(void)
151 int i;
153 ddassert(DLOG_COUNT == arysize(DLogNames));
154 for (i = 0; i < DLOG_COUNT; ++i) {
155 if (DLogFd[i] > 0) {
156 close(DLogFd[i]);
157 DLogFd[i] = -1;
159 (void)dlogfd(i, O_RDWR|O_CREAT|O_TRUNC|O_APPEND);
163 void
164 _dlog(int which, const char *ctl, ...)
166 va_list va;
167 char *buf;
168 char *ptr;
169 size_t len;
170 int fd;
171 int filter;
173 filter = which;
174 which &= DLOG_MASK;
176 ddassert((uint)which < DLOG_COUNT);
177 va_start(va, ctl);
178 vasprintf(&buf, ctl, va);
179 va_end(va);
180 len = strlen(buf);
183 * The special sequence ## right-justfies the text after the ##.
185 * NOTE: Alignment test includes \n so use 80 instead of 79 to
186 * leave one char unused on a 80-column terminal.
188 if ((ptr = strstr(buf, "##")) != NULL) {
189 size_t l2;
190 size_t l1;
191 char *b2;
192 int spc;
194 l1 = (int)(ptr - buf);
195 l2 = len - l1 - 2;
196 if (l1 <= 80 - l2) {
197 spc = 80 - l1 - l2;
198 buf[l1] = 0;
199 asprintf(&b2, "%s%*.*s%s",
200 buf, spc, spc, "", ptr + 2);
201 } else {
202 buf[l1] = 0;
203 asprintf(&b2, "%s%s", buf, ptr + 2);
205 len = strlen(b2);
206 free(buf);
207 buf = b2;
211 * All logs also go to log 00.
213 if (which != DLOG_ALL) {
214 fd = dlogfd(DLOG_ALL, O_RDWR|O_CREAT|O_APPEND);
215 if (fd > 0)
216 write(fd, buf, len);
220 * Nominal log target
222 fd = dlogfd(which, O_RDWR|O_CREAT|O_APPEND);
223 write(fd, buf, len);
226 * If ncurses is not being used, all log output also goes
227 * to stdout, unless filtered.
229 if ((UseNCurses == 0 || (filter & DLOG_STDOUT)) &&
230 (filter & DLOG_FILTER) == 0) {
231 if (ColorOpt) {
232 if (filter & DLOG_GRN)
233 write(1, "\x1b[0;32m", 7);
234 if (filter & DLOG_RED)
235 write(1, "\x1b[0;31m", 7);
237 write(1, buf, len);
238 if (ColorOpt && (filter & (DLOG_GRN|DLOG_RED))) {
239 write(1, "\x1b[0;39m", 7);
242 free(buf);
246 dlog00_fd(void)
248 return(dlogfd(DLOG_ALL, O_RDWR|O_CREAT|O_APPEND));
252 * Bulk and Build environment control. These routines are only called
253 * unthreaded or when dsynth threads are idle.
255 void
256 addbuildenv(const char *label, const char *data, int type)
258 buildenv_t *env;
260 env = calloc(1, sizeof(*env));
261 env->a1 = strdup(label);
262 env->a2 = strdup(data);
263 env->label = env->a1;
264 env->data = env->a2;
265 env->type = type;
266 *BuildEnvTail = env;
267 BuildEnvTail = &env->next;
270 void
271 delbuildenv(const char *label)
273 buildenv_t **envp;
274 buildenv_t *env;
276 envp = &BuildEnv;
277 while ((env = *envp) != NULL) {
278 if (strcmp(env->label, label) == 0) {
279 *envp = env->next;
280 if (env->a1)
281 free(env->a1);
282 if (env->a2)
283 free(env->a2);
284 free(env);
285 } else {
286 envp = &env->next;
289 BuildEnvTail = envp;
292 const char *
293 getbuildenv(const char *label)
295 buildenv_t **envp;
296 buildenv_t *env;
298 envp = &BuildEnv;
299 while ((env = *envp) != NULL) {
300 if (strcmp(env->label, label) == 0)
301 return env->data;
302 envp = &env->next;
304 return NULL;
307 void
308 freestrp(char **strp)
310 if (*strp) {
311 free(*strp);
312 *strp = NULL;
316 void
317 dupstrp(char **strp)
319 if (*strp)
320 *strp = strdup(*strp);
324 ipcreadmsg(int fd, wmsg_t *msg)
326 size_t res;
327 ssize_t r;
328 char *ptr;
330 res = sizeof(*msg);
331 ptr = (char *)(void *)msg;
332 while (res) {
333 r = read(fd, ptr, res);
334 if (r <= 0) {
335 if (errno == EINTR)
336 continue;
337 return -1;
339 res -= (size_t)r;
340 ptr += r;
342 return 0;
346 ipcwritemsg(int fd, wmsg_t *msg)
348 size_t res;
349 ssize_t r;
350 char *ptr;
352 res = sizeof(*msg);
353 ptr = (char *)(void *)msg;
354 while (res) {
355 r = write(fd, ptr, res);
356 if (r < 0) {
357 if (errno == EINTR)
358 continue;
359 return -1;
361 res -= (size_t)r;
362 ptr += r;
364 return 0;
368 askyn(const char *ctl, ...)
370 va_list va;
371 char buf[256];
372 int res = 0;
374 if (YesOpt)
375 return 1;
377 for (;;) {
378 va_start(va, ctl);
379 vprintf(ctl, va);
380 va_end(va);
381 fflush(stdout);
382 if (fgets(buf, sizeof(buf), stdin) == NULL)
383 break;
384 if (buf[0] == 'y' || buf[0] == 'Y') {
385 res = 1;
386 break;
388 if (buf[0] == 'n' || buf[0] == 'N') {
389 res = 0;
390 break;
392 printf("Please type y/n\n");
394 return res;
398 * Get swap% used 0.0-1.0.
400 * NOTE: This routine is intended to return quickly.
402 * NOTE: swap_cache (caching for hard drives) is persistent and should
403 * not be counted for our purposes.
405 double
406 getswappct(int *noswapp)
408 long swap_size = 0;
409 long swap_anon = 0;
410 long swap_cache __unused = 0;
411 size_t len;
412 double dswap;
414 len = sizeof(swap_size);
415 sysctlbyname("vm.swap_size", &swap_size, &len, NULL, 0);
416 len = sizeof(swap_size);
417 sysctlbyname("vm.swap_anon_use", &swap_anon, &len, NULL, 0);
418 len = sizeof(swap_size);
419 sysctlbyname("vm.swap_cache_use", &swap_cache, &len, NULL, 0);
420 if (swap_size) {
421 dswap = (double)(swap_anon /*+swap_cache*/) / (double)swap_size;
422 *noswapp = 0;
423 } else {
424 dswap = 0.0;
425 *noswapp = 1;
427 return dswap;
431 * dexec_open()/fgets/dexec_close()
433 * Similar to popen() but directly exec()s the argument list (cav[0] must
434 * be an absolute path).
436 * If xenv is non-NULL its an array of local buildenv_t's to be used.
437 * The array is terminated with a NULL xenv->label.
439 * If with_env is non-zero the configured environment is included.
441 * If with_mvars is non-zero the make environment is passed as VAR=DATA
442 * elements on the command line.
444 FILE *
445 dexec_open(const char *logid, const char **cav, int cac,
446 pid_t *pidp, buildenv_t *xenv, int with_env, int with_mvars)
448 buildenv_t *benv;
449 const char **cenv;
450 char *allocary[MAXCAC*2];
451 int env_basei;
452 int envi;
453 int alloci;
454 int nullfd;
455 int fds[2]; /* stdout */
456 pid_t pid;
457 FILE *fp;
458 struct logerrinfo *einfo;
459 static int warned;
462 * Error logging thread setup
464 if (ETid == 0) {
465 pthread_mutex_lock(&DLogFdMutex);
466 if (ETid == 0) {
467 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, EFds) < 0)
468 dfatal_errno("socketpair");
469 #ifdef SO_PASSCRED
470 int optval = 1;
471 if (setsockopt(EFds[0], SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < 0) {
472 if (warned == 0) {
473 warned = 1;
474 fprintf(stderr, "SO_PASSCRED not supported\n");
477 #endif
479 pthread_cond_init(&ECond, NULL);
480 pthread_create(&ETid, NULL, dexec_logerr_thread, NULL);
482 pthread_mutex_unlock(&DLogFdMutex);
485 env_basei = 0;
486 #if 0
488 * For now we are ignoring the passed-in environment, so don't
489 * copy the existing environment into the exec environment.
491 while (environ[env_basei])
492 ++env_basei;
493 #endif
494 cenv = calloc(env_basei + MAXCAC, sizeof(char *));
495 for (envi = 0; envi < env_basei; ++envi)
496 cenv[envi] = environ[envi];
498 alloci = 0;
499 for (benv = BuildEnv; benv; benv = benv->next) {
500 if (with_mvars &&
501 (benv->type & BENV_CMDMASK) == BENV_MAKECONF) {
502 asprintf(&allocary[alloci], "%s=%s",
503 benv->label, benv->data);
504 cav[cac++] = allocary[alloci];
505 ++alloci;
507 if (with_env &&
508 (benv->type & BENV_PKGLIST) &&
509 (benv->type & BENV_CMDMASK) == BENV_ENVIRONMENT) {
510 asprintf(&allocary[alloci], "%s=%s",
511 benv->label, benv->data);
512 cenv[envi++] = allocary[alloci];
513 ++alloci;
515 ddassert(cac < MAXCAC && envi - env_basei < MAXCAC);
519 * Extra environment specific to this particular dexec
521 while (xenv && xenv->label) {
522 asprintf(&allocary[alloci], "%s=%s",
523 xenv->label, xenv->data);
524 cenv[envi++] = allocary[alloci];
525 ++alloci;
526 ++xenv;
529 cav[cac] = NULL;
530 cenv[envi] = NULL;
532 if (pipe2(fds, O_CLOEXEC) < 0)
533 dfatal_errno("pipe");
534 nullfd = open("/dev/null", O_RDWR | O_CLOEXEC);
535 if (nullfd < 0)
536 dfatal_errno("open(\"/dev/null\")");
539 * We have to be very careful using vfork(), do only the bare
540 * minimum necessary in the child to set it up and exec it.
542 pid = vfork();
543 if (pid == 0) {
544 #if 0
545 int i;
546 printf("%s", cav[0]);
547 for (i = 0; cav[i]; ++i)
548 printf(" %s", cav[i]);
549 printf("\n");
550 printf("ENV: ");
551 for (i = 0; cenv[i]; ++i)
552 printf(" %s", cenv[i]);
553 #endif
555 if (fds[1] != 1) {
556 dup2(fds[1], 1);
557 close(fds[1]);
559 if (EFds[1] != 2) {
560 dup2(EFds[1], 2);
561 close(EFds[1]);
563 close(fds[0]); /* safety */
564 close(EFds[0]); /* safety */
565 dup2(nullfd, 0); /* no questions! */
566 closefrom(3); /* be nice */
569 * Self-nice to be nice (ignore any error)
571 if (NiceOpt)
572 setpriority(PRIO_PROCESS, 0, NiceOpt);
575 * Throw in some capability restrictions
577 set_capability_restrictions();
579 execve(cav[0], (void *)cav, (void *)cenv);
580 write(2, "EXEC FAILURE\n", 13);
581 _exit(1);
583 close(nullfd);
584 close(fds[1]);
585 if (pid < 0) {
586 close(fds[0]);
587 dfatal_errno("vfork failed");
589 fp = fdopen(fds[0], "r");
590 *pidp = pid;
593 * einfo setup
595 einfo = calloc(1, sizeof(*einfo));
596 if (logid)
597 einfo->logid = strdup(logid);
599 pthread_mutex_lock(&DLogFdMutex);
600 einfo->pid = pid;
601 einfo->next = *einfohash(pid);
602 *einfohash(pid) = einfo;
603 pthread_cond_signal(&ECond);
604 pthread_mutex_unlock(&DLogFdMutex);
606 while (--alloci >= 0)
607 free(allocary[alloci]);
608 free(cenv);
610 return fp;
614 dexec_close(FILE *fp, pid_t pid)
616 struct logerrinfo **einfop;
617 struct logerrinfo *einfo;
618 pid_t rpid;
619 int status;
621 fclose(fp);
622 while ((rpid = waitpid(pid, &status, 0)) != pid) {
623 if (rpid < 0) {
624 if (errno == EINTR)
625 continue;
626 return 1;
630 pthread_mutex_lock(&DLogFdMutex);
631 einfop = einfohash(pid);
632 while ((einfo = *einfop) != NULL) {
633 if (einfo->pid == pid) {
634 einfo->exited = 1;
635 break;
637 einfop = &einfo->next;
639 pthread_mutex_unlock(&DLogFdMutex);
641 return (WEXITSTATUS(status));
644 static void *
645 dexec_logerr_thread(void *dummy __unused)
647 char buf[4096];
648 union {
649 char cbuf[CMSG_SPACE(sizeof(struct ucred))];
650 struct cmsghdr cbuf_align;
651 } cmsg_buf;
652 struct cmsghdr *cmsg;
653 struct logerrinfo **einfop;
654 struct logerrinfo *einfo;
655 struct msghdr msg;
656 struct iovec iov;
657 ssize_t len;
658 int mflags = MSG_DONTWAIT;
659 int fd;
661 pthread_detach(pthread_self());
663 msg.msg_name = NULL;
664 msg.msg_namelen = 0;
665 msg.msg_iov = &iov;
667 msg.msg_control = cmsg_buf.cbuf;
668 msg.msg_controllen = sizeof(cmsg_buf.cbuf);
670 fd = EFds[0];
671 for (;;) {
672 int i;
674 msg.msg_iovlen = 1;
675 iov.iov_base = buf;
676 iov.iov_len = sizeof(buf) - 1;
679 * Wait for message, if none are pending then clean-up
680 * exited einfos (this ensures that we have flushed all
681 * error output before freeing the structure).
683 * Don't obtain the mutex until we really need it. The
684 * parent thread can only 'add' einfo entries to the hash
685 * table so we are basically scan-safe.
687 len = recvmsg(fd, &msg, mflags);
688 if (len < 0) {
689 if (errno != EAGAIN) { /* something messed up */
690 fprintf(stderr, "ERRNO %d\n", errno);
691 break;
694 for (i = 0; i < EINFO_HSIZE; ++i) {
695 einfo = EInfo[i];
696 while (einfo) {
697 if (einfo->exited)
698 break;
699 einfo = einfo->next;
701 if (einfo == NULL)
702 continue;
703 pthread_mutex_lock(&DLogFdMutex);
704 einfop = &EInfo[i];
705 while ((einfo = *einfop) != NULL) {
706 if (einfo->exited) {
707 *einfop = einfo->next;
708 if (einfo->logid)
709 free(einfo->logid);
710 free(einfo);
711 } else {
712 einfop = &einfo->next;
715 pthread_mutex_unlock(&DLogFdMutex);
717 mflags = 0;
718 continue;
722 * Process SCM_CREDS, if present. Throw away SCM_RIGHTS
723 * if some sub-process stupidly sent it.
725 einfo = NULL;
726 mflags = MSG_DONTWAIT;
728 if (len && buf[len-1] == '\n')
729 --len;
730 buf[len] = 0;
732 for (cmsg = CMSG_FIRSTHDR(&msg);
733 cmsg;
734 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
735 struct cmsgcred *cred;
736 int *fds;
737 int n;
739 if (cmsg->cmsg_level != SOL_SOCKET)
740 continue;
742 switch(cmsg->cmsg_type) {
743 case SCM_CREDS:
745 cred = (void *)CMSG_DATA(cmsg);
747 einfo = *einfohash(cred->cmcred_pid);
748 while (einfo && einfo->pid != cred->cmcred_pid)
749 einfo = einfo->next;
750 break;
751 case SCM_RIGHTS:
752 fds = (void *)CMSG_DATA(cmsg);
753 n = (cmsg->cmsg_len - sizeof(cmsg)) /
754 sizeof(int);
755 for (i = 0; i < n; ++i)
756 close(fds[i]);
757 break;
761 if (einfo && einfo->logid) {
762 dlog(DLOG_ALL | DLOG_STDOUT,
763 "%s: %s\n",
764 einfo->logid, buf);
765 } else {
766 dlog(DLOG_ALL | DLOG_STDOUT, "%s", buf);
769 return NULL;
772 const char *
773 getphasestr(worker_phase_t phaseid)
775 const char *phase;
777 switch(phaseid) {
778 case PHASE_PENDING:
779 phase = "pending";
780 break;
781 case PHASE_INSTALL_PKGS:
782 phase = "install-pkgs";
783 break;
784 case PHASE_CHECK_SANITY:
785 phase = "check-sanity";
786 break;
787 case PHASE_PKG_DEPENDS:
788 phase = "pkg-depends";
789 break;
790 case PHASE_FETCH_DEPENDS:
791 phase = "fetch-depends";
792 break;
793 case PHASE_FETCH:
794 phase = "fetch";
795 break;
796 case PHASE_CHECKSUM:
797 phase = "checksum";
798 break;
799 case PHASE_EXTRACT_DEPENDS:
800 phase = "extract-depends";
801 break;
802 case PHASE_EXTRACT:
803 phase = "extract";
804 break;
805 case PHASE_PATCH_DEPENDS:
806 phase = "patch-depends";
807 break;
808 case PHASE_PATCH:
809 phase = "patch";
810 break;
811 case PHASE_BUILD_DEPENDS:
812 phase = "build-depends";
813 break;
814 case PHASE_LIB_DEPENDS:
815 phase = "lib-depends";
816 break;
817 case PHASE_CONFIGURE:
818 phase = "configure";
819 break;
820 case PHASE_BUILD:
821 phase = "build";
822 break;
823 case PHASE_RUN_DEPENDS:
824 phase = "run-depends";
825 break;
826 case PHASE_STAGE:
827 phase = "stage";
828 break;
829 case PHASE_TEST:
830 phase = "test";
831 break;
832 case PHASE_CHECK_PLIST:
833 phase = "check-plist";
834 break;
835 case PHASE_PACKAGE:
836 phase = "package";
837 break;
838 case PHASE_INSTALL:
839 phase = "install";
840 break;
841 case PHASE_DEINSTALL:
842 phase = "deinstall";
843 break;
844 case PHASE_DUMP_ENV:
845 phase = "dump-env";
846 break;
847 case PHASE_DUMP_VAR:
848 phase = "dump-var";
849 break;
850 case PHASE_SHOW_CONFIG:
851 phase = "show-config";
852 break;
853 case PHASE_DUMP_MAKECONF:
854 phase = "make-conf";
855 break;
856 default:
857 phase = "Run-Unknown";
858 break;
860 return phase;
864 readlogline(monitorlog_t *log, char **bufp)
866 int r;
867 int n;
870 * Reset buffer as an optimization to avoid unnecessary
871 * shifts.
873 *bufp = NULL;
874 if (log->buf_beg == log->buf_end) {
875 log->buf_beg = 0;
876 log->buf_end = 0;
877 log->buf_scan = 0;
881 * Look for newline, handle discard mode
883 again:
884 for (n = log->buf_scan; n < log->buf_end; ++n) {
885 if (log->buf[n] == '\n') {
886 *bufp = log->buf + log->buf_beg;
887 r = n - log->buf_beg;
888 log->buf_beg = n + 1;
889 log->buf_scan = n + 1;
891 if (log->buf_discard_mode == 0)
892 return r;
893 log->buf_discard_mode = 0;
894 goto again;
899 * Handle overflow
901 if (n == sizeof(log->buf)) {
902 if (log->buf_beg) {
904 * Shift the buffer to make room and read more data.
906 bcopy(log->buf + log->buf_beg,
907 log->buf,
908 n - log->buf_beg);
909 log->buf_end -= log->buf_beg;
910 log->buf_scan -= log->buf_beg;
911 n -= log->buf_beg;
912 log->buf_beg = 0;
913 } else if (log->buf_discard_mode) {
915 * Overflow. If in discard mode just throw it all
916 * away. Stay in discard mode.
918 log->buf_beg = 0;
919 log->buf_end = 0;
920 log->buf_scan = 0;
921 } else {
923 * Overflow. If not in discard mode return a truncated
924 * line and enter discard mode.
926 * The caller will temporarily set ptr[r] = 0 so make
927 * sure that does not overflow our buffer as we are not
928 * at a newline.
930 * (log->buf_beg is 0);
932 *bufp = log->buf + log->buf_beg;
933 r = n - 1;
934 log->buf_beg = n;
935 log->buf_scan = n;
936 log->buf_discard_mode = 1;
938 return r;
943 * Read more data. If there is no data pending then return -1,
944 * otherwise loop up to see if more complete line(s) are available.
946 r = pread(log->fd,
947 log->buf + log->buf_end,
948 sizeof(log->buf) - log->buf_end,
949 log->offset);
950 if (r <= 0)
951 return -1;
952 log->offset += r;
953 log->buf_end += r;
954 goto again;
957 uint32_t
958 crcDirTree(const char *path)
960 FTS *fts;
961 FTSENT *fen;
962 struct stat *st;
963 char *pav[2];
964 uint32_t crc;
965 uint32_t val;
967 crc = 0;
968 pav[0] = strdup(path);
969 pav[1] = NULL;
971 fts = fts_open(pav, FTS_PHYSICAL | FTS_NOCHDIR, NULL);
972 if (fts == NULL)
973 goto failed;
974 while ((fen = fts_read(fts)) != NULL) {
975 if (fen->fts_info != FTS_F && fen->fts_info != FTS_SL)
976 continue;
978 * Ignore hidden dot files or ones ending with .core from the
979 * calculated CRC sum to prevent unnecessary rebuilds.
981 if (fen->fts_name[0] == '.')
982 continue;
983 if (fen->fts_namelen >= 5 &&
984 !strcmp(fen->fts_name + fen->fts_namelen - 5, ".core")) {
985 continue;
988 st = fen->fts_statp;
990 val = iscsi_crc32(&st->st_mtime, sizeof(st->st_mtime));
991 val = iscsi_crc32_ext(&st->st_size, sizeof(st->st_size), val);
992 val = iscsi_crc32_ext(fen->fts_path, fen->fts_pathlen, val);
993 crc ^= val;
995 fts_close(fts);
996 failed:
997 free(pav[0]);
999 return crc;
1002 void
1003 set_capability_restrictions(void)
1005 if (CapabilityRestrictions) {
1006 syscap_set(SYSCAP_RESTRICTEDROOT, __SYSCAP_ALL,
1007 NULL, 0);
1008 syscap_set(SYSCAP_SENSITIVEROOT, __SYSCAP_ALL,
1009 NULL, 0);
1010 syscap_set(SYSCAP_NONET_SENSITIVE, __SYSCAP_ALL,
1011 NULL, 0);
1012 syscap_set(SYSCAP_NOVFS_SENSITIVE, __SYSCAP_ALL,
1013 NULL, 0);
1014 syscap_set(SYSCAP_NOMOUNT, __SYSCAP_ALL,
1015 NULL, 0);
1016 syscap_set(SYSCAP_NOJAIL, __SYSCAP_ALL,
1017 NULL, 0);
1018 syscap_set(SYSCAP_NONET_RESPORT, __SYSCAP_ALL,
1019 NULL, 0);
1020 syscap_set(SYSCAP_NONET_RAW, __SYSCAP_ALL,
1021 NULL, 0);