tdb: allow reads after prepare commit
[ccan] / tools / tools.c
1 #include <ccan/talloc/talloc.h>
2 #include <ccan/grab_file/grab_file.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <stdarg.h>
6 #include <errno.h>
7 #include "tools.h"
8
9 char *talloc_basename(const void *ctx, const char *dir)
10 {
11         char *p = strrchr(dir, '/');
12
13         if (!p)
14                 return (char *)dir;
15         return talloc_strdup(ctx, p+1);
16 }
17
18 char *talloc_dirname(const void *ctx, const char *dir)
19 {
20         char *p = strrchr(dir, '/');
21
22         if (!p)
23                 return talloc_strdup(ctx, ".");
24         return talloc_strndup(ctx, dir, p - dir);
25 }
26
27 char *talloc_getcwd(const void *ctx)
28 {
29         unsigned int len;
30         char *cwd;
31
32         /* *This* is why people hate C. */
33         len = 32;
34         cwd = talloc_array(ctx, char, len);
35         while (!getcwd(cwd, len)) {
36                 if (errno != ERANGE) {
37                         talloc_free(cwd);
38                         return NULL;
39                 }
40                 cwd = talloc_realloc(ctx, cwd, char, len *= 2);
41         }
42         return cwd;
43 }
44
45 char *run_command(const void *ctx, const char *fmt, ...)
46 {
47         va_list ap;
48         char *cmd, *contents;
49         FILE *pipe;
50
51         va_start(ap, fmt);
52         cmd = talloc_vasprintf(ctx, fmt, ap);
53         va_end(ap);
54
55         /* Ensure stderr gets to us too. */
56         cmd = talloc_asprintf_append(cmd, " 2>&1");
57         
58         pipe = popen(cmd, "r");
59         if (!pipe)
60                 return talloc_asprintf(ctx, "Failed to run '%s'", cmd);
61
62         contents = grab_fd(cmd, fileno(pipe), NULL);
63         if (pclose(pipe) != 0)
64                 return talloc_asprintf(ctx, "Running '%s':\n%s",
65                                        cmd, contents);
66
67         talloc_free(cmd);
68         return NULL;
69 }