]> git.ozlabs.org Git - ccan/blobdiff - tools/tools.c
tdb: use tdb_nest_lock() for active lock.
[ccan] / tools / tools.c
index d50a67fd18256b0ab3668018d84e0db429b85477..18cc1b84cb299fcc8c5659a05b6c6c05da701a82 100644 (file)
@@ -1,11 +1,20 @@
 #include <ccan/talloc/talloc.h>
 #include <ccan/grab_file/grab_file.h>
+#include <ccan/noerr/noerr.h>
+#include <ccan/read_write_all/read_write_all.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
 #include <string.h>
 #include <unistd.h>
 #include <stdarg.h>
 #include <errno.h>
+#include <err.h>
 #include "tools.h"
 
+static char *tmpdir = NULL;
+static unsigned int count;
+
 char *talloc_basename(const void *ctx, const char *dir)
 {
        char *p = strrchr(dir, '/');
@@ -42,6 +51,7 @@ char *talloc_getcwd(const void *ctx)
        return cwd;
 }
 
+/* Returns output if command fails. */
 char *run_command(const void *ctx, const char *fmt, ...)
 {
        va_list ap;
@@ -54,7 +64,7 @@ char *run_command(const void *ctx, const char *fmt, ...)
 
        /* Ensure stderr gets to us too. */
        cmd = talloc_asprintf_append(cmd, " 2>&1");
-       
+
        pipe = popen(cmd, "r");
        if (!pipe)
                return talloc_asprintf(ctx, "Failed to run '%s'", cmd);
@@ -67,3 +77,72 @@ char *run_command(const void *ctx, const char *fmt, ...)
        talloc_free(cmd);
        return NULL;
 }
+
+static int unlink_all(char *dir)
+{
+       char cmd[strlen(dir) + sizeof("rm -rf ")];
+       sprintf(cmd, "rm -rf %s", dir);
+       if (system(cmd) != 0)
+               warn("Could not remove temporary work in %s", dir);
+       return 0;
+}
+
+char *temp_file(const void *ctx, const char *extension)
+{
+       /* For first call, create dir. */
+       while (!tmpdir) {
+               tmpdir = getenv("TMPDIR");
+               if (!tmpdir)
+                       tmpdir = "/tmp";
+               tmpdir = talloc_asprintf(talloc_autofree_context(),
+                                        "%s/ccanlint-%u.%lu",
+                                        tmpdir, getpid(), random());
+               if (mkdir(tmpdir, 0700) != 0) {
+                       if (errno == EEXIST) {
+                               talloc_free(tmpdir);
+                               tmpdir = NULL;
+                               continue;
+                       }
+                       err(1, "mkdir %s failed", tmpdir);
+               }
+               talloc_set_destructor(tmpdir, unlink_all);
+       }
+
+       return talloc_asprintf(ctx, "%s/%u%s", tmpdir, count++, extension);
+}
+
+bool move_file(const char *oldname, const char *newname)
+{
+       char *contents;
+       size_t size;
+       int fd;
+       bool ret;
+
+       /* Simple case: rename works. */
+       if (rename(oldname, newname) == 0)
+               return true;
+
+       /* Try copy and delete: not atomic! */
+       contents = grab_file(NULL, oldname, &size);
+       if (!contents)
+               return false;
+
+       fd = open(newname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+       if (fd < 0) {
+               ret = false;
+               goto free;
+       }
+
+       ret = write_all(fd, contents, size);
+       if (close(fd) != 0)
+               ret = false;
+
+       if (ret)
+               unlink(oldname);
+       else
+               unlink(newname);
+
+free:
+       talloc_free(contents);
+       return ret;
+}