common.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /*
  2. clsync - file tree sync utility based on fanotify and inotify
  3. Copyright (C) 2013 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #define _GNU_SOURCE
  16. #define _XOPEN_SOURCE 700
  17. #define _LARGEFILE64_SOURCE
  18. #define PROGRAM "clsync"
  19. #define VERSION_MAJ 0
  20. #define VERSION_MIN 1
  21. #define AUTHOR "Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C"
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <stdint.h>
  25. #include <string.h>
  26. #include <strings.h>
  27. #include <unistd.h>
  28. #include <getopt.h>
  29. #include <limits.h>
  30. #include <stdarg.h>
  31. #include <sys/types.h>
  32. #include <sys/stat.h>
  33. #include <fcntl.h>
  34. #include <sys/mman.h>
  35. #include <errno.h>
  36. #include <ctype.h>
  37. #include <regex.h>
  38. #include <signal.h>
  39. #include <wait.h>
  40. #include <fts.h>
  41. #ifdef FANOTIFY_SUPPORT
  42. #include <sys/fanotify.h>
  43. #endif
  44. #include <sys/inotify.h>
  45. #include <sys/time.h>
  46. #include <dirent.h>
  47. #include <glib.h>
  48. #include <sys/utsname.h>
  49. #include <sys/types.h>
  50. #include <sys/socket.h>
  51. #include <arpa/inet.h>
  52. #include <netinet/in.h>
  53. #include <libgen.h>
  54. #include <pthread.h>
  55. #ifdef HAVE_CAPABILITIES
  56. #include <sys/capability.h> // for capset()/capget() for --preserve-file-access
  57. #include <sys/prctl.h> // for prctl() for --preserve-fil-access
  58. #endif
  59. #include "configuration.h"
  60. #ifdef HAVE_CONFIG_H
  61. #include "config.h"
  62. #endif
  63. #ifndef MIN
  64. #define MIN(a,b) ((a)>(b)?(b):(a))
  65. #endif
  66. #ifndef MAX
  67. #define MAX(a,b) ((a)>(b)?(a):(b))
  68. #endif
  69. #ifndef IN_CREATE_SELF
  70. #define IN_CREATE_SELF IN_CREATE
  71. #endif
  72. #ifdef _DEBUG
  73. #define DEBUGV(...) __VA_ARGS__
  74. #else
  75. #define DEBUGV(...)
  76. #endif
  77. #ifdef PARANOID
  78. #define PARANOIDV(...) __VA_ARGS__
  79. #else
  80. #define PARANOIDV(...)
  81. #endif
  82. #define TOSTR(a) # a
  83. #define XTOSTR(a) TOSTR(a)
  84. #define COLLECTDELAY_INSTANT ((unsigned int)~0)
  85. #define OPTION_CONFIGONLY (1<<8)
  86. enum flags_enum {
  87. HELP = 'h',
  88. CONFIGPATH = 'H',
  89. CONFIGBLOCK = 'K',
  90. BACKGROUND = 'b',
  91. UID = 'u',
  92. GID = 'g',
  93. CAP_PRESERVE_FILEACCESS = 'C',
  94. PTHREAD = 'p',
  95. SYSLOG = 'Y',
  96. PIDFILE = 'z',
  97. #ifdef CLUSTER_SUPPORT
  98. CLUSTERIFACE = 'c',
  99. CLUSTERMCASTIPADDR = 'm',
  100. CLUSTERMCASTIPPORT = 'P',
  101. CLUSTERTIMEOUT = 'W',
  102. CLUSTERNODENAME = 'n',
  103. CLUSTERHDLMIN = 'o',
  104. CLUSTERHDLMAX = 'O',
  105. CLUSTERSDLMAX = 's',
  106. #endif
  107. DELAY = 't',
  108. BFILEDELAY = 'T',
  109. SYNCDELAY = 'w',
  110. BFILETHRESHOLD = 'B',
  111. DEBUG = 'D',
  112. QUIET = 'q',
  113. VERBOSE = 'v',
  114. OUTLISTSDIR = 'd',
  115. ENABLEINITIALSYNC = 'S',
  116. SYNCLISTSIMPLIFY= 'Z',
  117. AUTORULESW = 'A',
  118. SYNCHANDLERSO = 'M',
  119. RSYNC = 'R',
  120. RSYNCINCLIMIT = 'L',
  121. RSYNC_PREFERINCLUDE= 'I',
  122. IGNOREEXITCODE = 'x',
  123. DONTUNLINK = 'U',
  124. INITFULL = 'F',
  125. SYNCTIMEOUT = 'k',
  126. #ifdef FANOTIFY_SUPPORT
  127. FANOTIFY = 'f',
  128. #endif
  129. INOTIFY = 'i',
  130. LABEL = 'l',
  131. SHOW_VERSION = 'V',
  132. WATCHDIR = 0|OPTION_CONFIGONLY,
  133. SYNCHANDLER = 1|OPTION_CONFIGONLY,
  134. RULESPATH = 2|OPTION_CONFIGONLY,
  135. DESTDIR = 3|OPTION_CONFIGONLY,
  136. };
  137. typedef enum flags_enum flags_t;
  138. enum queue_enum {
  139. QUEUE_NORMAL,
  140. QUEUE_BIGFILE,
  141. QUEUE_INSTANT,
  142. QUEUE_MAX,
  143. QUEUE_AUTO
  144. };
  145. typedef enum queue_enum queue_id_t;
  146. enum ruleactionsign_enum {
  147. RS_REJECT = 0,
  148. RS_PERMIT = 1
  149. };
  150. typedef enum ruleactionsign_enum ruleactionsign_t;
  151. enum ruleaction_enum {
  152. RA_NONE = 0x00,
  153. RA_MONITOR = 0x01,
  154. RA_WALK = 0x02,
  155. RA_ALL = 0xff
  156. };
  157. typedef enum ruleaction_enum ruleaction_t;
  158. enum paramsource_enum {
  159. PS_UNKNOWN = 0,
  160. PS_ARGUMENT,
  161. PS_CONFIG
  162. };
  163. typedef enum paramsource_enum paramsource_t;
  164. // signals (man 7 signal)
  165. enum sigusr_enum {
  166. SIGUSR_PTHREAD_GC = 10,
  167. SIGUSR_INITSYNC = 12,
  168. SIGUSR_BLOPINT = 16
  169. };
  170. struct rule {
  171. int num;
  172. regex_t expr;
  173. mode_t objtype;
  174. ruleaction_t perm;
  175. ruleaction_t mask;
  176. };
  177. typedef struct rule rule_t;
  178. struct queueinfo {
  179. unsigned int collectdelay;
  180. time_t stime;
  181. };
  182. typedef struct queueinfo queueinfo_t;
  183. struct api_eventinfo {
  184. uint32_t evmask;
  185. uint32_t flags;
  186. size_t path_len;
  187. const char *path;
  188. };
  189. typedef struct api_eventinfo api_eventinfo_t;
  190. struct options;
  191. struct indexes;
  192. typedef int(*api_funct_init) (struct options *, struct indexes *);
  193. typedef int(*api_funct_sync) (int n, api_eventinfo_t *);
  194. typedef int(*api_funct_deinit)();
  195. struct api_functs {
  196. api_funct_init init;
  197. api_funct_sync sync;
  198. api_funct_deinit deinit;
  199. };
  200. typedef struct api_functs api_functs_t;
  201. struct options {
  202. uid_t uid;
  203. gid_t gid;
  204. rule_t rules[MAXRULES];
  205. int flags[1<<10];
  206. int flags_set[1<<10];
  207. char *config_path;
  208. char *config_block;
  209. char *label;
  210. char *watchdir;
  211. char *pidfile;
  212. char *destdir;
  213. char *watchdirwslash;
  214. char *destdirwslash;
  215. #ifdef CLUSTER_SUPPORT
  216. char *cluster_iface;
  217. char *cluster_mcastipaddr;
  218. char *cluster_nodename;
  219. uint32_t cluster_nodename_len;
  220. uint16_t cluster_mcastipport;
  221. uint16_t cluster_hash_dl_min;
  222. uint16_t cluster_hash_dl_max;
  223. uint16_t cluster_scan_dl_max;
  224. unsigned int cluster_timeout;
  225. #endif
  226. size_t watchdirlen;
  227. size_t destdirlen;
  228. size_t watchdirsize;
  229. size_t destdirsize;
  230. size_t watchdirwslashsize;
  231. size_t destdirwslashsize;
  232. short int watchdir_dirlevel;
  233. char *handlerfpath;
  234. void *handler_handle;
  235. api_functs_t handler_funct;
  236. char *rulfpath;
  237. char *listoutdir;
  238. int notifyengine;
  239. size_t bfilethreshold;
  240. unsigned int syncdelay;
  241. queueinfo_t _queues[QUEUE_MAX]; // TODO: remove this from here
  242. unsigned int rsyncinclimit;
  243. time_t synctime;
  244. unsigned int synctimeout;
  245. sigset_t *sigset;
  246. char isignoredexitcode[(1<<8)];
  247. };
  248. typedef struct options options_t;
  249. enum notifyengine_enum {
  250. NE_UNDEFINED = 0,
  251. #ifdef FANOTIFY_SUPPORT
  252. NE_FANOTIFY,
  253. #endif
  254. NE_INOTIFY
  255. };
  256. typedef enum notifyengine_enum notifyenfine_t;
  257. #define STATE_STARTING(state_p) (state_p == NULL)
  258. enum state_enum {
  259. STATE_EXIT = 0,
  260. STATE_RUNNING,
  261. STATE_REHASH,
  262. STATE_TERM,
  263. STATE_PTHREAD_GC,
  264. STATE_INITSYNC
  265. };
  266. typedef enum state_enum state_t;
  267. enum eventinfo_flags {
  268. EVIF_RECURSIVELY = 0x00000001
  269. };
  270. struct eventinfo {
  271. uint32_t evmask;
  272. int wd;
  273. size_t fsize;
  274. uint32_t flags;
  275. };
  276. typedef struct eventinfo eventinfo_t;
  277. struct indexes {
  278. GHashTable *wd2fpath_ht; // watching descriptor -> file path
  279. GHashTable *fpath2wd_ht; // file path -> watching descriptor
  280. GHashTable *fpath2ei_ht; // file path -> event information
  281. GHashTable *exc_fpath_ht; // excluded file path
  282. GHashTable *exc_fpath_coll_ht[QUEUE_MAX]; // excluded file path aggregation hashtable for every queue
  283. GHashTable *fpath2ei_coll_ht[QUEUE_MAX]; // "file path -> event information" aggregation hashtable for every queue
  284. GHashTable *out_lines_aggr_ht; // output lines aggregation hashtable
  285. };
  286. typedef struct indexes indexes_t;
  287. typedef int (*thread_callbackfunct_t)(options_t *options_p, char **argv);
  288. struct threadinfo {
  289. int thread_num;
  290. thread_callbackfunct_t callback;
  291. char **argv;
  292. pthread_t pthread;
  293. int exitcode;
  294. int errcode;
  295. state_t state;
  296. options_t *options_p;
  297. time_t starttime;
  298. time_t expiretime;
  299. int child_pid;
  300. // for so-synchandler
  301. int n;
  302. api_eventinfo_t *ei;
  303. };
  304. typedef struct threadinfo threadinfo_t;
  305. enum pthread_mutex_id {
  306. PTHREAD_MUTEX_STATE,
  307. PTHREAD_MUTEX_MAX
  308. };
  309. struct threadsinfo {
  310. pthread_mutex_t mutex[PTHREAD_MUTEX_MAX];
  311. pthread_cond_t cond [PTHREAD_MUTEX_MAX];
  312. char mutex_init;
  313. int allocated;
  314. int used;
  315. threadinfo_t *threads;
  316. threadinfo_t **threadsstack; // stack of threadinfo_t to be used on thread_new()
  317. int stacklen;
  318. };
  319. typedef struct threadsinfo threadsinfo_t;
  320. struct dosync_arg {
  321. int evcount;
  322. char excf_path[PATH_MAX+1];
  323. char outf_path[PATH_MAX+1];
  324. FILE *outf;
  325. options_t *options_p;
  326. indexes_t *indexes_p;
  327. void *data;
  328. int linescount;
  329. api_eventinfo_t *api_ei;
  330. int api_ei_count;
  331. char buf[BUFSIZ+1];
  332. };
  333. struct doubleentry {
  334. size_t size0;
  335. size_t size1;
  336. size_t alloc0;
  337. size_t alloc1;
  338. void *dat0;
  339. void *dat1;
  340. };
  341. struct pushdoubleentry_arg {
  342. int allocated;
  343. int total;
  344. size_t size;
  345. struct doubleentry *entry;
  346. };
  347. struct entry {
  348. size_t size;
  349. size_t alloc;
  350. void *dat;
  351. };
  352. struct pushentry_arg {
  353. int allocated;
  354. int total;
  355. size_t size;
  356. struct entry *entry;
  357. };
  358. enum initsync {
  359. INITSYNC_UNKNOWN = 0,
  360. INITSYNC_FULL,
  361. INITSYNC_SUBDIR
  362. };
  363. typedef enum initsync initsync_t;
  364. struct sighandler_arg {
  365. // options_t *options_p;
  366. // indexes_t *indexes_p;
  367. pthread_t pthread_parent;
  368. int *exitcode_p;
  369. sigset_t *sigset_p;
  370. };
  371. typedef struct sighandler_arg sighandler_arg_t;