1#include "refs.h"
2#include "cache.h"
34
#include <errno.h>
56
static int read_ref(const char *path, unsigned char *sha1)
7{
8int ret = -1;
9int fd = open(path, O_RDONLY);
1011
if (fd >= 0) {
12char buffer[60];
13if (read(fd, buffer, sizeof(buffer)) >= 40)
14ret = get_sha1_hex(buffer, sha1);
15close(fd);
16}
17return ret;
18}
1920
static int do_for_each_ref(const char *base, int (*fn)(const char *path, const unsigned char *sha1))
21{
22int retval = 0;
23DIR *dir = opendir(base);
2425
if (dir) {
26struct dirent *de;
27int baselen = strlen(base);
28char *path = xmalloc(baselen + 257);
29memcpy(path, base, baselen);
30if (baselen && base[baselen-1] != '/')
31path[baselen++] = '/';
3233
while ((de = readdir(dir)) != NULL) {
34unsigned char sha1[20];
35struct stat st;
36int namelen;
3738
if (de->d_name[0] == '.')
39continue;
40namelen = strlen(de->d_name);
41if (namelen > 255)
42continue;
43memcpy(path + baselen, de->d_name, namelen+1);
44if (lstat(path, &st) < 0)
45continue;
46if (S_ISDIR(st.st_mode)) {
47retval = do_for_each_ref(path, fn);
48if (retval)
49break;
50continue;
51}
52if (read_ref(path, sha1) < 0)
53continue;
54if (!has_sha1_file(sha1))
55continue;
56retval = fn(path, sha1);
57if (retval)
58break;
59}
60free(path);
61closedir(dir);
62}
63return retval;
64}
6566
int for_each_ref(int (*fn)(const char *path, const unsigned char *sha1))
67{
68return do_for_each_ref(get_refs_directory(), fn);
69}
7071
static char *ref_file_name(const char *ref)
72{
73char *base = get_refs_directory();
74int baselen = strlen(base);
75int reflen = strlen(ref);
76char *ret = xmalloc(baselen + 2 + reflen);
77sprintf(ret, "%s/%s", base, ref);
78return ret;
79}
8081
static char *ref_lock_file_name(const char *ref)
82{
83char *base = get_refs_directory();
84int baselen = strlen(base);
85int reflen = strlen(ref);
86char *ret = xmalloc(baselen + 7 + reflen);
87sprintf(ret, "%s/%s.lock", base, ref);
88return ret;
89}
9091
static int read_ref_file(const char *filename, unsigned char *sha1) {
92int fd = open(filename, O_RDONLY);
93char hex[41];
94if (fd < 0) {
95return error("Couldn't open %s\n", filename);
96}
97if ((read(fd, hex, 41) < 41) ||
98(hex[40] != '\n') ||
99get_sha1_hex(hex, sha1)) {
100error("Couldn't read a hash from %s\n", filename);
101close(fd);
102return -1;
103}
104close(fd);
105return 0;
106}
107108
int get_ref_sha1(const char *ref, unsigned char *sha1)
109{
110char *filename;
111int retval;
112if (check_ref_format(ref))
113return -1;
114filename = ref_file_name(ref);
115retval = read_ref_file(filename, sha1);
116free(filename);
117return retval;
118}
119120
static int lock_ref_file(const char *filename, const char *lock_filename,
121const unsigned char *old_sha1)
122{
123int fd = open(lock_filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
124unsigned char current_sha1[20];
125int retval;
126if (fd < 0) {
127return error("Couldn't open lock file for %s: %s",
128filename, strerror(errno));
129}
130retval = read_ref_file(filename, current_sha1);
131if (old_sha1) {
132if (retval) {
133close(fd);
134unlink(lock_filename);
135return error("Could not read the current value of %s",
136filename);
137}
138if (memcmp(current_sha1, old_sha1, 20)) {
139close(fd);
140unlink(lock_filename);
141error("The current value of %s is %s",
142filename, sha1_to_hex(current_sha1));
143return error("Expected %s",
144sha1_to_hex(old_sha1));
145}
146} else {
147if (!retval) {
148close(fd);
149unlink(lock_filename);
150return error("Unexpectedly found a value of %s for %s",
151sha1_to_hex(current_sha1), filename);
152}
153}
154return fd;
155}
156157
int lock_ref_sha1(const char *ref, const unsigned char *old_sha1)
158{
159char *filename;
160char *lock_filename;
161int retval;
162if (check_ref_format(ref))
163return -1;
164filename = ref_file_name(ref);
165lock_filename = ref_lock_file_name(ref);
166retval = lock_ref_file(filename, lock_filename, old_sha1);
167free(filename);
168free(lock_filename);
169return retval;
170}
171172
static int write_ref_file(const char *filename,
173const char *lock_filename, int fd,
174const unsigned char *sha1)
175{
176char *hex = sha1_to_hex(sha1);
177char term = '\n';
178if (write(fd, hex, 40) < 40 ||
179write(fd, &term, 1) < 1) {
180error("Couldn't write %s\n", filename);
181close(fd);
182return -1;
183}
184close(fd);
185rename(lock_filename, filename);
186return 0;
187}
188189
int write_ref_sha1(const char *ref, int fd, const unsigned char *sha1)
190{
191char *filename;
192char *lock_filename;
193int retval;
194if (fd < 0)
195return -1;
196if (check_ref_format(ref))
197return -1;
198filename = ref_file_name(ref);
199lock_filename = ref_lock_file_name(ref);
200retval = write_ref_file(filename, lock_filename, fd, sha1);
201free(filename);
202free(lock_filename);
203return retval;
204}
205206
int check_ref_format(const char *ref)
207{
208char *middle;
209if (ref[0] == '.' || ref[0] == '/')
210return -1;
211middle = strchr(ref, '/');
212if (!middle || !middle[1])
213return -1;
214if (strchr(middle + 1, '/'))
215return -1;
216return 0;
217}
218219
int write_ref_sha1_unlocked(const char *ref, const unsigned char *sha1)
220{
221char *filename;
222char *lock_filename;
223int fd;
224int retval;
225if (check_ref_format(ref))
226return -1;
227filename = ref_file_name(ref);
228lock_filename = ref_lock_file_name(ref);
229fd = open(lock_filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
230if (fd < 0) {
231error("Writing %s", lock_filename);
232perror("Open");
233}
234retval = write_ref_file(filename, lock_filename, fd, sha1);
235free(filename);
236free(lock_filename);
237return retval;
238}