10 #include <sys/statvfs.h>
11 #include <boost/filesystem.hpp>
12 #include <boost/lexical_cast.hpp>
23 if (resource_name_msparam ==
NULL) {
27 if (resource_name_msparam->
type ==
NULL) {
28 rodsLog(
LOG_ERROR,
"[%s]: resource_name_msparam->type is NULL", __FUNCTION__);
32 rodsLog(
LOG_ERROR,
"[%s]: first argument should be STR_MS_T, was [%s]", __FUNCTION__, resource_name_msparam->
type);
36 const char* resource_name_cstring =
static_cast<char*
>(resource_name_msparam->
inOutStruct);
37 if (resource_name_cstring ==
NULL) {
38 rodsLog(
LOG_ERROR,
"[%s]: input resource_name_msparam->inOutStruct is NULL", __FUNCTION__);
44 if (!resource_manager_resolve_error.
ok()) {
45 rodsLog(
LOG_ERROR,
"[%s]: failed to resolve resource [%s]", __FUNCTION__, resource_name_cstring);
47 return resource_manager_resolve_error.
status();
50 std::string resource_type_unnormalized;
52 if (!get_resource_type_error.
ok()) {
53 rodsLog(
LOG_ERROR,
"[%s]: failed to get resource type for [%s]", __FUNCTION__, resource_name_cstring);
55 return get_resource_type_error.
status();
59 if (resource_type_normalized !=
"unixfilesystem") {
63 std::string resource_vault_path;
65 if (!get_resource_vault_path_error.
ok()) {
66 rodsLog(
LOG_ERROR,
"[%s]: failed to get resource path for [%s]", __FUNCTION__, resource_name_cstring);
68 return get_resource_vault_path_error.
status();
71 boost::filesystem::path path_to_stat{resource_vault_path};
72 const auto absolute_vault_path{boost::filesystem::absolute(path_to_stat)};
74 rodsLog(
LOG_NOTICE,
"[%s]: path to stat [%s] for resource [%s] doesn't exist, moving to parent", __FUNCTION__, path_to_stat.string().c_str(), resource_name_cstring);
75 path_to_stat = path_to_stat.parent_path();
76 if (path_to_stat.empty()) {
77 rodsLog(
LOG_ERROR,
"[%s]: could not find existing path from vault path [%s] for resource [%s]", __FUNCTION__, resource_vault_path.c_str(), resource_name_cstring);
83 if (absolute_vault_path.root_path() == path_to_stat) {
84 rodsLog(
LOG_ERROR,
"[%s]: could not find existing non-root path from vault path [%s] for resource [%s]", __FUNCTION__, resource_vault_path.c_str(), resource_name_cstring);
88 struct statvfs statvfs_buf;
89 const int statvfs_ret = statvfs(path_to_stat.string().c_str(), &statvfs_buf);
90 if (statvfs_ret != 0) {
91 rodsLog(
LOG_ERROR,
"[%s]: statvfs() of [%s] for resource [%s] failed with return %d and errno %d", __FUNCTION__, path_to_stat.string().c_str(), resource_name_cstring, statvfs_ret, errno);
95 uintmax_t free_space_in_bytes;
96 if (statvfs_buf.f_bavail > ULONG_MAX / statvfs_buf.f_frsize) {
97 rodsLog(
LOG_NOTICE,
"[%s]: statvfs() of resource [%s] reports free space in excess of ULONG_MAX f_bavail %ju f_frsize %ju failed with return %d and errno %d", __FUNCTION__, resource_name_cstring,
static_cast<uintmax_t
>(statvfs_buf.f_bavail),
static_cast<uintmax_t
>(statvfs_buf.f_frsize));
98 free_space_in_bytes = ULONG_MAX;
100 free_space_in_bytes = statvfs_buf.f_bavail * statvfs_buf.f_frsize;
102 const std::string free_space_in_bytes_string = boost::lexical_cast<std::string>(free_space_in_bytes);
110 memset(&admin_in, 0,
sizeof(admin_in));
111 admin_in.
arg0 =
"modify";
112 admin_in.
arg1 =
"resource";
113 admin_in.
arg2 = resource_name_cstring;
114 admin_in.
arg3 =
"freespace";
115 admin_in.
arg4 = free_space_in_bytes_string.c_str();
118 rodsEnv service_account_environment;
119 const int getRodsEnv_ret =
getRodsEnv(&service_account_environment);
120 if (getRodsEnv_ret < 0) {
121 rodsLog(
LOG_ERROR,
"[%s]: getRodsEnv failure [%d]", __FUNCTION__, getRodsEnv_ret);
122 return getRodsEnv_ret;
126 memset(&errMsg, 0,
sizeof(errMsg));
129 if (admin_connection ==
NULL) {
130 char *mySubName =
NULL;
132 rodsLog(
LOG_ERROR,
"[%s]: rcConnect failure [%s] [%s] [%d] [%s]", __FUNCTION__,
133 myName, mySubName, errMsg.
status, errMsg.
msg);
137 const int clientLogin_ret =
clientLogin(admin_connection);
138 if (clientLogin_ret != 0) {
139 rodsLog(
LOG_ERROR,
"[%s]: clientLogin failure [%d]", __FUNCTION__, clientLogin_ret);
140 return clientLogin_ret;
143 const int rcGeneralAdmin_ret =
rcGeneralAdmin(admin_connection, &admin_in);
145 if (rcGeneralAdmin_ret < 0) {
147 rodsLog(
LOG_ERROR,
"[%s]: rcGeneralAdmin failure [%d]", __FUNCTION__, rcGeneralAdmin_ret);
149 return rcGeneralAdmin_ret;