Several MagiskHide improvements
- Directly get UID instead of traversing /data/data everytime - Use /data/user_de/0 instead of /data/data on Android 7.0+ - Update hide_uid set incrementally when adding/initializing targets - Guard hide_uid set with the same lock as hide_list vector - Do not add GMS package into database; only add to in-memory list
This commit is contained in:
parent
24da3485bd
commit
c66cabd80f
@ -17,8 +17,13 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
vector<string> hide_list;
|
// Protect access to both hide_list and hide_uid
|
||||||
pthread_mutex_t list_lock;
|
pthread_mutex_t list_lock;
|
||||||
|
vector<string> hide_list;
|
||||||
|
set<uid_t> hide_uid;
|
||||||
|
|
||||||
|
// Treat GMS separately as we're only interested in one component
|
||||||
|
int gms_uid = -1;
|
||||||
|
|
||||||
static pthread_t proc_monitor_thread;
|
static pthread_t proc_monitor_thread;
|
||||||
|
|
||||||
@ -157,6 +162,24 @@ static void kill_process(const char *name) {
|
|||||||
*slash = '/';
|
*slash = '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int add_pkg_uid(const char *proc) {
|
||||||
|
char path[4096];
|
||||||
|
struct stat st;
|
||||||
|
const char *data = SDK_INT >= 24 ? "/data/user_de/0" : "/data/data";
|
||||||
|
sprintf(path, "%s/%s", data, proc);
|
||||||
|
if (xstat(path, &st) == 0) {
|
||||||
|
hide_uid.insert(st.st_uid);
|
||||||
|
return st.st_uid;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void refresh_uid() {
|
||||||
|
hide_uid.clear();
|
||||||
|
for (auto &s : hide_list)
|
||||||
|
add_pkg_uid(s.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
void clean_magisk_props() {
|
void clean_magisk_props() {
|
||||||
LOGD("hide_utils: Cleaning magisk props\n");
|
LOGD("hide_utils: Cleaning magisk props\n");
|
||||||
getprop([](const char *name, auto, auto) -> void {
|
getprop([](const char *name, auto, auto) -> void {
|
||||||
@ -167,25 +190,25 @@ void clean_magisk_props() {
|
|||||||
|
|
||||||
int add_list(const char *proc) {
|
int add_list(const char *proc) {
|
||||||
for (auto &s : hide_list) {
|
for (auto &s : hide_list) {
|
||||||
// They should be unique
|
|
||||||
if (s == proc)
|
if (s == proc)
|
||||||
return HIDE_ITEM_EXIST;
|
return HIDE_ITEM_EXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGI("hide_list add: [%s]\n", proc);
|
|
||||||
|
|
||||||
// Add to database
|
// Add to database
|
||||||
char sql[4096];
|
char sql[4096];
|
||||||
snprintf(sql, sizeof(sql), "INSERT INTO hidelist (process) VALUES('%s')", proc);
|
snprintf(sql, sizeof(sql), "INSERT INTO hidelist (process) VALUES('%s')", proc);
|
||||||
char *err = db_exec(sql);
|
char *err = db_exec(sql);
|
||||||
db_err_cmd(err, return DAEMON_ERROR);
|
db_err_cmd(err, return DAEMON_ERROR);
|
||||||
|
|
||||||
|
LOGI("hide_list add: [%s]\n", proc);
|
||||||
|
|
||||||
// Critical region
|
// Critical region
|
||||||
pthread_mutex_lock(&list_lock);
|
pthread_mutex_lock(&list_lock);
|
||||||
hide_list.emplace_back(proc);
|
hide_list.emplace_back(proc);
|
||||||
kill_process(proc);
|
add_pkg_uid(proc);
|
||||||
pthread_mutex_unlock(&list_lock);
|
pthread_mutex_unlock(&list_lock);
|
||||||
|
|
||||||
|
kill_process(proc);
|
||||||
return DAEMON_SUCCESS;
|
return DAEMON_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,29 +216,27 @@ int add_list(int client) {
|
|||||||
char *proc = read_string(client);
|
char *proc = read_string(client);
|
||||||
int ret = add_list(proc);
|
int ret = add_list(proc);
|
||||||
free(proc);
|
free(proc);
|
||||||
|
update_inotify_mask();
|
||||||
// Update inotify list
|
|
||||||
update_apk_list();
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rm_list(const char *proc) {
|
static int rm_list(const char *proc) {
|
||||||
// Update list in critical region
|
// Critical region
|
||||||
bool do_rm = false;
|
bool remove = false;
|
||||||
pthread_mutex_lock(&list_lock);
|
pthread_mutex_lock(&list_lock);
|
||||||
for (auto it = hide_list.begin(); it != hide_list.end(); ++it) {
|
for (auto it = hide_list.begin(); it != hide_list.end(); ++it) {
|
||||||
if (*it == proc) {
|
if (*it == proc) {
|
||||||
do_rm = true;
|
remove = true;
|
||||||
LOGI("hide_list rm: [%s]\n", proc);
|
LOGI("hide_list rm: [%s]\n", proc);
|
||||||
hide_list.erase(it);
|
hide_list.erase(it);
|
||||||
kill_process(proc);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (remove)
|
||||||
|
refresh_uid();
|
||||||
pthread_mutex_unlock(&list_lock);
|
pthread_mutex_unlock(&list_lock);
|
||||||
|
|
||||||
if (do_rm) {
|
if (remove) {
|
||||||
char sql[4096];
|
char sql[4096];
|
||||||
snprintf(sql, sizeof(sql), "DELETE FROM hidelist WHERE process='%s'", proc);
|
snprintf(sql, sizeof(sql), "DELETE FROM hidelist WHERE process='%s'", proc);
|
||||||
char *err = db_exec(sql);
|
char *err = db_exec(sql);
|
||||||
@ -230,26 +251,30 @@ int rm_list(int client) {
|
|||||||
char *proc = read_string(client);
|
char *proc = read_string(client);
|
||||||
int ret = rm_list(proc);
|
int ret = rm_list(proc);
|
||||||
free(proc);
|
free(proc);
|
||||||
|
update_inotify_mask();
|
||||||
// Update inotify list
|
|
||||||
update_apk_list();
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int init_list(void *, int, char **data, char**) {
|
||||||
|
LOGI("hide_list init: [%s]\n", *data);
|
||||||
|
hide_list.emplace_back(*data);
|
||||||
|
kill_process(*data);
|
||||||
|
int uid = add_pkg_uid(*data);
|
||||||
|
if (strcmp(*data, SAFETYNET_PKG) == 0)
|
||||||
|
gms_uid = uid;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_list(const char *proc) {
|
||||||
|
init_list(nullptr, 0, (char **) &proc, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
#define LEGACY_LIST MODULEROOT "/.core/hidelist"
|
#define LEGACY_LIST MODULEROOT "/.core/hidelist"
|
||||||
|
|
||||||
static int collect_list(void *, int, char **data, char**) {
|
|
||||||
LOGI("hide_list: [%s]\n", data[0]);
|
|
||||||
hide_list.push_back(data[0]);
|
|
||||||
kill_process(data[0]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool init_list() {
|
bool init_list() {
|
||||||
LOGD("hide_list: initialize\n");
|
LOGD("hide_list: initialize\n");
|
||||||
|
|
||||||
char *err = db_exec("SELECT process FROM hidelist", collect_list);
|
char *err = db_exec("SELECT process FROM hidelist", init_list);
|
||||||
db_err_cmd(err, return false);
|
db_err_cmd(err, return false);
|
||||||
|
|
||||||
// Migrate old hide list into database
|
// Migrate old hide list into database
|
||||||
@ -260,6 +285,12 @@ bool init_list() {
|
|||||||
unlink(LEGACY_LIST);
|
unlink(LEGACY_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add SafetyNet by default
|
||||||
|
rm_list(SAFETYNET_PROCESS);
|
||||||
|
rm_list(SAFETYNET_COMPONENT);
|
||||||
|
init_list(SAFETYNET_PKG);
|
||||||
|
|
||||||
|
update_inotify_mask();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,11 +331,6 @@ int launch_magiskhide(int client) {
|
|||||||
if (!init_list())
|
if (!init_list())
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
// Add SafetyNet by default
|
|
||||||
rm_list(SAFETYNET_PROCESS);
|
|
||||||
rm_list(SAFETYNET_COMPONENT);
|
|
||||||
add_list(SAFETYNET_PKG);
|
|
||||||
|
|
||||||
// Get thread reference
|
// Get thread reference
|
||||||
proc_monitor_thread = pthread_self();
|
proc_monitor_thread = pthread_self();
|
||||||
if (client >= 0) {
|
if (client >= 0) {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "daemon.h"
|
#include "daemon.h"
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ int rm_list(int client);
|
|||||||
void ls_list(int client);
|
void ls_list(int client);
|
||||||
|
|
||||||
// Update APK list for inotify
|
// Update APK list for inotify
|
||||||
void update_apk_list();
|
void update_inotify_mask();
|
||||||
|
|
||||||
// Process monitor
|
// Process monitor
|
||||||
void proc_monitor();
|
void proc_monitor();
|
||||||
@ -30,14 +31,13 @@ void proc_monitor();
|
|||||||
void manage_selinux();
|
void manage_selinux();
|
||||||
void hide_sensitive_props();
|
void hide_sensitive_props();
|
||||||
void clean_magisk_props();
|
void clean_magisk_props();
|
||||||
|
void refresh_uid();
|
||||||
// List managements
|
|
||||||
int add_list(const char *proc);
|
|
||||||
bool init_list();
|
|
||||||
|
|
||||||
extern bool hide_enabled;
|
extern bool hide_enabled;
|
||||||
extern pthread_mutex_t list_lock;
|
extern pthread_mutex_t list_lock;
|
||||||
extern std::vector<std::string> hide_list;
|
extern std::vector<std::string> hide_list;
|
||||||
|
extern std::set<uid_t> hide_uid;
|
||||||
|
extern int gms_uid;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
LAUNCH_MAGISKHIDE,
|
LAUNCH_MAGISKHIDE,
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <set>
|
|
||||||
|
|
||||||
#include <magisk.h>
|
#include <magisk.h>
|
||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
@ -33,15 +32,21 @@ using namespace std;
|
|||||||
|
|
||||||
extern char *system_block, *vendor_block, *data_block;
|
extern char *system_block, *vendor_block, *data_block;
|
||||||
|
|
||||||
|
static int inotify_fd = -1;
|
||||||
|
|
||||||
#define EVENT_SIZE sizeof(struct inotify_event)
|
#define EVENT_SIZE sizeof(struct inotify_event)
|
||||||
#define EVENT_BUF_LEN (1024 * (EVENT_SIZE + 16))
|
#define EVENT_BUF_LEN (1024 * (EVENT_SIZE + 16))
|
||||||
|
#define __ALIGN_EVENT __attribute__ ((aligned(__alignof__(struct inotify_event))))
|
||||||
|
|
||||||
// Workaround for the lack of pthread_cancel
|
// Workaround for the lack of pthread_cancel
|
||||||
static void term_thread(int) {
|
static void term_thread(int) {
|
||||||
LOGD("proc_monitor: running cleanup\n");
|
LOGD("proc_monitor: running cleanup\n");
|
||||||
hide_list.clear();
|
hide_list.clear();
|
||||||
|
hide_uid.clear();
|
||||||
hide_enabled = false;
|
hide_enabled = false;
|
||||||
pthread_mutex_destroy(&list_lock);
|
pthread_mutex_destroy(&list_lock);
|
||||||
|
close(inotify_fd);
|
||||||
|
inotify_fd = -1;
|
||||||
LOGD("proc_monitor: terminating\n");
|
LOGD("proc_monitor: terminating\n");
|
||||||
pthread_exit(nullptr);
|
pthread_exit(nullptr);
|
||||||
}
|
}
|
||||||
@ -164,21 +169,16 @@ static inline int fast_atoi(const char *str) {
|
|||||||
static DIR *dfd;
|
static DIR *dfd;
|
||||||
// Use unordered map with pid and namespace inode number to avoid time-consuming GC
|
// Use unordered map with pid and namespace inode number to avoid time-consuming GC
|
||||||
static unordered_map<int, uint64_t> pid_ns_map;
|
static unordered_map<int, uint64_t> pid_ns_map;
|
||||||
// Use set for slow insertion but fast searching(which we'd encounter a lot more)
|
|
||||||
static set<uid_t> hide_uid;
|
|
||||||
// Treat GMS separately as we're only interested in one component
|
|
||||||
static int gms_uid = -1;
|
|
||||||
|
|
||||||
static void detect_new_processes() {
|
static void detect_new_processes() {
|
||||||
struct dirent *dp;
|
struct dirent *dp;
|
||||||
struct stat ns, pns;
|
struct stat ns, pns;
|
||||||
int pid, ppid;
|
int pid, ppid;
|
||||||
bool hide;
|
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
unordered_map<int, uint64_t>::const_iterator pos;
|
|
||||||
|
|
||||||
// Iterate through /proc and get a process that reads the target APK
|
// Iterate through /proc and get a process that reads the target APK
|
||||||
rewinddir(dfd);
|
rewinddir(dfd);
|
||||||
|
pthread_mutex_lock(&list_lock);
|
||||||
while ((dp = readdir(dfd))) {
|
while ((dp = readdir(dfd))) {
|
||||||
if (!isdigit(dp->d_name[0]))
|
if (!isdigit(dp->d_name[0]))
|
||||||
continue;
|
continue;
|
||||||
@ -191,23 +191,16 @@ static void detect_new_processes() {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
uid = get_uid(pid) % 100000; // Handle multiuser
|
uid = get_uid(pid) % 100000; // Handle multiuser
|
||||||
if (hide_uid.find(uid) != hide_uid.end()) {
|
bool is_target = hide_uid.count(uid) != 0;
|
||||||
|
if (is_target) {
|
||||||
// Make sure our target is alive
|
// Make sure our target is alive
|
||||||
if ((ppid = parse_ppid(pid)) < 0 || read_ns(ppid, &pns) || read_ns(pid, &ns))
|
if ((ppid = parse_ppid(pid)) < 0 || read_ns(ppid, &pns) || read_ns(pid, &ns))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Check if it's a process we haven't already hijacked
|
// Check if it's a process we haven't already hijacked
|
||||||
hide = false;
|
auto pos = pid_ns_map.find(pid);
|
||||||
pos = pid_ns_map.find(pid);
|
if (pos == pid_ns_map.end() || pos->second != ns.st_ino) {
|
||||||
if (pos == pid_ns_map.end()) {
|
pid_ns_map[pid] = ns.st_ino;
|
||||||
hide = true;
|
|
||||||
pid_ns_map.insert(pair<int, uint64_t>(pid, ns.st_ino));
|
|
||||||
} else if (pos->second != ns.st_ino) {
|
|
||||||
hide = true;
|
|
||||||
pid_ns_map[pos->first] = ns.st_ino;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hide) {
|
|
||||||
if (uid == gms_uid) {
|
if (uid == gms_uid) {
|
||||||
// Check /proc/uid/cmdline to see if it's SAFETYNET_PROCESS
|
// Check /proc/uid/cmdline to see if it's SAFETYNET_PROCESS
|
||||||
if (!is_pid_safetynet_process(pid))
|
if (!is_pid_safetynet_process(pid))
|
||||||
@ -231,9 +224,9 @@ static void detect_new_processes() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock(&list_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int inotify_fd = 0;
|
|
||||||
static void listdir_apk(const char *name) {
|
static void listdir_apk(const char *name) {
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
@ -260,9 +253,9 @@ static void listdir_apk(const char *name) {
|
|||||||
// Compare with (path + 10) to trim "/data/app/"
|
// Compare with (path + 10) to trim "/data/app/"
|
||||||
if (strncmp(path + 10, s.c_str(), s.length()) == 0) {
|
if (strncmp(path + 10, s.c_str(), s.length()) == 0) {
|
||||||
if (inotify_add_watch(inotify_fd, path, IN_OPEN | IN_DELETE) > 0) {
|
if (inotify_add_watch(inotify_fd, path, IN_OPEN | IN_DELETE) > 0) {
|
||||||
LOGI("proc_monitor: Monitoring %s\n", path, inotify_fd);
|
LOGI("proc_monitor: Monitoring %s\n", path);
|
||||||
} else {
|
} else {
|
||||||
LOGE("proc_monitor: Failed to monitor %s: %s\n", strerror(errno));
|
LOGE("proc_monitor: Failed to monitor %s: %s\n", path, strerror(errno));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -275,58 +268,12 @@ static void listdir_apk(const char *name) {
|
|||||||
closedir(dir);
|
closedir(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_pkg_list() {
|
|
||||||
DIR *dir;
|
|
||||||
struct dirent *entry;
|
|
||||||
struct stat st;
|
|
||||||
char path[4096];
|
|
||||||
const char* target;
|
|
||||||
const char data_path[] = "/data/data";
|
|
||||||
|
|
||||||
if (!(dir = opendir(data_path)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&list_lock);
|
|
||||||
for (auto &s : hide_list)
|
|
||||||
LOGD("proc_monitor: hide_list: %s\n", s.c_str());
|
|
||||||
pthread_mutex_unlock(&list_lock);
|
|
||||||
|
|
||||||
hide_uid.clear();
|
|
||||||
|
|
||||||
while ((entry = readdir(dir)) != NULL) {
|
|
||||||
snprintf(path, sizeof(path), "%s/%s", data_path,
|
|
||||||
entry->d_name);
|
|
||||||
|
|
||||||
if (entry->d_type == DT_DIR) {
|
|
||||||
pthread_mutex_lock(&list_lock);
|
|
||||||
for (auto &s : hide_list) {
|
|
||||||
target = s.c_str();
|
|
||||||
if (strcmp(entry->d_name, target) == 0) {
|
|
||||||
if (stat(path, &st) == -1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
LOGI("proc_monitor: %s UID is %d\n", target, st.st_uid);
|
|
||||||
hide_uid.insert(st.st_uid);
|
|
||||||
|
|
||||||
if (strcmp(entry->d_name, SAFETYNET_PKG) == 0) {
|
|
||||||
LOGI("proc_monitor: Got GMS: %d\n", st.st_uid);
|
|
||||||
gms_uid = st.st_uid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&list_lock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate through /data/app and search all .apk files
|
// Iterate through /data/app and search all .apk files
|
||||||
void update_apk_list() {
|
void update_inotify_mask() {
|
||||||
// Setup inotify
|
// Setup inotify
|
||||||
const char data_app[] = "/data/app";
|
const char data_app[] = "/data/app";
|
||||||
|
|
||||||
if (inotify_fd)
|
if (inotify_fd >= 0)
|
||||||
close(inotify_fd);
|
close(inotify_fd);
|
||||||
|
|
||||||
inotify_fd = inotify_init();
|
inotify_fd = inotify_init();
|
||||||
@ -344,9 +291,6 @@ void update_apk_list() {
|
|||||||
} else {
|
} else {
|
||||||
LOGE("proc_monitor: Failed to monitor %s: %s\n", strerror(errno));
|
LOGE("proc_monitor: Failed to monitor %s: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update pkg_uid_map by reading from /data/data
|
|
||||||
update_pkg_list();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void proc_monitor() {
|
void proc_monitor() {
|
||||||
@ -366,8 +310,6 @@ void proc_monitor() {
|
|||||||
term_thread(TERM_THREAD);
|
term_thread(TERM_THREAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
update_apk_list();
|
|
||||||
|
|
||||||
if ((dfd = opendir("/proc")) == NULL) {
|
if ((dfd = opendir("/proc")) == NULL) {
|
||||||
LOGE("proc_monitor: Unable to open /proc\n");
|
LOGE("proc_monitor: Unable to open /proc\n");
|
||||||
term_thread(TERM_THREAD);
|
term_thread(TERM_THREAD);
|
||||||
@ -380,11 +322,11 @@ void proc_monitor() {
|
|||||||
struct inotify_event *event;
|
struct inotify_event *event;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
char *p;
|
char *p;
|
||||||
char buffer[EVENT_BUF_LEN] __attribute__ ((aligned(__alignof__(struct inotify_event))));
|
char buffer[EVENT_BUF_LEN] __ALIGN_EVENT;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
len = read(inotify_fd, buffer, EVENT_BUF_LEN);
|
len = read(inotify_fd, buffer, EVENT_BUF_LEN);
|
||||||
if (len == -1) {
|
if (len == -1) {
|
||||||
LOGE("proc_monitor: failed to read from inotify: %s\n", strerror(errno));
|
PLOGE("proc_monitor: read inotify");
|
||||||
sleep(1);
|
sleep(1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -399,7 +341,10 @@ void proc_monitor() {
|
|||||||
detect_new_processes();
|
detect_new_processes();
|
||||||
} else {
|
} else {
|
||||||
LOGI("proc_monitor: inotify: /data/app change detected\n");
|
LOGI("proc_monitor: inotify: /data/app change detected\n");
|
||||||
update_apk_list();
|
pthread_mutex_lock(&list_lock);
|
||||||
|
refresh_uid();
|
||||||
|
pthread_mutex_unlock(&list_lock);
|
||||||
|
update_inotify_mask();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,7 +385,7 @@ void write_zero(int fd, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vector<string> file_to_vector(const char *filename) {
|
vector<string> file_to_vector(const char *filename) {
|
||||||
auto arr = vector<string>();
|
vector<string> arr;
|
||||||
if (access(filename, R_OK) != 0)
|
if (access(filename, R_OK) != 0)
|
||||||
return arr;
|
return arr;
|
||||||
char *line = nullptr;
|
char *line = nullptr;
|
||||||
|
Loading…
Reference in New Issue
Block a user