This repository has been archived by the owner on Sep 2, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
316 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,60 @@ | ||
#include <dirent.h> | ||
#include <unistd.h> | ||
#include <cerrno> | ||
|
||
int foreach_dir(const char *path, void(*callback)(int, struct dirent *)) { | ||
bool foreach_dir(const char *path, void(*callback)(int, struct dirent *, bool *)) { | ||
DIR *dir; | ||
struct dirent *entry; | ||
int fd; | ||
bool continue_read = true; | ||
|
||
if ((dir = opendir(path)) == nullptr) | ||
return -1; | ||
return false; | ||
|
||
fd = dirfd(dir); | ||
|
||
while ((entry = readdir(dir))) { | ||
if (entry->d_name[0] == '.') continue; | ||
callback(fd, entry); | ||
callback(fd, entry, &continue_read); | ||
if (!continue_read) break; | ||
} | ||
|
||
closedir(dir); | ||
return true; | ||
} | ||
|
||
static ssize_t read_eintr(int fd, void *out, size_t len) { | ||
ssize_t ret; | ||
do { | ||
ret = read(fd, out, len); | ||
} while (ret < 0 && errno == EINTR); | ||
return ret; | ||
} | ||
|
||
int read_full(int fd, void *out, size_t len) { | ||
while (len > 0) { | ||
ssize_t ret = read_eintr(fd, out, len); | ||
if (ret <= 0) { | ||
return -1; | ||
} | ||
out = (void *) ((uintptr_t) out + ret); | ||
len -= ret; | ||
} | ||
return 0; | ||
} | ||
|
||
int write_full(int fd, const void *buf, size_t count) { | ||
while (count > 0) { | ||
ssize_t size = write(fd, buf, count < SSIZE_MAX ? count : SSIZE_MAX); | ||
if (size == -1) { | ||
if (errno == EINTR) | ||
continue; | ||
else | ||
return -1; | ||
} | ||
|
||
buf = (const void *) ((uintptr_t) buf + size); | ||
count -= size; | ||
} | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
#include <sys/socket.h> | ||
#include <sys/un.h> | ||
#include <unistd.h> | ||
#include <cinttypes> | ||
#include <malloc.h> | ||
#include <dirent.h> | ||
#include "riru.h" | ||
#include "rirud.h" | ||
#include "logging.h" | ||
#include "socket.h" | ||
#include "misc.h" | ||
|
||
#define SOCKET_ADDRESS "rirud" | ||
|
||
static const uint32_t ACTION_READ_FILE = 4; | ||
static const uint32_t ACTION_READ_DIR = 5; | ||
|
||
bool rirud::ReadFile(const char *path, char *&bytes, size_t &bytes_size) { | ||
if (riru_api_version < 10) return false; | ||
|
||
struct sockaddr_un addr{}; | ||
uint32_t path_size = strlen(path); | ||
int32_t reply; | ||
int32_t file_size; | ||
int fd; | ||
socklen_t socklen; | ||
uint32_t buffer_size = 1024 * 8; | ||
bool res = false; | ||
|
||
bytes = nullptr; | ||
bytes_size = 0; | ||
|
||
if ((fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) < 0) { | ||
PLOGE("socket"); | ||
goto clean; | ||
} | ||
|
||
socklen = setup_sockaddr(&addr, SOCKET_ADDRESS); | ||
|
||
if (connect(fd, (struct sockaddr *) &addr, socklen) == -1) { | ||
PLOGE("connect %s", SOCKET_ADDRESS); | ||
goto clean; | ||
} | ||
|
||
if (write_full(fd, &ACTION_READ_FILE, sizeof(uint32_t)) != 0 | ||
|| write_full(fd, &path_size, sizeof(uint32_t)) != 0 | ||
|| write_full(fd, path, path_size) != 0) { | ||
PLOGE("write %s", SOCKET_ADDRESS); | ||
goto clean; | ||
} | ||
|
||
if (read_full(fd, &reply, sizeof(int32_t)) != 0) { | ||
PLOGE("read %s", SOCKET_ADDRESS); | ||
goto clean; | ||
} | ||
|
||
if (reply != 0) { | ||
LOGE("open %s failed with %d from remote: %s", path, reply, strerror(reply)); | ||
errno = reply; | ||
goto clean; | ||
} | ||
|
||
if (read_full(fd, &file_size, sizeof(uint32_t)) != 0) { | ||
PLOGE("read %s", SOCKET_ADDRESS); | ||
goto clean; | ||
} | ||
|
||
LOGD("%s size %d", path, file_size); | ||
|
||
if (file_size > 0) { | ||
bytes = (char *) malloc(file_size); | ||
while (file_size > 0) { | ||
LOGD("attempt to read %d bytes", (int) buffer_size); | ||
auto read_size = TEMP_FAILURE_RETRY(read(fd, bytes + bytes_size, buffer_size)); | ||
if (read_size == -1) { | ||
PLOGE("read"); | ||
goto clean; | ||
} | ||
|
||
file_size -= read_size; | ||
bytes_size += read_size; | ||
LOGD("read %d bytes (total %d)", (int) read_size, (int) bytes_size); | ||
} | ||
res = true; | ||
} else if (file_size == 0) { | ||
while (true) { | ||
if (bytes == nullptr) { | ||
bytes = (char *) malloc(buffer_size); | ||
} else { | ||
bytes = (char *) realloc(bytes, bytes_size + buffer_size); | ||
} | ||
|
||
LOGD("attempt to read %d bytes", (int) buffer_size); | ||
auto read_size = TEMP_FAILURE_RETRY(read(fd, bytes + bytes_size, buffer_size)); | ||
if (read_size == -1) { | ||
PLOGE("read"); | ||
goto clean; | ||
} | ||
if (read_size == 0) { | ||
res = true; | ||
goto clean; | ||
} | ||
|
||
bytes_size += read_size; | ||
LOGD("read %d bytes (total %d)", (int) read_size, (int) bytes_size); | ||
} | ||
} | ||
|
||
|
||
clean: | ||
if (fd != -1) close(fd); | ||
return res; | ||
} | ||
|
||
bool rirud::ForeachDir(const char *path, void(*callback)(struct dirent *, bool *continue_read)) { | ||
if (riru_api_version < 10) return false; | ||
|
||
struct sockaddr_un addr{}; | ||
uint32_t path_size = strlen(path); | ||
int32_t reply; | ||
int fd; | ||
socklen_t socklen; | ||
bool res = false; | ||
bool continue_read = true; | ||
|
||
dirent dirent{}; | ||
|
||
if ((fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) < 0) { | ||
PLOGE("socket"); | ||
goto clean; | ||
} | ||
|
||
socklen = setup_sockaddr(&addr, SOCKET_ADDRESS); | ||
|
||
if (connect(fd, (struct sockaddr *) &addr, socklen) == -1) { | ||
PLOGE("connect %s", SOCKET_ADDRESS); | ||
goto clean; | ||
} | ||
|
||
if (write_full(fd, &ACTION_READ_DIR, sizeof(uint32_t)) != 0 | ||
|| write_full(fd, &path_size, sizeof(uint32_t)) != 0 | ||
|| write_full(fd, path, path_size) != 0) { | ||
PLOGE("write %s", SOCKET_ADDRESS); | ||
goto clean; | ||
} | ||
|
||
if (read_full(fd, &reply, sizeof(int32_t)) != 0) { | ||
PLOGE("read %s", SOCKET_ADDRESS); | ||
goto clean; | ||
} | ||
|
||
if (reply != 0) { | ||
LOGE("opendir %s failed with %d from remote: %s", path, reply, strerror(reply)); | ||
errno = reply; | ||
goto clean; | ||
} | ||
|
||
while (true) { | ||
if (write_full(fd, &continue_read, sizeof(uint8_t)) != 0) { | ||
PLOGE("write %s", SOCKET_ADDRESS); | ||
goto clean; | ||
} | ||
|
||
if (read_full(fd, &reply, sizeof(int32_t)) != 0) { | ||
PLOGE("read %s", SOCKET_ADDRESS); | ||
goto clean; | ||
} | ||
|
||
if (reply == -1) { | ||
goto clean; | ||
} | ||
|
||
if (reply != 0) { | ||
LOGE("opendir %s failed with %d from remote: %s", path, reply, strerror(reply)); | ||
continue; | ||
} | ||
|
||
if (read_full(fd, &dirent.d_type, sizeof(unsigned char)) != 0 | ||
|| read_full(fd, dirent.d_name, 256) != 0) { | ||
PLOGE("read %s", SOCKET_ADDRESS); | ||
goto clean; | ||
} | ||
|
||
callback(&dirent, &continue_read); | ||
} | ||
|
||
clean: | ||
if (fd != -1) close(fd); | ||
return res; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#pragma once | ||
|
||
namespace rirud { | ||
|
||
bool ReadFile(const char *path, char *&bytes, size_t &bytes_size); | ||
bool ForeachDir(const char *path, void(*callback)(struct dirent *, bool *continue_read)); | ||
} |
Oops, something went wrong.