Apache Mesos
chown.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 #ifndef __STOUT_OS_POSIX_CHOWN_HPP__
14 #define __STOUT_OS_POSIX_CHOWN_HPP__
15 
16 #include <fts.h>
17 #include <sys/types.h>
18 #include <pwd.h>
19 
20 #include <stout/error.hpp>
21 #include <stout/nothing.hpp>
22 #include <stout/try.hpp>
23 
24 #include <stout/os/shell.hpp>
25 #include <stout/os/stat.hpp>
26 
27 namespace os {
28 
29 // Set the ownership for a path. This function never follows any symlinks.
31  uid_t uid,
32  gid_t gid,
33  const std::string& path,
34  bool recursive)
35 {
36  char* path_[] = {const_cast<char*>(path.c_str()), nullptr};
37 
38  FTS* tree = ::fts_open(
39  path_, FTS_NOCHDIR | FTS_PHYSICAL, nullptr);
40 
41  if (tree == nullptr) {
42  return ErrnoError();
43  }
44 
45  FTSENT *node;
46  while ((node = ::fts_read(tree)) != nullptr) {
47  switch (node->fts_info) {
48  // Preorder directory.
49  case FTS_D:
50  // Regular file.
51  case FTS_F:
52  // Symbolic link.
53  case FTS_SL:
54  // Symbolic link without target.
55  case FTS_SLNONE: {
56  if (::lchown(node->fts_path, uid, gid) < 0) {
58  ::fts_close(tree);
59  return error;
60  }
61 
62  break;
63  }
64 
65  // Unreadable directory.
66  case FTS_DNR:
67  // Error; errno is set.
68  case FTS_ERR:
69  // Directory that causes cycles.
70  case FTS_DC:
71  // `stat(2)` failed.
72  case FTS_NS: {
74  ::fts_close(tree);
75  return error;
76  }
77 
78  default:
79  break;
80  }
81 
82  if (node->fts_level == FTS_ROOTLEVEL && !recursive) {
83  break;
84  }
85  }
86 
87  ::fts_close(tree);
88  return Nothing();
89 }
90 
91 
92 // Changes the specified path's user and group ownership to that of
93 // the specified user.
95  const std::string& user,
96  const std::string& path,
97  bool recursive = true)
98 {
99  passwd* passwd;
100 
101  errno = 0;
102 
103  if ((passwd = ::getpwnam(user.c_str())) == nullptr) {
104  return errno
105  ? ErrnoError("Failed to get user information for '" + user + "'")
106  : Error("No such user '" + user + "'");
107  }
108 
109  return chown(passwd->pw_uid, passwd->pw_gid, path, recursive);
110 }
111 
112 } // namespace os {
113 
114 #endif // __STOUT_OS_POSIX_CHOWN_HPP__
Try< uid_t > uid(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:182
Definition: nothing.hpp:16
Definition: errorbase.hpp:35
Definition: try.hpp:34
Result< std::string > user(Option< uid_t > uid=None())
Definition: su.hpp:277
Definition: errorbase.hpp:49
gid_t pw_gid
Definition: pwd.hpp:30
uid_t pw_uid
Definition: pwd.hpp:29
int uid_t
Definition: windows.hpp:189
Definition: pwd.hpp:26
std::string error(const std::string &msg, uint32_t code)
Try< Nothing > chown(uid_t uid, gid_t gid, const std::string &path, bool recursive)
Definition: chown.hpp:30
int gid_t
Definition: windows.hpp:190