summaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
authorTony Cook <tony@develop-help.com>2016-08-04 14:30:13 +1000
committerTony Cook <tony@develop-help.com>2017-09-11 10:59:42 +1000
commite48855bdd2fc57fc51156f5e4b8dee6b544456c8 (patch)
tree79e0c472f0a2485d7ee7638c30fb5946ce8fae46 /util.c
parentf26b33bdaa1e41fbaf65c649a3208f081fa7571b (diff)
downloadperl-e48855bdd2fc57fc51156f5e4b8dee6b544456c8.tar.gz
(perl #127663) add our own mkstemp() implementation
Needed to generate temp files for safer in-place editing. Not based on any particular implementation, the BSD implementations tend to be wrappers around a megafunction that also does a few variations of mkstemp() and mkdtemp(), which we don't need (yet.) This might also be useful as a replacement for broken mkstemp() implementations that use a mode of 0666 when creating the file, though we'd need to add Configure probing for that.
Diffstat (limited to 'util.c')
-rw-r--r--util.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/util.c b/util.c
index 136e4ca1ec..e2feb7f473 100644
--- a/util.c
+++ b/util.c
@@ -5789,6 +5789,40 @@ Perl_my_dirfd(DIR * dir) {
#endif
}
+#ifndef HAS_MKSTEMP
+
+#define TEMP_FILE_CH "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvxyz0123456789"
+#define TEMP_FILE_CH_COUNT (sizeof(TEMP_FILE_CH)-1)
+
+int
+Perl_my_mkstemp(char *templte) {
+ dTHX;
+ STRLEN len = strlen(templte);
+ int fd;
+ int attempts = 0;
+
+ PERL_ARGS_ASSERT_MY_MKSTEMP;
+
+ if (len < 6 ||
+ templte[len-1] != 'X' || templte[len-2] != 'X' || templte[len-3] != 'X' ||
+ templte[len-4] != 'X' || templte[len-5] != 'X' || templte[len-6] != 'X') {
+ errno = EINVAL;
+ return -1;
+ }
+
+ do {
+ int i;
+ for (i = 1; i <= 6; ++i) {
+ templte[len-i] = TEMP_FILE_CH[(int)(Perl_internal_drand48() * TEMP_FILE_CH_COUNT)];
+ }
+ fd = PerlLIO_open3(templte, O_RDWR | O_CREAT | O_EXCL, 0600);
+ } while (fd == -1 && errno == EEXIST && ++attempts <= 100);
+
+ return fd;
+}
+
+#endif
+
REGEXP *
Perl_get_re_arg(pTHX_ SV *sv) {