Move functions from process to file
Move filesystem-related functions from process.[ch] to file.[ch].
This commit is contained in:
parent
be55e250ca
commit
d4c262301f
12 changed files with 212 additions and 172 deletions
|
@ -24,6 +24,7 @@ src = [
|
|||
'src/server.c',
|
||||
'src/stream.c',
|
||||
'src/video_buffer.c',
|
||||
'src/util/file.c',
|
||||
'src/util/log.c',
|
||||
'src/util/net.c',
|
||||
'src/util/process.c',
|
||||
|
@ -35,9 +36,15 @@ src = [
|
|||
]
|
||||
|
||||
if host_machine.system() == 'windows'
|
||||
src += [ 'src/sys/win/process.c' ]
|
||||
src += [
|
||||
'src/sys/win/file.c',
|
||||
'src/sys/win/process.c',
|
||||
]
|
||||
else
|
||||
src += [ 'src/sys/unix/process.c' ]
|
||||
src += [
|
||||
'src/sys/unix/file.c',
|
||||
'src/sys/unix/process.c',
|
||||
]
|
||||
endif
|
||||
|
||||
v4l2_support = host_machine.system() == 'linux'
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util/file.h"
|
||||
#include "util/log.h"
|
||||
#include "util/str_util.h"
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
|
||||
#include "config.h"
|
||||
#include "compat.h"
|
||||
#include "util/file.h"
|
||||
#include "util/log.h"
|
||||
#include "util/process.h"
|
||||
#include "util/str_util.h"
|
||||
|
||||
#define SCRCPY_PORTABLE_ICON_FILENAME "icon.png"
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <SDL2/SDL_platform.h>
|
||||
|
||||
#include "adb.h"
|
||||
#include "util/file.h"
|
||||
#include "util/log.h"
|
||||
#include "util/net.h"
|
||||
#include "util/str_util.h"
|
||||
|
|
75
app/src/sys/unix/file.c
Normal file
75
app/src/sys/unix/file.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
#include "util/file.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
bool
|
||||
search_executable(const char *file) {
|
||||
char *path = getenv("PATH");
|
||||
if (!path)
|
||||
return false;
|
||||
path = strdup(path);
|
||||
if (!path)
|
||||
return false;
|
||||
|
||||
bool ret = false;
|
||||
size_t file_len = strlen(file);
|
||||
char *saveptr;
|
||||
for (char *dir = strtok_r(path, ":", &saveptr); dir;
|
||||
dir = strtok_r(NULL, ":", &saveptr)) {
|
||||
size_t dir_len = strlen(dir);
|
||||
char *fullpath = malloc(dir_len + file_len + 2);
|
||||
if (!fullpath)
|
||||
continue;
|
||||
memcpy(fullpath, dir, dir_len);
|
||||
fullpath[dir_len] = '/';
|
||||
memcpy(fullpath + dir_len + 1, file, file_len + 1);
|
||||
|
||||
struct stat sb;
|
||||
bool fullpath_executable = stat(fullpath, &sb) == 0 &&
|
||||
sb.st_mode & S_IXUSR;
|
||||
free(fullpath);
|
||||
if (fullpath_executable) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
get_executable_path(void) {
|
||||
// <https://stackoverflow.com/a/1024937/1987178>
|
||||
#ifdef __linux__
|
||||
char buf[PATH_MAX + 1]; // +1 for the null byte
|
||||
ssize_t len = readlink("/proc/self/exe", buf, PATH_MAX);
|
||||
if (len == -1) {
|
||||
perror("readlink");
|
||||
return NULL;
|
||||
}
|
||||
buf[len] = '\0';
|
||||
return strdup(buf);
|
||||
#else
|
||||
// in practice, we only need this feature for portable builds, only used on
|
||||
// Windows, so we don't care implementing it for every platform
|
||||
// (it's useful to have a working version on Linux for debugging though)
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
is_regular_file(const char *path) {
|
||||
struct stat path_stat;
|
||||
|
||||
if (stat(path, &path_stat)) {
|
||||
perror("stat");
|
||||
return false;
|
||||
}
|
||||
return S_ISREG(path_stat.st_mode);
|
||||
}
|
||||
|
|
@ -3,53 +3,13 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
bool
|
||||
search_executable(const char *file) {
|
||||
char *path = getenv("PATH");
|
||||
if (!path)
|
||||
return false;
|
||||
path = strdup(path);
|
||||
if (!path)
|
||||
return false;
|
||||
|
||||
bool ret = false;
|
||||
size_t file_len = strlen(file);
|
||||
char *saveptr;
|
||||
for (char *dir = strtok_r(path, ":", &saveptr); dir;
|
||||
dir = strtok_r(NULL, ":", &saveptr)) {
|
||||
size_t dir_len = strlen(dir);
|
||||
char *fullpath = malloc(dir_len + file_len + 2);
|
||||
if (!fullpath)
|
||||
continue;
|
||||
memcpy(fullpath, dir, dir_len);
|
||||
fullpath[dir_len] = '/';
|
||||
memcpy(fullpath + dir_len + 1, file, file_len + 1);
|
||||
|
||||
struct stat sb;
|
||||
bool fullpath_executable = stat(fullpath, &sb) == 0 &&
|
||||
sb.st_mode & S_IXUSR;
|
||||
free(fullpath);
|
||||
if (fullpath_executable) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum process_result
|
||||
process_execute_redirect(const char *const argv[], pid_t *pid, int *pipe_stdin,
|
||||
int *pipe_stdout, int *pipe_stderr) {
|
||||
|
@ -232,37 +192,6 @@ process_close(pid_t pid) {
|
|||
process_wait(pid, true); // ignore exit code
|
||||
}
|
||||
|
||||
char *
|
||||
get_executable_path(void) {
|
||||
// <https://stackoverflow.com/a/1024937/1987178>
|
||||
#ifdef __linux__
|
||||
char buf[PATH_MAX + 1]; // +1 for the null byte
|
||||
ssize_t len = readlink("/proc/self/exe", buf, PATH_MAX);
|
||||
if (len == -1) {
|
||||
perror("readlink");
|
||||
return NULL;
|
||||
}
|
||||
buf[len] = '\0';
|
||||
return strdup(buf);
|
||||
#else
|
||||
// in practice, we only need this feature for portable builds, only used on
|
||||
// Windows, so we don't care implementing it for every platform
|
||||
// (it's useful to have a working version on Linux for debugging though)
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
is_regular_file(const char *path) {
|
||||
struct stat path_stat;
|
||||
|
||||
if (stat(path, &path_stat)) {
|
||||
perror("stat");
|
||||
return false;
|
||||
}
|
||||
return S_ISREG(path_stat.st_mode);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
read_pipe(int pipe, char *data, size_t len) {
|
||||
return read(pipe, data, len);
|
||||
|
|
43
app/src/sys/win/file.c
Normal file
43
app/src/sys/win/file.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
#include "util/file.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/str_util.h"
|
||||
|
||||
char *
|
||||
get_executable_path(void) {
|
||||
HMODULE hModule = GetModuleHandleW(NULL);
|
||||
if (!hModule) {
|
||||
return NULL;
|
||||
}
|
||||
WCHAR buf[MAX_PATH + 1]; // +1 for the null byte
|
||||
int len = GetModuleFileNameW(hModule, buf, MAX_PATH);
|
||||
if (!len) {
|
||||
return NULL;
|
||||
}
|
||||
buf[len] = '\0';
|
||||
return utf8_from_wide_char(buf);
|
||||
}
|
||||
|
||||
bool
|
||||
is_regular_file(const char *path) {
|
||||
wchar_t *wide_path = utf8_to_wide_char(path);
|
||||
if (!wide_path) {
|
||||
LOGC("Could not allocate wide char string");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct _stat path_stat;
|
||||
int r = _wstat(wide_path, &path_stat);
|
||||
free(wide_path);
|
||||
|
||||
if (r) {
|
||||
perror("stat");
|
||||
return false;
|
||||
}
|
||||
return S_ISREG(path_stat.st_mode);
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
#include "util/process.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/str_util.h"
|
||||
|
@ -174,40 +173,6 @@ process_close(HANDLE handle) {
|
|||
(void) closed;
|
||||
}
|
||||
|
||||
char *
|
||||
get_executable_path(void) {
|
||||
HMODULE hModule = GetModuleHandleW(NULL);
|
||||
if (!hModule) {
|
||||
return NULL;
|
||||
}
|
||||
WCHAR buf[MAX_PATH + 1]; // +1 for the null byte
|
||||
int len = GetModuleFileNameW(hModule, buf, MAX_PATH);
|
||||
if (!len) {
|
||||
return NULL;
|
||||
}
|
||||
buf[len] = '\0';
|
||||
return utf8_from_wide_char(buf);
|
||||
}
|
||||
|
||||
bool
|
||||
is_regular_file(const char *path) {
|
||||
wchar_t *wide_path = utf8_to_wide_char(path);
|
||||
if (!wide_path) {
|
||||
LOGC("Could not allocate wide char string");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct _stat path_stat;
|
||||
int r = _wstat(wide_path, &path_stat);
|
||||
free(wide_path);
|
||||
|
||||
if (r) {
|
||||
perror("stat");
|
||||
return false;
|
||||
}
|
||||
return S_ISREG(path_stat.st_mode);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
read_pipe(HANDLE pipe, char *data, size_t len) {
|
||||
DWORD r;
|
||||
|
|
48
app/src/util/file.c
Normal file
48
app/src/util/file.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
#include "file.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
char *
|
||||
get_local_file_path(const char *name) {
|
||||
char *executable_path = get_executable_path();
|
||||
if (!executable_path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// dirname() does not work correctly everywhere, so get the parent
|
||||
// directory manually.
|
||||
// See <https://github.com/Genymobile/scrcpy/issues/2619>
|
||||
char *p = strrchr(executable_path, PATH_SEPARATOR);
|
||||
if (!p) {
|
||||
LOGE("Unexpected executable path: \"%s\" (it should contain a '%c')",
|
||||
executable_path, PATH_SEPARATOR);
|
||||
free(executable_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*p = '\0'; // modify executable_path in place
|
||||
char *dir = executable_path;
|
||||
size_t dirlen = strlen(dir);
|
||||
size_t namelen = strlen(name);
|
||||
|
||||
size_t len = dirlen + namelen + 2; // +2: '/' and '\0'
|
||||
char *file_path = malloc(len);
|
||||
if (!file_path) {
|
||||
LOGE("Could not alloc path");
|
||||
free(executable_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(file_path, dir, dirlen);
|
||||
file_path[dirlen] = PATH_SEPARATOR;
|
||||
// namelen + 1 to copy the final '\0'
|
||||
memcpy(&file_path[dirlen + 1], name, namelen + 1);
|
||||
|
||||
free(executable_path);
|
||||
|
||||
return file_path;
|
||||
}
|
||||
|
34
app/src/util/file.h
Normal file
34
app/src/util/file.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#ifndef SC_FILE_H
|
||||
#define SC_FILE_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# define PATH_SEPARATOR '\\'
|
||||
#else
|
||||
# define PATH_SEPARATOR '/'
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
// only used to find package manager, not implemented for Windows
|
||||
bool
|
||||
search_executable(const char *file);
|
||||
#endif
|
||||
|
||||
// return the absolute path of the executable (the scrcpy binary)
|
||||
// may be NULL on error; to be freed by free()
|
||||
char *
|
||||
get_executable_path(void);
|
||||
|
||||
// Return the absolute path of a file in the same directory as he executable.
|
||||
// May be NULL on error. To be freed by free().
|
||||
char *
|
||||
get_local_file_path(const char *name);
|
||||
|
||||
// returns true if the file exists and is not a directory
|
||||
bool
|
||||
is_regular_file(const char *path);
|
||||
|
||||
#endif
|
|
@ -21,47 +21,6 @@ process_check_success(process_t proc, const char *name, bool close) {
|
|||
return true;
|
||||
}
|
||||
|
||||
char *
|
||||
get_local_file_path(const char *name) {
|
||||
char *executable_path = get_executable_path();
|
||||
if (!executable_path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// dirname() does not work correctly everywhere, so get the parent
|
||||
// directory manually.
|
||||
// See <https://github.com/Genymobile/scrcpy/issues/2619>
|
||||
char *p = strrchr(executable_path, PATH_SEPARATOR);
|
||||
if (!p) {
|
||||
LOGE("Unexpected executable path: \"%s\" (it should contain a '%c')",
|
||||
executable_path, PATH_SEPARATOR);
|
||||
free(executable_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*p = '\0'; // modify executable_path in place
|
||||
char *dir = executable_path;
|
||||
size_t dirlen = strlen(dir);
|
||||
size_t namelen = strlen(name);
|
||||
|
||||
size_t len = dirlen + namelen + 2; // +2: '/' and '\0'
|
||||
char *file_path = malloc(len);
|
||||
if (!file_path) {
|
||||
LOGE("Could not alloc path");
|
||||
free(executable_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(file_path, dir, dirlen);
|
||||
file_path[dirlen] = PATH_SEPARATOR;
|
||||
// namelen + 1 to copy the final '\0'
|
||||
memcpy(&file_path[dirlen + 1], name, namelen + 1);
|
||||
|
||||
free(executable_path);
|
||||
|
||||
return file_path;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
read_pipe_all(pipe_t pipe, char *data, size_t len) {
|
||||
size_t copied = 0;
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
// not needed here, but winsock2.h must never be included AFTER windows.h
|
||||
# include <winsock2.h>
|
||||
# include <windows.h>
|
||||
# define PATH_SEPARATOR '\\'
|
||||
# define PRIexitcode "lu"
|
||||
// <https://stackoverflow.com/a/44383330/1987178>
|
||||
# define PRIsizet "Iu"
|
||||
|
@ -23,7 +22,6 @@
|
|||
#else
|
||||
|
||||
# include <sys/types.h>
|
||||
# define PATH_SEPARATOR '/'
|
||||
# define PRIsizet "zu"
|
||||
# define PRIexitcode "d"
|
||||
# define PROCESS_NONE -1
|
||||
|
@ -73,26 +71,6 @@ process_close(process_t pid);
|
|||
bool
|
||||
process_check_success(process_t proc, const char *name, bool close);
|
||||
|
||||
#ifndef _WIN32
|
||||
// only used to find package manager, not implemented for Windows
|
||||
bool
|
||||
search_executable(const char *file);
|
||||
#endif
|
||||
|
||||
// return the absolute path of the executable (the scrcpy binary)
|
||||
// may be NULL on error; to be freed by free()
|
||||
char *
|
||||
get_executable_path(void);
|
||||
|
||||
// Return the absolute path of a file in the same directory as he executable.
|
||||
// May be NULL on error. To be freed by free().
|
||||
char *
|
||||
get_local_file_path(const char *name);
|
||||
|
||||
// returns true if the file exists and is not a directory
|
||||
bool
|
||||
is_regular_file(const char *path);
|
||||
|
||||
ssize_t
|
||||
read_pipe(pipe_t pipe, char *data, size_t len);
|
||||
|
||||
|
|
Loading…
Reference in a new issue