1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "fileio_native.h"
17 
18 #include <sys/xattr.h>
19 
20 #include "file_uri.h"
21 #include "filemgmt_libhilog.h"
22 
23 using namespace OHOS;
24 using namespace OHOS::FileManagement;
25 
26 namespace {
27     enum Location {
28         LOCAL = 1,
29         CLOUD = 2,
30         LOCAL_AND_CLOUD = 3
31     };
32 
33     const size_t MAX_ATTR_NAME = 64;
34     const std::string CLOUD_LOCATION_ATTR = "user.cloud.location";
35 
CheckLocation(const std::string & location)36     bool CheckLocation(const std::string &location)
37     {
38         if (!std::all_of(location.begin(), location.end(), ::isdigit)) {
39             return false;
40         }
41         int fileLocation = atoi(location.c_str());
42         if (fileLocation < Location::LOCAL || fileLocation > Location::LOCAL_AND_CLOUD) {
43             return false;
44         }
45         return true;
46     }
47 
GetLocationFromPath(const std::string & path)48     int GetLocationFromPath(const std::string &path)
49     {
50         std::unique_ptr<char[]> value = std::make_unique<char[]>(MAX_ATTR_NAME);
51         if (value == nullptr) {
52             HILOGE("Failed to request heap memory");
53             return -ENOMEM;
54         }
55         ssize_t size = 0;
56         size = getxattr(path.c_str(), CLOUD_LOCATION_ATTR.c_str(), value.get(), MAX_ATTR_NAME);
57         Location defaultLocation = LOCAL;
58         if (size <= 0) {
59             if (errno == ENOENT) {
60                 return -ENOENT;
61             } else if (errno != ENODATA && errno != EOPNOTSUPP) {
62                 HILOGE("Failed to getxattr, errno: %{public}d", errno);
63             }
64             return static_cast<int>(defaultLocation);
65         }
66         std::string location = std::string(value.get(), static_cast<size_t>(size));
67         if (!CheckLocation(location)) {
68             HILOGE("Invalid location from getxattr, location: %{public}s", location.c_str());
69             return static_cast<int>(defaultLocation);
70         }
71         defaultLocation = static_cast<Location>(atoi(location.c_str()));
72         return static_cast<int>(defaultLocation);
73     }
74 }
75 
GetFileLocation(char * uri,int uriLength,int * location)76 __attribute__((visibility("default"))) int GetFileLocation(char *uri, int uriLength, int *location)
77 {
78     if (uri == nullptr || location == nullptr || uriLength <= 0 || uriLength > PATH_MAX) {
79         return -EINVAL;
80     }
81     std::string uriStr(uri, uriLength);
82     AppFileService::ModuleFileUri::FileUri fileUri(uriStr);
83     int ret = GetLocationFromPath(fileUri.GetRealPath());
84     if (ret > 0) {
85         *location = ret;
86         return 0;
87     }
88     return ret;
89 }
90