summaryrefslogtreecommitdiffabout
path: root/shared.c
authorLars Hjemli <hjemli@gmail.com>2009-08-18 15:17:41 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2009-08-18 15:22:14 (UTC)
commite16f1783346a090e4ea1194dcaae7f03e813f6a2 (patch) (unidiff)
tree268f5ba231895ba3a63071497764c64d44733da5 /shared.c
parent523c133e2e5f7089a3d18ac23f2074b60991a7f0 (diff)
downloadcgit-e16f1783346a090e4ea1194dcaae7f03e813f6a2.zip
cgit-e16f1783346a090e4ea1194dcaae7f03e813f6a2.tar.gz
cgit-e16f1783346a090e4ea1194dcaae7f03e813f6a2.tar.bz2
Add and use a common readfile() function
This function is used to read the full content of a textfile into a newly allocated buffer (with zerotermination). It replaces the earlier readfile() in scan-tree.c (which was rather error-prone[1]), and is reused by read_agefile() in ui-repolist.c. 1: No checks for EINTR and EAGAIN, fixed-size buffer Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (limited to 'shared.c') (more/less context) (ignore whitespace changes)
-rw-r--r--shared.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/shared.c b/shared.c
index 911a55a..4cb9573 100644
--- a/shared.c
+++ b/shared.c
@@ -204,192 +204,213 @@ static int load_mmfile(mmfile_t *file, const unsigned char *sha1)
204{ 204{
205 enum object_type type; 205 enum object_type type;
206 206
207 if (is_null_sha1(sha1)) { 207 if (is_null_sha1(sha1)) {
208 file->ptr = (char *)""; 208 file->ptr = (char *)"";
209 file->size = 0; 209 file->size = 0;
210 } else { 210 } else {
211 file->ptr = read_sha1_file(sha1, &type, 211 file->ptr = read_sha1_file(sha1, &type,
212 (unsigned long *)&file->size); 212 (unsigned long *)&file->size);
213 } 213 }
214 return 1; 214 return 1;
215} 215}
216 216
217/* 217/*
218 * Receive diff-buffers from xdiff and concatenate them as 218 * Receive diff-buffers from xdiff and concatenate them as
219 * needed across multiple callbacks. 219 * needed across multiple callbacks.
220 * 220 *
221 * This is basically a copy of xdiff-interface.c/xdiff_outf(), 221 * This is basically a copy of xdiff-interface.c/xdiff_outf(),
222 * ripped from git and modified to use globals instead of 222 * ripped from git and modified to use globals instead of
223 * a special callback-struct. 223 * a special callback-struct.
224 */ 224 */
225char *diffbuf = NULL; 225char *diffbuf = NULL;
226int buflen = 0; 226int buflen = 0;
227 227
228int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf) 228int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf)
229{ 229{
230 int i; 230 int i;
231 231
232 for (i = 0; i < nbuf; i++) { 232 for (i = 0; i < nbuf; i++) {
233 if (mb[i].ptr[mb[i].size-1] != '\n') { 233 if (mb[i].ptr[mb[i].size-1] != '\n') {
234 /* Incomplete line */ 234 /* Incomplete line */
235 diffbuf = xrealloc(diffbuf, buflen + mb[i].size); 235 diffbuf = xrealloc(diffbuf, buflen + mb[i].size);
236 memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); 236 memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size);
237 buflen += mb[i].size; 237 buflen += mb[i].size;
238 continue; 238 continue;
239 } 239 }
240 240
241 /* we have a complete line */ 241 /* we have a complete line */
242 if (!diffbuf) { 242 if (!diffbuf) {
243 ((linediff_fn)priv)(mb[i].ptr, mb[i].size); 243 ((linediff_fn)priv)(mb[i].ptr, mb[i].size);
244 continue; 244 continue;
245 } 245 }
246 diffbuf = xrealloc(diffbuf, buflen + mb[i].size); 246 diffbuf = xrealloc(diffbuf, buflen + mb[i].size);
247 memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); 247 memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size);
248 ((linediff_fn)priv)(diffbuf, buflen + mb[i].size); 248 ((linediff_fn)priv)(diffbuf, buflen + mb[i].size);
249 free(diffbuf); 249 free(diffbuf);
250 diffbuf = NULL; 250 diffbuf = NULL;
251 buflen = 0; 251 buflen = 0;
252 } 252 }
253 if (diffbuf) { 253 if (diffbuf) {
254 ((linediff_fn)priv)(diffbuf, buflen); 254 ((linediff_fn)priv)(diffbuf, buflen);
255 free(diffbuf); 255 free(diffbuf);
256 diffbuf = NULL; 256 diffbuf = NULL;
257 buflen = 0; 257 buflen = 0;
258 } 258 }
259 return 0; 259 return 0;
260} 260}
261 261
262int cgit_diff_files(const unsigned char *old_sha1, 262int cgit_diff_files(const unsigned char *old_sha1,
263 const unsigned char *new_sha1, unsigned long *old_size, 263 const unsigned char *new_sha1, unsigned long *old_size,
264 unsigned long *new_size, int *binary, linediff_fn fn) 264 unsigned long *new_size, int *binary, linediff_fn fn)
265{ 265{
266 mmfile_t file1, file2; 266 mmfile_t file1, file2;
267 xpparam_t diff_params; 267 xpparam_t diff_params;
268 xdemitconf_t emit_params; 268 xdemitconf_t emit_params;
269 xdemitcb_t emit_cb; 269 xdemitcb_t emit_cb;
270 270
271 if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1)) 271 if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1))
272 return 1; 272 return 1;
273 273
274 *old_size = file1.size; 274 *old_size = file1.size;
275 *new_size = file2.size; 275 *new_size = file2.size;
276 276
277 if ((file1.ptr && buffer_is_binary(file1.ptr, file1.size)) || 277 if ((file1.ptr && buffer_is_binary(file1.ptr, file1.size)) ||
278 (file2.ptr && buffer_is_binary(file2.ptr, file2.size))) { 278 (file2.ptr && buffer_is_binary(file2.ptr, file2.size))) {
279 *binary = 1; 279 *binary = 1;
280 return 0; 280 return 0;
281 } 281 }
282 282
283 memset(&diff_params, 0, sizeof(diff_params)); 283 memset(&diff_params, 0, sizeof(diff_params));
284 memset(&emit_params, 0, sizeof(emit_params)); 284 memset(&emit_params, 0, sizeof(emit_params));
285 memset(&emit_cb, 0, sizeof(emit_cb)); 285 memset(&emit_cb, 0, sizeof(emit_cb));
286 diff_params.flags = XDF_NEED_MINIMAL; 286 diff_params.flags = XDF_NEED_MINIMAL;
287 emit_params.ctxlen = 3; 287 emit_params.ctxlen = 3;
288 emit_params.flags = XDL_EMIT_FUNCNAMES; 288 emit_params.flags = XDL_EMIT_FUNCNAMES;
289 emit_cb.outf = filediff_cb; 289 emit_cb.outf = filediff_cb;
290 emit_cb.priv = fn; 290 emit_cb.priv = fn;
291 xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb); 291 xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb);
292 return 0; 292 return 0;
293} 293}
294 294
295void cgit_diff_tree(const unsigned char *old_sha1, 295void cgit_diff_tree(const unsigned char *old_sha1,
296 const unsigned char *new_sha1, 296 const unsigned char *new_sha1,
297 filepair_fn fn, const char *prefix) 297 filepair_fn fn, const char *prefix)
298{ 298{
299 struct diff_options opt; 299 struct diff_options opt;
300 int ret; 300 int ret;
301 int prefixlen; 301 int prefixlen;
302 302
303 diff_setup(&opt); 303 diff_setup(&opt);
304 opt.output_format = DIFF_FORMAT_CALLBACK; 304 opt.output_format = DIFF_FORMAT_CALLBACK;
305 opt.detect_rename = 1; 305 opt.detect_rename = 1;
306 opt.rename_limit = ctx.cfg.renamelimit; 306 opt.rename_limit = ctx.cfg.renamelimit;
307 DIFF_OPT_SET(&opt, RECURSIVE); 307 DIFF_OPT_SET(&opt, RECURSIVE);
308 opt.format_callback = cgit_diff_tree_cb; 308 opt.format_callback = cgit_diff_tree_cb;
309 opt.format_callback_data = fn; 309 opt.format_callback_data = fn;
310 if (prefix) { 310 if (prefix) {
311 opt.nr_paths = 1; 311 opt.nr_paths = 1;
312 opt.paths = &prefix; 312 opt.paths = &prefix;
313 prefixlen = strlen(prefix); 313 prefixlen = strlen(prefix);
314 opt.pathlens = &prefixlen; 314 opt.pathlens = &prefixlen;
315 } 315 }
316 diff_setup_done(&opt); 316 diff_setup_done(&opt);
317 317
318 if (old_sha1 && !is_null_sha1(old_sha1)) 318 if (old_sha1 && !is_null_sha1(old_sha1))
319 ret = diff_tree_sha1(old_sha1, new_sha1, "", &opt); 319 ret = diff_tree_sha1(old_sha1, new_sha1, "", &opt);
320 else 320 else
321 ret = diff_root_tree_sha1(new_sha1, "", &opt); 321 ret = diff_root_tree_sha1(new_sha1, "", &opt);
322 diffcore_std(&opt); 322 diffcore_std(&opt);
323 diff_flush(&opt); 323 diff_flush(&opt);
324} 324}
325 325
326void cgit_diff_commit(struct commit *commit, filepair_fn fn) 326void cgit_diff_commit(struct commit *commit, filepair_fn fn)
327{ 327{
328 unsigned char *old_sha1 = NULL; 328 unsigned char *old_sha1 = NULL;
329 329
330 if (commit->parents) 330 if (commit->parents)
331 old_sha1 = commit->parents->item->object.sha1; 331 old_sha1 = commit->parents->item->object.sha1;
332 cgit_diff_tree(old_sha1, commit->object.sha1, fn, NULL); 332 cgit_diff_tree(old_sha1, commit->object.sha1, fn, NULL);
333} 333}
334 334
335int cgit_parse_snapshots_mask(const char *str) 335int cgit_parse_snapshots_mask(const char *str)
336{ 336{
337 const struct cgit_snapshot_format *f; 337 const struct cgit_snapshot_format *f;
338 static const char *delim = " \t,:/|;"; 338 static const char *delim = " \t,:/|;";
339 int tl, sl, rv = 0; 339 int tl, sl, rv = 0;
340 340
341 /* favor legacy setting */ 341 /* favor legacy setting */
342 if(atoi(str)) 342 if(atoi(str))
343 return 1; 343 return 1;
344 for(;;) { 344 for(;;) {
345 str += strspn(str,delim); 345 str += strspn(str,delim);
346 tl = strcspn(str,delim); 346 tl = strcspn(str,delim);
347 if (!tl) 347 if (!tl)
348 break; 348 break;
349 for (f = cgit_snapshot_formats; f->suffix; f++) { 349 for (f = cgit_snapshot_formats; f->suffix; f++) {
350 sl = strlen(f->suffix); 350 sl = strlen(f->suffix);
351 if((tl == sl && !strncmp(f->suffix, str, tl)) || 351 if((tl == sl && !strncmp(f->suffix, str, tl)) ||
352 (tl == sl-1 && !strncmp(f->suffix+1, str, tl-1))) { 352 (tl == sl-1 && !strncmp(f->suffix+1, str, tl-1))) {
353 rv |= f->bit; 353 rv |= f->bit;
354 break; 354 break;
355 } 355 }
356 } 356 }
357 str += tl; 357 str += tl;
358 } 358 }
359 return rv; 359 return rv;
360} 360}
361 361
362int cgit_open_filter(struct cgit_filter *filter) 362int cgit_open_filter(struct cgit_filter *filter)
363{ 363{
364 364
365 filter->old_stdout = chk_positive(dup(STDOUT_FILENO), 365 filter->old_stdout = chk_positive(dup(STDOUT_FILENO),
366 "Unable to duplicate STDOUT"); 366 "Unable to duplicate STDOUT");
367 chk_zero(pipe(filter->pipe_fh), "Unable to create pipe to subprocess"); 367 chk_zero(pipe(filter->pipe_fh), "Unable to create pipe to subprocess");
368 filter->pid = chk_non_negative(fork(), "Unable to create subprocess"); 368 filter->pid = chk_non_negative(fork(), "Unable to create subprocess");
369 if (filter->pid == 0) { 369 if (filter->pid == 0) {
370 close(filter->pipe_fh[1]); 370 close(filter->pipe_fh[1]);
371 chk_non_negative(dup2(filter->pipe_fh[0], STDIN_FILENO), 371 chk_non_negative(dup2(filter->pipe_fh[0], STDIN_FILENO),
372 "Unable to use pipe as STDIN"); 372 "Unable to use pipe as STDIN");
373 execvp(filter->cmd, filter->argv); 373 execvp(filter->cmd, filter->argv);
374 die("Unable to exec subprocess %s: %s (%d)", filter->cmd, 374 die("Unable to exec subprocess %s: %s (%d)", filter->cmd,
375 strerror(errno), errno); 375 strerror(errno), errno);
376 } 376 }
377 close(filter->pipe_fh[0]); 377 close(filter->pipe_fh[0]);
378 chk_non_negative(dup2(filter->pipe_fh[1], STDOUT_FILENO), 378 chk_non_negative(dup2(filter->pipe_fh[1], STDOUT_FILENO),
379 "Unable to use pipe as STDOUT"); 379 "Unable to use pipe as STDOUT");
380 close(filter->pipe_fh[1]); 380 close(filter->pipe_fh[1]);
381 return 0; 381 return 0;
382} 382}
383 383
384int cgit_close_filter(struct cgit_filter *filter) 384int cgit_close_filter(struct cgit_filter *filter)
385{ 385{
386 chk_non_negative(dup2(filter->old_stdout, STDOUT_FILENO), 386 chk_non_negative(dup2(filter->old_stdout, STDOUT_FILENO),
387 "Unable to restore STDOUT"); 387 "Unable to restore STDOUT");
388 close(filter->old_stdout); 388 close(filter->old_stdout);
389 if (filter->pid < 0) 389 if (filter->pid < 0)
390 return 0; 390 return 0;
391 waitpid(filter->pid, &filter->exitstatus, 0); 391 waitpid(filter->pid, &filter->exitstatus, 0);
392 if (WIFEXITED(filter->exitstatus) && !WEXITSTATUS(filter->exitstatus)) 392 if (WIFEXITED(filter->exitstatus) && !WEXITSTATUS(filter->exitstatus))
393 return 0; 393 return 0;
394 die("Subprocess %s exited abnormally", filter->cmd); 394 die("Subprocess %s exited abnormally", filter->cmd);
395} 395}
396
397/* Read the content of the specified file into a newly allocated buffer,
398 * zeroterminate the buffer and return 0 on success, errno otherwise.
399 */
400int readfile(const char *path, char **buf, size_t *size)
401{
402 int fd;
403 struct stat st;
404
405 fd = open(path, O_RDONLY);
406 if (fd == -1)
407 return errno;
408 if (fstat(fd, &st))
409 return errno;
410 if (!S_ISREG(st.st_mode))
411 return EISDIR;
412 *buf = xmalloc(st.st_size + 1);
413 *size = read_in_full(fd, *buf, st.st_size);
414 (*buf)[*size] = '\0';
415 return (*size == st.st_size ? 0 : errno);
416}