clsync
control.c
Go to the documentation of this file.
1 /*
2  clsync - file tree sync utility based on inotify
3 
4  Copyright (C) 2013 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "common.h"
21 
22 #include <sys/un.h> // for "struct sockaddr_un"
23 #include <sys/stat.h> // mkdir()
24 #include <sys/types.h> // mkdir()
25 #include <fcntl.h> // mkdirat()
26 #include <glib.h> // g_hash_table_foreach()
27 
28 
29 #include "indexes.h"
30 #include "main.h"
31 #include "ctx.h"
32 #include "error.h"
33 #include "sync.h"
34 #include "control.h"
35 #include "socket.h"
36 
37 static pthread_t pthread_control;
38 
39 
40 static inline int control_error ( clsyncsock_t *clsyncsock_p, sockcmd_t *sockcmd_p, const char *const funct, const char *const args )
41 {
42  debug ( 3, "%s(%s): %u: %s", funct, args, errno, strerror ( errno ) );
43  return socket_reply ( clsyncsock_p, sockcmd_p, SOCKCMD_REPLY_ECUSTOM, funct, args, errno, strerror ( errno ) );
44 }
45 
46 
47 int control_dump ( ctx_t *ctx_p, clsyncsock_t *clsyncsock_p, sockcmd_t *sockcmd_p )
48 {
49  sockcmd_dat_dump_t *dat = sockcmd_p->data;
50  debug ( 3, "%s", dat->dir_path );
51  return ( sync_dump ( ctx_p, dat->dir_path ) ) ?
52  control_error ( clsyncsock_p, sockcmd_p, "sync_dump", dat->dir_path ) :
53  socket_reply ( clsyncsock_p, sockcmd_p, SOCKCMD_REPLY_DUMP );
54 }
55 
57 {
58  int rc;
59  clsyncsock_t *clsyncsock_p = arg->clsyncsock_p;
60  ctx_t *ctx_p = ( ctx_t * ) arg->arg;
61 
62  switch ( sockcmd_p->cmd_id ) {
64  rc = control_dump ( ctx_p, clsyncsock_p, sockcmd_p );
65  break;
66 
68  rc = socket_reply ( clsyncsock_p, sockcmd_p, SOCKCMD_REPLY_INFO, ctx_p->config_block, ctx_p->label, ctx_p->flags, ctx_p->flags_set );
69  break;
70 
71  case SOCKCMD_REQUEST_SET: {
72  sockcmd_dat_set_t *dat = sockcmd_p->data;
73  rc = ctx_set ( ctx_p, dat->key, dat->value );
74 
75  if ( rc ) {
76  control_error ( clsyncsock_p, sockcmd_p, "ctx_set", dat->key );
77  break;
78  }
79 
80  rc = socket_reply ( clsyncsock_p, sockcmd_p, SOCKCMD_REPLY_SET );
81  break;
82  }
83 
85  rc = sync_term ( SIGTERM );
86  break;
87 
88  default:
89  return EINVAL;
90  }
91 
92  debug ( 3, "rc == %u", rc );
93  return rc;
94 }
95 
96 static inline void closecontrol ( ctx_t *ctx_p )
97 {
98  if ( ctx_p->socket ) {
99  close ( ctx_p->socket );
100  ctx_p->socket = 0;
101  }
102 }
103 
105 {
106  // Starting
107  debug ( 1, "started (ctx_p->socket == %u)", ctx_p->socket );
108  int s;
109 
110  while ( ( s = ctx_p->socket ) ) {
111  // Check if the socket is still alive
112  if ( socket_check_bysock ( s ) ) {
113  error ( "Control socket closed [case 0]" );
114  closecontrol ( ctx_p );
115  continue;
116  }
117 
118  // Waiting for event
119  debug ( 3, "waiting for events on the socket" );
120  fd_set rfds;
121  FD_ZERO ( &rfds );
122  FD_SET ( s, &rfds );
123  int count = select ( s + 1, &rfds, NULL, NULL, NULL );
124  // Processing the events
125  debug ( 2, "got %i events with select()", count );
126 
127  // Processing the events: checks
128  if ( count == 0 ) {
129  debug ( 2, "select() timed out." );
130  continue;
131  }
132 
133  if ( count < 0 ) {
134  debug ( 1, "Got negative events count. Closing the socket." );
135  closecontrol ( ctx_p );
136  continue;
137  }
138 
139  if ( !FD_ISSET ( s, &rfds ) ) {
140  error ( "Got event, but not on the control socket. Closing the socket (cannot use \"select()\")." );
141  closecontrol ( ctx_p );
142  continue;
143  }
144 
145  // Processing the events: accepting new clsyncsock
146  clsyncsock_t *clsyncsock_p = socket_accept ( s );
147 
148  if ( clsyncsock_p == NULL ) {
149  if ( errno == EUSERS ) // Too many connections. Just ignoring the new one.
150  continue;
151 
152  // Got unknown error. Closing control socket just in case.
153  error ( "Cannot socket_accept()" );
154  closecontrol ( ctx_p );
155  continue;
156  }
157 
158  debug ( 2, "Starting new thread for new connection." );
159  socket_sockthreaddata_t *threaddata_p = socket_thread_attach ( clsyncsock_p );
160 
161  if ( threaddata_p == NULL ) {
162  error ( "Cannot create a thread for connection" );
163  closecontrol ( ctx_p );
164  continue;
165  }
166 
167  threaddata_p->procfunct = control_procclsyncsock;
168  threaddata_p->clsyncsock_p = clsyncsock_p;
169  threaddata_p->arg = ctx_p;
170  threaddata_p->running = &ctx_p->socket;
171  threaddata_p->authtype = ctx_p->flags[SOCKETAUTH];
172  threaddata_p->flags = 0;
173 
174  if ( socket_thread_start ( threaddata_p ) ) {
175  error ( "Cannot start a thread for connection" );
176  closecontrol ( ctx_p );
177  continue;
178  }
179 
180 #ifdef DEBUG
181  // To prevent too often connections
182  sleep ( 1 );
183 #endif
184  }
185 
186  // Cleanup
187  debug ( 1, "control_loop() finished" );
188  return 0;
189 }
190 
192 {
193  if ( ctx_p->socketpath != NULL ) {
194  int ret = 0;
195  int s = -1;
196 
197  // initializing clsync-socket subsystem
198  if ( ( ret = socket_init() ) )
199  error ( "Cannot init clsync-sockets subsystem." );
200 
201  if ( !ret ) {
203 
204  if ( clsyncsock == NULL ) {
205  ret = errno;
206  } else {
207  s = clsyncsock->sock;
209  }
210  }
211 
212  // fixing privileges
213  if ( !ret ) {
214  if ( ctx_p->flags[SOCKETMOD] )
215  if ( chmod ( ctx_p->socketpath, ctx_p->socketmod ) ) {
216  error ( "Error, Cannot chmod(\"%s\", %o)",
218  ret = errno;
219  }
220 
221  if ( ctx_p->flags[SOCKETOWN] )
222  if ( chown ( ctx_p->socketpath, ctx_p->socketuid, ctx_p->socketgid ) ) {
223  error ( "Error, Cannot chown(\"%s\", %u, %u)",
225  ret = errno;
226  }
227  }
228 
229  // finish
230  if ( ret ) {
231  close ( s );
232  return ret;
233  }
234 
235  ctx_p->socket = s;
236  debug ( 2, "ctx_p->socket = %u", ctx_p->socket );
237  ret = pthread_create ( &pthread_control, NULL, ( void * ( * ) ( void * ) ) control_loop, ctx_p );
238  }
239 
240  return 0;
241 }
242 
244 {
245  if ( ctx_p->socketpath != NULL ) {
246  unlink ( ctx_p->socketpath );
247  closecontrol ( ctx_p );
248  // TODO: kill pthread_control and join
249 // pthread_join(pthread_control, NULL);
250  socket_deinit();
251  }
252 
253  return 0;
254 }
255 
socket_sockthreaddata
Definition: socket.h:209
ctx.h
ctx::config_block
const char * config_block
Definition: ctx.h:342
SOCKCMD_REQUEST_DIE
@ SOCKCMD_REQUEST_DIE
Definition: socket.h:115
socket_sockthreaddata::clsyncsock_p
clsyncsock_t * clsyncsock_p
Definition: socket.h:213
ctx
Definition: ctx.h:315
socket_sockthreaddata::arg
void * arg
Definition: socket.h:214
sockcmd_dat_dump::dir_path
char dir_path[PATH_MAX]
Definition: socket.h:166
sockcmd_dat_set::value
char value[BUFSIZ]
Definition: socket.h:182
ctx::socketmod
mode_t socketmod
Definition: ctx.h:361
SOCKCMD_REQUEST_SET
@ SOCKCMD_REQUEST_SET
Definition: socket.h:114
close
close(fd_w)
control.h
socket_thread_start
int socket_thread_start(socket_sockthreaddata_t *threaddata_p)
Definition: socket.c:808
sync.h
ctx_set
int ctx_set(ctx_t *ctx_p, const char *const parameter_name, const char *const parameter_value)
Definition: main.c:2560
socket_listen_unix
clsyncsock_t * socket_listen_unix(const char *const socket_path)
Definition: socket.c:192
ctx::flags_set
int flags_set[(1<< 10)]
Definition: ctx.h:339
socket_sockthreaddata::flags
sockprocflags_t flags
Definition: socket.h:218
control_procclsyncsock
int control_procclsyncsock(socket_sockthreaddata_t *arg, sockcmd_t *sockcmd_p)
Definition: control.c:56
sockcmd_dat_dump
Definition: socket.h:165
ctx::flags
int flags[(1<< 10)]
Definition: ctx.h:338
control_error
static int control_error(clsyncsock_t *clsyncsock_p, sockcmd_t *sockcmd_p, const char *const funct, const char *const args)
Definition: control.c:40
socket_sockthreaddata::running
int * running
Definition: socket.h:217
socket_reply
int socket_reply(clsyncsock_t *clsyncsock_p, sockcmd_t *sockcmd_p, sockcmd_id_t cmd_id,...)
Definition: socket.c:331
sockcmd_dat_set::key
char key[BUFSIZ]
Definition: socket.h:181
ctx::socketgid
gid_t socketgid
Definition: ctx.h:363
socket_deinit
int socket_deinit()
Definition: socket.c:823
socket_cleanup
int socket_cleanup(clsyncsock_t *clsyncsock_p)
Definition: socket.c:140
SOCKETOWN
@ SOCKETOWN
Definition: ctx.h:99
sockcmd::cmd_id
uint16_t cmd_id
Definition: socket.h:188
error
#define error(...)
Definition: error.h:36
SOCKETMOD
@ SOCKETMOD
Definition: ctx.h:98
SOCKCMD_REPLY_INFO
@ SOCKCMD_REPLY_INFO
Definition: socket.h:118
ctx::label
char * label
Definition: ctx.h:344
indexes.h
SOCKCMD_REPLY_ECUSTOM
@ SOCKCMD_REPLY_ECUSTOM
Definition: socket.h:109
error.h
debug
#define debug(debug_level,...)
Definition: error.h:50
control_dump
int control_dump(ctx_t *ctx_p, clsyncsock_t *clsyncsock_p, sockcmd_t *sockcmd_p)
Definition: control.c:47
socket_sockthreaddata::authtype
sockauth_id_t authtype
Definition: socket.h:216
control_cleanup
int control_cleanup(ctx_t *ctx_p)
Definition: control.c:243
pthread_control
static pthread_t pthread_control
Definition: control.c:37
clsyncsock::sock
int sock
Definition: socket.h:66
SOCKCMD_REPLY_SET
@ SOCKCMD_REPLY_SET
Definition: socket.h:121
SOCKCMD_REQUEST_INFO
@ SOCKCMD_REQUEST_INFO
Definition: socket.h:111
sync_term
int sync_term(int exitcode)
Definition: sync.c:3991
common.h
main.h
control_loop
int control_loop(ctx_t *ctx_p)
Definition: control.c:104
socket_sockthreaddata::procfunct
clsyncsock_procfunct_t procfunct
Definition: socket.h:211
sockcmd
Definition: socket.h:186
socket.h
socket_init
int socket_init()
Definition: socket.c:818
control_run
int control_run(ctx_t *ctx_p)
Definition: control.c:191
socket_check_bysock
int socket_check_bysock(int sock)
Definition: socket.c:108
SOCKETAUTH
@ SOCKETAUTH
Definition: ctx.h:97
ctx::socketuid
uid_t socketuid
Definition: ctx.h:362
clsyncsock
Definition: socket.h:65
SOCKCMD_REPLY_DUMP
@ SOCKCMD_REPLY_DUMP
Definition: socket.h:119
socket_thread_attach
socket_sockthreaddata_t * socket_thread_attach(clsyncsock_t *clsyncsock_p)
Definition: socket.c:797
closecontrol
static void closecontrol(ctx_t *ctx_p)
Definition: control.c:96
sync_dump
int sync_dump(ctx_t *ctx_p, const char *const dir_path)
Definition: sync.c:3773
sockcmd::data
void * data
Definition: socket.h:190
socket_accept
clsyncsock_t * socket_accept(int sock)
Definition: socket.c:177
SOCKCMD_REQUEST_DUMP
@ SOCKCMD_REQUEST_DUMP
Definition: socket.h:112
sockcmd_dat_set
Definition: socket.h:180
ctx::socket
int socket
Definition: ctx.h:360
ctx::socketpath
char * socketpath
Definition: ctx.h:355
ctx_p
ctx_t * ctx_p
Definition: mon_kqueue.c:85