static void write_merge_msg(void) { int fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666); if (fd < 0) die_errno(_("Could not open '%s' for writing"), git_path("MERGE_MSG")); if (write_in_full(fd, merge_msg.buf, merge_msg.len) != merge_msg.len) die_errno(_("Could not write to '%s'"), git_path("MERGE_MSG")); close(fd); }
static void create_temp(mmfile_t *src, char *path, size_t len) { int fd; xsnprintf(path, len, ".merge_file_XXXXXX"); fd = xmkstemp(path); if (write_in_full(fd, src->ptr, src->size) < 0) die_errno("unable to write temp-file"); close(fd); }
int write_or_whine(int fd, const void *buf, size_t count, const char *msg) { if (write_in_full(fd, buf, count) < 0) { fprintf(stderr, "%s: write error (%s)\n", msg, strerror(errno)); return 0; } return 1; }
static void create_temp(mmfile_t *src, char *path) { int fd; strcpy(path, ".merge_file_XXXXXX"); fd = xmkstemp(path); if (write_in_full(fd, src->ptr, src->size) != src->size) die("unable to write temp-file"); close(fd); }
static int run_gpg_verify(const char *buf, unsigned long size, int verbose) { struct child_process gpg; const char *args_gpg[] = {"gpg", "--verify", "FILE", "-", NULL}; char path[PATH_MAX], *eol; size_t len; int fd, ret; fd = git_mkstemp(path, PATH_MAX, ".git_vtag_tmpXXXXXX"); if (fd < 0) return error("could not create temporary file '%s': %s", path, strerror(errno)); if (write_in_full(fd, buf, size) < 0) return error("failed writing temporary file '%s': %s", path, strerror(errno)); close(fd); /* find the length without signature */ len = 0; while (len < size && prefixcmp(buf + len, PGP_SIGNATURE)) { eol = memchr(buf + len, '\n', size - len); len += eol ? eol - (buf + len) + 1 : size - len; } if (verbose) write_in_full(1, buf, len); memset(&gpg, 0, sizeof(gpg)); gpg.argv = args_gpg; gpg.in = -1; args_gpg[2] = path; if (start_command(&gpg)) { unlink(path); return error("could not run gpg."); } write_in_full(gpg.in, buf, len); close(gpg.in); ret = finish_command(&gpg); unlink(path); return ret; }
static int write_rr(struct string_list *rr, int out_fd) { int i; for (i = 0; i < rr->nr; i++) { const char *path; int length; if (!rr->items[i].util) continue; path = rr->items[i].string; length = strlen(path) + 1; if (write_in_full(out_fd, rr->items[i].util, 40) != 40 || write_str_in_full(out_fd, "\t") != 1 || write_in_full(out_fd, path, length) != length) die("unable to write rerere record"); } if (commit_lock_file(&write_lock) != 0) die("unable to write rerere record"); return 0; }
int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) { const char *inpath = NULL; const char *message = NULL; int shortlog_len = -1; struct option options[] = { { OPTION_INTEGER, 0, "log", &shortlog_len, N_("n"), N_("populate log with at most <n> entries from shortlog"), PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN }, { OPTION_INTEGER, 0, "summary", &shortlog_len, N_("n"), N_("alias for --log (deprecated)"), PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN, NULL, DEFAULT_MERGE_LOG_LEN }, OPT_STRING('m', "message", &message, N_("text"), N_("use <text> as start of message")), OPT_FILENAME('F', "file", &inpath, N_("file to read from")), OPT_END() }; FILE *in = stdin; struct strbuf input = STRBUF_INIT, output = STRBUF_INIT; int ret; struct fmt_merge_msg_opts opts; git_config(fmt_merge_msg_config, NULL); argc = parse_options(argc, argv, prefix, options, fmt_merge_msg_usage, 0); if (argc > 0) usage_with_options(fmt_merge_msg_usage, options); if (shortlog_len < 0) shortlog_len = (merge_log_config > 0) ? merge_log_config : 0; if (inpath && strcmp(inpath, "-")) { in = fopen(inpath, "r"); if (!in) die_errno("cannot open '%s'", inpath); } if (strbuf_read(&input, fileno(in), 0) < 0) die_errno("could not read input file"); if (message) strbuf_addstr(&output, message); memset(&opts, 0, sizeof(opts)); opts.add_title = !message; opts.credit_people = 1; opts.shortlog_len = shortlog_len; ret = fmt_merge_msg(&input, &output, &opts); if (ret) return ret; write_in_full(STDOUT_FILENO, output.buf, output.len); return 0; }
static int run_pre_push_hook(struct transport *transport, struct ref *remote_refs) { int ret = 0, x; struct ref *r; struct child_process proc = CHILD_PROCESS_INIT; struct strbuf buf; const char *argv[4]; if (!(argv[0] = find_hook("pre-push"))) return 0; argv[1] = transport->remote->name; argv[2] = transport->url; argv[3] = NULL; proc.argv = argv; proc.in = -1; if (start_command(&proc)) { finish_command(&proc); return -1; } strbuf_init(&buf, 256); for (r = remote_refs; r; r = r->next) { if (!r->peer_ref) continue; if (r->status == REF_STATUS_REJECT_NONFASTFORWARD) continue; if (r->status == REF_STATUS_REJECT_STALE) continue; if (r->status == REF_STATUS_UPTODATE) continue; strbuf_reset(&buf); strbuf_addf( &buf, "%s %s %s %s\n", r->peer_ref->name, sha1_to_hex(r->new_sha1), r->name, sha1_to_hex(r->old_sha1)); if (write_in_full(proc.in, buf.buf, buf.len) != buf.len) { ret = -1; break; } } strbuf_release(&buf); x = close(proc.in); if (!ret) ret = x; x = finish_command(&proc); if (!ret) ret = x; return ret; }
static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_state) { struct child_process proc = CHILD_PROCESS_INIT; struct async muxer; const char *argv[2]; int code; argv[0] = find_hook(hook_name); if (!argv[0]) return 0; argv[1] = NULL; proc.argv = argv; proc.in = -1; proc.stdout_to_stderr = 1; if (use_sideband) { memset(&muxer, 0, sizeof(muxer)); muxer.proc = copy_to_sideband; muxer.in = -1; code = start_async(&muxer); if (code) return code; proc.err = muxer.in; } prepare_push_cert_sha1(&proc); code = start_command(&proc); if (code) { if (use_sideband) finish_async(&muxer); return code; } sigchain_push(SIGPIPE, SIG_IGN); while (1) { const char *buf; size_t n; if (feed(feed_state, &buf, &n)) break; if (write_in_full(proc.in, buf, n) != n) break; } close(proc.in); if (use_sideband) finish_async(&muxer); sigchain_pop(SIGPIPE); return finish_command(&proc); }
static void write_merge_msg(struct strbuf *msg) { const char *filename = git_path("MERGE_MSG"); int fd = open(filename, O_WRONLY | O_CREAT, 0666); if (fd < 0) die_errno(_("Could not open '%s' for writing"), filename); if (write_in_full(fd, msg->buf, msg->len) != msg->len) die_errno(_("Could not write to '%s'"), filename); close(fd); }
int stream_blob_to_fd(int fd, unsigned const char *sha1, struct stream_filter *filter, int can_seek) { struct git_istream *st; enum object_type type; unsigned long sz; ssize_t kept = 0; int result = -1; st = open_istream(sha1, &type, &sz, filter); if (!st) { if (filter) free_stream_filter(filter); return result; } if (type != OBJ_BLOB) goto close_and_exit; for (;;) { char buf[1024 * 16]; ssize_t wrote, holeto; ssize_t readlen = read_istream(st, buf, sizeof(buf)); if (readlen < 0) goto close_and_exit; if (!readlen) break; if (can_seek && sizeof(buf) == readlen) { for (holeto = 0; holeto < readlen; holeto++) if (buf[holeto]) break; if (readlen == holeto) { kept += holeto; continue; } } if (kept && lseek(fd, kept, SEEK_CUR) == (off_t) -1) goto close_and_exit; else kept = 0; wrote = write_in_full(fd, buf, readlen); if (wrote != readlen) goto close_and_exit; } if (kept && (lseek(fd, kept - 1, SEEK_CUR) == (off_t) -1 || xwrite(fd, "", 1) != 1)) goto close_and_exit; result = 0; close_and_exit: close_istream(st); return result; }
static int feed_msg_to_hook(int fd, const char *fmt, ...) { int cnt; char buf[1024]; va_list params; va_start(params, fmt); cnt = vsprintf(buf, fmt, params); va_end(params); return write_in_full(fd, buf, cnt) != cnt; }
static void inflate_request(const char *prog_name, int out, int buffer_input) { git_zstream stream; unsigned char *full_request = NULL; unsigned char in_buf[8192]; unsigned char out_buf[8192]; unsigned long cnt = 0; memset(&stream, 0, sizeof(stream)); git_inflate_init_gzip_only(&stream); while (1) { ssize_t n; if (buffer_input) { if (full_request) n = 0; /* nothing left to read */ else n = read_request(0, &full_request); stream.next_in = full_request; } else { n = xread(0, in_buf, sizeof(in_buf)); stream.next_in = in_buf; } if (n <= 0) die("request ended in the middle of the gzip stream"); stream.avail_in = n; while (0 < stream.avail_in) { int ret; stream.next_out = out_buf; stream.avail_out = sizeof(out_buf); ret = git_inflate(&stream, Z_NO_FLUSH); if (ret != Z_OK && ret != Z_STREAM_END) die("zlib error inflating request, result %d", ret); n = stream.total_out - cnt; if (write_in_full(out, out_buf, n) != n) die("%s aborted reading request", prog_name); cnt += n; if (ret == Z_STREAM_END) goto done; } } done: git_inflate_end(&stream); close(out); free(full_request); }
static void copy_request(const char *prog_name, int out) { unsigned char *buf; ssize_t n = read_request(0, &buf); if (n < 0) die_errno("error reading request body"); if (write_in_full(out, buf, n) != n) die("%s aborted reading request", prog_name); close(out); free(buf); }
static void write_message(struct strbuf *msgbuf, const char *filename) { static struct lock_file msg_file; int msg_fd = hold_lock_file_for_update(&msg_file, filename, LOCK_DIE_ON_ERROR); if (write_in_full(msg_fd, msgbuf->buf, msgbuf->len) < 0) die_errno(_("Could not write to %s"), filename); strbuf_release(msgbuf); if (commit_lock_file(&msg_file) < 0) die(_("Error wrapping up %s."), filename); }
/* * Create a detached signature for the contents of "buffer" and append * it after "signature"; "buffer" and "signature" can be the same * strbuf instance, which would cause the detached signature appended * at the end. */ int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key) { struct child_process gpg; const char *args[4]; ssize_t len; size_t i, j, bottom; memset(&gpg, 0, sizeof(gpg)); gpg.argv = args; gpg.in = -1; gpg.out = -1; args[0] = gpg_program; args[1] = "-bsau"; args[2] = signing_key; args[3] = NULL; if (start_command(&gpg)) return error(_("could not run gpg.")); /* * When the username signingkey is bad, program could be terminated * because gpg exits without reading and then write gets SIGPIPE. */ sigchain_push(SIGPIPE, SIG_IGN); if (write_in_full(gpg.in, buffer->buf, buffer->len) != buffer->len) { close(gpg.in); close(gpg.out); finish_command(&gpg); return error(_("gpg did not accept the data")); } close(gpg.in); bottom = signature->len; len = strbuf_read(signature, gpg.out, 1024); close(gpg.out); sigchain_pop(SIGPIPE); if (finish_command(&gpg) || !len || len < 0) return error(_("gpg failed to sign the data")); /* Strip CR from the line endings, in case we are on Windows. */ for (i = j = bottom; i < signature->len; i++) if (signature->buf[i] != '\r') { if (i != j) signature->buf[j] = signature->buf[i]; j++; } strbuf_setlen(signature, j); return 0; }
static char *shell_prompt(const char *prompt, int echo) { const char *read_input[] = { /* Note: call 'bash' explicitly, as 'read -s' is bash-specific */ "bash", "-c", echo ? "test \"a$SHELL\" != \"a${SHELL%.exe}\" || exit 127; cat >/dev/tty &&" " read -r line </dev/tty && echo \"$line\"" : "test \"a$SHELL\" != \"a${SHELL%.exe}\" || exit 127; cat >/dev/tty &&" " read -r -s line </dev/tty && echo \"$line\" && echo >/dev/tty", NULL }; struct child_process child = CHILD_PROCESS_INIT; static struct strbuf buffer = STRBUF_INIT; int prompt_len = strlen(prompt), len = -1, code; child.argv = read_input; child.in = -1; child.out = -1; child.silent_exec_failure = 1; if (start_command(&child)) return NULL; if (write_in_full(child.in, prompt, prompt_len) != prompt_len) { error("could not write to prompt script"); close(child.in); goto ret; } close(child.in); strbuf_reset(&buffer); len = strbuf_read(&buffer, child.out, 1024); if (len < 0) { error("could not read from prompt script"); goto ret; } strbuf_strip_suffix(&buffer, "\n"); strbuf_strip_suffix(&buffer, "\r"); ret: close(child.out); code = finish_command(&child); if (code) { if (code != 127) error("failed to execute prompt script (exit code %d)", code); return NULL; } return len < 0 ? NULL : buffer.buf; }
static int run_gpg_verify(const char *buf, unsigned long size, int verbose) { int len; len = parse_signature(buf, size); if (verbose) write_in_full(1, buf, len); if (size == len) return error("no signature found"); return verify_signed_buffer(buf, len, buf + len, size - len, NULL); }
static void save_head(const char *head) { static struct lock_file head_lock; struct strbuf buf = STRBUF_INIT; int fd; fd = hold_lock_file_for_update(&head_lock, git_path_head_file(), LOCK_DIE_ON_ERROR); strbuf_addf(&buf, "%s\n", head); if (write_in_full(fd, buf.buf, buf.len) < 0) die_errno(_("Could not write to %s"), git_path_head_file()); if (commit_lock_file(&head_lock) < 0) die(_("Error wrapping up %s."), git_path_head_file()); }
static void write_merge_state(struct commit_list *remoteheads) { const char *filename; int fd; struct commit_list *j; struct strbuf buf = STRBUF_INIT; for (j = remoteheads; j; j = j->next) { struct object_id *oid; struct commit *c = j->item; if (c->util && merge_remote_util(c)->obj) { oid = &merge_remote_util(c)->obj->oid; } else { oid = &c->object.oid; } strbuf_addf(&buf, "%s\n", oid_to_hex(oid)); } filename = git_path_merge_head(); fd = open(filename, O_WRONLY | O_CREAT, 0666); if (fd < 0) die_errno(_("Could not open '%s' for writing"), filename); if (write_in_full(fd, buf.buf, buf.len) != buf.len) die_errno(_("Could not write to '%s'"), filename); close(fd); strbuf_addch(&merge_msg, '\n'); write_merge_msg(&merge_msg); filename = git_path_merge_mode(); fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) die_errno(_("Could not open '%s' for writing"), filename); strbuf_reset(&buf); if (fast_forward == FF_NO) strbuf_addf(&buf, "no-ff"); if (write_in_full(fd, buf.buf, buf.len) != buf.len) die_errno(_("Could not write to '%s'"), filename); close(fd); }
static void write_merge_state(struct commit_list *remoteheads) { const char *filename; int fd; struct commit_list *j; struct strbuf buf = STRBUF_INIT; for (j = remoteheads; j; j = j->next) { unsigned const char *sha1; struct commit *c = j->item; if (c->util && merge_remote_util(c)->obj) { sha1 = merge_remote_util(c)->obj->sha1; } else { sha1 = c->object.sha1; } strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1)); } filename = git_path("MERGE_HEAD"); fd = open(filename, O_WRONLY | O_CREAT, 0666); if (fd < 0) die_errno(_("Could not open '%s' for writing"), filename); if (write_in_full(fd, buf.buf, buf.len) != buf.len) die_errno(_("Could not write to '%s'"), filename); close(fd); strbuf_addch(&merge_msg, '\n'); write_merge_msg(&merge_msg); filename = git_path("MERGE_MODE"); fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) die_errno(_("Could not open '%s' for writing"), filename); strbuf_reset(&buf); if (!allow_fast_forward) strbuf_addf(&buf, "no-ff"); if (write_in_full(fd, buf.buf, buf.len) != buf.len) die_errno(_("Could not write to '%s'"), filename); close(fd); }
static int set_helper_option(struct transport *transport, const char *name, const char *value) { struct helper_data *data = transport->data; struct child_process *helper = get_helper(transport); struct strbuf buf = STRBUF_INIT; int i, ret, is_bool = 0; if (!data->option) return 1; for (i = 0; i < ARRAY_SIZE(unsupported_options); i++) { if (!strcmp(name, unsupported_options[i])) return 1; } for (i = 0; i < ARRAY_SIZE(boolean_options); i++) { if (!strcmp(name, boolean_options[i])) { is_bool = 1; break; } } strbuf_addf(&buf, "option %s ", name); if (is_bool) strbuf_addstr(&buf, value ? "true" : "false"); else quote_c_style(value, &buf, NULL, 0); strbuf_addch(&buf, '\n'); if (write_in_full(helper->in, buf.buf, buf.len) != buf.len) die_errno("cannot send option to %s", data->name); strbuf_reset(&buf); if (strbuf_getline(&buf, data->out, '\n') == EOF) exit(128); /* child died, message supplied already */ if (!strcmp(buf.buf, "ok")) ret = 0; else if (!prefixcmp(buf.buf, "error")) { ret = -1; } else if (!strcmp(buf.buf, "unsupported")) ret = 1; else { warning("%s unexpectedly said: '%s'", data->name, buf.buf); ret = 1; } strbuf_release(&buf); return ret; }
int copy_fd(int ifd, int ofd) { while (1) { char buffer[8192]; ssize_t len = xread(ifd, buffer, sizeof(buffer)); if (!len) break; if (len < 0) return COPY_READ_ERROR; if (write_in_full(ofd, buffer, len) < 0) return COPY_WRITE_ERROR; } return 0; }
static void write_cherry_pick_head(struct commit *commit) { int fd; struct strbuf buf = STRBUF_INIT; strbuf_addf(&buf, "%s\n", sha1_to_hex(commit->object.sha1)); fd = open(git_path("CHERRY_PICK_HEAD"), O_WRONLY | O_CREAT, 0666); if (fd < 0) die_errno(_("Could not open '%s' for writing"), git_path("CHERRY_PICK_HEAD")); if (write_in_full(fd, buf.buf, buf.len) != buf.len || close(fd)) die_errno(_("Could not write to '%s'"), git_path("CHERRY_PICK_HEAD")); strbuf_release(&buf); }
static int store_write_pair(int fd, const char* key, const char* value) { int i, success; int length = strlen(key + store.baselen + 1); const char *quote = ""; struct strbuf sb; /* * Check to see if the value needs to be surrounded with a dq pair. * Note that problematic characters are always backslash-quoted; this * check is about not losing leading or trailing SP and strings that * follow beginning-of-comment characters (i.e. ';' and '#') by the * configuration parser. */ if (value[0] == ' ') quote = "\""; for (i = 0; value[i]; i++) if (value[i] == ';' || value[i] == '#') quote = "\""; if (i && value[i - 1] == ' ') quote = "\""; strbuf_init(&sb, 0); strbuf_addf(&sb, "\t%.*s = %s", length, key + store.baselen + 1, quote); for (i = 0; value[i]; i++) switch (value[i]) { case '\n': strbuf_addstr(&sb, "\\n"); break; case '\t': strbuf_addstr(&sb, "\\t"); break; case '"': case '\\': strbuf_addch(&sb, '\\'); default: strbuf_addch(&sb, value[i]); break; } strbuf_addf(&sb, "%s\n", quote); success = write_in_full(fd, sb.buf, sb.len) == sb.len; strbuf_release(&sb); return success; }
static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_state) { struct child_process proc; struct async muxer; const char *argv[2]; int code; if (access(hook_name, X_OK) < 0) return 0; argv[0] = hook_name; argv[1] = NULL; memset(&proc, 0, sizeof(proc)); proc.argv = argv; proc.in = -1; proc.stdout_to_stderr = 1; if (use_sideband) { memset(&muxer, 0, sizeof(muxer)); muxer.proc = copy_to_sideband; muxer.in = -1; code = start_async(&muxer); if (code) return code; proc.err = muxer.in; } code = start_command(&proc); if (code) { if (use_sideband) finish_async(&muxer); return code; } while (1) { const char *buf; size_t n; if (feed(feed_state, &buf, &n)) break; if (write_in_full(proc.in, buf, n) != n) break; } close(proc.in); if (use_sideband) finish_async(&muxer); return finish_command(&proc); }
static void write_cherry_pick_head(struct commit *commit, const char *pseudoref) { const char *filename; int fd; struct strbuf buf = STRBUF_INIT; strbuf_addf(&buf, "%s\n", sha1_to_hex(commit->object.sha1)); filename = git_path("%s", pseudoref); fd = open(filename, O_WRONLY | O_CREAT, 0666); if (fd < 0) die_errno(_("Could not open '%s' for writing"), filename); if (write_in_full(fd, buf.buf, buf.len) != buf.len || close(fd)) die_errno(_("Could not write to '%s'"), filename); strbuf_release(&buf); }
static void flush_buffer(int fd, const char *buf, unsigned long size) { while (size > 0) { long ret = write_in_full(fd, buf, size); if (ret < 0) { /* Ignore epipe */ if (errno == EPIPE) break; die("merge-recursive: %s", strerror(errno)); } else if (!ret) { die("merge-recursive: disk full?"); } size -= ret; buf += ret; } }
static int packet_write_gently(const int fd_out, const char *buf, size_t size) { static char packet_write_buffer[LARGE_PACKET_MAX]; size_t packet_size; if (size > sizeof(packet_write_buffer) - 4) return error("packet write failed - data exceeds max packet size"); packet_trace(buf, size, 1); packet_size = size + 4; set_packet_header(packet_write_buffer, packet_size); memcpy(packet_write_buffer + 4, buf, size); if (write_in_full(fd_out, packet_write_buffer, packet_size) == packet_size) return 0; return error("packet write failed"); }
/** * Sign buffer */ static int do_sign(struct strbuf *buffer, char * signingkey) { struct child_process gpg; const char *args[4]; int len; int i, j; /* When the username signingkey is bad, program could be terminated * because gpg exits without reading and then write gets SIGPIPE. */ signal(SIGPIPE, SIG_IGN); memset(&gpg, 0, sizeof(gpg)); gpg.argv = args; gpg.in = -1; gpg.out = -1; args[0] = "gpg"; args[1] = "-bsau"; args[2] = signingkey; args[3] = NULL; if (start_command(&gpg)) return error("could not run gpg."); if (write_in_full(gpg.in, buffer->buf, buffer->len) != buffer->len) { close(gpg.in); close(gpg.out); finish_command(&gpg); return error("gpg did not accept the tag data"); } close(gpg.in); len = strbuf_read(buffer, gpg.out, 1024); close(gpg.out); if (finish_command(&gpg) || !len || len < 0) return error("gpg failed to sign the tag"); /* Strip CR from the line endings, in case we are on Windows. */ for (i = j = 0; i < buffer->len; i++) if (buffer->buf[i] != '\r') { if (i != j) buffer->buf[j] = buffer->buf[i]; j++; } strbuf_setlen(buffer, j); return 0; }