summaryrefslogtreecommitdiff
path: root/tempfile.c
diff options
context:
space:
mode:
authorClint Adams <schizo@debian.org>2005-06-21 23:30:25 +0000
committerClint Adams <schizo@debian.org>2005-06-21 23:30:25 +0000
commitc2a1c435ef5e7d590328802ce333de410ce40cb6 (patch)
tree6095e344242e76daf58d6d42afc5ca29673d2a0a /tempfile.c
downloaddebianutils-c2a1c435ef5e7d590328802ce333de410ce40cb6.tar.gz
tag of schizo@debian.org--2004-primary/debianutils--etch--0--version-0
(automatically generated log message) git-archimport-id: schizo@debian.org--etch/debianutils--etch--0--base-0
Diffstat (limited to 'tempfile.c')
-rw-r--r--tempfile.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/tempfile.c b/tempfile.c
new file mode 100644
index 0000000..c259349
--- /dev/null
+++ b/tempfile.c
@@ -0,0 +1,151 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif /* HAVE_GETOPT_H */
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+char *progname;
+
+void
+usage (int status)
+{
+ if (status)
+ fprintf(stderr, "Try `%s --help' for more information.\n", progname);
+ else
+ printf("Usage: %s [OPTION]\n\n"
+"Create a temporary file in a safe manner.\n\n"
+"-d, --directory=DIR place temporary file in DIR\n"
+"-p, --prefix=STRING set temporary file's prefix to STRING\n"
+"-s, --suffix=STRING set temporary file's suffix to STRING\n"
+"-m, --mode=MODE open with MODE instead of 0600\n"
+"-n, --name=FILE use FILE instead of tempnam(3)\n"
+" --help display this help and exit\n"
+" --version output version information and exit\n", progname);
+ exit(status);
+}
+
+
+void
+syserror (const char *fx)
+{
+ perror(fx);
+ exit(1);
+}
+
+
+int
+parsemode (const char *in, mode_t *out)
+{
+ char *endptr;
+ long int mode;
+ mode = strtol(in, &endptr, 8);
+ if (*endptr || mode<0 || mode>07777)
+ return 1;
+ *out = (mode_t) mode;
+ return 0;
+}
+
+
+int
+main (int argc, char **argv)
+{
+ char *name=0, *dir=0, *pfx=0, *sfx=0;
+ mode_t mode = 0600;
+ int fd, optc;
+ struct option long_options[] = {
+ {"prefix", required_argument, 0, 'p'},
+ {"suffix", required_argument, 0, 's'},
+ {"directory", required_argument, 0, 'd'},
+ {"mode", required_argument, 0, 'm'},
+ {"name", required_argument, 0, 'n'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+ progname = argv[0];
+
+ while ((optc = getopt_long (argc, argv, "p:s:d:m:n:", long_options, 0))
+ != EOF) {
+ switch (optc) {
+ case 0:
+ break;
+ case 'p':
+ pfx = optarg;
+ break;
+ case 's':
+ sfx = optarg;
+ break;
+ case 'd':
+ dir = optarg;
+ break;
+ case 'm':
+ if (parsemode(optarg, &mode)) {
+ fprintf(stderr, "Invalid mode `%s'. Mode must be octal.\n", optarg);
+ usage(1);
+ }
+ break;
+ case 'n':
+ name = optarg;
+ break;
+ case 'h':
+ usage(0);
+ case 'v':
+ puts("tempfile " PACKAGE_VERSION);
+ exit(0);
+ default:
+ usage(1);
+ }
+ }
+
+ if (name) {
+ if ((fd = open(name, O_RDWR | O_CREAT | O_EXCL, mode)) < 0)
+ syserror("open");
+ }
+
+ else {
+ for (;;) {
+ if (!(name = tempnam(dir, pfx)))
+ syserror("tempnam");
+ if ((fd = open(name, O_RDWR | O_CREAT | O_EXCL, mode)) < 0) {
+ if (errno == EEXIST) {
+ free(name);
+ continue;
+ }
+ syserror("open");
+ }
+ if (sfx) {
+ char *namesfx;
+ if (!(namesfx = malloc(strlen(name) + strlen(sfx) + 1)))
+ syserror("malloc");
+ strcpy(namesfx, name);
+ strcat(namesfx, sfx);
+ if (link(name, namesfx) < 0) {
+ if (errno == EEXIST) {
+ if (unlink(name) < 0)
+ syserror("unlink");
+ free(name);
+ free(namesfx);
+ continue;
+ }
+ syserror("link");
+ }
+ if (unlink(name) < 0)
+ syserror("unlink");
+ free(name);
+ name = namesfx;
+ }
+ break;
+ }
+ }
+
+ if (close(fd))
+ syserror("close");
+ puts(name);
+ exit(0);
+}