retvalue markdone_create(const char *codename, struct markdonefile **done_p) { struct markdonefile *done; done = NEW(struct markdonefile); if (FAILEDTOALLOC(done)) return RET_ERROR_OOM; done->finalfilename = donefilename(codename); if (FAILEDTOALLOC(done->finalfilename)) { free(done); return RET_ERROR_OOM; } done->tempfilename = calc_addsuffix(done->finalfilename, "new"); if (FAILEDTOALLOC(done->tempfilename)) { free(done->finalfilename); free(done); return RET_ERROR_OOM; } done->file = fopen(done->tempfilename, "w+"); if (done->file == NULL) { int e = errno; fprintf(stderr, "Error %d creating '%s': %s\n", e, done->tempfilename, strerror(e)); free(done->finalfilename); free(done->tempfilename); free(done); return RET_ERROR; } fprintf(done->file, "Updates already processed for %s:\n", codename); *done_p = done; return RET_OK; }
static retvalue callexporthook(/*@null@*/const char *hook, const char *relfilename, const char *mode, struct release *release) { pid_t f, c; int status; int io[2]; char buffer[1000]; int already = 0; if (hook == NULL) return RET_NOTHING; status = pipe(io); if (status < 0) { int e = errno; fprintf(stderr, "Error %d creating pipe: %s!\n", e, strerror(e)); return RET_ERRNO(e); } f = fork(); if (f < 0) { int e = errno; (void)close(io[0]); (void)close(io[1]); fprintf(stderr, "Error %d while forking for exporthook: %s\n", e, strerror(e)); return RET_ERRNO(e); } if (f == 0) { char *reltmpfilename; int e; if (dup2(io[1], 3) < 0) { e = errno; fprintf(stderr, "Error %d dup2'ing fd %d to 3: %s\n", e, io[1], strerror(e)); exit(255); } /* "Doppelt haelt besser": */ if (io[0] != 3) (void)close(io[0]); if (io[1] != 3) (void)close(io[1]); closefrom(4); /* backward compatibilty */ reltmpfilename = calc_addsuffix(relfilename, "new"); if (reltmpfilename == NULL) { exit(255); } setenv("REPREPRO_BASE_DIR", global.basedir, true); setenv("REPREPRO_OUT_DIR", global.outdir, true); setenv("REPREPRO_CONF_DIR", global.confdir, true); setenv("REPREPRO_DIST_DIR", global.distdir, true); setenv("REPREPRO_LOG_DIR", global.logdir, true); (void)execl(hook, hook, release_dirofdist(release), reltmpfilename, relfilename, mode, ENDOFARGUMENTS); e = errno; fprintf(stderr, "Error %d while executing '%s': %s\n", e, hook, strerror(e)); exit(255); } close(io[1]); markcloseonexec(io[0]); if (verbose > 6) printf("Called %s '%s' '%s.new' '%s' '%s'\n", hook, release_dirofdist(release), relfilename, relfilename, mode); /* read what comes from the client */ while (true) { ssize_t r; int last, j; r = read(io[0], buffer + already, 999 - already); if (r < 0) { int e = errno; fprintf(stderr, "Error %d reading from exporthook: %s!\n", e, strerror(e)); break; } already += r; if (r == 0) { buffer[already] = '\0'; already++; } last = 0; for (j = 0 ; j < already ; j++) { if (buffer[j] == '\n' || buffer[j] == '\0') { int next = j+1; int e = (j>0)?(j-1):j; retvalue ret; while (last < j && xisspace(buffer[last])) last++; if (last >= j) { last = next; continue; } while (xisspace(buffer[e])) { e--; assert (e >= last); } ret = gotfilename(buffer + last, e - last + 1, release); if (RET_WAS_ERROR(ret)) { (void)close(io[0]); return ret; } last = next; } } if (last > 0) { if (already > last) memmove(buffer, buffer + last, already - last); already -= last; } if (r == 0) break; } (void)close(io[0]); do { c = waitpid(f, &status, WUNTRACED); if (c < 0) { int e = errno; fprintf(stderr, "Error %d while waiting for hook '%s' to finish: %s\n", e, hook, strerror(e)); return RET_ERRNO(e); } } while (c != f); if (WIFEXITED(status)) { if (WEXITSTATUS(status) == 0) { if (verbose > 6) printf("Exporthook successfully returned!\n"); return RET_OK; } else { fprintf(stderr, "Exporthook failed with exitcode %d!\n", (int)WEXITSTATUS(status)); return RET_ERROR; } } else if (WIFSIGNALED(status)) { fprintf(stderr, "Exporthook killed by signal %d!\n", (int)(WTERMSIG(status))); return RET_ERROR; } else { fprintf(stderr, "Exporthook terminated abnormally. (status is %x)!\n", status); return RET_ERROR; } }