4
#include "commit.h"
5
#include "tag.h"
6
7
-/* refs */
8
-static FILE *info_ref_fp;
7
+/*
8
+ * Create the file "path" by writing to a temporary file and renaming
9
+ * it into place. The contents of the file come from "generate", which
10
+ * should return non-zero if it encounters an error.
11
+ */
12
+static int update_info_file(char *path, int (*generate)(FILE *))
13
+{
14
+ char *tmp = mkpathdup("%s_XXXXXX", path);
15
+ int ret = -1;
16
+ int fd = -1;
17
+ FILE *fp = NULL;
18
+
19
+ safe_create_leading_directories(path);
20
+ fd = mkstemp(tmp);
21
+ if (fd < 0)
22
+ goto out;
23
+ fp = fdopen(fd, "w");
24
+ if (!fp)
25
+ goto out;
26
+ ret = generate(fp);
27
+ if (ret)
28
+ goto out;
29
+ if (fclose(fp))
30
+ goto out;
31
+ if (adjust_shared_perm(tmp) < 0)
32
+ goto out;
33
+ if (rename(tmp, path) < 0)
34
+ goto out;
35
+ ret = 0;
36
+
37
+out:
38
+ if (ret) {
39
+ error("unable to update %s: %s", path, strerror(errno));
40
+ if (fp)
41
+ fclose(fp);
42
+ else if (fd >= 0)
43
+ close(fd);
44
+ unlink(tmp);
45
+ }
46
+ free(tmp);
47
+ return ret;
48
+}
49
50
static int add_info_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
51
{
52
+ FILE *fp = cb_data;
53
struct object *o = parse_object(sha1);
54
if (!o)
55
return -1;
56
16
- fprintf(info_ref_fp, "%s %s\n", sha1_to_hex(sha1), path);
57
+ if (fprintf(fp, "%s %s\n", sha1_to_hex(sha1), path) < 0)
58
+ return -1;
59
+
60
if (o->type == OBJ_TAG) {
61
o = deref_tag(o, path, 0);
62
if (o)
20
- fprintf(info_ref_fp, "%s %s^{}\n",
21
- sha1_to_hex(o->sha1), path);
63
+ if (fprintf(fp, "%s %s^{}\n",
64
+ sha1_to_hex(o->sha1), path) < 0)
65
+ return -1;
66
}
67
return 0;
68
}
69
70
+static int generate_info_refs(FILE *fp)
71
+{
72
+ return for_each_ref(add_info_ref, fp);
73
+}
74
+
75
static int update_info_refs(int force)
76
{
28
- char *path0 = git_pathdup("info/refs");
29
- int len = strlen(path0);
30
- char *path1 = xmalloc(len + 2);
31
-
32
- strcpy(path1, path0);
33
- strcpy(path1 + len, "+");
34
-
35
- safe_create_leading_directories(path0);
36
- info_ref_fp = fopen(path1, "w");
37
- if (!info_ref_fp)
38
- return error("unable to update %s", path1);
39
- for_each_ref(add_info_ref, NULL);
40
- fclose(info_ref_fp);
41
- adjust_shared_perm(path1);
42
- rename(path1, path0);
43
- free(path0);
44
- free(path1);
45
- return 0;
77
+ char *path = git_pathdup("info/refs");
78
+ int ret = update_info_file(path, generate_info_refs);
79
+ free(path);
80
+ return ret;
81
}
82
83
/* packs */
233
info[i]->new_num = i;
234
}
235
201
-static void write_pack_info_file(FILE *fp)
236
+static int write_pack_info_file(FILE *fp)
237
{
238
int i;
204
- for (i = 0; i < num_pack; i++)
205
- fprintf(fp, "P %s\n", info[i]->p->pack_name + objdirlen + 6);
206
- fputc('\n', fp);
239
+ for (i = 0; i < num_pack; i++) {
240
+ if (fprintf(fp, "P %s\n", info[i]->p->pack_name + objdirlen + 6) < 0)
241
+ return -1;
242
+ }
243
+ if (fputc('\n', fp) == EOF)
244
+ return -1;
245
+ return 0;
246
}
247
248
static int update_info_packs(int force)
249
{
211
- char infofile[PATH_MAX];
212
- char name[PATH_MAX];
213
- int namelen;
214
- FILE *fp;
215
-
216
- namelen = sprintf(infofile, "%s/info/packs", get_object_directory());
217
- strcpy(name, infofile);
218
- strcpy(name + namelen, "+");
250
+ char *infofile = mkpathdup("%s/info/packs", get_object_directory());
251
+ int ret;
252
253
init_pack_info(infofile, force);
221
-
222
- safe_create_leading_directories(name);
223
- fp = fopen(name, "w");
224
- if (!fp)
225
- return error("cannot open %s", name);
226
- write_pack_info_file(fp);
227
- fclose(fp);
228
- adjust_shared_perm(name);
229
- rename(name, infofile);
230
- return 0;
254
+ ret = update_info_file(infofile, write_pack_info_file);
255
+ free(infofile);
256
+ return ret;
257
}
258
259
/* public */