lots of changes, see description.
- enable sftp by default. - add more descriptive stdio errors. - disable devoptab timeout by default. - handle errors for devoptab seek. - add r/d/w progress events for threaded_file_transfer - remove system album from file browser, only show sd card. - do not clear game selection in games menu. useful for selecting games to backup, then delete after. - change smb2 r/w to only send max amount, matches nfs behaviour. not sure if its needed as smb probably handles it for us.
This commit is contained in:
@@ -26,7 +26,7 @@ option(ENABLE_DEVOPTAB_WEBDAV "" ON)
|
|||||||
# max speed is 8MiB/s, which is fine for wifi, but awful for ethernet.
|
# max speed is 8MiB/s, which is fine for wifi, but awful for ethernet.
|
||||||
# other clients get 36-40MiB/s.
|
# other clients get 36-40MiB/s.
|
||||||
# it also adds 230k to binary size, and i don't think anyone will use it.
|
# it also adds 230k to binary size, and i don't think anyone will use it.
|
||||||
option(ENABLE_DEVOPTAB_SFTP "" OFF)
|
option(ENABLE_DEVOPTAB_SFTP "" ON)
|
||||||
|
|
||||||
set(sphaira_VERSION 0.13.3)
|
set(sphaira_VERSION 0.13.3)
|
||||||
|
|
||||||
|
|||||||
@@ -511,7 +511,22 @@ enum class SphairaResult : Result {
|
|||||||
FsNewPathEmpty,
|
FsNewPathEmpty,
|
||||||
FsLoadingCancelled,
|
FsLoadingCancelled,
|
||||||
FsBrokenRoot,
|
FsBrokenRoot,
|
||||||
|
|
||||||
FsUnknownStdioError,
|
FsUnknownStdioError,
|
||||||
|
FsStdioFailedToSeek,
|
||||||
|
FsStdioFailedToRead,
|
||||||
|
FsStdioFailedToWrite,
|
||||||
|
FsStdioFailedToOpenFile,
|
||||||
|
FsStdioFailedToCreate,
|
||||||
|
FsStdioFailedToTruncate,
|
||||||
|
FsStdioFailedToFlush,
|
||||||
|
FsStdioFailedToCreateDirectory,
|
||||||
|
FsStdioFailedToDeleteFile,
|
||||||
|
FsStdioFailedToDeleteDirectory,
|
||||||
|
FsStdioFailedToOpenDirectory,
|
||||||
|
FsStdioFailedToRename,
|
||||||
|
FsStdioFailedToStat,
|
||||||
|
|
||||||
FsReadOnly,
|
FsReadOnly,
|
||||||
FsNotActive,
|
FsNotActive,
|
||||||
FsFailedStdioStat,
|
FsFailedStdioStat,
|
||||||
@@ -680,6 +695,19 @@ enum : Result {
|
|||||||
MAKE_SPHAIRA_RESULT_ENUM(FsLoadingCancelled),
|
MAKE_SPHAIRA_RESULT_ENUM(FsLoadingCancelled),
|
||||||
MAKE_SPHAIRA_RESULT_ENUM(FsBrokenRoot),
|
MAKE_SPHAIRA_RESULT_ENUM(FsBrokenRoot),
|
||||||
MAKE_SPHAIRA_RESULT_ENUM(FsUnknownStdioError),
|
MAKE_SPHAIRA_RESULT_ENUM(FsUnknownStdioError),
|
||||||
|
MAKE_SPHAIRA_RESULT_ENUM(FsStdioFailedToSeek),
|
||||||
|
MAKE_SPHAIRA_RESULT_ENUM(FsStdioFailedToRead),
|
||||||
|
MAKE_SPHAIRA_RESULT_ENUM(FsStdioFailedToWrite),
|
||||||
|
MAKE_SPHAIRA_RESULT_ENUM(FsStdioFailedToOpenFile),
|
||||||
|
MAKE_SPHAIRA_RESULT_ENUM(FsStdioFailedToCreate),
|
||||||
|
MAKE_SPHAIRA_RESULT_ENUM(FsStdioFailedToTruncate),
|
||||||
|
MAKE_SPHAIRA_RESULT_ENUM(FsStdioFailedToFlush),
|
||||||
|
MAKE_SPHAIRA_RESULT_ENUM(FsStdioFailedToCreateDirectory),
|
||||||
|
MAKE_SPHAIRA_RESULT_ENUM(FsStdioFailedToDeleteFile),
|
||||||
|
MAKE_SPHAIRA_RESULT_ENUM(FsStdioFailedToDeleteDirectory),
|
||||||
|
MAKE_SPHAIRA_RESULT_ENUM(FsStdioFailedToOpenDirectory),
|
||||||
|
MAKE_SPHAIRA_RESULT_ENUM(FsStdioFailedToRename),
|
||||||
|
MAKE_SPHAIRA_RESULT_ENUM(FsStdioFailedToStat),
|
||||||
MAKE_SPHAIRA_RESULT_ENUM(FsReadOnly),
|
MAKE_SPHAIRA_RESULT_ENUM(FsReadOnly),
|
||||||
MAKE_SPHAIRA_RESULT_ENUM(FsNotActive),
|
MAKE_SPHAIRA_RESULT_ENUM(FsNotActive),
|
||||||
MAKE_SPHAIRA_RESULT_ENUM(FsFailedStdioStat),
|
MAKE_SPHAIRA_RESULT_ENUM(FsFailedStdioStat),
|
||||||
|
|||||||
@@ -91,6 +91,8 @@ bool fix_path(const char* str, char* out, bool strip_leading_slash = false);
|
|||||||
void update_devoptab_for_read_only(devoptab_t* devoptab, bool read_only);
|
void update_devoptab_for_read_only(devoptab_t* devoptab, bool read_only);
|
||||||
|
|
||||||
struct PushPullThreadData {
|
struct PushPullThreadData {
|
||||||
|
static constexpr size_t MAX_BUFFER_SIZE = 1024 * 64; // 64KB max buffer
|
||||||
|
|
||||||
PushPullThreadData(CURL* _curl);
|
PushPullThreadData(CURL* _curl);
|
||||||
virtual ~PushPullThreadData();
|
virtual ~PushPullThreadData();
|
||||||
Result CreateAndStart();
|
Result CreateAndStart();
|
||||||
@@ -130,7 +132,7 @@ struct MountConfig {
|
|||||||
std::string pass{};
|
std::string pass{};
|
||||||
std::string dump_path{};
|
std::string dump_path{};
|
||||||
std::optional<long> port{};
|
std::optional<long> port{};
|
||||||
int timeout{5000}; // 5 seconds.
|
long timeout{};
|
||||||
bool read_only{};
|
bool read_only{};
|
||||||
bool no_stat_file{true};
|
bool no_stat_file{true};
|
||||||
bool no_stat_dir{true};
|
bool no_stat_dir{true};
|
||||||
@@ -164,7 +166,7 @@ struct MountDevice {
|
|||||||
virtual int devoptab_close(void *fd) { return -EIO; }
|
virtual int devoptab_close(void *fd) { return -EIO; }
|
||||||
virtual ssize_t devoptab_read(void *fd, char *ptr, size_t len) { return -EIO; }
|
virtual ssize_t devoptab_read(void *fd, char *ptr, size_t len) { return -EIO; }
|
||||||
virtual ssize_t devoptab_write(void *fd, const char *ptr, size_t len) { return -EIO; }
|
virtual ssize_t devoptab_write(void *fd, const char *ptr, size_t len) { return -EIO; }
|
||||||
virtual off_t devoptab_seek(void *fd, off_t pos, int dir) { return 0; }
|
virtual ssize_t devoptab_seek(void *fd, off_t pos, int dir) { return 0; }
|
||||||
virtual int devoptab_fstat(void *fd, struct stat *st) { return -EIO; }
|
virtual int devoptab_fstat(void *fd, struct stat *st) { return -EIO; }
|
||||||
virtual int devoptab_unlink(const char *path) { return -EIO; }
|
virtual int devoptab_unlink(const char *path) { return -EIO; }
|
||||||
virtual int devoptab_rename(const char *oldName, const char *newName) { return -EIO; }
|
virtual int devoptab_rename(const char *oldName, const char *newName) { return -EIO; }
|
||||||
|
|||||||
@@ -321,12 +321,12 @@ Result CreateFile(const FsPathReal& path, u64 size, u32 option, bool ignore_read
|
|||||||
}
|
}
|
||||||
|
|
||||||
R_TRY(fsdevGetLastResult());
|
R_TRY(fsdevGetLastResult());
|
||||||
return Result_FsUnknownStdioError;
|
return Result_FsStdioFailedToCreate;
|
||||||
}
|
}
|
||||||
ON_SCOPE_EXIT(close(fd));
|
ON_SCOPE_EXIT(close(fd));
|
||||||
|
|
||||||
if (size) {
|
if (size) {
|
||||||
R_UNLESS(!ftruncate(fd, size), Result_FsUnknownStdioError);
|
R_UNLESS(!ftruncate(fd, size), Result_FsStdioFailedToTruncate);
|
||||||
}
|
}
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@@ -341,7 +341,7 @@ Result CreateDirectory(const FsPathReal& path, bool ignore_read_only) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
R_TRY(fsdevGetLastResult());
|
R_TRY(fsdevGetLastResult());
|
||||||
return Result_FsUnknownStdioError;
|
return Result_FsStdioFailedToCreateDirectory;
|
||||||
}
|
}
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
@@ -363,7 +363,7 @@ Result DeleteFile(const FsPathReal& path, bool ignore_read_only) {
|
|||||||
|
|
||||||
if (unlink(path)) {
|
if (unlink(path)) {
|
||||||
R_TRY(fsdevGetLastResult());
|
R_TRY(fsdevGetLastResult());
|
||||||
return Result_FsUnknownStdioError;
|
return Result_FsStdioFailedToDeleteFile;
|
||||||
}
|
}
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
@@ -373,7 +373,7 @@ Result DeleteDirectory(const FsPathReal& path, bool ignore_read_only) {
|
|||||||
|
|
||||||
if (rmdir(path)) {
|
if (rmdir(path)) {
|
||||||
R_TRY(fsdevGetLastResult());
|
R_TRY(fsdevGetLastResult());
|
||||||
return Result_FsUnknownStdioError;
|
return Result_FsStdioFailedToDeleteDirectory;
|
||||||
}
|
}
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
@@ -405,7 +405,7 @@ Result RenameFile(const FsPathReal& src, const FsPathReal& dst, bool ignore_read
|
|||||||
|
|
||||||
if (rename(src, dst)) {
|
if (rename(src, dst)) {
|
||||||
R_TRY(fsdevGetLastResult());
|
R_TRY(fsdevGetLastResult());
|
||||||
return Result_FsUnknownStdioError;
|
return Result_FsStdioFailedToRename;
|
||||||
}
|
}
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
@@ -421,7 +421,7 @@ Result GetEntryType(const FsPathReal& path, FsDirEntryType* out) {
|
|||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(path, &st)) {
|
if (stat(path, &st)) {
|
||||||
R_TRY(fsdevGetLastResult());
|
R_TRY(fsdevGetLastResult());
|
||||||
return Result_FsUnknownStdioError;
|
return Result_FsStdioFailedToStat;
|
||||||
}
|
}
|
||||||
*out = S_ISREG(st.st_mode) ? FsDirEntryType_File : FsDirEntryType_Dir;
|
*out = S_ISREG(st.st_mode) ? FsDirEntryType_File : FsDirEntryType_Dir;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@@ -431,7 +431,7 @@ Result GetFileTimeStampRaw(const FsPathReal& path, FsTimeStampRaw *out) {
|
|||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(path, &st)) {
|
if (stat(path, &st)) {
|
||||||
R_TRY(fsdevGetLastResult());
|
R_TRY(fsdevGetLastResult());
|
||||||
return Result_FsUnknownStdioError;
|
return Result_FsStdioFailedToStat;
|
||||||
}
|
}
|
||||||
|
|
||||||
out->is_valid = true;
|
out->is_valid = true;
|
||||||
@@ -489,7 +489,7 @@ Result OpenFile(fs::Fs* fs, const FsPathReal& path, u32 mode, File* f) {
|
|||||||
f->m_stdio = std::fopen(path, "rb+");
|
f->m_stdio = std::fopen(path, "rb+");
|
||||||
}
|
}
|
||||||
|
|
||||||
R_UNLESS(f->m_stdio, Result_FsUnknownStdioError);
|
R_UNLESS(f->m_stdio, Result_FsStdioFailedToOpenFile);
|
||||||
|
|
||||||
// disable buffering to match native fs behavior.
|
// disable buffering to match native fs behavior.
|
||||||
// this also causes problems with network io as it will do double reads.
|
// this also causes problems with network io as it will do double reads.
|
||||||
@@ -515,9 +515,11 @@ Result File::Read( s64 off, void* buf, u64 read_size, u32 option, u64* bytes_rea
|
|||||||
} else {
|
} else {
|
||||||
R_UNLESS(m_stdio, Result_FsUnknownStdioError);
|
R_UNLESS(m_stdio, Result_FsUnknownStdioError);
|
||||||
|
|
||||||
if (std::ftell(m_stdio) != off) {
|
if (off != std::ftell(m_stdio)) {
|
||||||
const auto ret = std::fseek(m_stdio, off, SEEK_SET);
|
const auto ret = std::fseek(m_stdio, off, SEEK_SET);
|
||||||
R_UNLESS(ret == 0, Result_FsUnknownStdioError);
|
log_write("[FS] fseek to %ld ret: %d new_off: %zd\n", off, ret, std::ftell(m_stdio));
|
||||||
|
R_UNLESS(ret == 0, Result_FsStdioFailedToSeek);
|
||||||
|
R_UNLESS(off == std::ftell(m_stdio), Result_FsStdioFailedToSeek);
|
||||||
}
|
}
|
||||||
|
|
||||||
*bytes_read = std::fread(buf, 1, read_size, m_stdio);
|
*bytes_read = std::fread(buf, 1, read_size, m_stdio);
|
||||||
@@ -526,7 +528,7 @@ Result File::Read( s64 off, void* buf, u64 read_size, u32 option, u64* bytes_rea
|
|||||||
if (*bytes_read < read_size) {
|
if (*bytes_read < read_size) {
|
||||||
if (!std::feof(m_stdio) && std::ferror(m_stdio)) {
|
if (!std::feof(m_stdio) && std::ferror(m_stdio)) {
|
||||||
log_write("[FS] fread error: %d\n", std::ferror(m_stdio));
|
log_write("[FS] fread error: %d\n", std::ferror(m_stdio));
|
||||||
R_THROW(Result_FsUnknownStdioError);
|
R_THROW(Result_FsStdioFailedToRead);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -542,14 +544,15 @@ Result File::Write(s64 off, const void* buf, u64 write_size, u32 option) {
|
|||||||
} else {
|
} else {
|
||||||
R_UNLESS(m_stdio, Result_FsUnknownStdioError);
|
R_UNLESS(m_stdio, Result_FsUnknownStdioError);
|
||||||
|
|
||||||
if (std::ftell(m_stdio) != off) {
|
if (off != std::ftell(m_stdio)) {
|
||||||
const auto ret = std::fseek(m_stdio, off, SEEK_SET);
|
const auto ret = std::fseek(m_stdio, off, SEEK_SET);
|
||||||
R_UNLESS(ret == 0, Result_FsUnknownStdioError);
|
R_UNLESS(ret == 0, Result_FsStdioFailedToSeek);
|
||||||
|
R_UNLESS(off == std::ftell(m_stdio), Result_FsStdioFailedToSeek);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto result = std::fwrite(buf, 1, write_size, m_stdio);
|
const auto result = std::fwrite(buf, 1, write_size, m_stdio);
|
||||||
// log_write("[FS] fwrite res: %zu vs %zu\n", result, write_size);
|
// log_write("[FS] fwrite res: %zu vs %zu\n", result, write_size);
|
||||||
R_UNLESS(result == write_size, Result_FsUnknownStdioError);
|
R_UNLESS(result == write_size, Result_FsStdioFailedToWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@@ -563,8 +566,8 @@ Result File::SetSize(s64 sz) {
|
|||||||
} else {
|
} else {
|
||||||
R_UNLESS(m_stdio, Result_FsUnknownStdioError);
|
R_UNLESS(m_stdio, Result_FsUnknownStdioError);
|
||||||
const auto fd = fileno(m_stdio);
|
const auto fd = fileno(m_stdio);
|
||||||
R_UNLESS(fd > 0, Result_FsUnknownStdioError);
|
R_UNLESS(fd > 0, Result_FsStdioFailedToTruncate);
|
||||||
R_UNLESS(!ftruncate(fd, sz), Result_FsUnknownStdioError);
|
R_UNLESS(!ftruncate(fd, sz), Result_FsStdioFailedToTruncate);
|
||||||
}
|
}
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@@ -579,7 +582,7 @@ Result File::GetSize(s64* out) {
|
|||||||
R_UNLESS(m_stdio, Result_FsUnknownStdioError);
|
R_UNLESS(m_stdio, Result_FsUnknownStdioError);
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
R_UNLESS(!fstat(fileno(m_stdio), &st), Result_FsUnknownStdioError);
|
R_UNLESS(!fstat(fileno(m_stdio), &st), Result_FsStdioFailedToStat);
|
||||||
*out = st.st_size;
|
*out = st.st_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -617,7 +620,7 @@ Result OpenDirectory(fs::Fs* fs, const FsPathReal& path, u32 mode, Dir* d) {
|
|||||||
R_TRY(fsFsOpenDirectory(&fs->m_fs, path, mode, &d->m_native));
|
R_TRY(fsFsOpenDirectory(&fs->m_fs, path, mode, &d->m_native));
|
||||||
} else {
|
} else {
|
||||||
d->m_stdio = opendir(path);
|
d->m_stdio = opendir(path);
|
||||||
R_UNLESS(d->m_stdio, Result_FsUnknownStdioError);
|
R_UNLESS(d->m_stdio, Result_FsStdioFailedToOpenDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|||||||
@@ -82,6 +82,14 @@ struct ThreadData {
|
|||||||
return read_running || decompress_running || write_running;
|
return read_running || decompress_running || write_running;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto GetReadOffset() volatile const -> s64 {
|
||||||
|
return read_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GetDecompressOffset() volatile const -> s64 {
|
||||||
|
return decompress_offset;
|
||||||
|
}
|
||||||
|
|
||||||
auto GetWriteOffset() volatile const -> s64 {
|
auto GetWriteOffset() volatile const -> s64 {
|
||||||
return write_offset;
|
return write_offset;
|
||||||
}
|
}
|
||||||
@@ -94,8 +102,16 @@ struct ThreadData {
|
|||||||
return &m_uevent_done;
|
return &m_uevent_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GetProgressEvent() {
|
auto GetReadProgressEvent() {
|
||||||
return &m_uevent_progres;
|
return &m_uevent_read_progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GetDecompressProgressEvent() {
|
||||||
|
return &m_uevent_decompress_progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GetWriteProgressEvent() {
|
||||||
|
return &m_uevent_write_progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetReadResult(Result result) {
|
void SetReadResult(Result result) {
|
||||||
@@ -174,7 +190,9 @@ private:
|
|||||||
CondVar can_pull_write{};
|
CondVar can_pull_write{};
|
||||||
|
|
||||||
UEvent m_uevent_done{};
|
UEvent m_uevent_done{};
|
||||||
UEvent m_uevent_progres{};
|
UEvent m_uevent_read_progress{};
|
||||||
|
UEvent m_uevent_decompress_progress{};
|
||||||
|
UEvent m_uevent_write_progress{};
|
||||||
|
|
||||||
RingBuf<2> read_buffers{};
|
RingBuf<2> read_buffers{};
|
||||||
RingBuf<2> write_buffers{};
|
RingBuf<2> write_buffers{};
|
||||||
@@ -219,8 +237,10 @@ ThreadData::ThreadData(ui::ProgressBox* _pbox, s64 size, const ReadCallback& _rf
|
|||||||
condvarInit(std::addressof(can_pull));
|
condvarInit(std::addressof(can_pull));
|
||||||
condvarInit(std::addressof(can_pull_write));
|
condvarInit(std::addressof(can_pull_write));
|
||||||
|
|
||||||
ueventCreate(&m_uevent_done, false);
|
ueventCreate(GetDoneEvent(), false);
|
||||||
ueventCreate(&m_uevent_progres, true);
|
ueventCreate(GetReadProgressEvent(), true);
|
||||||
|
ueventCreate(GetDecompressProgressEvent(), true);
|
||||||
|
ueventCreate(GetWriteProgressEvent(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ThreadData::GetResults() volatile -> Result {
|
auto ThreadData::GetResults() volatile -> Result {
|
||||||
@@ -379,6 +399,7 @@ Result ThreadData::readFuncInternal() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ueventSignal(GetReadProgressEvent());
|
||||||
auto buf_size = bytes_read;
|
auto buf_size = bytes_read;
|
||||||
R_TRY(this->SetDecompressBuf(buf, buffer_offset, buf_size));
|
R_TRY(this->SetDecompressBuf(buf, buffer_offset, buf_size));
|
||||||
}
|
}
|
||||||
@@ -423,25 +444,17 @@ Result ThreadData::decompressFuncInternal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size -= rsize;
|
size -= rsize;
|
||||||
this->decompress_offset += rsize;
|
|
||||||
data += rsize;
|
data += rsize;
|
||||||
|
this->decompress_offset += rsize;
|
||||||
// const auto buf_off = temp_buf.size();
|
ueventSignal(GetDecompressProgressEvent());
|
||||||
// temp_buf.resize(buf_off + size);
|
|
||||||
// std::memcpy(temp_buf.data() + buf_off, data, size);
|
|
||||||
// this->decompress_offset += size;
|
|
||||||
|
|
||||||
// if (temp_buf.size() >= temp_buf_flush_max) {
|
|
||||||
// // log_write("flushing data: %zu %.2f MiB\n", temp_buf.size(), temp_buf.size() / 1024.0 / 1024.0);
|
|
||||||
// R_TRY(this->SetWriteBuf(temp_buf, temp_buf.size()));
|
|
||||||
// temp_buf.resize(0);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
this->decompress_offset += buf.size();
|
this->decompress_offset += buf.size();
|
||||||
|
ueventSignal(GetDecompressProgressEvent());
|
||||||
|
|
||||||
R_TRY(this->SetWriteBuf(buf, buf.size()));
|
R_TRY(this->SetWriteBuf(buf, buf.size()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -479,7 +492,7 @@ Result ThreadData::writeFuncInternal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->write_offset += size;
|
this->write_offset += size;
|
||||||
ueventSignal(GetProgressEvent());
|
ueventSignal(GetWriteProgressEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
log_write("finished write thread success!\n");
|
log_write("finished write thread success!\n");
|
||||||
@@ -586,7 +599,11 @@ Result TransferInternal(ui::ProgressBox* pbox, s64 size, const ReadCallback& rfu
|
|||||||
R_TRY(start_threads());
|
R_TRY(start_threads());
|
||||||
log_write("[THREAD] started threads\n");
|
log_write("[THREAD] started threads\n");
|
||||||
|
|
||||||
const auto waiter_progress = waiterForUEvent(t_data.GetProgressEvent());
|
// use the read progress as the write output may be smaller due to compressing
|
||||||
|
// so read will show a more accurate progress.
|
||||||
|
// TODO: show progress bar for all 3 threads.
|
||||||
|
// NOTE: went back to using write progress for now.
|
||||||
|
const auto waiter_progress = waiterForUEvent(t_data.GetWriteProgressEvent());
|
||||||
const auto waiter_cancel = waiterForUEvent(pbox->GetCancelEvent());
|
const auto waiter_cancel = waiterForUEvent(pbox->GetCancelEvent());
|
||||||
const auto waiter_done = waiterForUEvent(t_data.GetDoneEvent());
|
const auto waiter_done = waiterForUEvent(t_data.GetDoneEvent());
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,19 @@ auto GetCodeMessage(Result rc) -> const char* {
|
|||||||
case Result_FsLoadingCancelled: return "SphairaError_FsLoadingCancelled";
|
case Result_FsLoadingCancelled: return "SphairaError_FsLoadingCancelled";
|
||||||
case Result_FsBrokenRoot: return "SphairaError_FsBrokenRoot";
|
case Result_FsBrokenRoot: return "SphairaError_FsBrokenRoot";
|
||||||
case Result_FsUnknownStdioError: return "SphairaError_FsUnknownStdioError";
|
case Result_FsUnknownStdioError: return "SphairaError_FsUnknownStdioError";
|
||||||
|
case Result_FsStdioFailedToSeek: return "SphairaError_FsStdioFailedToSeek";
|
||||||
|
case Result_FsStdioFailedToRead: return "SphairaError_FsStdioFailedToRead";
|
||||||
|
case Result_FsStdioFailedToWrite: return "SphairaError_FsStdioFailedToWrite";
|
||||||
|
case Result_FsStdioFailedToOpenFile: return "SphairaError_FsStdioFailedToOpenFile";
|
||||||
|
case Result_FsStdioFailedToCreate: return "SphairaError_FsStdioFailedToCreate";
|
||||||
|
case Result_FsStdioFailedToTruncate: return "SphairaError_FsStdioFailedToTruncate";
|
||||||
|
case Result_FsStdioFailedToFlush: return "SphairaError_FsStdioFailedToFlush";
|
||||||
|
case Result_FsStdioFailedToCreateDirectory: return "SphairaError_FsStdioFailedToCreateDirectory";
|
||||||
|
case Result_FsStdioFailedToDeleteFile: return "SphairaError_FsStdioFailedToDeleteFile";
|
||||||
|
case Result_FsStdioFailedToDeleteDirectory: return "SphairaError_FsStdioFailedToDeleteDirectory";
|
||||||
|
case Result_FsStdioFailedToOpenDirectory: return "SphairaError_FsStdioFailedToOpenDirectory";
|
||||||
|
case Result_FsStdioFailedToRename: return "SphairaError_FsStdioFailedToRename";
|
||||||
|
case Result_FsStdioFailedToStat: return "SphairaError_FsStdioFailedToStat";
|
||||||
case Result_FsReadOnly: return "SphairaError_FsReadOnly";
|
case Result_FsReadOnly: return "SphairaError_FsReadOnly";
|
||||||
case Result_FsNotActive: return "SphairaError_FsNotActive";
|
case Result_FsNotActive: return "SphairaError_FsNotActive";
|
||||||
case Result_FsFailedStdioStat: return "SphairaError_FsFailedStdioStat";
|
case Result_FsFailedStdioStat: return "SphairaError_FsFailedStdioStat";
|
||||||
|
|||||||
@@ -81,8 +81,7 @@ constexpr FsEntry FS_ENTRY_DEFAULT{
|
|||||||
|
|
||||||
constexpr FsEntry FS_ENTRIES[]{
|
constexpr FsEntry FS_ENTRIES[]{
|
||||||
FS_ENTRY_DEFAULT,
|
FS_ENTRY_DEFAULT,
|
||||||
{ "Image System memory", "/", FsType::ImageNand },
|
{ "Album", "/", FsType::ImageSd},
|
||||||
{ "Image microSD card", "/", FsType::ImageSd},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr std::string_view AUDIO_EXTENSIONS[] = {
|
constexpr std::string_view AUDIO_EXTENSIONS[] = {
|
||||||
|
|||||||
@@ -706,7 +706,6 @@ void Menu::ExportOptions(bool to_nsz) {
|
|||||||
|
|
||||||
void Menu::DumpGames(u32 flags, bool to_nsz) {
|
void Menu::DumpGames(u32 flags, bool to_nsz) {
|
||||||
auto targets = GetSelectedEntries();
|
auto targets = GetSelectedEntries();
|
||||||
ClearSelection();
|
|
||||||
|
|
||||||
std::vector<NspEntry> nsp_entries;
|
std::vector<NspEntry> nsp_entries;
|
||||||
for (auto& e : targets) {
|
for (auto& e : targets) {
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ private:
|
|||||||
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
||||||
int devoptab_close(void *fd) override;
|
int devoptab_close(void *fd) override;
|
||||||
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
||||||
off_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
ssize_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
||||||
int devoptab_fstat(void *fd, struct stat *st) override;
|
int devoptab_fstat(void *fd, struct stat *st) override;
|
||||||
int devoptab_diropen(void* fd, const char *path) override;
|
int devoptab_diropen(void* fd, const char *path) override;
|
||||||
int devoptab_dirreset(void* fd) override;
|
int devoptab_dirreset(void* fd) override;
|
||||||
@@ -134,7 +134,7 @@ ssize_t Device::devoptab_read(void *fd, char *ptr, size_t len) {
|
|||||||
return bytes_read;
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
ssize_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
const auto& info = file->info;
|
const auto& info = file->info;
|
||||||
|
|
||||||
|
|||||||
@@ -171,9 +171,14 @@ off_t devoptab_seek(struct _reent *r, void *fd, off_t pos, int dir) {
|
|||||||
SCOPED_RWLOCK(&g_rwlock, false);
|
SCOPED_RWLOCK(&g_rwlock, false);
|
||||||
SCOPED_MUTEX(&file->device->mutex);
|
SCOPED_MUTEX(&file->device->mutex);
|
||||||
|
|
||||||
const auto off = file->device->mount_device->devoptab_seek(file->fd, pos, dir);
|
const auto ret = file->device->mount_device->devoptab_seek(file->fd, pos, dir);
|
||||||
|
if (ret < 0) {
|
||||||
|
set_errno(r, -ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
r->_errno = 0;
|
r->_errno = 0;
|
||||||
return off;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int devoptab_fstat(struct _reent *r, void *fd, struct stat *st) {
|
int devoptab_fstat(struct _reent *r, void *fd, struct stat *st) {
|
||||||
@@ -960,11 +965,17 @@ PushPullThreadData::PushPullThreadData(CURL* _curl) : curl{_curl} {
|
|||||||
|
|
||||||
PushPullThreadData::~PushPullThreadData() {
|
PushPullThreadData::~PushPullThreadData() {
|
||||||
Cancel();
|
Cancel();
|
||||||
|
|
||||||
|
if (started) {
|
||||||
threadWaitForExit(&thread);
|
threadWaitForExit(&thread);
|
||||||
|
}
|
||||||
|
|
||||||
threadClose(&thread);
|
threadClose(&thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result PushPullThreadData::CreateAndStart() {
|
Result PushPullThreadData::CreateAndStart() {
|
||||||
|
SCOPED_MUTEX(&mutex);
|
||||||
|
|
||||||
if (started) {
|
if (started) {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
@@ -989,6 +1000,10 @@ bool PushPullThreadData::IsRunning() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t PushPullThreadData::PullData(char* data, size_t total_size) {
|
size_t PushPullThreadData::PullData(char* data, size_t total_size) {
|
||||||
|
if (!data || !total_size) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
SCOPED_MUTEX(&mutex);
|
SCOPED_MUTEX(&mutex);
|
||||||
ON_SCOPE_EXIT(condvarWakeOne(&can_push));
|
ON_SCOPE_EXIT(condvarWakeOne(&can_push));
|
||||||
|
|
||||||
@@ -1014,12 +1029,16 @@ size_t PushPullThreadData::PullData(char* data, size_t total_size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t PushPullThreadData::PushData(const char* data, size_t total_size) {
|
size_t PushPullThreadData::PushData(const char* data, size_t total_size) {
|
||||||
|
if (!data || !total_size) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
SCOPED_MUTEX(&mutex);
|
SCOPED_MUTEX(&mutex);
|
||||||
ON_SCOPE_EXIT(condvarWakeOne(&can_pull));
|
ON_SCOPE_EXIT(condvarWakeOne(&can_pull));
|
||||||
|
|
||||||
size_t bytes_written = 0;
|
size_t bytes_written = 0;
|
||||||
while (bytes_written < total_size && !error && !finished) {
|
while (bytes_written < total_size && !error && !finished) {
|
||||||
const size_t space_left = (1024 * 64) - buffer.size(); // 64K max buffer
|
const size_t space_left = MAX_BUFFER_SIZE - buffer.size();
|
||||||
if (space_left == 0) {
|
if (space_left == 0) {
|
||||||
condvarWakeOne(&can_pull);
|
condvarWakeOne(&can_pull);
|
||||||
condvarWait(&can_push, &mutex);
|
condvarWait(&can_push, &mutex);
|
||||||
@@ -1035,11 +1054,19 @@ size_t PushPullThreadData::PushData(const char* data, size_t total_size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t PushPullThreadData::push_thread_callback(const char *ptr, size_t size, size_t nmemb, void *userdata) {
|
size_t PushPullThreadData::push_thread_callback(const char *ptr, size_t size, size_t nmemb, void *userdata) {
|
||||||
|
if (!ptr || !userdata || !size || !nmemb) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
auto* data = static_cast<PushPullThreadData*>(userdata);
|
auto* data = static_cast<PushPullThreadData*>(userdata);
|
||||||
return data->PushData(ptr, size * nmemb);
|
return data->PushData(ptr, size * nmemb);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t PushPullThreadData::pull_thread_callback(char *ptr, size_t size, size_t nmemb, void *userdata) {
|
size_t PushPullThreadData::pull_thread_callback(char *ptr, size_t size, size_t nmemb, void *userdata) {
|
||||||
|
if (!ptr || !userdata || !size || !nmemb) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
auto* data = static_cast<PushPullThreadData*>(userdata);
|
auto* data = static_cast<PushPullThreadData*>(userdata);
|
||||||
return data->PullData(ptr, size * nmemb);
|
return data->PullData(ptr, size * nmemb);
|
||||||
}
|
}
|
||||||
@@ -1067,10 +1094,29 @@ PullThreadData::~PullThreadData() {
|
|||||||
if (started) {
|
if (started) {
|
||||||
SCOPED_MUTEX(&mutex);
|
SCOPED_MUTEX(&mutex);
|
||||||
|
|
||||||
|
// for now, always wait until the dat is flushed.
|
||||||
|
// may enable a timeout later on, however i don't want to risk
|
||||||
|
// data loss for users that have slow hdd / connections.
|
||||||
|
#if 1
|
||||||
while (!finished && !error && !buffer.empty()) {
|
while (!finished && !error && !buffer.empty()) {
|
||||||
condvarWakeOne(&can_pull);
|
condvarWakeOne(&can_pull);
|
||||||
condvarWaitTimeout(&can_push, &mutex, 5e+9);
|
condvarWait(&can_push, &mutex);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
u64 timeout = 5e+9;
|
||||||
|
const auto deadline = armGetSystemTick() + armNsToTicks(timeout);
|
||||||
|
|
||||||
|
while (!finished && !error && !buffer.empty()) {
|
||||||
|
const s64 remaining = deadline - armGetSystemTick();
|
||||||
|
timeout = remaining > 0 ? armTicksToNs(remaining) : 0;
|
||||||
|
|
||||||
|
condvarWakeOne(&can_pull);
|
||||||
|
if (R_FAILED(condvarWaitTimeout(&can_push, &mutex, timeout))) {
|
||||||
|
log_write("[PullThreadData] condvarWaitTimeout() timed out flushing data: %zu\n", buffer.size());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1276,11 +1322,6 @@ void MountCurlDevice::curl_set_common_options(CURL* curl, const std::string& url
|
|||||||
// NOTE: port, user and pass are set in the curl_url.
|
// NOTE: port, user and pass are set in the curl_url.
|
||||||
curl_easy_reset(curl);
|
curl_easy_reset(curl);
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||||
// cancel if speed is less than 1 bytes/sec for timeout seconds.
|
|
||||||
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1L);
|
|
||||||
// todo: change config to accept seconds rather than ms.
|
|
||||||
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, config.timeout / 1000L);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, config.timeout);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1L);
|
curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1L);
|
||||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||||
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 15L);
|
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 15L);
|
||||||
@@ -1291,6 +1332,14 @@ void MountCurlDevice::curl_set_common_options(CURL* curl, const std::string& url
|
|||||||
curl_easy_setopt(curl, CURLOPT_UPLOAD_BUFFERSIZE, 1024L * 64L);
|
curl_easy_setopt(curl, CURLOPT_UPLOAD_BUFFERSIZE, 1024L * 64L);
|
||||||
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");
|
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");
|
||||||
|
|
||||||
|
if (config.timeout > 0) {
|
||||||
|
// cancel if speed is less than 1 bytes/sec for timeout seconds.
|
||||||
|
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1L);
|
||||||
|
// todo: change config to accept seconds rather than ms.
|
||||||
|
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, config.timeout / 1000L);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, config.timeout);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_curl_share) {
|
if (m_curl_share) {
|
||||||
curl_easy_setopt(curl, CURLOPT_SHARE, m_curl_share);
|
curl_easy_setopt(curl, CURLOPT_SHARE, m_curl_share);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ private:
|
|||||||
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
||||||
int devoptab_close(void *fd) override;
|
int devoptab_close(void *fd) override;
|
||||||
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
||||||
off_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
ssize_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
||||||
int devoptab_fstat(void *fd, struct stat *st) override;
|
int devoptab_fstat(void *fd, struct stat *st) override;
|
||||||
int devoptab_diropen(void* fd, const char *path) override;
|
int devoptab_diropen(void* fd, const char *path) override;
|
||||||
int devoptab_dirreset(void* fd) override;
|
int devoptab_dirreset(void* fd) override;
|
||||||
@@ -331,7 +331,7 @@ ssize_t Device::devoptab_read(void *fd, char *ptr, size_t len) {
|
|||||||
return total_bytes_read;
|
return total_bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
ssize_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
const auto size = get_size_from_files(file);
|
const auto size = get_size_from_files(file);
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ private:
|
|||||||
int devoptab_close(void *fd) override;
|
int devoptab_close(void *fd) override;
|
||||||
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
||||||
ssize_t devoptab_write(void *fd, const char *ptr, size_t len) override;
|
ssize_t devoptab_write(void *fd, const char *ptr, size_t len) override;
|
||||||
off_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
ssize_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
||||||
int devoptab_fstat(void *fd, struct stat *st) override;
|
int devoptab_fstat(void *fd, struct stat *st) override;
|
||||||
int devoptab_unlink(const char *path) override;
|
int devoptab_unlink(const char *path) override;
|
||||||
int devoptab_rename(const char *oldName, const char *newName) override;
|
int devoptab_rename(const char *oldName, const char *newName) override;
|
||||||
@@ -546,7 +546,7 @@ ssize_t Device::devoptab_write(void *fd, const char *ptr, size_t len) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
ssize_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
|
|
||||||
if (dir == SEEK_CUR) {
|
if (dir == SEEK_CUR) {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ private:
|
|||||||
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
||||||
int devoptab_close(void *fd) override;
|
int devoptab_close(void *fd) override;
|
||||||
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
||||||
off_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
ssize_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
||||||
int devoptab_fstat(void *fd, struct stat *st) override;
|
int devoptab_fstat(void *fd, struct stat *st) override;
|
||||||
int devoptab_diropen(void* fd, const char *path) override;
|
int devoptab_diropen(void* fd, const char *path) override;
|
||||||
int devoptab_dirreset(void* fd) override;
|
int devoptab_dirreset(void* fd) override;
|
||||||
@@ -318,7 +318,7 @@ ssize_t Device::devoptab_read(void *fd, char *ptr, size_t len) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
ssize_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
|
|
||||||
if (dir == SEEK_CUR) {
|
if (dir == SEEK_CUR) {
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ private:
|
|||||||
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
||||||
int devoptab_close(void *fd) override;
|
int devoptab_close(void *fd) override;
|
||||||
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
||||||
off_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
ssize_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
||||||
int devoptab_fstat(void *fd, struct stat *st) override;
|
int devoptab_fstat(void *fd, struct stat *st) override;
|
||||||
int devoptab_diropen(void* fd, const char *path) override;
|
int devoptab_diropen(void* fd, const char *path) override;
|
||||||
int devoptab_dirreset(void* fd) override;
|
int devoptab_dirreset(void* fd) override;
|
||||||
@@ -207,7 +207,7 @@ ssize_t Device::devoptab_read(void *fd, char *ptr, size_t len) {
|
|||||||
return bytes_read;
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
ssize_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
const auto& entry = file->entry;
|
const auto& entry = file->entry;
|
||||||
|
|
||||||
@@ -343,9 +343,11 @@ Result MountNcaInternal(fs::Fs* fs, const std::shared_ptr<yati::source::Base>& s
|
|||||||
|
|
||||||
// check if this is a ncz.
|
// check if this is a ncz.
|
||||||
ncz::Header ncz_header{};
|
ncz::Header ncz_header{};
|
||||||
|
if (size >= NCZ_NORMAL_SIZE) {
|
||||||
R_TRY(source->Read2(&ncz_header, NCZ_NORMAL_SIZE, sizeof(ncz_header)));
|
R_TRY(source->Read2(&ncz_header, NCZ_NORMAL_SIZE, sizeof(ncz_header)));
|
||||||
|
}
|
||||||
|
|
||||||
if (ncz_header.magic == NCZ_SECTION_MAGIC) {
|
if (size >= NCZ_NORMAL_SIZE && ncz_header.magic == NCZ_SECTION_MAGIC) {
|
||||||
// read all the sections.
|
// read all the sections.
|
||||||
s64 ncz_offset = NCZ_SECTION_OFFSET;
|
s64 ncz_offset = NCZ_SECTION_OFFSET;
|
||||||
ncz::Sections ncz_sections(ncz_header.total_sections);
|
ncz::Sections ncz_sections(ncz_header.total_sections);
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
#ifdef ENABLE_DEVOPTAB_NFS
|
|
||||||
|
|
||||||
#include "utils/devoptab_common.hpp"
|
#include "utils/devoptab_common.hpp"
|
||||||
#include "defines.hpp"
|
#include "defines.hpp"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
@@ -25,7 +23,7 @@ private:
|
|||||||
int devoptab_close(void *fd) override;
|
int devoptab_close(void *fd) override;
|
||||||
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
||||||
ssize_t devoptab_write(void *fd, const char *ptr, size_t len) override;
|
ssize_t devoptab_write(void *fd, const char *ptr, size_t len) override;
|
||||||
off_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
ssize_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
||||||
int devoptab_fstat(void *fd, struct stat *st) override;
|
int devoptab_fstat(void *fd, struct stat *st) override;
|
||||||
int devoptab_unlink(const char *path) override;
|
int devoptab_unlink(const char *path) override;
|
||||||
int devoptab_rename(const char *oldName, const char *newName) override;
|
int devoptab_rename(const char *oldName, const char *newName) override;
|
||||||
@@ -111,8 +109,10 @@ bool Device::Mount() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->config.timeout > 0) {
|
||||||
nfs_set_timeout(nfs, this->config.timeout);
|
nfs_set_timeout(nfs, this->config.timeout);
|
||||||
nfs_set_readonly(nfs, this->config.read_only);
|
nfs_set_readonly(nfs, this->config.read_only);
|
||||||
|
}
|
||||||
// nfs_set_mountport(nfs, url->port);
|
// nfs_set_mountport(nfs, url->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ bool Device::Mount() {
|
|||||||
url = "nfs://" + url;
|
url = "nfs://" + url;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nfs_url = nfs_parse_url_dir(nfs, url.c_str());
|
auto nfs_url = nfs_parse_url_full(nfs, url.c_str());
|
||||||
if (!nfs_url) {
|
if (!nfs_url) {
|
||||||
log_write("[NFS] nfs_parse_url() failed for url: %s\n", url.c_str());
|
log_write("[NFS] nfs_parse_url() failed for url: %s\n", url.c_str());
|
||||||
return false;
|
return false;
|
||||||
@@ -225,7 +225,7 @@ ssize_t Device::devoptab_write(void *fd, const char *ptr, size_t len) {
|
|||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
ssize_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
|
|
||||||
u64 current_offset = 0;
|
u64 current_offset = 0;
|
||||||
@@ -414,17 +414,3 @@ Result MountNfsAll() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sphaira::devoptab
|
} // namespace sphaira::devoptab
|
||||||
|
|
||||||
#else // ENABLE_DEVOPTAB_NFS
|
|
||||||
|
|
||||||
#include "defines.hpp"
|
|
||||||
|
|
||||||
namespace sphaira::devoptab {
|
|
||||||
|
|
||||||
Result MountNfsAll() {
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sphaira::devoptab
|
|
||||||
|
|
||||||
#endif // ENABLE_DEVOPTAB_NFS
|
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ private:
|
|||||||
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
||||||
int devoptab_close(void *fd) override;
|
int devoptab_close(void *fd) override;
|
||||||
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
||||||
off_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
ssize_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
||||||
int devoptab_fstat(void *fd, struct stat *st) override;
|
int devoptab_fstat(void *fd, struct stat *st) override;
|
||||||
int devoptab_diropen(void* fd, const char *path) override;
|
int devoptab_diropen(void* fd, const char *path) override;
|
||||||
int devoptab_dirreset(void* fd) override;
|
int devoptab_dirreset(void* fd) override;
|
||||||
@@ -166,7 +166,7 @@ ssize_t Device::devoptab_read(void *fd, char *ptr, size_t len) {
|
|||||||
return bytes_read;
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
ssize_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
const auto& entry = file->entry;
|
const auto& entry = file->entry;
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ private:
|
|||||||
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
||||||
int devoptab_close(void *fd) override;
|
int devoptab_close(void *fd) override;
|
||||||
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
||||||
off_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
ssize_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
||||||
int devoptab_fstat(void *fd, struct stat *st) override;
|
int devoptab_fstat(void *fd, struct stat *st) override;
|
||||||
int devoptab_diropen(void* fd, const char *path) override;
|
int devoptab_diropen(void* fd, const char *path) override;
|
||||||
int devoptab_dirreset(void* fd) override;
|
int devoptab_dirreset(void* fd) override;
|
||||||
@@ -90,7 +90,7 @@ ssize_t Device::devoptab_read(void *fd, char *ptr, size_t len) {
|
|||||||
return bytes_read;
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
ssize_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
const auto& collection = file->collection;
|
const auto& collection = file->collection;
|
||||||
|
|
||||||
@@ -171,7 +171,7 @@ int Device::devoptab_lstat(const char *path, struct stat *st) {
|
|||||||
st->st_size = it->size;
|
st->st_size = it->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -ENOENT;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ private:
|
|||||||
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
||||||
int devoptab_close(void *fd) override;
|
int devoptab_close(void *fd) override;
|
||||||
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
||||||
off_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
ssize_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
||||||
int devoptab_fstat(void *fd, struct stat *st) override;
|
int devoptab_fstat(void *fd, struct stat *st) override;
|
||||||
int devoptab_diropen(void* fd, const char *path) override;
|
int devoptab_diropen(void* fd, const char *path) override;
|
||||||
int devoptab_dirreset(void* fd) override;
|
int devoptab_dirreset(void* fd) override;
|
||||||
@@ -101,7 +101,7 @@ ssize_t Device::devoptab_read(void *fd, char *ptr, size_t len) {
|
|||||||
return bytes_read;
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
ssize_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
|
|
||||||
if (dir == SEEK_CUR) {
|
if (dir == SEEK_CUR) {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ private:
|
|||||||
int devoptab_close(void *fd) override;
|
int devoptab_close(void *fd) override;
|
||||||
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
||||||
ssize_t devoptab_write(void *fd, const char *ptr, size_t len) override;
|
ssize_t devoptab_write(void *fd, const char *ptr, size_t len) override;
|
||||||
off_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
ssize_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
||||||
int devoptab_fstat(void *fd, struct stat *st) override;
|
int devoptab_fstat(void *fd, struct stat *st) override;
|
||||||
int devoptab_unlink(const char *path) override;
|
int devoptab_unlink(const char *path) override;
|
||||||
int devoptab_rename(const char *oldName, const char *newName) override;
|
int devoptab_rename(const char *oldName, const char *newName) override;
|
||||||
@@ -247,12 +247,15 @@ bool Device::Mount() {
|
|||||||
|
|
||||||
libssh2_session_set_blocking(m_session, 1);
|
libssh2_session_set_blocking(m_session, 1);
|
||||||
libssh2_session_flag(m_session, LIBSSH2_FLAG_COMPRESS, 1);
|
libssh2_session_flag(m_session, LIBSSH2_FLAG_COMPRESS, 1);
|
||||||
|
|
||||||
|
if (this->config.timeout > 0) {
|
||||||
libssh2_session_set_timeout(m_session, this->config.timeout);
|
libssh2_session_set_timeout(m_session, this->config.timeout);
|
||||||
// dkp libssh2 is too old for this.
|
// dkp libssh2 is too old for this.
|
||||||
#if LIBSSH2_VERSION_NUM >= 0x010B00
|
#if LIBSSH2_VERSION_NUM >= 0x010B00
|
||||||
libssh2_session_set_read_timeout(m_session, this->config.timeout);
|
libssh2_session_set_read_timeout(m_session, this->config.timeout);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this->config.user.empty() || this->config.pass.empty()) {
|
if (this->config.user.empty() || this->config.pass.empty()) {
|
||||||
log_write("[SFTP] Missing username or password\n");
|
log_write("[SFTP] Missing username or password\n");
|
||||||
@@ -353,7 +356,7 @@ ssize_t Device::devoptab_write(void *fd, const char *ptr, size_t len) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
ssize_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
const auto current_pos = libssh2_sftp_tell64(file->fd);
|
const auto current_pos = libssh2_sftp_tell64(file->fd);
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ private:
|
|||||||
int devoptab_close(void *fd) override;
|
int devoptab_close(void *fd) override;
|
||||||
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
||||||
ssize_t devoptab_write(void *fd, const char *ptr, size_t len) override;
|
ssize_t devoptab_write(void *fd, const char *ptr, size_t len) override;
|
||||||
off_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
ssize_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
||||||
int devoptab_fstat(void *fd, struct stat *st) override;
|
int devoptab_fstat(void *fd, struct stat *st) override;
|
||||||
int devoptab_unlink(const char *path) override;
|
int devoptab_unlink(const char *path) override;
|
||||||
int devoptab_rename(const char *oldName, const char *newName) override;
|
int devoptab_rename(const char *oldName, const char *newName) override;
|
||||||
@@ -118,8 +118,10 @@ bool Device::Mount() {
|
|||||||
smb2_set_workstation(this->smb2, workstation->second.c_str());
|
smb2_set_workstation(this->smb2, workstation->second.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.timeout > 0) {
|
||||||
smb2_set_timeout(this->smb2, this->config.timeout);
|
smb2_set_timeout(this->smb2, this->config.timeout);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto smb2_url = smb2_parse_url(this->smb2, this->config.url.c_str());
|
auto smb2_url = smb2_parse_url(this->smb2, this->config.url.c_str());
|
||||||
if (!smb2_url) {
|
if (!smb2_url) {
|
||||||
@@ -160,28 +162,56 @@ int Device::devoptab_close(void *fd) {
|
|||||||
ssize_t Device::devoptab_read(void *fd, char *ptr, size_t len) {
|
ssize_t Device::devoptab_read(void *fd, char *ptr, size_t len) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
|
|
||||||
const auto ret = smb2_read(this->smb2, file->fd, reinterpret_cast<uint8_t*>(ptr), len);
|
const auto max_read = smb2_get_max_read_size(this->smb2);
|
||||||
|
size_t bytes_read = 0;
|
||||||
|
|
||||||
|
while (bytes_read < len) {
|
||||||
|
const auto to_read = std::min<size_t>(len - bytes_read, max_read);
|
||||||
|
const auto ret = smb2_read(this->smb2, file->fd, (u8*)ptr, to_read);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
log_write("[SMB2] smb2_read() failed: %s errno: %s\n", smb2_get_error(this->smb2), std::strerror(-ret));
|
log_write("[SMB2] smb2_read() failed: %s errno: %s\n", smb2_get_error(this->smb2), std::strerror(-ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
ptr += ret;
|
||||||
|
bytes_read += ret;
|
||||||
|
|
||||||
|
if (ret < to_read) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t Device::devoptab_write(void *fd, const char *ptr, size_t len) {
|
ssize_t Device::devoptab_write(void *fd, const char *ptr, size_t len) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
|
|
||||||
const auto ret = smb2_write(this->smb2, file->fd, reinterpret_cast<const uint8_t*>(ptr), len);
|
const auto max_write = smb2_get_max_write_size(this->smb2);
|
||||||
|
size_t written = 0;
|
||||||
|
|
||||||
|
while (written < len) {
|
||||||
|
const auto to_write = std::min<size_t>(len - written, max_write);
|
||||||
|
const auto ret = smb2_write(this->smb2, file->fd, (const u8*)ptr, to_write);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
log_write("[SMB2] smb2_write() failed: %s errno: %s\n", smb2_get_error(this->smb2), std::strerror(-ret));
|
log_write("[SMB2] smb2_write() failed: %s errno: %s\n", smb2_get_error(this->smb2), std::strerror(-ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
ptr += ret;
|
||||||
|
written += ret;
|
||||||
|
|
||||||
|
if (ret < to_write) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
|
|
||||||
u64 current_offset = 0;
|
u64 current_offset = 0;
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ private:
|
|||||||
int devoptab_close(void *fd) override;
|
int devoptab_close(void *fd) override;
|
||||||
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
||||||
ssize_t devoptab_write(void *fd, const char *ptr, size_t len) override;
|
ssize_t devoptab_write(void *fd, const char *ptr, size_t len) override;
|
||||||
off_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
ssize_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
||||||
int devoptab_fstat(void *fd, struct stat *st) override;
|
int devoptab_fstat(void *fd, struct stat *st) override;
|
||||||
int devoptab_unlink(const char *path) override;
|
int devoptab_unlink(const char *path) override;
|
||||||
int devoptab_rename(const char *oldName, const char *newName) override;
|
int devoptab_rename(const char *oldName, const char *newName) override;
|
||||||
@@ -124,7 +124,7 @@ ssize_t Device::devoptab_write(void *fd, const char *ptr, size_t len) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
ssize_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
|
|
||||||
return lseek(file->fd, pos, dir);
|
return lseek(file->fd, pos, dir);
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ private:
|
|||||||
int devoptab_close(void *fd) override;
|
int devoptab_close(void *fd) override;
|
||||||
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
||||||
ssize_t devoptab_write(void *fd, const char *ptr, size_t len) override;
|
ssize_t devoptab_write(void *fd, const char *ptr, size_t len) override;
|
||||||
off_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
ssize_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
||||||
int devoptab_fstat(void *fd, struct stat *st) override;
|
int devoptab_fstat(void *fd, struct stat *st) override;
|
||||||
int devoptab_unlink(const char *path) override;
|
int devoptab_unlink(const char *path) override;
|
||||||
int devoptab_rename(const char *oldName, const char *newName) override;
|
int devoptab_rename(const char *oldName, const char *newName) override;
|
||||||
@@ -188,6 +188,7 @@ int Device::webdav_dirlist(const std::string& path, DirEntries& out) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: fix requested path still being displayed.
|
||||||
const auto href = url_decode(href_x.node().text().as_string());
|
const auto href = url_decode(href_x.node().text().as_string());
|
||||||
if (href.empty() || href == requested_path || href == requested_path + '/') {
|
if (href.empty() || href == requested_path || href == requested_path + '/') {
|
||||||
continue;
|
continue;
|
||||||
@@ -483,7 +484,7 @@ ssize_t Device::devoptab_write(void *fd, const char *ptr, size_t len) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
ssize_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
|
|
||||||
if (dir == SEEK_CUR) {
|
if (dir == SEEK_CUR) {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ private:
|
|||||||
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
||||||
int devoptab_close(void *fd) override;
|
int devoptab_close(void *fd) override;
|
||||||
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
||||||
off_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
ssize_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
||||||
int devoptab_fstat(void *fd, struct stat *st) override;
|
int devoptab_fstat(void *fd, struct stat *st) override;
|
||||||
int devoptab_diropen(void* fd, const char *path) override;
|
int devoptab_diropen(void* fd, const char *path) override;
|
||||||
int devoptab_dirreset(void* fd) override;
|
int devoptab_dirreset(void* fd) override;
|
||||||
@@ -90,7 +90,7 @@ ssize_t Device::devoptab_read(void *fd, char *ptr, size_t len) {
|
|||||||
return bytes_read;
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
ssize_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
const auto& collection = file->collection;
|
const auto& collection = file->collection;
|
||||||
|
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ private:
|
|||||||
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
int devoptab_open(void *fileStruct, const char *path, int flags, int mode) override;
|
||||||
int devoptab_close(void *fd) override;
|
int devoptab_close(void *fd) override;
|
||||||
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
ssize_t devoptab_read(void *fd, char *ptr, size_t len) override;
|
||||||
off_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
ssize_t devoptab_seek(void *fd, off_t pos, int dir) override;
|
||||||
int devoptab_fstat(void *fd, struct stat *st) override;
|
int devoptab_fstat(void *fd, struct stat *st) override;
|
||||||
int devoptab_diropen(void* fd, const char *path) override;
|
int devoptab_diropen(void* fd, const char *path) override;
|
||||||
int devoptab_dirreset(void* fd) override;
|
int devoptab_dirreset(void* fd) override;
|
||||||
@@ -338,7 +338,7 @@ ssize_t Device::devoptab_read(void *fd, char *ptr, size_t len) {
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
ssize_t Device::devoptab_seek(void *fd, off_t pos, int dir) {
|
||||||
auto file = static_cast<File*>(fd);
|
auto file = static_cast<File*>(fd);
|
||||||
|
|
||||||
// seek like normal.
|
// seek like normal.
|
||||||
|
|||||||
Reference in New Issue
Block a user