1 Star 3 Fork 4

jiftle / minidlna

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
monitor_kqueue.c 7.46 KB
一键复制 编辑 原始数据 按行查看 历史
jiftle 提交于 2018-11-05 15:03 . 导入minidlna 1.2.1代码
/*
* Copyright (c) 2017 Gleb Smirnoff <glebius@FreeBSD.org>
* Copyright (c) 2013 Bernard Spil <brnrd@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/stat.h>
#include <sys/event.h>
#include <limits.h>
#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include "event.h"
#include "log.h"
#include "monitor.h"
#include "minidlnatypes.h"
#include "upnpglobalvars.h"
#include "sql.h"
#include "utils.h"
struct watch {
struct event ev;
const char *path;
bool isdir;
};
static void
dir_vnode_process(struct event *ev, u_int fflags)
{
struct watch *wt;
const char *path;
char *sql, **result, tmp_path[PATH_MAX], *esc_name;
int rows, result_path_len, i;
DIR* d;
struct dirent *entry;
bool found_flag;
wt = (struct watch *)ev->data;
path = wt->path;
if (fflags & NOTE_DELETE) {
DPRINTF(E_DEBUG, L_INOTIFY, "Path [%s] deleted.\n", path);
close(ev->fd);
free(wt);
monitor_remove_directory(0, path);
return;
} else if ((fflags & (NOTE_WRITE | NOTE_LINK)) ==
(NOTE_WRITE | NOTE_LINK)) {
DPRINTF(E_DEBUG, L_INOTIFY, "Directory [%s] content updated\n",
path);
sql = sqlite3_mprintf("SELECT PATH from DETAILS where "
"(PATH > '%q/' and PATH <= '%q/%c') and SIZE IS NULL",
path, path, 0xFF);
DPRINTF(E_DEBUG, L_INOTIFY, "SQL: %s\n", sql);
if ((sql_get_table(db, sql, &result, &rows, NULL) !=
SQLITE_OK)) {
DPRINTF(E_WARN, L_INOTIFY,
"Read state [%s]: Query failed\n", path);
goto err1;
}
for (i = 1; i <= rows; i++) {
DPRINTF(E_DEBUG, L_INOTIFY,
"Indexed content: %s\n", result[i]);
if (access(result[i], R_OK) == -1)
monitor_remove_directory(0, result[i]);
}
if ((d = opendir(path)) == NULL) {
DPRINTF(E_ERROR, L_INOTIFY, "Can't list [%s] (%s)\n",
path, strerror(errno));
goto err2;
}
for (entry = readdir(d); entry != NULL; entry = readdir(d)) {
if ((entry->d_type != DT_DIR) ||
(strcmp(entry->d_name, "..") == 0) ||
(strcmp(entry->d_name, ".") == 0))
continue;
result_path_len = snprintf(tmp_path, PATH_MAX,
"%s/%s", path, entry->d_name);
if (result_path_len >= PATH_MAX) {
DPRINTF(E_ERROR, L_INOTIFY,
"File path too long for %s!",
entry->d_name);
continue;
}
DPRINTF(E_DEBUG, L_INOTIFY, "Walking %s\n", tmp_path);
found_flag = false;
for (i = 1; i <= rows; i++) {
if (strcmp(result[i], tmp_path) == 0) {
found_flag = true;
break;
}
}
if (!found_flag) {
esc_name = strdup(entry->d_name);
if (esc_name == NULL) {
DPRINTF(E_ERROR, L_INOTIFY,
"strdup error");
continue;
}
esc_name = modifyString(esc_name, "&", "&amp;amp;", 0);
monitor_insert_directory(1, esc_name, tmp_path);
free(esc_name);
}
}
} else if (fflags & NOTE_WRITE) {
DPRINTF(E_DEBUG, L_INOTIFY, "File [%s] content updated\n",
path);
sql = sqlite3_mprintf("SELECT PATH from DETAILS where "
"(PATH > '%q/' and PATH <= '%q/%c') and SIZE IS NOT NULL",
path, path, 0xFF);
if (sql_get_table(db, sql, &result, &rows, NULL) != SQLITE_OK) {
DPRINTF(E_WARN, L_INOTIFY,
"Read state [%s]: Query failed\n", path);
goto err1;
}
for (i = 1; i <= rows; i++) {
DPRINTF(E_DEBUG, L_INOTIFY,
"Indexed content: %s\n", result[i]);
if (access(result[i], R_OK) == -1)
monitor_remove_file(result[i]);
}
if ((d = opendir(path)) == NULL) {
DPRINTF(E_ERROR, L_INOTIFY,
"Can't list [%s] (%s)\n", path, strerror(errno));
goto err2;
}
for (entry = readdir(d); entry != NULL; entry = readdir(d)) {
if ((entry->d_type != DT_REG) &&
(entry->d_type != DT_LNK))
continue;
result_path_len = snprintf(tmp_path, PATH_MAX, "%s/%s",
path, entry->d_name);
if (result_path_len >= PATH_MAX) {
DPRINTF(E_ERROR, L_INOTIFY,
"File path too long for %s!",
entry->d_name);
continue;
}
DPRINTF(E_DEBUG, L_INOTIFY, "Walking %s\n", tmp_path);
found_flag = false;
for (i = 1; i <= rows; i++)
if (strcmp(result[i], tmp_path) == 0) {
found_flag = true;
break;
}
if (!found_flag ) {
struct stat st;
if (stat(tmp_path, &st) != 0) {
DPRINTF(E_ERROR, L_INOTIFY,
"stat(%s): %s\n", tmp_path,
strerror(errno));
continue;
}
esc_name = strdup(entry->d_name);
if (esc_name == NULL) {
DPRINTF(E_ERROR, L_INOTIFY,
"strdup error");
continue;
}
esc_name = modifyString(esc_name, "&", "&amp;amp;", 0);
if (S_ISDIR(st.st_mode))
monitor_insert_directory(1, esc_name, tmp_path);
else
monitor_insert_file(esc_name, tmp_path);
free(esc_name);
}
}
} else
return;
closedir(d);
err2:
sqlite3_free_table(result);
err1:
sqlite3_free(sql);
}
int
add_watch(int fd __unused, const char *path)
{
struct watch *wt;
struct event *ev;
int wd;
wd = open(path, O_RDONLY);
if (wd < 0) {
DPRINTF(E_ERROR, L_INOTIFY, "open(%s) [%s]\n",
path, strerror(errno));
return (errno);
}
if ((wt = malloc(sizeof(struct watch))) == NULL) {
DPRINTF(E_ERROR, L_INOTIFY, "malloc() error\n");
close(wd);
return (ENOMEM);
}
if ((wt->path = strdup(path)) == NULL) {
DPRINTF(E_ERROR, L_INOTIFY, "strdup() error\n");
close(wd);
free(wt);
return (ENOMEM);
}
wt->isdir = true;
ev = &wt->ev;
ev->data = wt;
ev->fd = wd;
ev->rdwr = EVENT_VNODE;
ev->process_vnode = dir_vnode_process;
DPRINTF(E_DEBUG, L_INOTIFY, "kqueue add_watch [%s]\n", path);
event_module.add(ev);
return (0);
}
/*
* XXXGL: this function has too much copypaste of inotify_create_watches().
* We need to split out inotify stuff from monitor.c into monitor_inotify.c,
* compile the latter on Linux and this file on FreeBSD, and keep monitor.c
* itself platform independent.
*/
void
kqueue_monitor_start()
{
struct media_dir_s *media_path;
char **result;
int rows, i;
DPRINTF(E_DEBUG, L_INOTIFY, "kqueue monitoring starting\n");
for (media_path = media_dirs; media_path != NULL;
media_path = media_path->next)
add_watch(0, media_path->path);
sql_get_table(db, "SELECT PATH from DETAILS where MIME is NULL and PATH is not NULL", &result, &rows, NULL);
for (i = 1; i <= rows; i++ )
add_watch(0, result[i]);
sqlite3_free_table(result);
}
C
1
https://gitee.com/yctxkj/minidlna.git
git@gitee.com:yctxkj/minidlna.git
yctxkj
minidlna
minidlna
master

搜索帮助