Line data Source code
1 : /*
2 : * If not stated otherwise in this file or this component's LICENSE file the
3 : * following copyright and licenses apply:
4 : *
5 : * Copyright 2025 Sky UK
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : #include "LinuxUtils.h"
21 : #include "RialtoCommonLogging.h"
22 : #include <cstdint>
23 : #include <grp.h>
24 : #include <pwd.h>
25 : #include <sys/stat.h>
26 : #include <unistd.h>
27 : #include <vector>
28 :
29 : namespace
30 : {
31 : constexpr uid_t kNoOwnerChange = -1; // -1 means chown() won't change the owner
32 : constexpr gid_t kNoGroupChange = -1; // -1 means chown() won't change the group
33 : constexpr size_t kDefaultBufferSize = 4096; // Fallback buffer size
34 :
35 20 : uid_t getFileOwnerId(const std::string &fileOwner)
36 : {
37 20 : uid_t ownerId = kNoOwnerChange;
38 20 : if (!fileOwner.empty())
39 : {
40 1 : int64_t bufferSizeLong = sysconf(_SC_GETPW_R_SIZE_MAX);
41 1 : const size_t kBufferSize = (bufferSizeLong > 0) ? static_cast<size_t>(bufferSizeLong) : kDefaultBufferSize;
42 :
43 1 : errno = 0;
44 1 : passwd passwordStruct{};
45 1 : passwd *passwordResult = nullptr;
46 1 : std::vector<char> buffer(kBufferSize);
47 1 : int result = getpwnam_r(fileOwner.c_str(), &passwordStruct, buffer.data(), buffer.size(), &passwordResult);
48 1 : if (result == 0)
49 : {
50 1 : if (passwordResult)
51 : {
52 0 : ownerId = passwordResult->pw_uid;
53 : }
54 : else
55 : {
56 1 : RIALTO_COMMON_LOG_WARN("Owner name '%s' not found", fileOwner.c_str());
57 : }
58 : }
59 : else
60 : {
61 0 : RIALTO_COMMON_LOG_SYS_WARN(result, "Failed to lookup ownerId for '%s'", fileOwner.c_str());
62 : }
63 1 : }
64 20 : return ownerId;
65 : }
66 :
67 20 : gid_t getFileGroupId(const std::string &fileGroup)
68 : {
69 20 : gid_t groupId = kNoGroupChange;
70 20 : if (!fileGroup.empty())
71 : {
72 1 : int64_t bufferSizeLong = sysconf(_SC_GETGR_R_SIZE_MAX);
73 1 : const size_t kBufferSize = (bufferSizeLong > 0) ? static_cast<size_t>(bufferSizeLong) : kDefaultBufferSize;
74 :
75 1 : errno = 0;
76 1 : group groupStruct{};
77 1 : group *groupResult = nullptr;
78 1 : std::vector<char> buffer(kBufferSize);
79 1 : int result = getgrnam_r(fileGroup.c_str(), &groupStruct, buffer.data(), buffer.size(), &groupResult);
80 1 : if (result == 0)
81 : {
82 1 : if (groupResult)
83 : {
84 0 : groupId = groupResult->gr_gid;
85 : }
86 : else
87 : {
88 1 : RIALTO_COMMON_LOG_WARN("Group name '%s' not found", fileGroup.c_str());
89 : }
90 : }
91 : else
92 : {
93 0 : RIALTO_COMMON_LOG_SYS_WARN(result, "Failed to lookup groupId for '%s'", fileGroup.c_str());
94 : }
95 1 : }
96 20 : return groupId;
97 : }
98 : } // namespace
99 :
100 : namespace firebolt::rialto::common
101 : {
102 20 : bool setFilePermissions(const std::string &filePath, unsigned int filePermissions)
103 : {
104 20 : errno = 0;
105 20 : if (chmod(filePath.c_str(), filePermissions) != 0)
106 : {
107 20 : RIALTO_COMMON_LOG_SYS_WARN(errno, "Failed to change the permissions on %s", filePath.c_str());
108 20 : return false;
109 : }
110 0 : return true;
111 : }
112 :
113 20 : bool setFileOwnership(const std::string &filePath, const std::string &fileOwner, const std::string &fileGroup)
114 : {
115 20 : uid_t ownerId = getFileOwnerId(fileOwner);
116 20 : gid_t groupId = getFileGroupId(fileGroup);
117 :
118 20 : if (ownerId != kNoOwnerChange || groupId != kNoGroupChange)
119 : {
120 0 : errno = 0;
121 0 : if (chown(filePath.c_str(), ownerId, groupId) != 0)
122 : {
123 0 : RIALTO_COMMON_LOG_SYS_WARN(errno, "Failed to change the owner/group for %s", filePath.c_str());
124 : }
125 : }
126 20 : return true;
127 : }
128 : } // namespace firebolt::rialto::common
|