#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/mount.h>
#include <sys/procctl.h>
#include <sys/resource.h>
#include <sys/caps.h>
#if defined(__DragonFly__)
#include <sys/vmmeter.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <fts.h>
#include <ndbm.h>
#include <signal.h>
#include <poll.h>
#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <pthread_np.h>
#include <dirent.h>
#include <termios.h>
#include <time.h>
#include <ctype.h>
#include <libutil.h>
#include <arpa/inet.h>
#include <elf.h>
struct pkglink;
#define DSYNTH_VERSION "1.0.2"
#define MAXWORKERS 1024
#define MAXLOGLINES 1024
#define MAXJOBS 8192
#define MAXBULK MAXWORKERS
#define MAKE_BINARY "/usr/bin/make"
#define PKG_BINARY "/usr/local/sbin/pkg"
#define MOUNT_BINARY "/sbin/mount"
#define UMOUNT_BINARY "/sbin/umount"
#define STATS_FILE "monitor.dat"
#define STATS_LOCKFILE "monitor.lk"
#define ONEGB (1024L * 1024 * 1024)
#define DISABLED_STR "disabled"
#define USE_PKG_SUFX ".txz"
typedef struct pkglink {
struct pkglink *next;
struct pkglink *prev;
struct pkg *pkg;
int dep_type;
} pkglink_t;
#define DEP_TYPE_FETCH 1
#define DEP_TYPE_EXT 2
#define DEP_TYPE_PATCH 3
#define DEP_TYPE_BUILD 4
#define DEP_TYPE_LIB 5
#define DEP_TYPE_RUN 6
typedef struct pkg {
struct pkg *build_next;
struct pkg *bnext;
struct pkg *hnext1;
struct pkg *hnext2;
pkglink_t idepon_list;
pkglink_t deponi_list;
char *portdir;
char *logfile;
char *version;
char *pkgfile;
char *distfiles;
char *distsubdir;
char *ignore;
char *fetch_deps;
char *ext_deps;
char *patch_deps;
char *build_deps;
char *lib_deps;
char *run_deps;
char *pos_options;
char *neg_options;
char *flavors;
char *uses;
int make_jobs_number;
int use_linux;
int idep_count;
int depi_count;
int depi_depth;
int dsynth_install_flg;
int flags;
int rscan;
uint32_t crc32;
size_t pkgfile_size;
} pkg_t;
#define PKGF_PACKAGED 0x00000001
#define PKGF_DUMMY 0x00000002
#define PKGF_NOTFOUND 0x00000004
#define PKGF_CORRUPT 0x00000008
#define PKGF_PLACEHOLD 0x00000010
#define PKGF_BUILDLIST 0x00000020
#define PKGF_BUILDLOOP 0x00000040
#define PKGF_BUILDTRAV 0x00000080
#define PKGF_NOBUILD_D 0x00000100
#define PKGF_NOBUILD_S 0x00000200
#define PKGF_NOBUILD_F 0x00000400
#define PKGF_NOBUILD_I 0x00000800
#define PKGF_SUCCESS 0x00001000
#define PKGF_FAILURE 0x00002000
#define PKGF_RUNNING 0x00004000
#define PKGF_PKGPKG 0x00008000
#define PKGF_NOTREADY 0x00010000
#define PKGF_MANUALSEL 0x00020000
#define PKGF_META 0x00040000
#define PKGF_DEBUGSTOP 0x00080000
#define PKGF_ERROR (PKGF_PLACEHOLD | PKGF_CORRUPT | PKGF_NOTFOUND | \
PKGF_FAILURE)
#define PKGF_NOBUILD (PKGF_NOBUILD_D | PKGF_NOBUILD_S | PKGF_NOBUILD_F | \
PKGF_NOBUILD_I)
#define PKGLIST_EMPTY(pkglink) ((pkglink)->next == (pkglink))
#define PKGLIST_FOREACH(var, head) \
for (var = (head)->next; var != (head); var = (var)->next)
typedef struct bulk {
struct bulk *next;
pthread_t td;
int debug;
int flags;
enum { UNLISTED, ONSUBMIT, ONRUN, ISRUNNING, ONRESPONSE } state;
char *s1;
char *s2;
char *s3;
char *s4;
char *r1;
char *r2;
char *r3;
char *r4;
pkg_t *list;
} bulk_t;
enum worker_state { WORKER_NONE, WORKER_IDLE, WORKER_PENDING,
WORKER_RUNNING, WORKER_DONE, WORKER_FAILED,
WORKER_FROZEN, WORKER_EXITING };
typedef enum worker_state worker_state_t;
enum worker_phase { PHASE_PENDING,
PHASE_INSTALL_PKGS,
PHASE_CHECK_SANITY,
PHASE_PKG_DEPENDS,
PHASE_FETCH_DEPENDS,
PHASE_FETCH,
PHASE_CHECKSUM,
PHASE_EXTRACT_DEPENDS,
PHASE_EXTRACT,
PHASE_PATCH_DEPENDS,
PHASE_PATCH,
PHASE_BUILD_DEPENDS,
PHASE_LIB_DEPENDS,
PHASE_CONFIGURE,
PHASE_BUILD,
PHASE_RUN_DEPENDS,
PHASE_STAGE,
PHASE_TEST,
PHASE_CHECK_PLIST,
PHASE_PACKAGE,
PHASE_INSTALL,
PHASE_DEINSTALL,
PHASE_DUMP_ENV,
PHASE_DUMP_VAR,
PHASE_SHOW_CONFIG,
PHASE_DUMP_MAKECONF
};
typedef enum worker_phase worker_phase_t;
#define WDOG1 (5)
#define WDOG2 (10)
#define WDOG3 (15)
#define WDOG4 (30)
#define WDOG5 (60)
#define WDOG6 (60 + 30)
#define WDOG7 (60 * 2)
#define WDOG8 (60 * 2 + 30)
#define WDOG9 (60 * 3)
typedef struct worker {
int index;
int flags;
int accum_error;
int mount_error;
int terminate : 1;
char *basedir;
char *flavor;
pthread_t td;
pthread_cond_t cond;
pkg_t *pkg;
worker_state_t state;
worker_phase_t phase;
time_t start_time;
long lines;
long memuse;
pid_t pid;
int fds[2];
char status[64];
size_t pkg_dep_size;
} worker_t;
#define WORKERF_STATUS_UPDATE 0x0001
#define WORKERF_SUCCESS 0x0002
#define WORKERF_FAILURE 0x0004
#define WORKERF_FREEZE 0x0008
#define MOUNT_TYPE_MASK 0x000F
#define MOUNT_TYPE_TMPFS 0x0001
#define MOUNT_TYPE_NULLFS 0x0002
#define MOUNT_TYPE_DEVFS 0x0003
#define MOUNT_TYPE_PROCFS 0x0004
#define MOUNT_TYPE_RW 0x0010
#define MOUNT_TYPE_BIG 0x0020
#define MOUNT_TYPE_TMP 0x0040
#define MOUNT_TYPE_MED 0x0080
#define NULLFS_RO (MOUNT_TYPE_NULLFS)
#define NULLFS_RW (MOUNT_TYPE_NULLFS | MOUNT_TYPE_RW)
#define PROCFS_RO (MOUNT_TYPE_PROCFS)
#define TMPFS_RW (MOUNT_TYPE_TMPFS | MOUNT_TYPE_RW)
#define TMPFS_RW_BIG (MOUNT_TYPE_TMPFS | MOUNT_TYPE_RW | \
MOUNT_TYPE_BIG)
#define TMPFS_RW_MED (MOUNT_TYPE_TMPFS | MOUNT_TYPE_RW | \
MOUNT_TYPE_MED)
#define DEVFS_RW (MOUNT_TYPE_DEVFS | MOUNT_TYPE_RW)
typedef struct wmsg {
int cmd;
int status;
long lines;
long memuse;
worker_phase_t phase;
} wmsg_t;
#define WMSG_CMD_STATUS_UPDATE 0x0001
#define WMSG_CMD_SUCCESS 0x0002
#define WMSG_CMD_FAILURE 0x0003
#define WMSG_CMD_INSTALL_PKGS 0x0004
#define WMSG_RES_INSTALL_PKGS 0x0005
#define WMSG_CMD_FREEZEWORKER 0x0006
typedef struct buildenv {
struct buildenv *next;
const char *label;
const char *data;
char *a1;
char *a2;
int type;
} buildenv_t;
enum os_id {
OS_UNKNOWN, OS_DRAGONFLY, OS_FREEBSD, OS_NETBSD, OS_LINUX
};
typedef enum os_id os_id_t;
#define DLOG_ALL 0
#define DLOG_SUCC 1
#define DLOG_FAIL 2
#define DLOG_IGN 3
#define DLOG_SKIP 4
#define DLOG_ABN 5
#define DLOG_OBS 6
#define DLOG_DEBUG 7
#define DLOG_COUNT 8
#define DLOG_MASK 0x0FF
#define DLOG_FILTER 0x100
#define DLOG_RED 0x200
#define DLOG_GRN 0x400
#define DLOG_STDOUT 0x800
#define dassert(exp, fmt, ...) \
if (!(exp)) dpanic(fmt, ## __VA_ARGS__)
#define ddassert(exp) \
dassert((exp), "\"%s\" line %d", __FILE__, __LINE__)
#define dassert_errno(exp, fmt, ...) \
if (!(exp)) dpanic_errno(fmt, ## __VA_ARGS__)
#define dlog_tab(which, tab, fmt, ...) \
_dlog(which, "%*.*s" fmt, (int)tab, (int)tab, "", ## __VA_ARGS__)
#define dlog(which, fmt, ...) \
_dlog(which, fmt, ## __VA_ARGS__)
#define dlog_tsnl(which, fmt, ...) \
_dlog(which, fmt, ## __VA_ARGS__)
#define dfatal(fmt, ...) \
_dfatal(__FILE__, __LINE__, __func__, 0, fmt, ## __VA_ARGS__)
#define dpanic(fmt, ...) \
_dfatal(__FILE__, __LINE__, __func__, 2, fmt, ## __VA_ARGS__)
#define dfatal_errno(fmt, ...) \
_dfatal(__FILE__, __LINE__, __func__, 1, fmt, ## __VA_ARGS__)
#define dpanic_errno(fmt, ...) \
_dfatal(__FILE__, __LINE__, __func__, 3, fmt, ## __VA_ARGS__)
#define ddprintf(tab, fmt, ...) \
do { \
if (DebugOpt == 1) dlog_tab(DLOG_DEBUG, tab, fmt, ## __VA_ARGS__); \
if (DebugOpt > 1) _ddprintf(tab, fmt, ## __VA_ARGS__); \
} while(0)
#define BENV_ENVIRONMENT 1
#define BENV_MAKECONF 2
#define BENV_CMDMASK 0x000F
#define BENV_PKGLIST 0x0010
#define WORKER_PROC_DEBUGSTOP 0x0001
#define WORKER_PROC_DEVELOPER 0x0002
#define WORKER_PROC_CHECK_PLIST 0x0004
#define WORKER_PROC_INSTALL 0x0008
#define WORKER_PROC_DEINSTALL 0x0010
#define WORKER_PROC_PKGV17 0x0020
#define WORKER_PROC_FETCHONLY 0x0040
#define WORKER_PROC_PORTSBASEOPT 0x0080
#define DOSTRING(label) #label
#define SCRIPTPATH(x) DOSTRING(x)
#define MAXCAC 256
typedef struct topinfo {
int active;
int pkgimpulse;
int pkgrate;
int noswap;
int h;
int m;
int s;
int total;
int successful;
int ignored;
int remaining;
int failed;
int skipped;
int meta;
int dynmaxworkers;
double dswap;
double dload[3];
} topinfo_t;
typedef struct runstats {
struct runstats *next;
void (*init)(void);
void (*done)(void);
void (*reset)(void);
void (*update)(worker_t *work, const char *portdir);
void (*updateTop)(topinfo_t *info);
void (*updateLogs)(void);
void (*updateCompletion)(worker_t *work, int dlogid, pkg_t *pkg,
const char *reason, const char *skipbuf);
void (*sync)(void);
} runstats_t;
typedef struct monitorlog {
off_t offset;
int fd;
int buf_beg;
int buf_end;
int buf_scan;
int buf_discard_mode;
char buf[1024];
} monitorlog_t;
extern runstats_t NCursesRunStats;
extern runstats_t MonitorRunStats;
extern runstats_t HtmlRunStats;
extern int GlobalExitCode;
extern int BuildCount;
extern int BuildTotal;
extern int BuildFailCount;
extern int BuildSkipCount;
extern int BuildIgnoreCount;
extern int BuildSuccessCount;
extern int BuildMissingCount;
extern int BuildMetaCount;
extern int DynamicMaxWorkers;
extern buildenv_t *BuildEnv;
extern int WorkerProcFlags;
extern int DebugOpt;
extern int NiceOpt;
extern int CapabilityRestrictions;
extern int MaskProbeAbort;
extern int ColorOpt;
extern int SlowStartOpt;
extern int ForceOpt;
extern int DFlyPortsBaseOpt;
extern int OverridePkgDeleteOpt;
extern int FetchOnlyOpt;
extern int YesOpt;
extern int NullStdinOpt;
extern int NumaSetSize;
extern int DeleteObsoletePkgs;
extern int UseCCache;
extern int UseUsrSrc;
extern int UseTmpfs;
extern int NumCores;
extern long PhysMem;
extern long PkgDepMemoryTarget;
extern long PkgDepScaleTarget;
extern int MaxBulk;
extern int MaxWorkers;
extern int MaxJobs;
extern int UseTmpfsWork;
extern int UseTmpfsBase;
extern int UseNCurses;
extern int LeveragePrebuilt;
extern char *DSynthExecPath;
extern char *ProfileOverrideOpt;
extern const char *OperatingSystemName;
extern const char *ArchitectureName;
extern const char *MachineName;
extern const char *ReleaseName;
extern const char *VersionName;
extern const char *VersionOnlyName;
extern const char *VersionFromParamHeader;
extern const char *ConfigBase1;
extern const char *ConfigBase2;
extern const char *ConfigBase;
extern const char *DPortsPath;
extern const char *CCachePath;
extern const char *PackagesPath;
extern const char *RepositoryPath;
extern const char *OptionsPath;
extern const char *DistFilesPath;
extern const char *BuildBase;
extern const char *LogsPath;
extern const char *SystemPath;
extern const char *UsePkgSufx;
extern const char *Profile;
extern int MetaVersion;
extern char *StatsBase;
extern char *StatsFilePath;
extern char *StatsLockPath;
extern int UsingHooks;
extern const char *HookRunStart;
extern const char *HookRunEnd;
extern const char *HookPkgSuccess;
extern const char *HookPkgFailure;
extern const char *HookPkgIgnored;
extern const char *HookPkgSkipped;
extern const char *HookPkgStarted;
void _dfatal(const char *file, int line, const char *func, int do_errno,
const char *fmt, ...);
void _ddprintf(int tab, const char *fmt, ...);
void _dlog(int which, const char *fmt, ...);
char *strdup_or_null(char *str);
void dlogreset(void);
int dlog00_fd(void);
void addbuildenv(const char *label, const char *data, int type);
void delbuildenv(const char *label);
const char *getbuildenv(const char *label);
int readlogline(monitorlog_t *log, char **bufp);
uint32_t crcDirTree(const char *path);
void initbulk(void (*func)(bulk_t *bulk), int jobs);
void queuebulk(const char *s1, const char *s2, const char *s3,
const char *s4);
bulk_t *getbulk(void);
void donebulk(void);
void freebulk(bulk_t *bulk);
void freestrp(char **strp);
void dupstrp(char **strp);
int askyn(const char *ctl, ...);
double getswappct(int *noswapp);
FILE *dexec_open(const char *logid, const char **cav, int cac,
pid_t *pidp, buildenv_t *xenv,
int with_env, int with_mvars);
int dexec_close(FILE *fp, pid_t pid);
const char *getphasestr(worker_phase_t phase);
void set_capability_restrictions(void);
void ParseConfiguration(int isworker);
pkg_t *ParsePackageList(int ac, char **av, int debugstop);
void FreePackageList(pkg_t *pkgs);
pkg_t *GetLocalPackageList(void);
pkg_t *GetFullPackageList(void);
pkg_t *GetPkgPkg(pkg_t **listp);
void DoConfigure(void);
void DoStatus(pkg_t *pkgs);
void DoBuild(pkg_t *pkgs);
void DoInitBuild(int slot_override);
void DoCleanBuild(int resetlogs);
void OptimizeEnv(void);
void WorkerProcess(int ac, char **av);
int DoCreateTemplate(int force);
void DoDestroyTemplate(void);
void DoWorkerMounts(worker_t *work);
void DoWorkerUnmounts(worker_t *work);
void DoRebuildRepo(int ask);
void DoUpgradePkgs(pkg_t *pkgs, int ask);
void RemovePackages(pkg_t *pkgs);
void PurgeDistfiles(pkg_t *pkgs);
void RunStatsInit(void);
void RunStatsDone(void);
void RunStatsReset(void);
void RunStatsUpdate(worker_t *work, const char *portdir);
void RunStatsUpdateTop(int active);
void RunStatsUpdateLogs(void);
void RunStatsSync(void);
void RunStatsUpdateCompletion(worker_t *work, int logid, pkg_t *pkg,
const char *reason, const char *skipbuf);
void setNumaDomain(int slot);
int copyfile(char *src, char *dst);
int ipcreadmsg(int fd, wmsg_t *msg);
int ipcwritemsg(int fd, wmsg_t *msg);
extern void MonitorDirective(const char *datfile, const char *lkfile);
uint32_t iscsi_crc32(const void *buf, size_t size);
uint32_t iscsi_crc32_ext(const void *buf, size_t size, uint32_t ocrc);