@@ -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+
99137bool 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