smbnetfs  0.6.3
About: SMBNetFS is a Linux/FreeBSD filesystem that allow you to use samba/microsoft network in the same manner as the network neighborhood in Microsoft Windows.
  Fossies Dox: smbnetfs-0.6.3.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

process.c
Go to the documentation of this file.
1 #include "config.h"
2 #include <errno.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <sys/types.h>
7 #include <sys/wait.h>
8 #include <sys/socket.h>
9 #include <signal.h>
10 #include <pthread.h>
11 #include <langinfo.h>
12 
13 #include "common.h"
14 #include "list.h"
15 #include "smb_conn_proto.h"
16 #include "process.h"
17 
18 #define CHARSET_LEN 64
19 
20 struct process_rec{
22  int child_fd;
23  pid_t child_pid;
24 };
25 
26 static char process_system_charset[CHARSET_LEN] = "UTF-8";
30 static int process_server_smb_timeout = 20000;
32 static int process_start_enabled = 1;
33 
35 static pthread_mutex_t m_process = PTHREAD_MUTEX_INITIALIZER;
36 
37 
38 int process_init(void){
39  static int initialized = 0;
40 
41  char *charset;
42 
43  if (! initialized){
44  if ((charset = nl_langinfo(CODESET)) == NULL){
45  DPRINTF(0, "Can't find system charset, use utf-8 instead. Check your locale.\n");
46  charset = "UTF-8";
47  }else{
48  initialized = 1;
49  }
50  strncpy(process_system_charset, charset, CHARSET_LEN);
52  DPRINTF(5, "system_charset=%s\n", process_system_charset);
53  }
54  pthread_mutex_lock(&m_process);
57  strncpy(process_server_samba_charset, "UTF-8", CHARSET_LEN);
59  pthread_mutex_unlock(&m_process);
60  return initialized;
61 }
62 
64  DPRINTF(7, "disable new process starting at %u\n", (unsigned int) time(NULL));
65  pthread_mutex_lock(&m_process);
67  pthread_mutex_unlock(&m_process);
68 }
69 
71  if (timeout < 30) return 0;
72  DPRINTF(7, "timeout=%d\n", timeout);
73  pthread_mutex_lock(&m_process);
75  pthread_mutex_unlock(&m_process);
76  return 1;
77 }
78 
80  if (timeout < 1000) return 0;
81  DPRINTF(7, "smb_timeout=%d\n", timeout);
82  pthread_mutex_lock(&m_process);
84  pthread_mutex_unlock(&m_process);
85  return 1;
86 }
87 
89  if ((level < 0) || (level > 10)) return 0;
90  DPRINTF(7, "level=%d\n", level);
91  pthread_mutex_lock(&m_process);
93  pthread_mutex_unlock(&m_process);
94  return 1;
95 }
96 
97 int process_set_server_local_charset(const char *charset){
98  if ((charset == NULL) || (*charset == '\0'))
99  charset = process_system_charset;
100 
101  DPRINTF(7, "local_charset=%s\n", charset);
102  pthread_mutex_lock(&m_process);
103  strncpy(process_server_local_charset, charset, CHARSET_LEN);
105  pthread_mutex_unlock(&m_process);
106  return 1;
107 }
108 
109 int process_set_server_samba_charset(const char *charset){
110  if ((charset == NULL) || (*charset == '\0')) charset = "UTF-8";
111 
112  DPRINTF(7, "samba_charset=%s\n", charset);
113  pthread_mutex_lock(&m_process);
114  strncpy(process_server_samba_charset, charset, CHARSET_LEN);
116  pthread_mutex_unlock(&m_process);
117  return 1;
118 }
119 
120 int process_start_new_smb_conn(char *shmem_ptr, size_t shmem_size){
121  int error;
122  int debug_level;
123  int pair[2];
124  pid_t pid;
125  struct process_rec *rec;
126 
127  if ((shmem_ptr == NULL) || (shmem_size < (size_t) getpagesize())){
128  errno = EINVAL;
129  return -1;
130  }
131 
132  error = 0;
133  pid = (pid_t) (-1);
134  pthread_mutex_lock(&m_process);
135  if (process_start_enabled != 1){
136  error = EPERM;
137  pair[0] = -1;
138  goto error;
139  }
140  if ((rec = malloc(sizeof(struct process_rec))) == NULL){
141  error = errno;
142  pair[0] = -1;
143  DPRINTF(6, "starting new child failed on malloc(): errno=%d, %s\n",
144  errno, strerror(errno));
145  goto error;
146  }
147  if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0){
148  DPRINTF(6, "using SOCK_DGRAM instead of SOCK_SEQPACKET\n");
149  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0){
150  error = errno;
151  free(rec);
152  pair[0] = -1;
153  DPRINTF(6, "starting new child failed on socketpair(): errno=%d, %s\n",
154  errno, strerror(errno));
155  goto error;
156  }
157  }
158 
159  memset(rec, 0, sizeof(struct process_rec));
160  debug_level = common_get_smbnetfs_debug_level();
161 
162  if ((pid = fork()) == -1){
163  error = errno;
164  close(pair[0]);
165  close(pair[1]);
166  free(rec);
167  pair[0] = -1;
168  DPRINTF(6, "starting new child failed on fork(): errno=%d, %s\n",
169  errno, strerror(errno));
170  goto error;
171  }
172 
173  if (pid == 0){
174  struct smb_conn_srv_ctx srv_ctx;
175 
176  pthread_mutex_unlock(&m_process);
177  close(pair[0]);
178 
179  /* We are after fork here, so we are in single thread situation. *
180  * This mean we may read any variable without acquiring locks. *
181  * Moreover, we can NOT use safely any mutex protected code, *
182  * as the mutexes after the fork() are in UNKNOWN state */
183  srv_ctx.conn_fd = pair[1];
184  srv_ctx.shmem_ptr = shmem_ptr;
185  srv_ctx.shmem_size = shmem_size;
188  srv_ctx.debug_level = debug_level;
192  smb_conn_srv_listen(&srv_ctx);
193  exit(EXIT_SUCCESS);
194  }
195 
196  close(pair[1]);
197  rec->child_pid = pid;
198  rec->child_fd = pair[0];
200  DPRINTF(6, "starting new child with pid=%d, fd=%d\n", (int) pid, pair[0]);
201 
202  error:
203  pthread_mutex_unlock(&m_process);
204  errno = error;
205  return pair[0];
206 }
207 
209  int result;
210  LIST *elem;
211  struct process_rec *rec;
212 
213  result = 0;
214  pthread_mutex_lock(&m_process);
215  elem = first_list_elem(&process_list);
216  while(is_valid_list_elem(&process_list, elem)){
217  rec = list_entry(elem, struct process_rec, entries);
218  elem = elem->next;
219 
220  if ((rec->child_fd == fd) &&
221  (rec->child_pid != (pid_t) (-1))){
222  result = 1;
223  break;
224  }
225  }
226  pthread_mutex_unlock(&m_process);
227  return result;
228 }
229 
230 void process_kill_all(void){
231  LIST *elem;
232  struct process_rec *rec;
233 
234  pthread_mutex_lock(&m_process);
235  elem = first_list_elem(&process_list);
236  while(is_valid_list_elem(&process_list, elem)){
237  rec = list_entry(elem, struct process_rec, entries);
238  elem = elem->next;
239 
240  if (rec->child_pid != (pid_t) (-1)){
241  DPRINTF(6, "kill child with pid=%d, fd=%d\n",
242  (int) rec->child_pid, rec->child_fd);
243  kill(rec->child_pid, SIGKILL);
244  }
245  }
246  pthread_mutex_unlock(&m_process);
247 }
248 
250  LIST *elem;
251  struct process_rec *rec;
252 
253  pthread_mutex_lock(&m_process);
254  elem = first_list_elem(&process_list);
255  while(is_valid_list_elem(&process_list, elem)){
256  rec = list_entry(elem, struct process_rec, entries);
257  elem = elem->next;
258 
259  if (rec->child_fd == fd){
260  DPRINTF(6, "closing child connection with pid=%d, fd=%d\n",
261  (int) rec->child_pid, rec->child_fd);
262  close(rec->child_fd);
263  rec->child_fd = -1;
264  if (rec->child_pid == (pid_t) (-1)){
265  DPRINTF(6, "cleanup child record with fd=%d\n", fd);
267  free(rec);
268  }else
269  kill(rec->child_pid, SIGKILL);
270  break;
271  }
272  }
273  pthread_mutex_unlock(&m_process);
274 }
275 
277  pid_t pid;
278  LIST *elem;
279  struct process_rec *rec;
280 
281  pthread_mutex_lock(&m_process);
282  while(1){
283  pid = waitpid((pid_t) (-1), NULL, WNOHANG);
284  if (pid <= 0) break;
285 
286  elem = first_list_elem(&process_list);
287  while(is_valid_list_elem(&process_list, elem)){
288  rec = list_entry(elem, struct process_rec, entries);
289  elem = elem->next;
290 
291  if (rec->child_pid == pid){
292  DPRINTF(6, "R.I.P. child with pid=%d, fd=%d\n",
293  (int) rec->child_pid, rec->child_fd);
294  rec->child_pid = (pid_t) (-1);
295  if (rec->child_fd == -1){
296  DPRINTF(6, "cleanup child record with pid=%d\n", (int) pid);
298  free(rec);
299  }
300  break;
301  }
302  }
303  }
304  pthread_mutex_unlock(&m_process);
305 }
static int common_get_smbnetfs_debug_level(void)
Definition: common.h:28
#define DPRINTF(level, fmt, args...)
Definition: common.h:47
static int is_valid_list_elem(LIST *list, LIST *elem)
Definition: list.h:88
static LIST * first_list_elem(LIST *list)
Definition: list.h:16
#define list_entry(ptr, type, member)
Definition: list.h:11
#define STATIC_LIST_INITIALIZER(list)
Definition: list.h:14
static void add_to_list(LIST *list, LIST *elem)
Definition: list.h:24
static void remove_from_list(LIST *list, LIST *elem)
Definition: list.h:77
void process_kill_all(void)
Definition: process.c:230
int process_set_server_samba_charset(const char *charset)
Definition: process.c:109
#define CHARSET_LEN
Definition: process.c:18
int process_init(void)
Definition: process.c:38
void process_kill_by_smb_conn_fd(int fd)
Definition: process.c:249
static pthread_mutex_t m_process
Definition: process.c:35
static int process_server_smb_debug_level
Definition: process.c:31
static LIST process_list
Definition: process.c:34
int process_set_server_smb_debug_level(int level)
Definition: process.c:88
static char process_system_charset[64]
Definition: process.c:26
static char process_server_samba_charset[64]
Definition: process.c:28
static int process_start_enabled
Definition: process.c:32
int process_set_server_listen_timeout(int timeout)
Definition: process.c:70
int process_is_smb_conn_alive(int fd)
Definition: process.c:208
static int process_server_smb_timeout
Definition: process.c:30
static int process_server_listen_timeout
Definition: process.c:29
void process_disable_new_smb_conn_starting(void)
Definition: process.c:63
static char process_server_local_charset[64]
Definition: process.c:27
int process_set_server_local_charset(const char *charset)
Definition: process.c:97
int process_start_new_smb_conn(char *shmem_ptr, size_t shmem_size)
Definition: process.c:120
void process_cleanup_from_zombies(void)
Definition: process.c:276
int process_set_server_smb_timeout(int timeout)
Definition: process.c:79
void smb_conn_srv_listen(struct smb_conn_srv_ctx *ctx)
Definition: smb_conn_srv.c:185
Definition: list.h:6
struct __LIST * next
Definition: list.h:7
pid_t child_pid
Definition: process.c:23
int child_fd
Definition: process.c:22
LIST entries
Definition: process.c:21
const char * local_charset
const char * samba_charset