Commit 9c26de0fd175c2fbb9c67908a0f8bcd37e81252b

Edward Thomson 2015-04-27T15:38:44

config: lock the file for write before reading When writing a configuration file, we want to take a lock on the new file (eg, `config.lock`) before opening the configuration file (`config`) for reading so that we can prevent somebody from changing the contents underneath us.

diff --git a/src/config_file.c b/src/config_file.c
index c6c9ef5..713183a 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -1789,7 +1789,12 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
 	struct reader *reader = git_array_get(cfg->readers, 0);
 	struct write_data write_data;
 
-	/* TODO: take the lock before reading */
+	/* Lock the file */
+	if ((result = git_filebuf_open(
+		&file, cfg->file_path, 0, GIT_CONFIG_FILE_MODE)) < 0) {
+			git_buf_free(&reader->buffer);
+			return result;
+	}
 
 	/* We need to read in our own config file */
 	result = git_futils_readbuffer(&reader->buffer, cfg->file_path);
@@ -1805,16 +1810,10 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
 		reader->eof = 0;
 		data_start = reader->read_ptr;
 	} else {
+		git_filebuf_cleanup(&file);
 		return -1; /* OS error when reading the file */
 	}
 
-	/* Lock the file */
-	if ((result = git_filebuf_open(
-		&file, cfg->file_path, 0, GIT_CONFIG_FILE_MODE)) < 0) {
-			git_buf_free(&reader->buffer);
-			return result;
-	}
-
 	ldot = strrchr(key, '.');
 	name = ldot + 1;
 	section = git__strndup(key, ldot - key);