Skip to content

Commit 67064f0

Browse files
committed
Fix sticky permissions
1 parent d80b5a6 commit 67064f0

2 files changed

Lines changed: 47 additions & 2 deletions

File tree

include/openPMD/auxiliary/Filesystem.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#pragma once
2222

2323
#include <string>
24+
#include <sys/types.h>
2425
#include <vector>
2526

2627
#include "openPMD/config.hpp"
@@ -66,6 +67,10 @@ namespace auxiliary
6667
*/
6768
std::vector<std::string> list_directory(std::string const &path);
6869

70+
std::string get_parent(std::string const &path);
71+
72+
mode_t get_permissions(std::string const &path);
73+
6974
/** Create all required directories to have a reachable given absolute or
7075
* relative path.
7176
*

src/auxiliary/Filesystem.cpp

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,44 @@ std::vector<std::string> list_directory(std::string const &path)
9696
return ret;
9797
}
9898

99+
std::string get_parent(std::string const &path)
100+
{
101+
std::string parent = path;
102+
size_t pos = parent.find_last_of(directory_separator);
103+
if (pos != std::string::npos)
104+
{
105+
parent = parent.substr(0, pos);
106+
if (parent.empty())
107+
parent = "/";
108+
}
109+
else
110+
{
111+
parent.clear();
112+
}
113+
return parent;
114+
}
115+
116+
mode_t get_permissions(std::string const &path)
117+
{
118+
std::string parent = get_parent(path);
119+
if (parent.empty())
120+
{
121+
return 0;
122+
}
123+
if (!directory_exists(parent))
124+
{
125+
return 0;
126+
}
127+
128+
struct stat s;
129+
if (stat(parent.c_str(), &s) != 0)
130+
{
131+
return 0;
132+
}
133+
134+
return s.st_mode & 07777;
135+
}
136+
99137
bool create_directories(std::string const &path)
100138
{
101139
if (directory_exists(path))
@@ -106,10 +144,12 @@ bool create_directories(std::string const &path)
106144
return CreateDirectory(p.c_str(), nullptr);
107145
};
108146
#else
147+
// preserve sticky and setgid from parent
148+
mode_t parentPerms = get_permissions(path) & (S_ISVTX | S_ISGID);
109149
mode_t mask = umask(0);
110150
umask(mask);
111-
auto mk = [mask](std::string const &p) -> bool {
112-
return (0 == mkdir(p.c_str(), 0777 & ~mask));
151+
auto mk = [parentPerms, mask](std::string const &p) -> bool {
152+
return (0 == mkdir(p.c_str(), (0777 & ~mask) | parentPerms));
113153
};
114154
#endif
115155
std::istringstream ss(path);

0 commit comments

Comments
 (0)