Tools: tempfile and tempfile_contents
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Mon, 4 Apr 2016 12:43:56 +0000 (14:43 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Tue, 5 Apr 2016 04:18:41 +0000 (06:18 +0200)
src/PVE/Tools.pm

index d6b501e..40dfc5a 100644 (file)
@@ -75,7 +75,8 @@ use constant {CLONE_NEWNS   => 0x00020000,
               CLONE_NEWPID  => 0x20000000,
               CLONE_NEWNET  => 0x40000000};
 
-use constant O_PATH => 0x00200000;
+use constant {O_PATH    => 0x00200000,
+              O_TMPFILE => 0x00410000}; # This includes O_DIRECTORY
 
 sub run_with_timeout {
     my ($timeout, $code, @param) = @_;
@@ -1213,4 +1214,35 @@ sub sync_mountpoint {
     return $result;
 }
 
+sub tempfile {
+    my ($perm, %opts) = @_;
+
+    # default permissions are stricter than with file_set_contents
+    $perm = 0600 if !defined($perm);
+
+    my $dir = $opts{dir} // '/tmp';
+    my $mode = $opts{mode} // O_RDWR;
+    $mode |= O_EXCL if !$opts{allow_links};
+
+    my $fh = IO::File->new($dir, $mode | O_TMPFILE, $perm)
+       or die "failed to create tempfile: $!\n";
+    return $fh;
+}
+
+sub tempfile_contents {
+    my ($data, $perm, %opts) = @_;
+
+    my $fh = tempfile($perm, %opts);
+    eval {
+       die "unable to write to tempfile: $!\n" if !print {$fh} $data;
+       die "unable to flush to tempfile: $!\n" if !defined($fh->flush());
+    };
+    if (my $err = $@) {
+       close $fh;
+       die $err;
+    }
+
+    return ("/proc/$$/fd/".$fh->fileno, $fh);
+}
+
 1;