blob: 66af8c47d999d8f55c2eac389328ce6f3f629345 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <fs/fs.h>
#include <mgmt/mgmt.h>
#include <fs_mgmt/fs_mgmt_impl.h>
int
fs_mgmt_impl_filelen(const char *path, size_t *out_len)
{
struct fs_dirent dirent;
int rc;
rc = fs_stat(path, &dirent);
if (rc != 0) {
return MGMT_ERR_EUNKNOWN;
}
if (dirent.type != FS_DIR_ENTRY_FILE) {
return MGMT_ERR_EUNKNOWN;
}
*out_len = dirent.size;
return 0;
}
int
fs_mgmt_impl_read(const char *path, size_t offset, size_t len,
void *out_data, size_t *out_len)
{
struct fs_file_t file;
ssize_t bytes_read;
int rc;
rc = fs_open(&file, path);
if (rc != 0) {
return MGMT_ERR_EUNKNOWN;
}
rc = fs_seek(&file, offset, FS_SEEK_SET);
if (rc != 0) {
goto done;
}
bytes_read = fs_read(&file, out_data, len);
if (bytes_read < 0) {
goto done;
}
*out_len = bytes_read;
done:
fs_close(&file);
if (rc != 0) {
return MGMT_ERR_EUNKNOWN;
} else {
return 0;
}
}
static int
zephyr_fs_mgmt_truncate(const char *path)
{
size_t len;
int rc;
/* Attempt to get the length of the file at the specified path. This is a
* quick way to determine if there is already a file there.
*/
rc = fs_mgmt_impl_filelen(path, &len);
if (rc == 0) {
/* There is already a file with the specified path. Unlink it to
* simulate a truncate operation.
*
* XXX: This isn't perfect - if the file is currently open, the unlink
* operation won't actually delete the file. Consequently, the file
* will get partially overwritten rather than truncated. The NFFS port
* doesn't support the truncate operation, so this is an imperfect
* workaround.
*/
rc = fs_unlink(path);
if (rc != 0) {
return MGMT_ERR_EUNKNOWN;
}
}
return 0;
}
int
fs_mgmt_impl_write(const char *path, size_t offset, const void *data,
size_t len)
{
struct fs_file_t file;
int rc;
/* Truncate the file before writing the first chunk. This is done to
* properly handle an overwrite of an existing file.
*
*/
if (offset == 0) {
rc = zephyr_fs_mgmt_truncate(path);
if (rc != 0) {
return rc;
}
}
rc = fs_open(&file, path);
if (rc != 0) {
return MGMT_ERR_EUNKNOWN;
}
rc = fs_seek(&file, offset, FS_SEEK_SET);
if (rc != 0) {
goto done;
}
rc = fs_write(&file, data, len);
if (rc < 0) {
goto done;
}
rc = 0;
done:
fs_close(&file);
if (rc != 0) {
return MGMT_ERR_EUNKNOWN;
} else {
return 0;
}
}