/** * Lock a file. * * @param lockfd The pointer to the lock file descriptor. It must be allocated * statically as its addresses is passed to a cleanup handler. * @param flags The lock flags specifying what type of locking to perform. * @param filename The name of the file to lock. * @param desc The description of the file to lock. */ void file_lock(int *lockfd, enum file_lock_flags flags, const char *filename, const char *desc) { struct flock fl; int lock_cmd; setcloexec(*lockfd, filename); file_lock_setup(&fl, F_WRLCK); if (flags == FILE_LOCK_WAIT) lock_cmd = F_SETLKW; else lock_cmd = F_SETLK; if (fcntl(*lockfd, lock_cmd, &fl) == -1) { if (errno == EACCES || errno == EAGAIN) ohshit(_("%s is locked by another process"), desc); else ohshite(_("unable to lock %s"), desc); } push_cleanup(file_unlock_cleanup, ~0, NULL, 0, 2, lockfd, desc); }
void log_message(const char *fmt, ...) { static struct varbuf log; static FILE *logfd = NULL; char time_str[20]; time_t now; va_list args; if (!log_file) return; if (!logfd) { logfd = fopen(log_file, "a"); if (!logfd) { notice(_("could not open log '%s': %s"), log_file, strerror(errno)); log_file = NULL; return; } setlinebuf(logfd); setcloexec(fileno(logfd), log_file); } va_start(args, fmt); varbuf_reset(&log); varbuf_vprintf(&log, fmt, args); va_end(args); time(&now); strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", localtime(&now)); fprintf(logfd, "%s %s\n", time_str, log.buf); }
/** * Set the debugging output file. * * Marks the file descriptor as close-on-exec. */ void debug_set_output(FILE *output, const char *filename) { setcloexec(fileno(output), filename); dpkg_set_report_buffer(output); debug_output = output; }
static int upload_pipe_ropen(void) { struct stat st; int upload_pipe_fd; unsigned int tries = OPEN_TRIES; again: if ((upload_pipe_fd = open(UPLOAD_PIPE_FILE, O_RDONLY | O_NOFOLLOW)) == -1) { if (tries > 0) { tries--; (void) sleep(OPEN_DELAY); goto again; } perror("Unable to open " UPLOAD_PIPE_FILE); return -1; } setcloexec(upload_pipe_fd); if (fstat(upload_pipe_fd, &st) < 0 || (st.st_mode & 0777) != 0600 || !S_ISFIFO(st.st_mode) || #ifdef NON_ROOT_FTP st.st_uid != geteuid() #else st.st_uid != (uid_t) 0 #endif ) { fprintf(stderr, "Insecure permissions on " UPLOAD_PIPE_FILE "\n"); (void) close(upload_pipe_fd); return -1; } return upload_pipe_fd; }
void statusfd_add(int fd) { struct pipef *pipe_new; setcloexec(fd, _("<package status and progress file descriptor>")); pipe_new = nfmalloc(sizeof(struct pipef)); pipe_new->fd = fd; pipe_new->next = status_pipes; status_pipes = pipe_new; }
void openlogs() { if(logconfig->error) { int oldlogfile = logfile; logfile = open(logconfig->error, O_APPEND|O_WRONLY|O_CREAT, 0666); if(logfile <= 0) { logfile = oldlogfile; LWARN("Can't open logfile. Continuing writing to stdout"); } else { LINFO("Log sucessfully opened"); setcloexec(logfile); dup2(logfile, STDOUT); dup2(logfile, STDERR); } } }
static void setpipe(const struct cmdinfo *cip, const char *value) { struct pipef **pipe_head = cip->parg; struct pipef *pipe_new; unsigned long v; char *ep; v= strtoul(value,&ep,0); if (value == ep || *ep || v > INT_MAX) badusage(_("invalid integer for --%s: `%.250s'"),cip->olong,value); setcloexec(v, _("<package status and progress file descriptor>")); pipe_new = nfmalloc(sizeof(struct pipef)); pipe_new->fd = v; pipe_new->next = *pipe_head; *pipe_head = pipe_new; }
/* lockfd must be allocated statically as its addresses is passed to * a cleanup handler. */ void file_lock(int *lockfd, const char *filename, const char *emsg, const char *emsg_eagain) { struct flock fl; setcloexec(*lockfd, filename); file_lock_setup(&fl, F_WRLCK); if (fcntl(*lockfd, emsg_eagain ? F_SETLK : F_SETLKW, &fl) == -1) { if (emsg_eagain && (errno == EACCES || errno == EAGAIN)) ohshit(emsg_eagain); ohshite(emsg); } push_cleanup(file_unlock_cleanup, ~0, NULL, 0, 1, lockfd); }
void reopenlogs() { if(logconfig->error) { int oldlogfile = logfile; logfile = open(logconfig->error, O_APPEND|O_WRONLY|O_CREAT, 0666); if(logfile <= 0) { logfile = oldlogfile; SWARN2("Can't open logfile. Continuing writing old file"); } else { LINFO("New log file successfully opened"); setcloexec(logfile); dup2(logfile, STDOUT); dup2(logfile, STDERR); close(oldlogfile); } } else { LWARN("No logfile specified"); } }
static void createimptmp(void) { int i; onerr_abort++; importanttmp= fopen(importanttmpfile,"w"); if (!importanttmp) ohshite(_("unable to create `%.255s'"), importanttmpfile); setcloexec(fileno(importanttmp),importanttmpfile); for (i=0; i<512; i++) fputs("#padding\n",importanttmp); if (ferror(importanttmp)) ohshite(_("unable to fill %.250s with padding"),importanttmpfile); if (fflush(importanttmp)) ohshite(_("unable to flush %.250s after padding"), importanttmpfile); if (fseek(importanttmp,0,SEEK_SET)) ohshite(_("unable to seek to start of %.250s after padding"), importanttmpfile); onerr_abort--; }
void ensure_diversions(void) { static struct varbuf vb; struct stat stab1, stab2; char linebuf[MAXDIVERTFILENAME]; FILE *file; struct diversion *ov, *oicontest, *oialtname; varbufreset(&vb); varbufaddstr(&vb, admindir); varbufaddstr(&vb, "/" DIVERSIONSFILE); varbufaddc(&vb, 0); onerr_abort++; file = fopen(vb.buf,"r"); if (!file) { if (errno != ENOENT) ohshite(_("failed to open diversions file")); if (!diversionsfile) { onerr_abort--; return; } } else if (diversionsfile) { if (fstat(fileno(diversionsfile), &stab1)) ohshite(_("failed to fstat previous diversions file")); if (fstat(fileno(file), &stab2)) ohshite(_("failed to fstat diversions file")); if (stab1.st_dev == stab2.st_dev && stab1.st_ino == stab2.st_ino) { fclose(file); onerr_abort--; return; } } if (diversionsfile) fclose(diversionsfile); diversionsfile = file; setcloexec(fileno(diversionsfile), vb.buf); for (ov = diversions; ov; ov = ov->next) { ov->useinstead->divert->camefrom->divert = NULL; ov->useinstead->divert = NULL; } diversions = NULL; if (!file) { onerr_abort--; return; } while (fgets_checked(linebuf, sizeof(linebuf), file, vb.buf) >= 0) { oicontest = nfmalloc(sizeof(struct diversion)); oialtname = nfmalloc(sizeof(struct diversion)); oialtname->camefrom = findnamenode(linebuf, 0); oialtname->useinstead = NULL; fgets_must(linebuf, sizeof(linebuf), file, vb.buf); oicontest->useinstead = findnamenode(linebuf, 0); oicontest->camefrom = NULL; fgets_must(linebuf, sizeof(linebuf), file, vb.buf); oicontest->pkg = oialtname->pkg = strcmp(linebuf, ":") ? pkg_db_find(linebuf) : NULL; if (oialtname->camefrom->divert || oicontest->useinstead->divert) ohshit(_("conflicting diversions involving `%.250s' or `%.250s'"), oialtname->camefrom->name, oicontest->useinstead->name); oialtname->camefrom->divert = oicontest; oicontest->useinstead->divert = oialtname; oicontest->next = diversions; diversions = oicontest; } onerr_abort--; }
void ensure_statoverrides(void) { static struct varbuf vb; struct stat stab1, stab2; FILE *file; char *loaded_list, *loaded_list_end, *thisline, *nextline, *ptr; struct file_stat *fso; struct filenamenode *fnn; varbufreset(&vb); varbufaddstr(&vb, admindir); varbufaddstr(&vb, "/" STATOVERRIDEFILE); varbufaddc(&vb, 0); onerr_abort++; file = fopen(vb.buf,"r"); if (!file) { if (errno != ENOENT) ohshite(_("failed to open statoverride file")); if (!statoverridefile) { onerr_abort--; return; } } else { if (fstat(fileno(file), &stab2)) ohshite(_("failed to fstat statoverride file")); if (statoverridefile) { if (fstat(fileno(statoverridefile), &stab1)) ohshite(_("failed to fstat previous statoverride file")); if (stab1.st_dev == stab2.st_dev && stab1.st_ino == stab2.st_ino) { fclose(file); onerr_abort--; return; } } } if (statoverridefile) fclose(statoverridefile); statoverridefile = file; setcloexec(fileno(statoverridefile), vb.buf); /* If the statoverride list is empty we don't need to bother * reading it. */ if (!stab2.st_size) { onerr_abort--; return; } loaded_list = nfmalloc(stab2.st_size); loaded_list_end = loaded_list + stab2.st_size; fd_buf_copy(fileno(file), loaded_list, stab2.st_size, _("statoverride file `%.250s'"), vb.buf); thisline = loaded_list; while (thisline < loaded_list_end) { fso = nfmalloc(sizeof(struct file_stat)); if (!(ptr = memchr(thisline, '\n', loaded_list_end - thisline))) ohshit(_("statoverride file is missing final newline")); /* Where to start next time around. */ nextline = ptr + 1; if (ptr == thisline) ohshit(_("statoverride file contains empty line")); *ptr = '\0'; /* Extract the uid. */ if (!(ptr = memchr(thisline, ' ', nextline - thisline))) ohshit(_("syntax error in statoverride file")); *ptr = '\0'; fso->uid = statdb_parse_uid(thisline); /* Move to the next bit */ thisline = ptr + 1; if (thisline >= loaded_list_end) ohshit(_("unexpected end of line in statoverride file")); /* Extract the gid */ if (!(ptr = memchr(thisline, ' ', nextline - thisline))) ohshit(_("syntax error in statoverride file")); *ptr = '\0'; fso->gid = statdb_parse_gid(thisline); /* Move to the next bit */ thisline = ptr + 1; if (thisline >= loaded_list_end) ohshit(_("unexpected end of line in statoverride file")); /* Extract the mode */ if (!(ptr = memchr(thisline, ' ', nextline - thisline))) ohshit(_("syntax error in statoverride file")); *ptr = '\0'; fso->mode = statdb_parse_mode(thisline); /* Move to the next bit */ thisline = ptr + 1; if (thisline >= loaded_list_end) ohshit(_("unexpected end of line in statoverride file")); fnn = findnamenode(thisline, 0); if (fnn->statoverride) ohshit(_("multiple statusoverrides present for file '%.250s'"), thisline); fnn->statoverride = fso; /* Moving on.. */ thisline = nextline; } onerr_abort--; }