15bebb993Sopenharmony_ci/*
25bebb993Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
35bebb993Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
45bebb993Sopenharmony_ci * you may not use this file except in compliance with the License.
55bebb993Sopenharmony_ci * You may obtain a copy of the License at
65bebb993Sopenharmony_ci *
75bebb993Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
85bebb993Sopenharmony_ci *
95bebb993Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
105bebb993Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
115bebb993Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125bebb993Sopenharmony_ci * See the License for the specific language governing permissions and
135bebb993Sopenharmony_ci * limitations under the License.
145bebb993Sopenharmony_ci */
155bebb993Sopenharmony_ci
165bebb993Sopenharmony_ci#include "fileio_native.h"
175bebb993Sopenharmony_ci
185bebb993Sopenharmony_ci#include <sys/xattr.h>
195bebb993Sopenharmony_ci
205bebb993Sopenharmony_ci#include "file_uri.h"
215bebb993Sopenharmony_ci#include "filemgmt_libhilog.h"
225bebb993Sopenharmony_ci
235bebb993Sopenharmony_ciusing namespace OHOS;
245bebb993Sopenharmony_ciusing namespace OHOS::FileManagement;
255bebb993Sopenharmony_ci
265bebb993Sopenharmony_cinamespace {
275bebb993Sopenharmony_ci    enum Location {
285bebb993Sopenharmony_ci        LOCAL = 1,
295bebb993Sopenharmony_ci        CLOUD = 2,
305bebb993Sopenharmony_ci        LOCAL_AND_CLOUD = 3
315bebb993Sopenharmony_ci    };
325bebb993Sopenharmony_ci
335bebb993Sopenharmony_ci    const size_t MAX_ATTR_NAME = 64;
345bebb993Sopenharmony_ci    const std::string CLOUD_LOCATION_ATTR = "user.cloud.location";
355bebb993Sopenharmony_ci
365bebb993Sopenharmony_ci    bool CheckLocation(const std::string &location)
375bebb993Sopenharmony_ci    {
385bebb993Sopenharmony_ci        if (!std::all_of(location.begin(), location.end(), ::isdigit)) {
395bebb993Sopenharmony_ci            return false;
405bebb993Sopenharmony_ci        }
415bebb993Sopenharmony_ci        int fileLocation = atoi(location.c_str());
425bebb993Sopenharmony_ci        if (fileLocation < Location::LOCAL || fileLocation > Location::LOCAL_AND_CLOUD) {
435bebb993Sopenharmony_ci            return false;
445bebb993Sopenharmony_ci        }
455bebb993Sopenharmony_ci        return true;
465bebb993Sopenharmony_ci    }
475bebb993Sopenharmony_ci
485bebb993Sopenharmony_ci    int GetLocationFromPath(const std::string &path)
495bebb993Sopenharmony_ci    {
505bebb993Sopenharmony_ci        std::unique_ptr<char[]> value = std::make_unique<char[]>(MAX_ATTR_NAME);
515bebb993Sopenharmony_ci        if (value == nullptr) {
525bebb993Sopenharmony_ci            HILOGE("Failed to request heap memory");
535bebb993Sopenharmony_ci            return -ENOMEM;
545bebb993Sopenharmony_ci        }
555bebb993Sopenharmony_ci        ssize_t size = 0;
565bebb993Sopenharmony_ci        size = getxattr(path.c_str(), CLOUD_LOCATION_ATTR.c_str(), value.get(), MAX_ATTR_NAME);
575bebb993Sopenharmony_ci        Location defaultLocation = LOCAL;
585bebb993Sopenharmony_ci        if (size <= 0) {
595bebb993Sopenharmony_ci            if (errno == ENOENT) {
605bebb993Sopenharmony_ci                return -ENOENT;
615bebb993Sopenharmony_ci            } else if (errno != ENODATA && errno != EOPNOTSUPP) {
625bebb993Sopenharmony_ci                HILOGE("Failed to getxattr, errno: %{public}d", errno);
635bebb993Sopenharmony_ci            }
645bebb993Sopenharmony_ci            return static_cast<int>(defaultLocation);
655bebb993Sopenharmony_ci        }
665bebb993Sopenharmony_ci        std::string location = std::string(value.get(), static_cast<size_t>(size));
675bebb993Sopenharmony_ci        if (!CheckLocation(location)) {
685bebb993Sopenharmony_ci            HILOGE("Invalid location from getxattr, location: %{public}s", location.c_str());
695bebb993Sopenharmony_ci            return static_cast<int>(defaultLocation);
705bebb993Sopenharmony_ci        }
715bebb993Sopenharmony_ci        defaultLocation = static_cast<Location>(atoi(location.c_str()));
725bebb993Sopenharmony_ci        return static_cast<int>(defaultLocation);
735bebb993Sopenharmony_ci    }
745bebb993Sopenharmony_ci}
755bebb993Sopenharmony_ci
765bebb993Sopenharmony_ci__attribute__((visibility("default"))) int GetFileLocation(char *uri, int uriLength, int *location)
775bebb993Sopenharmony_ci{
785bebb993Sopenharmony_ci    if (uri == nullptr || location == nullptr || uriLength <= 0 || uriLength > PATH_MAX) {
795bebb993Sopenharmony_ci        return -EINVAL;
805bebb993Sopenharmony_ci    }
815bebb993Sopenharmony_ci    std::string uriStr(uri, uriLength);
825bebb993Sopenharmony_ci    AppFileService::ModuleFileUri::FileUri fileUri(uriStr);
835bebb993Sopenharmony_ci    int ret = GetLocationFromPath(fileUri.GetRealPath());
845bebb993Sopenharmony_ci    if (ret > 0) {
855bebb993Sopenharmony_ci        *location = ret;
865bebb993Sopenharmony_ci        return 0;
875bebb993Sopenharmony_ci    }
885bebb993Sopenharmony_ci    return ret;
895bebb993Sopenharmony_ci}
90