[pve-devel] [PATCH common 2/2] Tools: add create_file with owner and permissions

Wolfgang Bumiller w.bumiller at proxmox.com
Fri Jan 22 11:55:28 CET 2016


Helper to create a file with specified owner and
permissions. This supports named and numeric owners as well
as permissions in the usual octal, hex or decimal format.
---
 src/PVE/Tools.pm | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/src/PVE/Tools.pm b/src/PVE/Tools.pm
index 9f08aa6..f0b2c31 100644
--- a/src/PVE/Tools.pm
+++ b/src/PVE/Tools.pm
@@ -1190,4 +1190,58 @@ sub setns($$) {
     return 0 == syscall(308, $fileno, $nstype);
 }
 
+# File creation with specified ownership and permissions.
+# User and group can be names or decimal numbers.
+# Permissions are explicit (not affected by umask) and can be numeric with the
+# usual 0/0x prefixes for octal/hex.
+sub create_file {
+    my ($path, $perms, $user, $group) = @_;
+    my ($uid, $gid);
+    if (defined($user)) {
+	if ($user =~ /^\d+$/) {
+	    $uid = int($user);
+	} else {
+	    $uid = getpwnam($user) or die "failed to get uid for: $user\n"
+	}
+    }
+    if (defined($group)) {
+	if ($group =~ /^\d+$/) {
+	    $gid = int($group);
+	} else {
+	    $gid = getgrnam($group) or die "failed to get gid for: $group\n"
+	}
+    }
+
+    if (defined($perms)) {
+	$! = 0;
+	my ($mode, $unparsed) = POSIX::strtoul($perms, 0);
+	die "invalid mode: '$perms'\n" if $perms eq '' || $unparsed > 0 || $!;
+	$perms = $mode;
+    }
+
+    sysopen(my $fd, $path, O_WRONLY | O_CREAT | O_TRUNC)
+	or die "failed to create file: $path: $!\n";
+
+    my $trunc = 0;
+
+    if (defined($perms)) {
+	$trunc = 1;
+	chmod($perms, $fd);
+    }
+
+    if (defined($uid) || defined($gid)) {
+	$trunc = 1;
+	my ($fuid, $fgid) = (stat($fd))[4,5] if !defined($uid) || !defined($gid);
+	$uid = $fuid if !defined($uid);
+	$gid = $fgid if !defined($gid);
+	chown($uid, $gid, $fd)
+	    or die "failed to change file owner: $!\n";
+    }
+
+    # if we modified permissions or ownership truncate again in case someone
+    # raced into writing to the file.
+    truncate($fd, 0) if $trunc;
+    return $fd;
+}
+
 1;
-- 
2.1.4





More information about the pve-devel mailing list