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 :
28 : namespace
29 : {
30 : constexpr uid_t kNoOwnerChange = -1; // -1 means chown() won't change the owner
31 : constexpr gid_t kNoGroupChange = -1; // -1 means chown() won't change the group
32 :
33 20 : uid_t getFileOwnerId(const std::string &fileOwner)
34 : {
35 20 : uid_t ownerId = kNoOwnerChange;
36 : // sysconf returns long; -1 on error. Store as int64_t to avoid unsigned conversion issues.
37 20 : const int64_t bufferSizeLong = sysconf(_SC_GETPW_R_SIZE_MAX);
38 20 : if (!fileOwner.empty() && bufferSizeLong > 0)
39 : {
40 1 : const size_t kBufferSize = static_cast<size_t>(bufferSizeLong);
41 1 : errno = 0;
42 1 : passwd passwordStruct{};
43 1 : passwd *passwordResult = nullptr;
44 1 : char buffer[kBufferSize];
45 1 : int result = getpwnam_r(fileOwner.c_str(), &passwordStruct, buffer, kBufferSize, &passwordResult);
46 1 : if (result == 0 && passwordResult)
47 : {
48 0 : ownerId = passwordResult->pw_uid;
49 : }
50 : else
51 : {
52 1 : RIALTO_COMMON_LOG_SYS_WARN(errno, "Failed to determine ownerId for '%s'", fileOwner.c_str());
53 : }
54 : }
55 20 : return ownerId;
56 : }
57 :
58 20 : gid_t getFileGroupId(const std::string &fileGroup)
59 : {
60 20 : gid_t groupId = kNoGroupChange;
61 : // sysconf returns long; -1 on error. Store as int64_t to avoid unsigned conversion issues.
62 20 : const int64_t bufferSizeLong = sysconf(_SC_GETGR_R_SIZE_MAX);
63 20 : if (!fileGroup.empty() && bufferSizeLong > 0)
64 : {
65 1 : const size_t kBufferSize = static_cast<size_t>(bufferSizeLong);
66 1 : errno = 0;
67 1 : group groupStruct{};
68 1 : group *groupResult = nullptr;
69 1 : char buffer[kBufferSize];
70 1 : int result = getgrnam_r(fileGroup.c_str(), &groupStruct, buffer, kBufferSize, &groupResult);
71 1 : if (result == 0 && groupResult)
72 : {
73 0 : groupId = groupResult->gr_gid;
74 : }
75 : else
76 : {
77 1 : RIALTO_COMMON_LOG_SYS_WARN(errno, "Failed to determine groupId for '%s'", fileGroup.c_str());
78 : }
79 : }
80 20 : return groupId;
81 : }
82 : } // namespace
83 :
84 : namespace firebolt::rialto::common
85 : {
86 20 : bool setFilePermissions(const std::string &filePath, unsigned int filePermissions)
87 : {
88 20 : errno = 0;
89 20 : if (chmod(filePath.c_str(), filePermissions) != 0)
90 : {
91 20 : RIALTO_COMMON_LOG_SYS_WARN(errno, "Failed to change the permissions on %s", filePath.c_str());
92 20 : return false;
93 : }
94 0 : return true;
95 : }
96 :
97 20 : bool setFileOwnership(const std::string &filePath, const std::string &fileOwner, const std::string &fileGroup)
98 : {
99 20 : uid_t ownerId = getFileOwnerId(fileOwner);
100 20 : gid_t groupId = getFileGroupId(fileGroup);
101 :
102 20 : if (ownerId != kNoOwnerChange || groupId != kNoGroupChange)
103 : {
104 0 : errno = 0;
105 0 : if (chown(filePath.c_str(), ownerId, groupId) != 0)
106 : {
107 0 : RIALTO_COMMON_LOG_SYS_WARN(errno, "Failed to change the owner/group for %s", filePath.c_str());
108 : }
109 : }
110 20 : return true;
111 : }
112 : } // namespace firebolt::rialto::common
|