redmine

Finished basic socket support

... ... @@ -13,6 +13,16 @@
// clsync should be used, if there's more than 5-10 nodes. So the limit in 255 is quite enough. :)
#define MAXNODES ((1<<8)-1)
// max user/group lengths
#define USER_LEN (1<<8)
#define GROUP_LEN USER_LEN
// control socket listen backlog (man 2 listen)
#define SOCKET_BACKLOG 2
// control socket clients limit
#define SOCKET_CLIENTS_MAX 8
// children count limit
#define MAXCHILDREN (1<<8)
... ...
... ... @@ -26,6 +26,14 @@ AS_IF([test "x$enable_cluster" = "xyes"], [CPPFLAGS+=" -DCLUSTER_SUPPORT"
])
])
dnl --enable-socket
AC_ARG_ENABLE(socket,
AS_HELP_STRING(--enable-socket,
[enable control socket support, default: no]))
AS_IF([test "x$enable_socket" = "xyes"],
[CPPFLAGS+=" -DENABLE_SOCKET"])
dnl --enable-debug
AC_ARG_ENABLE(debug,
AS_HELP_STRING(--enable-debug,
... ...
... ... @@ -19,12 +19,15 @@
#include "common.h"
#include <pwd.h> // For getpwnam()
#include <grp.h> // For getgrnam()
#include "output.h"
#include "sync.h"
#include "malloc.h"
#include "cluster.h"
#include "fileutils.h"
#include "socket.h"
#include "revision.h"
... ... @@ -36,6 +39,9 @@ static const struct option long_options[] =
{"destination-dir", required_argument, NULL, DESTDIR},
{"mode", required_argument, NULL, MODE},
{"socket", required_argument, NULL, SOCKETPATH},
{"socket-auth", required_argument, NULL, SOCKETAUTH},
{"socket-mod", required_argument, NULL, SOCKETMOD},
{"socket-own", required_argument, NULL, SOCKETOWN},
{"status-file", required_argument, NULL, STATUSFILE},
{"background", optional_argument, NULL, BACKGROUND},
... ... @@ -95,6 +101,13 @@ static const struct option long_options[] =
{NULL, 0, NULL, 0}
};
static char *const socketauth[] = {
[SOCKAUTH_UNSET] = "",
[SOCKAUTH_NULL] = "null",
// [SOCKAUTH_PAM] = "pam",
NULL
};
static char *const modes[] = {
[MODE_UNSET] = "",
[MODE_SIMPLE] = "simple",
... ... @@ -140,7 +153,7 @@ int clsyncapi_getapiversion() {
return CLSYNC_API_VERSION;
}
static inline int parse_parameter(options_t *options_p, uint16_t param_id, char *arg, paramsource_t paramsource) {
int parse_parameter(options_t *options_p, uint16_t param_id, char *arg, paramsource_t paramsource) {
#ifdef _DEBUG
fprintf(stderr, "Force-Debug: parse_parameter(): %i: %i = \"%s\"\n", paramsource, param_id, arg);
#endif
... ... @@ -308,6 +321,76 @@ static inline int parse_parameter(options_t *options_p, uint16_t param_id, char
case SOCKETPATH:
options_p->socketpath = arg;
break;
case SOCKETAUTH: {
char *value;
options_p->flags[SOCKETAUTH] = getsubopt(&arg, modes, &value);
if(options_p->flags[SOCKETAUTH] == -1) {
printf_e("Error: Wrong socket auth mech entered: \"%s\"\n", arg);
return EINVAL;
}
}
case SOCKETMOD:
if(!sscanf(arg, "%o", &options_p->socketmod)) {
printf_e("Error: Non octal value passed to --socket-mod: \"%s\"\n", arg);
return EINVAL;
}
options_p->flags[param_id]++;
break;
case SOCKETOWN: {
char *colon = strchr(arg, ':');
uid_t uid;
gid_t gid;
if(colon == NULL) {
struct passwd *pwent = getpwnam(arg);
if(pwent == NULL) {
printf_e("Error: Cannot find username \"%s\" (case #0): %s (errno: %i)\n",
arg, strerror(errno), errno);
return EINVAL;
}
uid = pwent->pw_uid;
gid = pwent->pw_gid;
} else {
char user[USER_LEN+2], group[GROUP_LEN+2];
memcpy(user, arg, MIN(USER_LEN, colon-arg));
user[colon-arg] = 0;
strncpy(group, &colon[1], GROUP_LEN);
errno=0;
struct passwd *pwent = getpwnam(user);
if(pwent == NULL) {
printf_e("Error: Cannot find username \"%s\" (case #1): %s (errno: %i)\n",
user, strerror(errno), errno);
return EINVAL;
}
errno=0;
struct group *grent = getgrnam(group);
if(grent == NULL) {
printf_e("Error: Cannot find group \"%s\": %s (errno: %i)\n",
group, strerror(errno), errno);
return EINVAL;
}
uid = pwent->pw_uid;
gid = grent->gr_gid;
}
options_p->socketuid = uid;
options_p->socketgid = gid;
options_p->flags[param_id]++;
printf_dd("Debug2: socket: uid == %u; gid == %u\n", uid, gid);
break;
}
case STATUSFILE:
options_p->statusfile = arg;
break;
... ... @@ -886,7 +969,8 @@ int main(int argc, char *argv[]) {
options.config_block = DEFAULT_CONFIG_BLOCK;
options.retries = DEFAULT_RETRIES;
arguments_parse(argc, argv, &options);
nret = arguments_parse(argc, argv, &options);
if(nret) ret = nret;
out_init(options.flags);
nret = configs_parse(&options);
if(nret) ret = nret;
... ... @@ -894,6 +978,30 @@ int main(int argc, char *argv[]) {
main_status_update(&options, STATE_STARTING);
if(options.socketpath != NULL) {
#ifndef ENABLE_SOCKET
printf_e("Error: clsync is compiled without control socket support, option \"--socket\" cannot be used.\n");
ret = EINVAL;
#endif
if(options.flags[SOCKETAUTH] == SOCKAUTH_UNSET)
options.flags[SOCKETAUTH] = SOCKAUTH_NULL;
}
if((options.flags[SOCKETOWN]) && (options.socketpath == NULL)) {
printf_e("Error: \"--socket-own\" is useless without \"--socket\"");
ret = EINVAL;
}
if((options.flags[SOCKETMOD]) && (options.socketpath == NULL)) {
printf_e("Error: \"--socket-mod\" is useless without \"--socket\"");
ret = EINVAL;
}
if((options.flags[SOCKETAUTH]) && (options.socketpath == NULL)) {
printf_e("Error: \"--socket-auth\" is useless without \"--socket\"");
ret = EINVAL;
}
#ifdef VERYPARANOID
if((options.retries != 1) && options.flags[PTHREAD]) {
printf_e("Error: \"--retries\" values should be equal to \"1\" for \"--pthread\" mode.\n");
... ... @@ -1362,19 +1470,11 @@ preserve_fileaccess_end:
printf_ddd("Debug3: main(): Current errno is %i.\n", ret);
if(ret == 0)
if(options.socketpath != NULL)
ret = socket_run(&options);
if(ret == 0) {
// == RUNNING ==
// == RUNNING ==
if(ret == 0)
ret = sync_run(&options);
// == RUNNING ==
if(options.socketpath != NULL)
socket_cleanup(&options);
}
// == RUNNING ==
if(options.pidfile != NULL) {
if(unlink(options.pidfile)) {
... ...
... ... @@ -82,9 +82,20 @@ enum flags_enum {
EXITONNOEVENTS = 8|OPTION_LONGOPTONLY,
STANDBYFILE = 9|OPTION_LONGOPTONLY,
EXITHOOK = 10|OPTION_LONGOPTONLY,
SOCKETAUTH = 12|OPTION_LONGOPTONLY,
SOCKETMOD = 13|OPTION_LONGOPTONLY,
SOCKETOWN = 14|OPTION_LONGOPTONLY,
};
typedef enum flags_enum flags_t;
enum sockauth_id {
SOCKAUTH_UNSET = 0,
SOCKAUTH_NULL,
SOCKAUTH_PAM,
};
typedef enum sockauth_id sockauth_id_t;
enum mode_id {
MODE_UNSET = 0,
MODE_SIMPLE,
... ... @@ -171,6 +182,9 @@ struct options {
char *statusfile;
char *socketpath;
int socket;
mode_t socketmod;
uid_t socketuid;
gid_t socketgid;
#ifdef CLUSTER_SUPPORT
char *cluster_iface;
char *cluster_mcastipaddr;
... ...
... ... @@ -28,7 +28,7 @@ printf_funct _printf_ddd=NULL;
printf_funct _printf_dd=NULL;
printf_funct _printf_d=NULL;
printf_funct _printf_v=NULL;
printf_funct printf_e=NULL;
printf_funct printf_e=printf_stderr;
write_funct _write_ddd=NULL;
write_funct _write_dd=NULL;
write_funct _write_d=NULL;
... ...
This diff is collapsed. Click to expand it.
... ... @@ -26,6 +26,7 @@
#include "cluster.h"
#include "sync.h"
#include "glibex.h"
#include "socket.h"
#include <dlfcn.h>
... ... @@ -1870,7 +1871,7 @@ int sync_idle_dosync_collectedevents_uniqfname(options_t *options_p, char *fpath
lstat64(fpath, &stat64);
if(counter++ > COUNTER_LIMIT) {
printf_e("Error: Cannot file unused filename for list-file. The last try was \"%s\".\n", fpath);
return ELOOP;
return ENOENT;
}
} while(errno != ENOENT); // TODO: find another way to check if the object exists
errno=0;
... ... @@ -2850,6 +2851,8 @@ int sync_inotify_loop(int inotify_d, options_t *options_p, indexes_t *indexes_p)
}
SYNC_INOTIFY_LOOP_IDLE;
printf_d("Debug: sync_inotify_loop(): end\n");
return exitcode;
#ifdef DOXYGEN
... ... @@ -3044,7 +3047,6 @@ int sync_run(options_t *options_p) {
int ret, i;
sighandler_arg_t sighandler_arg = {0};
// Creating signal handler thread
sigset_t sigset_sighandler;
sigemptyset(&sigset_sighandler);
... ... @@ -3185,6 +3187,12 @@ int sync_run(options_t *options_p) {
int notify_d=0;
#ifdef ENABLE_SOCKET
// Creating control socket
if(options_p->socketpath != NULL)
ret = socket_run(options_p);
#endif
if(!options_p->flags[ONLYINITSYNC]) {
// Initializing FS monitor kernel subsystem in this userspace application
... ... @@ -3201,7 +3209,15 @@ int sync_run(options_t *options_p) {
// "Infinite" loop of processling the events
ret = sync_notify_loop(notify_d, options_p, &indexes);
if(ret) return ret;
printf_d("Debug2: sync_run(): sync_notify_loop() ended\n");
#ifdef ENABLE_SOCKET
// Removing control socket
if(options_p->socketpath != NULL)
socket_cleanup(options_p);
#endif
printf_d("Debug2: sync_run(): killing sighandler\n");
// TODO: Do cleanup of watching points
pthread_kill(pthread_sighandler, SIGTERM);
pthread_join(pthread_sighandler, NULL);
... ... @@ -3210,7 +3226,7 @@ int sync_run(options_t *options_p) {
thread_cleanup(options_p);
// Closing sockets and files
// Closing rest sockets and files
printf_ddd("sync_run(): Closing notify_d\n");
close(notify_d);
... ...