Skip to content

Commit

Permalink
short i/o: fix config updates to use write_in_full
Browse files Browse the repository at this point in the history
We need to check that the writes we perform during the update of
the users configuration work.  Convert to using write_in_full().

Signed-off-by: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
Andy Whitcroft authored and Junio C Hamano committed Jan 8, 2007
1 parent 93822c2 commit 480c9e5
Showing 1 changed file with 77 additions and 29 deletions.
106 changes: 77 additions & 29 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,15 @@ static int store_aux(const char* key, const char* value)
return 0;
}

static void store_write_section(int fd, const char* key)
static int write_error()
{
fprintf(stderr, "Failed to write new configuration file\n");

/* Same error code as "failed to rename". */
return 4;
}

static int store_write_section(int fd, const char* key)
{
const char *dot = strchr(key, '.');
int len1 = store.baselen, len2 = -1;
Expand All @@ -478,37 +486,60 @@ static void store_write_section(int fd, const char* key)
}
}

write(fd, "[", 1);
write(fd, key, len1);
if (write_in_full(fd, "[", 1) != 1 ||
write_in_full(fd, key, len1) != len1)
return 0;
if (len2 >= 0) {
write(fd, " \"", 2);
if (write_in_full(fd, " \"", 2) != 2)
return 0;
while (--len2 >= 0) {
unsigned char c = *++dot;
if (c == '"')
write(fd, "\\", 1);
write(fd, &c, 1);
if (write_in_full(fd, "\\", 1) != 1)
return 0;
if (write_in_full(fd, &c, 1) != 1)
return 0;
}
write(fd, "\"", 1);
if (write_in_full(fd, "\"", 1) != 1)
return 0;
}
write(fd, "]\n", 2);
if (write_in_full(fd, "]\n", 2) != 2)
return 0;

return 1;
}

static void store_write_pair(int fd, const char* key, const char* value)
static int store_write_pair(int fd, const char* key, const char* value)
{
int i;
int length = strlen(key+store.baselen+1);

write(fd, "\t", 1);
write(fd, key+store.baselen+1,
strlen(key+store.baselen+1));
write(fd, " = ", 3);
if (write_in_full(fd, "\t", 1) != 1 ||
write_in_full(fd, key+store.baselen+1, length) != length ||
write_in_full(fd, " = ", 3) != 3)
return 0;
for (i = 0; value[i]; i++)
switch (value[i]) {
case '\n': write(fd, "\\n", 2); break;
case '\t': write(fd, "\\t", 2); break;
case '"': case '\\': write(fd, "\\", 1);
default: write(fd, value+i, 1);
}
write(fd, "\n", 1);
case '\n':
if (write_in_full(fd, "\\n", 2) != 2)
return 0;
break;
case '\t':
if (write_in_full(fd, "\\t", 2) != 2)
return 0;
break;
case '"':
case '\\':
if (write_in_full(fd, "\\", 1) != 1)
return 0;
default:
if (write_in_full(fd, value+i, 1) != 1)
return 0;
break;
}
if (write_in_full(fd, "\n", 1) != 1)
return 0;
return 1;
}

static int find_beginning_of_line(const char* contents, int size,
Expand Down Expand Up @@ -648,8 +679,11 @@ int git_config_set_multivar(const char* key, const char* value,
}

store.key = (char*)key;
store_write_section(fd, key);
store_write_pair(fd, key, value);
if (!store_write_section(fd, key) ||
!store_write_pair(fd, key, value)) {
ret = write_error();
goto out_free;
}
} else{
struct stat st;
char* contents;
Expand Down Expand Up @@ -729,24 +763,30 @@ int git_config_set_multivar(const char* key, const char* value,

/* write the first part of the config */
if (copy_end > copy_begin) {
write(fd, contents + copy_begin,
write_in_full(fd, contents + copy_begin,
copy_end - copy_begin);
if (new_line)
write(fd, "\n", 1);
write_in_full(fd, "\n", 1);
}
copy_begin = store.offset[i];
}

/* write the pair (value == NULL means unset) */
if (value != NULL) {
if (store.state == START)
store_write_section(fd, key);
store_write_pair(fd, key, value);
if (!store_write_section(fd, key)) {
ret = write_error();
goto out_free;
}
if (!store_write_pair(fd, key, value)) {
ret = write_error();
goto out_free;
}
}

/* write the rest of the config */
if (copy_begin < st.st_size)
write(fd, contents + copy_begin,
write_in_full(fd, contents + copy_begin,
st.st_size - copy_begin);

munmap(contents, st.st_size);
Expand Down Expand Up @@ -800,6 +840,7 @@ int git_config_rename_section(const char *old_name, const char *new_name)

while (fgets(buf, sizeof(buf), config_file)) {
int i;
int length;
for (i = 0; buf[i] && isspace(buf[i]); i++)
; /* do nothing */
if (buf[i] == '[') {
Expand Down Expand Up @@ -830,15 +871,22 @@ int git_config_rename_section(const char *old_name, const char *new_name)
/* old_name matches */
ret++;
store.baselen = strlen(new_name);
store_write_section(out_fd, new_name);
if (!store_write_section(out_fd, new_name)) {
ret = write_error();
goto out;
}
continue;
}
}
write(out_fd, buf, strlen(buf));
length = strlen(buf);
if (write_in_full(out_fd, buf, length) != length) {
ret = write_error();
goto out;
}
}
fclose(config_file);
if (close(out_fd) || commit_lock_file(lock) < 0)
ret = error("Cannot commit config file!");
ret = error("Cannot commit config file!");
out:
free(config_filename);
return ret;
Expand Down

0 comments on commit 480c9e5

Please sign in to comment.