removed BSD special cases
This commit is contained in:
parent
c9a66c4c3d
commit
cf8d14f2aa
|
|
@ -2301,25 +2301,7 @@ psync_set_crtime_mtime(const char *path, time_t crtime, time_t mtime){
|
|||
|
||||
int
|
||||
psync_set_crtime_mtime_by_fd(psync_file_t fd, const char *path, time_t crtime, time_t mtime){
|
||||
#if defined(_BSD_SOURCE) || defined(P_OS_BSD)
|
||||
if (mtime){
|
||||
struct timeval tm[2];
|
||||
tm[0].tv_sec=mtime;
|
||||
tm[0].tv_usec=0;
|
||||
tm[1].tv_sec=mtime;
|
||||
tm[1].tv_usec=0;
|
||||
if (unlikely(futimes(fd, tm))){
|
||||
debug(D_NOTICE, "got errno %d while setting modification time of %s to %lu: %s", errno, path, (unsigned long)mtime, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
#else
|
||||
return psync_set_crtime_mtime(path, crtime, mtime);
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
|
|
|||
|
|
@ -44,8 +44,6 @@ typedef struct{
|
|||
psync_syncid_t syncid;
|
||||
} localnotify_msg;
|
||||
|
||||
#if defined(P_OS_LINUX)
|
||||
|
||||
#include <sys/inotify.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/types.h>
|
||||
|
|
@ -312,313 +310,3 @@ void psync_localnotify_del_sync(psync_syncid_t syncid){
|
|||
debug(D_ERROR, "write to pipe failed");
|
||||
}
|
||||
|
||||
#elif defined(P_OS_BSD)
|
||||
|
||||
/* this implementation only monitors folder changes - it does not catch
|
||||
* file changes (however it does catch deleted and created files).
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/time.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct{
|
||||
psync_list nextfolder;
|
||||
psync_list subfolders;
|
||||
psync_syncid_t syncid;
|
||||
int fd;
|
||||
uint32_t nameoff; /* can also be uint16_t */
|
||||
char path[];
|
||||
} localnotify_dir;
|
||||
|
||||
typedef struct{
|
||||
psync_list list;
|
||||
uint32_t nameoff;
|
||||
char path[];
|
||||
} localnotify_tmpdir;
|
||||
|
||||
static int pipe_read, pipe_write, kevent_fd;
|
||||
static psync_list dirs=PSYNC_LIST_STATIC_INIT(dirs);
|
||||
|
||||
static int sort_dir_by_name(const psync_list *l1, const psync_list *l2){
|
||||
const localnotify_dir *d1=psync_list_element(l1, localnotify_dir, nextfolder);
|
||||
const localnotify_dir *d2=psync_list_element(l2, localnotify_dir, nextfolder);
|
||||
return strcmp(d1->path+d1->nameoff, d2->path+d2->nameoff);
|
||||
}
|
||||
|
||||
static int sort_tdir_by_name(const psync_list *l1, const psync_list *l2){
|
||||
const localnotify_tmpdir *d1=psync_list_element(l1, localnotify_tmpdir, list);
|
||||
const localnotify_tmpdir *d2=psync_list_element(l2, localnotify_tmpdir, list);
|
||||
return strcmp(d1->path+d1->nameoff, d2->path+d2->nameoff);
|
||||
}
|
||||
|
||||
static localnotify_dir *get_dir_scan(const char *path, psync_syncid_t syncid){
|
||||
struct kevent ke;
|
||||
struct timespec ts;
|
||||
localnotify_dir *dir, *child;
|
||||
char *str, *cpath;
|
||||
DIR *dh;
|
||||
struct dirent *de, *entry;
|
||||
size_t len, entrylen;
|
||||
long namelen;
|
||||
struct stat st;
|
||||
len=strlen(path)+1;
|
||||
dir=(localnotify_dir *)psync_malloc(offsetof(localnotify_dir, path)+len);
|
||||
psync_list_init(&dir->subfolders);
|
||||
memcpy(dir->path, path, len);
|
||||
str=strrchr(dir->path, '/');
|
||||
if (str)
|
||||
dir->nameoff=str-dir->path+1;
|
||||
else
|
||||
dir->nameoff=0;
|
||||
dir->syncid=syncid;
|
||||
dir->fd=open(dir->path,
|
||||
#ifdef O_EVTONLY
|
||||
O_EVTONLY
|
||||
#else
|
||||
O_RDONLY
|
||||
#endif
|
||||
);
|
||||
if (unlikely_log(dir->fd==-1))
|
||||
goto err;
|
||||
EV_SET(&ke, dir->fd, EVFILT_VNODE, EV_ADD|EV_CLEAR, NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB, 0, dir);
|
||||
memset(&ts, 0, sizeof(ts));
|
||||
if (unlikely_log(kevent(kevent_fd, &ke, 1, NULL, 0, &ts)==-1))
|
||||
goto err2;
|
||||
namelen=pathconf(path, _PC_NAME_MAX);
|
||||
if (namelen==-1)
|
||||
namelen=255;
|
||||
if (namelen<sizeof(de->d_name)-1)
|
||||
namelen=sizeof(de->d_name)-1;
|
||||
if (likely_log(dh=opendir(path))){
|
||||
entrylen=offsetof(struct dirent, d_name)+namelen+1;
|
||||
cpath=(char *)psync_malloc(len+namelen+1);
|
||||
entry=(struct dirent *)psync_malloc(entrylen);
|
||||
len--;
|
||||
memcpy(cpath, path, len);
|
||||
if (!len || cpath[len-1]!=PSYNC_DIRECTORY_SEPARATORC)
|
||||
cpath[len++]=PSYNC_DIRECTORY_SEPARATORC;
|
||||
while (!readdir_r(dh, entry, &de) && de)
|
||||
if (de->d_name[0]!='.' || (de->d_name[1]!=0 && (de->d_name[1]!='.' || de->d_name[2]!=0))){
|
||||
psync_strlcpy(cpath+len, de->d_name, namelen+1);
|
||||
if (!lstat(cpath, &st) && S_ISDIR(st.st_mode)){
|
||||
child=get_dir_scan(cpath, syncid);
|
||||
if (child)
|
||||
psync_list_add_tail(&dir->subfolders, &child->nextfolder);
|
||||
}
|
||||
}
|
||||
psync_free(entry);
|
||||
psync_free(cpath);
|
||||
closedir(dh);
|
||||
}
|
||||
psync_list_sort(&dir->subfolders, sort_dir_by_name);
|
||||
return dir;
|
||||
err2:
|
||||
close(dir->fd);
|
||||
err:
|
||||
psync_free(dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void add_syncid(psync_syncid_t syncid){
|
||||
psync_sql_res *res;
|
||||
psync_str_row row;
|
||||
char *str;
|
||||
localnotify_dir *dir;
|
||||
res=psync_sql_query("SELECT localpath FROM syncfolder WHERE id=?");
|
||||
psync_sql_bind_uint(res, 1, syncid);
|
||||
if (likely(row=psync_sql_fetch_rowstr(res))){
|
||||
str=psync_strdup(row[0]);
|
||||
psync_sql_free_result(res);
|
||||
}
|
||||
else{
|
||||
psync_sql_free_result(res);
|
||||
debug(D_ERROR, "could not find syncfolder with id %u", (unsigned int)syncid);
|
||||
return;
|
||||
}
|
||||
dir=get_dir_scan(str, syncid);
|
||||
if (!dir)
|
||||
debug(D_ERROR, "could not scan folder %s", str);
|
||||
psync_free(str);
|
||||
if (dir)
|
||||
psync_list_add_tail(&dirs, &dir->nextfolder);
|
||||
}
|
||||
|
||||
static void free_dir(localnotify_dir *dir){
|
||||
psync_list *e, *b;
|
||||
psync_list_for_each_safe(e, b, &dir->subfolders)
|
||||
free_dir(psync_list_element(e, localnotify_dir, nextfolder));
|
||||
close(dir->fd);
|
||||
psync_free(dir);
|
||||
}
|
||||
|
||||
static void del_syncid(psync_syncid_t syncid){
|
||||
psync_list *e;
|
||||
localnotify_dir *dir;
|
||||
psync_list_for_each(e, &dirs){
|
||||
dir=psync_list_element(e, localnotify_dir, nextfolder);
|
||||
if (dir->syncid==syncid){
|
||||
psync_list_del(e);
|
||||
free_dir(dir);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void process_pipe(){
|
||||
localnotify_msg msg;
|
||||
if (read(pipe_read, &msg, sizeof(msg))!=sizeof(msg)){
|
||||
debug(D_ERROR, "read from pipe failed");
|
||||
return;
|
||||
}
|
||||
if (msg.type==NOTIFY_MSG_ADD)
|
||||
add_syncid(msg.syncid);
|
||||
else if (msg.type==NOTIFY_MSG_DEL)
|
||||
del_syncid(msg.syncid);
|
||||
else
|
||||
debug(D_ERROR, "invalid message type %u", (unsigned int)msg.type);
|
||||
}
|
||||
|
||||
static void process_notification(localnotify_dir *dir){
|
||||
DIR *dh;
|
||||
char *cpath;
|
||||
struct dirent *de, *entry;
|
||||
localnotify_tmpdir *tdir;
|
||||
localnotify_dir *cdir;
|
||||
psync_list tlist;
|
||||
psync_list *l1, *l2;
|
||||
size_t len, len2, entrylen;
|
||||
long namelen;
|
||||
struct stat st;
|
||||
int cmp;
|
||||
debug(D_NOTICE, "got notification for folder %s", dir->path);
|
||||
dh=opendir(dir->path);
|
||||
if (unlikely_log(!dh)){
|
||||
psync_list_del(&dir->nextfolder);
|
||||
free_dir(dir);
|
||||
return;
|
||||
}
|
||||
len=strlen(dir->path);
|
||||
namelen=pathconf(dir->path, _PC_NAME_MAX);
|
||||
if (namelen==-1)
|
||||
namelen=255;
|
||||
entrylen=offsetof(struct dirent, d_name)+namelen+1;
|
||||
cpath=(char *)psync_malloc(len+namelen+2);
|
||||
entry=(struct dirent *)psync_malloc(entrylen);
|
||||
memcpy(cpath, dir->path, len);
|
||||
if (!len || cpath[len-1]!=PSYNC_DIRECTORY_SEPARATORC)
|
||||
cpath[len++]=PSYNC_DIRECTORY_SEPARATORC;
|
||||
psync_list_init(&tlist);
|
||||
while (!readdir_r(dh, entry, &de) && de)
|
||||
if (de->d_name[0]!='.' || (de->d_name[1]!=0 && (de->d_name[1]!='.' || de->d_name[2]!=0))){
|
||||
len2=strlen(de->d_name);
|
||||
memcpy(cpath+len, de->d_name, len2+1);
|
||||
if (!lstat(cpath, &st) && S_ISDIR(st.st_mode)){
|
||||
tdir=(localnotify_tmpdir *)psync_malloc(offsetof(localnotify_tmpdir, path)+len+len2+1);
|
||||
tdir->nameoff=len;
|
||||
memcpy(tdir->path, cpath, len+len2+1);
|
||||
psync_list_add_tail(&tlist, &tdir->list);
|
||||
}
|
||||
}
|
||||
psync_free(entry);
|
||||
psync_free(cpath);
|
||||
closedir(dh);
|
||||
psync_list_sort(&tlist, sort_tdir_by_name);
|
||||
l1=dir->subfolders.next;
|
||||
l2=tlist.next;
|
||||
while (l1!=&dir->subfolders && l2!=&tlist){
|
||||
cdir=psync_list_element(l1, localnotify_dir, nextfolder);
|
||||
tdir=psync_list_element(l2, localnotify_tmpdir, list);
|
||||
cmp=strcmp(cdir->path+cdir->nameoff, tdir->path+tdir->nameoff);
|
||||
if (cmp==0){
|
||||
l1=l1->next;
|
||||
l2=l2->next;
|
||||
}
|
||||
else if (cmp<0){ /* deleted folder */
|
||||
l1=l1->next;
|
||||
psync_list_del(&cdir->nextfolder);
|
||||
free_dir(cdir);
|
||||
}
|
||||
else{
|
||||
l2=l2->next;
|
||||
cdir=get_dir_scan(tdir->path, dir->syncid);
|
||||
if (cdir)
|
||||
psync_list_add_between(l1->prev, l1, &cdir->nextfolder);
|
||||
}
|
||||
}
|
||||
psync_list_for_each_element_call(&tlist, localnotify_tmpdir, list, psync_free);
|
||||
psync_wake_localscan();
|
||||
}
|
||||
|
||||
static void psync_localnotify_thread(){
|
||||
struct kevent ke;
|
||||
while (psync_do_run){
|
||||
if (unlikely_log(kevent(kevent_fd, NULL, 0, &ke, 1, NULL)!=1))
|
||||
continue;
|
||||
if (ke.udata)
|
||||
process_notification((localnotify_dir *)ke.udata);
|
||||
else
|
||||
process_pipe();
|
||||
}
|
||||
}
|
||||
|
||||
int psync_localnotify_init(){
|
||||
struct kevent ke;
|
||||
struct timespec ts;
|
||||
int pfd[2];
|
||||
if (unlikely_log(pipe(pfd)))
|
||||
goto err0;
|
||||
pipe_read=pfd[0];
|
||||
pipe_write=pfd[1];
|
||||
kevent_fd=kqueue();
|
||||
if (unlikely_log(kevent_fd==-1))
|
||||
goto err1;
|
||||
EV_SET(&ke, pipe_read, EVFILT_READ, EV_ADD|EV_CLEAR, 0, 0, 0);
|
||||
memset(&ts, 0, sizeof(ts));
|
||||
if (unlikely_log(kevent(kevent_fd, &ke, 1, NULL, 0, &ts)==-1))
|
||||
goto err2;
|
||||
psync_run_thread("localnotify", psync_localnotify_thread);
|
||||
/* return -1 so we still run frequent rescans */
|
||||
return -1;
|
||||
err2:
|
||||
close(kevent_fd);
|
||||
err1:
|
||||
close(pfd[0]);
|
||||
close(pfd[1]);
|
||||
err0:
|
||||
pipe_read=pipe_write=-1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void psync_localnotify_add_sync(psync_syncid_t syncid){
|
||||
localnotify_msg msg;
|
||||
msg.type=NOTIFY_MSG_ADD;
|
||||
msg.syncid=syncid;
|
||||
if (write(pipe_write, &msg, sizeof(msg))!=sizeof(msg))
|
||||
debug(D_ERROR, "write to pipe failed");
|
||||
}
|
||||
|
||||
void psync_localnotify_del_sync(psync_syncid_t syncid){
|
||||
localnotify_msg msg;
|
||||
msg.type=NOTIFY_MSG_DEL;
|
||||
msg.syncid=syncid;
|
||||
if (write(pipe_write, &msg, sizeof(msg))!=sizeof(msg))
|
||||
debug(D_ERROR, "write to pipe failed");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int psync_localnotify_init(){
|
||||
return -1;
|
||||
}
|
||||
|
||||
void psync_localnotify_add_sync(psync_syncid_t syncid){
|
||||
}
|
||||
|
||||
void psync_localnotify_del_sync(psync_syncid_t syncid){
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@
|
|||
#include "pcompat.h"
|
||||
#include "plibs.h"
|
||||
|
||||
#if defined(P_OS_LINUX) || defined(P_OS_BSD)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
|
@ -133,4 +131,3 @@ void instance_thread(void* lpvParam)
|
|||
return;
|
||||
};
|
||||
|
||||
#endif //defined(P_OS_LINUX) || defined(P_OS_BSD)
|
||||
|
|
|
|||
Loading…
Reference in New Issue