static void tar_writeback_barrier(struct fileinlist *files, struct pkginfo *pkg) { struct fileinlist *cfile; for (cfile = files; cfile; cfile = cfile->next) { struct filenamenode *usenode; const char *usename; int fd; if (!(cfile->namenode->flags & fnnf_deferred_fsync)) continue; usenode = namenodetouse(cfile->namenode, pkg); usename = usenode->name + 1; /* Skip the leading '/'. */ setupfnamevbs(usename); fd = open(fnamenewvb.buf, O_WRONLY); if (fd < 0) ohshite(_("unable to open '%.255s'"), fnamenewvb.buf); sync_file_range(fd, 0, 0, SYNC_FILE_RANGE_WAIT_BEFORE); if (close(fd)) ohshite(_("error closing/writing `%.255s'"), fnamenewvb.buf); } }
/** * Returns the path to the script inside the chroot. */ static const char * preexecscript(struct command *cmd) { const char *admindir = dpkg_db_get_dir(); size_t instdirl = strlen(instdir); if (*instdir) { if (strncmp(admindir, instdir, instdirl) != 0) ohshit(_("admindir must be inside instdir for dpkg to work properly")); if (setenv("DPKG_ADMINDIR", admindir + instdirl, 1) < 0) ohshite(_("unable to setenv for subprocesses")); if (chroot(instdir)) ohshite(_("failed to chroot to `%.250s'"),instdir); if (chdir("/")) ohshite(_("failed to chdir to `%.255s'"), "/"); } if (debug_has_flag(dbg_scripts)) { struct varbuf args = VARBUF_INIT; const char **argv = cmd->argv; while (*++argv) { varbuf_add_char(&args, ' '); varbuf_add_str(&args, *argv); } varbuf_end_str(&args); debug(dbg_scripts, "fork/exec %s (%s )", cmd->filename, args.buf); varbuf_destroy(&args); } if (!instdirl) return cmd->filename; assert(strlen(cmd->filename) >= instdirl); return cmd->filename + instdirl; }
/** * Remove a pathname and anything below it. * * This function removes pathname and all its contents recursively. */ void path_remove_tree(const char *pathname) { pid_t pid; const char *u; u = path_skip_slash_dotslash(pathname); assert(*u); debug(dbg_eachfile, "%s '%s'", __func__, pathname); if (!rmdir(pathname)) return; /* Deleted it OK, it was a directory. */ if (errno == ENOENT || errno == ELOOP) return; if (errno == ENOTDIR) { /* Either it's a file, or one of the path components is. If * one of the path components is this will fail again ... */ if (secure_unlink(pathname) == 0) return; /* OK, it was. */ if (errno == ENOTDIR) return; } if (errno != ENOTEMPTY && errno != EEXIST) /* Huh? */ ohshite(_("unable to securely remove '%.255s'"), pathname); pid = subproc_fork(); if (pid == 0) { execlp(RM, "rm", "-rf", "--", pathname, NULL); ohshite(_("unable to execute %s (%s)"), _("rm command for cleanup"), RM); } debug(dbg_eachfile, "%s running rm -rf '%s'", __func__, pathname); subproc_reap(pid, _("rm command for cleanup"), 0); }
static void decompress_bzip2(int fd_in, int fd_out, const char *desc) { char buffer[DPKG_BUFFER_SIZE]; BZFILE *bzfile = BZ2_bzdopen(fd_in, "r"); if (bzfile == NULL) ohshit(_("%s: error binding input to bzip2 stream"), desc); for (;;) { int actualread, actualwrite; actualread = BZ2_bzread(bzfile, buffer, sizeof(buffer)); if (actualread < 0) { int bz_errnum = 0; const char *errmsg = BZ2_bzerror(bzfile, &bz_errnum); if (bz_errnum == BZ_IO_ERROR) errmsg = strerror(errno); ohshit(_("%s: internal bzip2 read error: '%s'"), desc, errmsg); } if (actualread == 0) /* EOF. */ break; actualwrite = fd_write(fd_out, buffer, actualread); if (actualwrite != actualread) ohshite(_("%s: internal bzip2 write error"), desc); } if (close(fd_out)) ohshite(_("%s: internal bzip2 write error"), desc); }
void cu_installsharedconf(int argc, void **argv) { struct fileinlist *nifd = (struct fileinlist*)argv[0]; struct filenamenode *namenode; struct stat stab; cleanup_pkg_failed++; cleanup_conflictor_failed++; namenode = nifd->namenode; debug(dbg_eachfile, "cu_installsharedconf `%s' flags=%o", namenode->name, namenode->flags); setupfnamevbs(namenode->name); if ((namenode->flags & fnnf_new_conff) && !lstat(fnametmpvb.buf, &stab)) { /* OK, <foo>.dpkg-tmp exists. Restore it to <foo>.dpkg-new as it was a * previously unpacked (but not configured) configuration file. */ if (secure_remove(fnamenewvb.buf) && errno != ENOENT && errno != ENOTDIR) ohshite(_("unable to remove newly-installed version of `%.250s' to allow" " reinstallation of backup copy"), fnamenewvb.buf); /* Either we can do an atomic restore, or we've made room: */ if (rename(fnametmpvb.buf, fnamenewvb.buf)) ohshite(_("unable to restore backup version of `%.250s'"), fnamenewvb.buf); } else { debug(dbg_eachfiledetail,"cu_installsharedconf not restoring"); } cleanup_pkg_failed--; cleanup_conflictor_failed--; }
void push_cleanup(void (*call1)(int argc, void **argv), int mask1, void (*call2)(int argc, void **argv), int mask2, unsigned int nargs, ...) { struct cleanup_entry *cep; void **argv; int e = 0; va_list args; onerr_abort++; cep = malloc(sizeof(struct cleanup_entry) + sizeof(char *) * (nargs + 1)); if (!cep) { if (nargs > array_count(emergency.args)) ohshite(_("out of memory for new cleanup entry with many arguments")); e= errno; cep= &emergency.ce; } cep->calls[0].call= call1; cep->calls[0].mask= mask1; cep->calls[1].call= call2; cep->calls[1].mask= mask2; cep->cpmask=~0; cep->cpvalue=0; cep->argc= nargs; va_start(args, nargs); argv = cep->argv; while (nargs-- > 0) *argv++ = va_arg(args, void *); *argv++ = NULL; va_end(args); cep->next= econtext->cleanups; econtext->cleanups= cep; if (cep == &emergency.ce) { errno = e; ohshite(_("out of memory for new cleanup entry")); } onerr_abort--; }
static void decompress_gzip(int fd_in, int fd_out, const char *desc) { char buffer[DPKG_BUFFER_SIZE]; gzFile gzfile = gzdopen(fd_in, "r"); if (gzfile == NULL) ohshit(_("%s: error binding input to gzip stream"), desc); for (;;) { int actualread, actualwrite; actualread = gzread(gzfile, buffer, sizeof(buffer)); if (actualread < 0) { int z_errnum = 0; const char *errmsg = gzerror(gzfile, &z_errnum); if (z_errnum == Z_ERRNO) errmsg = strerror(errno); ohshit(_("%s: internal gzip read error: '%s'"), desc, errmsg); } if (actualread == 0) /* EOF. */ break; actualwrite = fd_write(fd_out, buffer, actualread); if (actualwrite != actualread) ohshite(_("%s: internal gzip write error"), desc); } if (close(fd_out)) ohshite(_("%s: internal gzip write error"), desc); }
void trig_incorporate(enum modstatdb_rw cstatus) { enum trigdef_update_status ur; enum trigdef_updateflags tduf; free(triggersdir); triggersdir = dpkg_db_get_path(TRIGGERSDIR); free(triggersfilefile); triggersfilefile = trig_get_filename(triggersdir, "File"); free(triggersnewfilefile); triggersnewfilefile = trig_get_filename(triggersdir, "File.new"); trigdef_set_methods(&tdm_incorp); trig_file_interests_ensure(); tduf = tduf_nolockok; if (cstatus >= msdbrw_write) { tduf |= tduf_write; if (trigh.transitional_activate) tduf |= tduf_writeifenoent; } ur = trigdef_update_start(tduf); if (ur == tdus_error_no_dir && cstatus >= msdbrw_write) { if (mkdir(triggersdir, 0755)) { if (errno != EEXIST) ohshite(_("unable to create triggers state" " directory `%.250s'"), triggersdir); } else if (chown(triggersdir, 0, 0)) { ohshite(_("unable to set ownership of triggers state" " directory `%.250s'"), triggersdir); } ur = trigdef_update_start(tduf); } switch (ur) { case tdus_error_empty_deferred: return; case tdus_error_no_dir: case tdus_error_no_deferred: if (!trigh.transitional_activate) return; /* Fall through. */ case tdus_no_deferred: trigh.transitional_activate(cstatus); break; case tdus_ok: /* Read and incorporate triggers. */ trigdef_parse(); break; default: internerr("unknown trigdef_update_start return value '%d'", ur); } /* Right, that's it. New (empty) Unincorp can be installed. */ trigdef_process_done(); }
void atomic_file_remove(struct atomic_file *file) { if (unlink(file->name_new)) ohshite(_("cannot remove '%.250s'"), file->name_new); if (unlink(file->name) && errno != ENOENT) ohshite(_("cannot remove '%.250s'"), file->name); }
void setcloexec(int fd, const char* fn) { int f; if ((f=fcntl(fd, F_GETFD))==-1) ohshite(_("unable to read filedescriptor flags for %.250s"),fn); if (fcntl(fd, F_SETFD, (f|FD_CLOEXEC))==-1) ohshite(_("unable to set close-on-exec flag for %.250s"),fn); }
static void statdb_node_apply(const char *filename, struct file_stat *filestat) { if (chown(filename, filestat->uid, filestat->gid) < 0) ohshite(_("error setting ownership of `%.255s'"), filename); if (chmod(filename, filestat->mode)) ohshite(_("error setting permissions of `%.255s'"), filename); }
static void trk_explicit_interest_remove(const char *newfilename) { if (unlink(newfilename)) ohshite(_("cannot remove `%.250s'"), newfilename); if (unlink(trk_explicit_fn.buf) && errno != ENOENT) ohshite(_("cannot remove `%.250s'"), trk_explicit_fn.buf); }
void cu_installnew(int argc, void **argv) { /* Something went wrong and we're undoing. * We have the following possible situations for non-conffiles: * <foo>.dpkg-tmp exists - in this case we want to remove * <foo> if it exists and replace it with <foo>.dpkg-tmp. * This undoes the backup operation. * <foo>.dpkg-tmp does not exist - <foo> may be on the disk, * as a new file which didn't fail, remove it if it is. * In both cases, we also make sure we delete <foo>.dpkg-new in * case that's still hanging around. * For conffiles, we simply delete <foo>.dpkg-new. For these, * <foo>.dpkg-tmp shouldn't exist, as we don't make a backup * at this stage. Just to be on the safe side, though, we don't * look for it. */ struct fileinlist *nifd= (struct fileinlist*)argv[0]; struct filenamenode *namenode; struct stat stab; cleanup_pkg_failed++; cleanup_conflictor_failed++; namenode= nifd->namenode; debug(dbg_eachfile,"cu_installnew `%s' flags=%o",namenode->name,namenode->flags); setupfnamevbs(namenode->name); if (!(namenode->flags & fnnf_new_conff) && !lstat(fnametmpvb.buf,&stab)) { /* OK, <foo>.dpkg-tmp exists. Remove <foo> and * restore <foo>.dpkg-tmp ... */ if (namenode->flags & fnnf_no_atomic_overwrite) { /* If we can't do an atomic overwrite we have to delete first any * link to the new version we may have created. */ debug(dbg_eachfiledetail,"cu_installnew restoring nonatomic"); if (unlinkorrmdir(fnamevb.buf) && errno != ENOENT && errno != ENOTDIR) ohshite(_("unable to remove newly-installed version of `%.250s' to allow" " reinstallation of backup copy"),namenode->name); } else { debug(dbg_eachfiledetail,"cu_installnew restoring atomic"); } /* Either we can do an atomic restore, or we've made room: */ if (rename(fnametmpvb.buf,fnamevb.buf)) ohshite(_("unable to restore backup version of `%.250s'"),namenode->name); } else if (namenode->flags & fnnf_placed_on_disk) { debug(dbg_eachfiledetail,"cu_installnew removing new file"); if (unlinkorrmdir(fnamevb.buf) && errno != ENOENT && errno != ENOTDIR) ohshite(_("unable to remove newly-installed version of `%.250s'"), namenode->name); } else { debug(dbg_eachfiledetail,"cu_installnew not restoring"); } /* Whatever, we delete <foo>.dpkg-new now, if it still exists. */ if (unlinkorrmdir(fnamenewvb.buf) && errno != ENOENT && errno != ENOTDIR) ohshite(_("unable to remove newly-extracted version of `%.250s'"),namenode->name); cleanup_pkg_failed--; cleanup_conflictor_failed--; }
void m_dup2(int oldfd, int newfd) { const char *const stdstrings[]= { "in", "out", "err" }; if (dup2(oldfd,newfd) == newfd) return; onerr_abort++; if (newfd < 3) ohshite(_("failed to dup for std%s"),stdstrings[newfd]); ohshite(_("failed to dup for fd %d"),newfd); }
void myfileopt(const char* fn, const struct cmdinfo* cmdinfos) { FILE* file; char linebuf[MAXDIVERTFILENAME]; file= fopen(fn, "r"); if (!file) { if (errno==ENOENT) return; warningf(_("failed to open configuration file `%.255s' for reading"),fn); return; } while (fgets(linebuf, sizeof(linebuf), file)) { char* opt; const struct cmdinfo *cip; int l; if ((linebuf[0]=='#') || (linebuf[0]=='\n') || (linebuf[0]==0)) continue; l=strlen(linebuf); if (linebuf[l-1]=='\n') linebuf[l-1]=0; for (opt=linebuf;isalnum(*opt)||*opt=='-';opt++) ; if (*opt==0) opt=NULL; else { *opt++=0; if (*opt=='=') opt++; while (isspace(*opt)) opt++; } for (cip=cmdinfos; cip->olong || cip->oshort; cip++) { int l; if (!cip->olong) continue; if (!strcmp(cip->olong,linebuf)) break; l=strlen(cip->olong); if ((cip->takesvalue==2) && (linebuf[l]=='-') && !opt && !strncmp(linebuf,cip->olong,l)) { opt=linebuf+l+1; break; } } if (!cip->olong) ohshite(_("configuration error: unknown option %s"), linebuf); if (cip->takesvalue) { if (!opt) ohshite(_("configuration error: %s needs a value"), linebuf); if (cip->call) cip->call(cip,opt); else *cip->sassignto = m_strdup(opt); } else { if (opt) ohshite(_("configuration error: %s does not take a value"), linebuf); if (cip->call) cip->call(cip,NULL); else *cip->iassignto= cip->arg; } } if (ferror(file)) ohshite(_("read error in configuration file `%.255s'"), fn); if (fclose(file)) ohshite(_("error closing configuration file `%.255s'"), fn); }
void mustgetpartinfo(const char *filename, struct partinfo *ri) { FILE *part; part= fopen(filename,"r"); if (!part) ohshite(_("cannot open archive part file `%.250s'"),filename); if (!read_info(part,filename,ri)) ohshite(_("file `%.250s' is not an archive part"),filename); fclose(part); }
static void newtarobject_allmodes(const char *path, struct file_stat *st) { if (chown(path, st->uid, st->gid)) ohshite(_("error setting ownership of `%.255s'"), path); if (chmod(path, st->mode & ~S_IFMT)) ohshite(_("error setting permissions of `%.255s'"), path); newtarobject_utime(path, st); }
void trig_incorporate(enum modstatdb_rw cstatus) { enum trigdef_update_status ur; enum trigdef_update_flags tduf; free(triggersdir); triggersdir = dpkg_db_get_path(TRIGGERSDIR); free(triggersfilefile); triggersfilefile = trig_get_filename(triggersdir, TRIGGERSFILEFILE); trigdef_set_methods(&tdm_incorp); trig_file_interests_ensure(); tduf = TDUF_NO_LOCK_OK; if (cstatus >= msdbrw_write) { tduf |= TDUF_WRITE; if (trigh.transitional_activate) tduf |= TDUF_WRITE_IF_ENOENT; } ur = trigdef_update_start(tduf); if (ur == TDUS_ERROR_NO_DIR && cstatus >= msdbrw_write) { if (mkdir(triggersdir, 0755)) { if (errno != EEXIST) ohshite(_("unable to create triggers state" " directory '%.250s'"), triggersdir); } else if (chown(triggersdir, 0, 0)) { ohshite(_("unable to set ownership of triggers state" " directory '%.250s'"), triggersdir); } ur = trigdef_update_start(tduf); } switch (ur) { case TDUS_ERROR_EMPTY_DEFERRED: return; case TDUS_ERROR_NO_DIR: case TDUS_ERROR_NO_DEFERRED: if (!trigh.transitional_activate) return; /* Fall through. */ case TDUS_NO_DEFERRED: trigh.transitional_activate(cstatus); break; case TDUS_OK: /* Read and incorporate triggers. */ trigdef_parse(); break; default: internerr("unknown trigdef_update_start return value '%d'", ur); } /* Right, that's it. New (empty) Unincorp can be installed. */ trigdef_process_done(); }
void mustgetpartinfo(const char *filename, struct partinfo *ri) { struct dpkg_ar *part; part = dpkg_ar_open(filename); if (!part) ohshite(_("cannot open archive part file '%.250s'"), filename); if (!read_info(part, ri)) ohshite(_("file '%.250s' is not an archive part"), filename); dpkg_ar_close(part); }
void atomic_file_sync(struct atomic_file *file) { if (ferror(file->fp)) ohshite(_("unable to write new file '%.250s'"), file->name_new); if (fflush(file->fp)) ohshite(_("unable to flush new file '%.250s'"), file->name_new); if (fsync(fileno(file->fp))) ohshite(_("unable to sync new file '%.250s'"), file->name_new); }
static void info_field(const char *debar, const char *directory, const char *const *fields, bool showfieldname) { FILE *cc; char fieldname[MAXFIELDNAME+1]; char *pf; const char *const *fp; int c, lno, fnl; bool doing; if (!(cc= fopen("control","r"))) ohshite(_("could not open the `control' component")); doing = true; lno = 1; for (;;) { c = getc(cc); if (c == EOF) { doing = false; break; } if (c == '\n') { lno++; doing = true; continue; } if (!isspace(c)) { for (pf=fieldname, fnl=0; fnl <= MAXFIELDNAME && c!=EOF && !isspace(c) && c!=':'; c= getc(cc)) { *pf++= c; fnl++; } *pf = '\0'; doing= fnl >= MAXFIELDNAME || c=='\n' || c==EOF; for (fp=fields; !doing && *fp; fp++) if (!strcasecmp(*fp, fieldname)) doing = true; if (showfieldname) { if (doing) fputs(fieldname,stdout); } else { if (c==':') c= getc(cc); while (c != '\n' && isspace(c)) c= getc(cc); } } for(;;) { if (c == EOF) break; if (doing) putc(c,stdout); if (c == '\n') { lno++; break; } c= getc(cc); } if (c == EOF) break; } if (ferror(cc)) ohshite(_("failed during read of `control' component")); if (fclose(cc)) ohshite(_("error closing the '%s' component"), "control"); if (doing) putc('\n',stdout); m_output(stdout, _("<standard output>")); }
/** * Pack the contents of a directory into a tarball. */ static void tarball_pack(const char *dir, filenames_feed_func *tar_filenames_feeder, time_t timestamp, struct compress_params *tar_compress_params, int fd_out) { int pipe_filenames[2], pipe_tarball[2]; pid_t pid_tar, pid_comp; /* Fork off a tar. We will feed it a list of filenames on stdin later. */ m_pipe(pipe_filenames); m_pipe(pipe_tarball); pid_tar = subproc_fork(); if (pid_tar == 0) { char mtime[50]; m_dup2(pipe_filenames[0], 0); close(pipe_filenames[0]); close(pipe_filenames[1]); m_dup2(pipe_tarball[1], 1); close(pipe_tarball[0]); close(pipe_tarball[1]); if (chdir(dir)) ohshite(_("failed to chdir to '%.255s'"), dir); snprintf(mtime, sizeof(mtime), "@%ld", timestamp); execlp(TAR, "tar", "-cf", "-", "--format=gnu", "--mtime", mtime, "--clamp-mtime", "--null", "--no-unquote", "--no-recursion", "-T", "-", NULL); ohshite(_("unable to execute %s (%s)"), "tar -cf", TAR); } close(pipe_filenames[0]); close(pipe_tarball[1]); /* Of course we should not forget to compress the archive as well. */ pid_comp = subproc_fork(); if (pid_comp == 0) { close(pipe_filenames[1]); compress_filter(tar_compress_params, pipe_tarball[0], fd_out, _("compressing tar member")); exit(0); } close(pipe_tarball[0]); /* All the pipes are set, now lets start feeding filenames to tar. */ tar_filenames_feeder(dir, pipe_filenames[1]); /* All done, clean up wait for tar and <compress> to finish their job. */ close(pipe_filenames[1]); subproc_reap(pid_comp, _("<compress> from tar -cf"), 0); subproc_reap(pid_tar, "tar -cf", 0); }
static void statdb_node_apply(const char *filename, struct file_stat *filestat) { if (chown(filename, filestat->uid, filestat->gid) < 0) ohshite(_("error setting ownership of '%.255s'"), filename); if (chmod(filename, filestat->mode)) ohshite(_("error setting permissions of '%.255s'"), filename); dpkg_selabel_load(); dpkg_selabel_set_context(filename, filename, filestat->mode); dpkg_selabel_close(); }
/** * Sync a directory to disk from a DIR structure. * * @param dir The directory to sync. * @param path The name of the directory to sync (for error messages). */ static void dir_sync(DIR *dir, const char *path) { int fd; fd = dirfd(dir); if (fd < 0) ohshite(_("unable to get file descriptor for directory '%s'"), path); if (fsync(fd)) ohshite(_("unable to sync directory '%s'"), path); }
static void trk_explicit_interest_flush(const char *newfilename, FILE *nf) { if (ferror(nf)) ohshite(_("unable to write new trigger interest file `%.250s'"), newfilename); if (fflush(nf)) ohshite(_("unable to flush new trigger interest file '%.250s'"), newfilename); if (fsync(fileno(nf))) ohshite(_("unable to sync new trigger interest file '%.250s'"), newfilename); }
int userdb_change(const char *filename, const struct userentry *uep, int create) { /* possible values for `create' are: * 0: never create a new record (return 1 if not already there). * 1: create a new record if required. * 2: fail (and return 1) if already exists (ie, force creation) * -1: delete an existing record (return 1 if it doesn't exist). * return values are: * 0: OK * 1: Value for `create' prevented us from going ahead * 2: Wanted to create a new record, but there is no room. */ static struct userentry ue; int n, initial, i, place; FILE *file; initbyuserid(filename,"r+b",F_WRLCK,uep->userid,uep->access,&file,&initial,&n); i= initial; place= -1; for(;;) { getentry(file,&ue,filename); if (!ue.userid[0]) { if (place==-1) place= i; } else if (!strncmp(uep->userid,ue.userid,USERID_MAXLEN)) /* && (uep->access < 0 || uep->access == ue.access)) */ { if (create==2) { ufclose(file,filename); return 1; } place=i; break; } i= nextentry(file,i,n,filename); if (i == initial) { /* OK, we didn't find it. We may have found a space, though */ if (create<=0) { ufclose(file,filename); return 1; } if (place==-1) { ufclose(file,filename); return 2; } break; } } if (fseek(file,sizeof(struct userentry)*place,SEEK_SET)) ohshite("User database `%s' unseekable for update",filename); if (create<0) { ue.userid[0]= 0; ue.secretbytes= 0; ue.disabled= 0; memset(ue.secret,0,SECRET_MAXBYTES); uep= &ue; } else { assert(uep->access >= 0); } errno=0; if (fwrite(uep,sizeof(*uep),1,file)!=1) ohshite("User database `%s' unwriteable",filename); if (ufclose(file,filename)) ohshite("User database `%s' uncloseable",filename); return 0; }
void dpkg_ar_member_put_mem(const char *ar_name, int ar_fd, const char *name, const void *data, size_t size) { dpkg_ar_member_put_header(ar_name, ar_fd, name, size); /* Copy data contents. */ if (fd_write(ar_fd, data, size) < 0) ohshite(_("unable to write file '%s'"), ar_name); if (size & 1) if (fd_write(ar_fd, "\n", 1) < 0) ohshite(_("unable to write file '%s'"), ar_name); }
static void atomic_file_backup(struct atomic_file *file) { char *name_old; name_old = str_fmt("%s%s", file->name, ATOMIC_FILE_OLD_EXT); if (unlink(name_old) && errno != ENOENT) ohshite(_("error removing old backup file '%s'"), name_old); if (link(file->name, name_old) && errno != ENOENT) ohshite(_("error creating new backup file '%s'"), name_old); free(name_old); }
static void compress_bzip2(int fd_in, int fd_out, struct compress_params *params, const char *desc) { char buffer[DPKG_BUFFER_SIZE]; char combuf[6]; int bz_errnum; BZFILE *bzfile; snprintf(combuf, sizeof(combuf), "w%d", params->level); bzfile = BZ2_bzdopen(fd_out, combuf); if (bzfile == NULL) ohshit(_("%s: error binding output to bzip2 stream"), desc); for (;;) { int actualread, actualwrite; actualread = fd_read(fd_in, buffer, sizeof(buffer)); if (actualread < 0) ohshite(_("%s: internal bzip2 read error"), desc); if (actualread == 0) /* EOF. */ break; actualwrite = BZ2_bzwrite(bzfile, buffer, actualread); if (actualwrite != actualread) { const char *errmsg = BZ2_bzerror(bzfile, &bz_errnum); if (bz_errnum == BZ_IO_ERROR) errmsg = strerror(errno); ohshit(_("%s: internal bzip2 write error: '%s'"), desc, errmsg); } } BZ2_bzWriteClose(&bz_errnum, bzfile, 0, NULL, NULL); if (bz_errnum != BZ_OK) { const char *errmsg = _("unexpected bzip2 error"); if (bz_errnum == BZ_IO_ERROR) errmsg = strerror(errno); ohshit(_("%s: internal bzip2 write error: '%s'"), desc, errmsg); } /* Because BZ2_bzWriteClose has done a fflush on the file handle, * doing a close on the file descriptor associated with it should * be safe™. */ if (close(fd_out)) ohshite(_("%s: internal bzip2 write error"), desc); }
static void file_treewalk_feed(const char *dir, int fd_out) { int pipefd[2]; pid_t pid; struct file_info *fi; struct file_info *symlist = NULL; struct file_info *symlist_end = NULL; m_pipe(pipefd); pid = subproc_fork(); if (pid == 0) { m_dup2(pipefd[1], 1); close(pipefd[0]); close(pipefd[1]); if (chdir(dir)) ohshite(_("failed to chdir to `%.255s'"), dir); execlp(FIND, "find", ".", "-path", "./" BUILDCONTROLDIR, "-prune", "-o", "-print0", NULL); ohshite(_("unable to execute %s (%s)"), "find", FIND); } close(pipefd[1]); /* We need to reorder the files so we can make sure that symlinks * will not appear before their target. */ while ((fi = file_info_get(dir, pipefd[0])) != NULL) { if (S_ISLNK(fi->st.st_mode)) { file_info_list_append(&symlist, &symlist_end, fi); } else { if (fd_write(fd_out, fi->fn, strlen(fi->fn) + 1) < 0) ohshite(_("failed to write filename to tar pipe (%s)"), _("data member")); file_info_free(fi); } } close(pipefd[0]); subproc_wait_check(pid, "find", 0); for (fi = symlist; fi; fi = fi->next) if (fd_write(fd_out, fi->fn, strlen(fi->fn) + 1) < 0) ohshite(_("failed to write filename to tar pipe (%s)"), _("data member")); file_info_list_free(symlist); }