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)  

smb_conn_srv.c
Go to the documentation of this file.
1 #include "config.h"
2 #include <errno.h>
3 #include <stdio.h>
4 #include <iconv.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <stdarg.h>
8 #include <unistd.h>
9 #include <sys/uio.h>
10 #include <sys/mman.h>
11 #include <sys/select.h>
12 #include <libsmbclient.h>
13 
14 #include "charset.h"
15 #include "smb_conn_proto.h"
16 #include "smb_conn_srv.h"
17 
19  enum smb_conn_cmd msg_type,
20  int errno_value,
21  int level, int no_fallback,
22  const char *fmt, ...){
23 
24  static char buf[COMM_BUF_SIZE];
25  ssize_t bytes;
26  va_list ap;
27 
28  if (ctx == NULL) goto fallback;
29  if ((msg_type != MESSAGE) && (msg_type != DIE_MSG)) return;
30  if (level > ctx->debug_level) return;
31 
32  bytes = sizeof(buf) - sizeof(struct smb_conn_reply_hdr) -
33  sizeof(struct smb_conn_message_req) - 1;
34  if (bytes <= 0) goto fallback;
35 
36  va_start(ap, fmt);
37  vsnprintf(buf, (size_t) bytes, fmt, ap);
38  buf[bytes] = '\0';
39  va_end(ap);
40 
41  if (smb_conn_srv_send_msg(ctx, msg_type,
42  errno_value, level, buf) == 0) return;
43 
44  fallback:
45  if (no_fallback) return;
46  va_start(ap, fmt);
47  vfprintf(stderr, fmt, ap);
48  fflush(stderr);
49  va_end(ap);
50 }
51 
52 static void smb_conn_srv_auth_fn(SMBCCTX *ctx,
53  const char *server,
54  const char *share,
55  char *wrkgrp, int wrkgrplen,
56  char *user, int userlen,
57  char *passwd, int passwdlen){
58 
59  static char buf[COMM_BUF_SIZE];
60  static char charset_buf[CHARSET_BUF_SIZE];
61  struct smb_conn_srv_ctx *srv_ctx;
62  int retval;
63  ssize_t bytes;
64  fd_set readfds, exceptfds;
65  struct timeval tv;
66  struct iovec iov[4];
67  struct smb_conn_reply_hdr reply_header;
68  struct smb_conn_passwd_req reply;
69  struct smb_conn_query_hdr *query_hdr;
70  struct smb_conn_passwd *passwd_hdr;
71  const char *domain, *username, *password;
72 
73  srv_ctx = NULL;
74 
75  if (ctx == NULL) goto error;
76  if ((srv_ctx = smbc_getOptionUserData(ctx)) == NULL) goto error;
77  if ((server = charset_smb2local_r(server,
78  charset_buf, sizeof(charset_buf))) == NULL) goto error;
79  if ((server = strdup(server)) == NULL) goto error;
80  if ((share = charset_smb2local_r(share,
81  charset_buf, sizeof(charset_buf))) == NULL) goto error;
82 
83  iov[0].iov_base = &reply_header;
84  iov[0].iov_len = sizeof(reply_header);
85  iov[1].iov_base = &reply;
86  iov[1].iov_len = sizeof(reply);
87  iov[2].iov_base = (char *) server;
88  iov[2].iov_len = strlen(server) + 1;
89  iov[3].iov_base = (char *) share;
90  iov[3].iov_len = strlen(share) + 1;
91 
92  reply_header.reply_len = iov[0].iov_len + iov[1].iov_len +
93  iov[2].iov_len + iov[3].iov_len;
94  reply_header.reply_cmd = PASSWORD;
95  reply_header.errno_value = 0;
96  reply.server_offs = sizeof(reply);
97  reply.share_offs = sizeof(reply) + iov[2].iov_len;
98 
99  if (reply_header.reply_len > COMM_BUF_SIZE) goto error;
100 
101  /* send password request */
102  bytes = writev(srv_ctx->conn_fd, iov, 4);
103  if (bytes != (ssize_t) reply_header.reply_len) goto error;
104 
105  tv.tv_sec = srv_ctx->timeout;
106  tv.tv_usec = 0;
107 
108  FD_ZERO(&readfds);
109  FD_SET(srv_ctx->conn_fd, &readfds);
110 
111  FD_ZERO(&exceptfds);
112  FD_SET(srv_ctx->conn_fd, &exceptfds);
113 
114  /* wait for password */
115  retval = select(srv_ctx->conn_fd + 1, &readfds, NULL, &exceptfds, &tv);
116  if ((retval <= 0) || FD_ISSET(srv_ctx->conn_fd, &exceptfds)) goto error;
117 
118  /* read password data */
119  bytes = read(srv_ctx->conn_fd, buf, COMM_BUF_SIZE);
120  if (buf[bytes - 1] != '\0' ) goto error;
121  if (bytes < (ssize_t) sizeof(struct smb_conn_query_hdr)) goto error;
122 
123  /* check query */
124  query_hdr = (struct smb_conn_query_hdr *) buf;
125  if (bytes != (ssize_t) query_hdr->query_len) goto error;
126  if (query_hdr->query_cmd != PASSWORD) goto error;
127 
128  bytes -= sizeof(struct smb_conn_query_hdr);
129  if (bytes < (ssize_t) sizeof(struct smb_conn_passwd)) goto error;
130 
131  /* process password */
132  passwd_hdr = (struct smb_conn_passwd *) (query_hdr + 1);
133  if ((passwd_hdr->domain_offs != sizeof(struct smb_conn_passwd)) ||
134  (passwd_hdr->username_offs <= passwd_hdr->domain_offs) ||
135  (passwd_hdr->password_offs <= passwd_hdr->username_offs) ||
136  ((ssize_t) passwd_hdr->password_offs > bytes - 1)) goto error;
137  bytes -= sizeof(struct smb_conn_passwd);
138 
139  domain = smb_conn_srv_get_url_from_query(passwd_hdr,
140  passwd_hdr->domain_offs);
141  username = smb_conn_srv_get_url_from_query(passwd_hdr,
142  passwd_hdr->username_offs);
143  password = smb_conn_srv_get_url_from_query(passwd_hdr,
144  passwd_hdr->password_offs);
145  if (bytes != (ssize_t) (strlen(domain) + strlen(username) +
146  strlen(password) + 3)) goto error;
147 
148  if (*domain != '\0'){
149  strncpy(wrkgrp, domain, wrkgrplen);
150  wrkgrp[wrkgrplen - 1] = '\0';
151  }
152  strncpy(user, username, userlen); user[userlen - 1] = '\0';
153  strncpy(passwd, password, passwdlen); passwd[passwdlen - 1] = '\0';
154  DSRVPRINTF(srv_ctx, 6, "url=smb://%s/%s, grp=%s, user=%s, passwd=%s\n",
155  server, share, wrkgrp, user, "********");
156  free((char *) server);
157  return;
158 
159  error:
160  DSRVDIEMSG(srv_ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
161  exit(EXIT_FAILURE);
162 }
163 
164 static void smb_conn_srv_samba_init(struct smb_conn_srv_ctx *srv_ctx){
165  SMBCCTX *ctx;
166 
167  if ((ctx = smbc_new_context()) == NULL) goto error;
168  smbc_setTimeout(ctx, srv_ctx->smb_timeout);
169  smbc_setDebug(ctx, srv_ctx->smb_debug_level);
170  smbc_setFunctionAuthDataWithContext(ctx, smb_conn_srv_auth_fn);
171  smbc_setOptionUserData(ctx, srv_ctx);
172 #if defined(SMB_CTX_FLAG_USE_KERBEROS) && defined(SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS)
173  smbc_setOptionUseKerberos(ctx, 1);
174  smbc_setOptionFallbackAfterKerberos(ctx, 1);
175 #endif
176  if (smbc_init_context(ctx) == NULL) goto error;
177  smbc_set_context(ctx);
178  return;
179 
180  error:
181  DSRVDIEMSG(srv_ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
182  exit(EXIT_FAILURE);
183 }
184 
186 
187  static char buf[COMM_BUF_SIZE];
188 
189  if (charset_init(ctx->local_charset, ctx->samba_charset) != 0){
190  DSRVDIEMSG(ctx, EINVAL, "Can't set samba or local charset\n");
191  exit(EXIT_FAILURE);
192  }
194  while(1){
195  fd_set readfds, exceptfds;
196  struct timeval tv;
197  int retval;
198  void *query;
199  ssize_t query_len;
200  struct smb_conn_query_hdr *query_hdr;
201 
202  tv.tv_sec = ctx->timeout;
203  tv.tv_usec = 0;
204 
205  FD_ZERO(&readfds);
206  FD_SET(ctx->conn_fd, &readfds);
207 
208  FD_ZERO(&exceptfds);
209  FD_SET(ctx->conn_fd, &exceptfds);
210 
211  /* wait for query */
212  retval = select(ctx->conn_fd + 1, &readfds, NULL, &exceptfds, &tv);
213  if ((retval < 0)) goto error;
214  if (retval == 0){
215  /* we treat timeout as signal to exit, */
216  /* no cleanup should be required */
217  DSRVDIEMSG(ctx, 0, "Timeout expired\n");
218  exit(EXIT_SUCCESS);
219  }
220  if (FD_ISSET(ctx->conn_fd, &exceptfds)) goto error;
221 
222  /* read query */
223  query_len = read(ctx->conn_fd, buf, COMM_BUF_SIZE);
224  if (query_len < (ssize_t) sizeof(struct smb_conn_query_hdr)) goto error;
225 
226  /* check query */
227  query_hdr = (struct smb_conn_query_hdr *) buf;
228  if (query_len != (ssize_t) query_hdr->query_len) goto error;
229 
230  /* update debug_level from query */
231  ctx->debug_level = query_hdr->debug_level;
232 
233  /* process query */
234  errno = 0;
235  query = (void*) (query_hdr + 1);
236  query_len -= sizeof(struct smb_conn_query_hdr);
237  DSRVPRINTF(ctx, 6, "process query=%d, query_len=%zd\n",
238  query_hdr->query_cmd, query_len);
239  switch(query_hdr->query_cmd){
240  case OPEN:
241  smb_conn_srv_open(ctx, query, query_len);
242  break;
243  case CREAT:
244  smb_conn_srv_creat(ctx, query, query_len);
245  break;
246  case READ:
247  smb_conn_srv_read(ctx, query, query_len);
248  break;
249  case WRITE:
250  smb_conn_srv_write(ctx, query, query_len);
251  break;
252  case CLOSE:
253  smb_conn_srv_close(ctx, query, query_len);
254  break;
255  case UNLINK:
256  smb_conn_srv_unlink(ctx, query, query_len);
257  break;
258  case RENAME:
259  smb_conn_srv_rename(ctx, query, query_len);
260  break;
261  case OPENDIR:
262  smb_conn_srv_opendir(ctx, query, query_len);
263  break;
264  case CLOSEDIR:
265  smb_conn_srv_closedir(ctx, query, query_len);
266  break;
267  case READDIR:
268  smb_conn_srv_readdir(ctx, query, query_len);
269  break;
270  case MKDIR:
271  smb_conn_srv_mkdir(ctx, query, query_len);
272  break;
273  case RMDIR:
274  smb_conn_srv_rmdir(ctx, query, query_len);
275  break;
276  case STAT:
277  smb_conn_srv_stat(ctx, query, query_len);
278  break;
279  case FSTAT:
280  smb_conn_srv_fstat(ctx, query, query_len);
281  break;
282  case FTRUNCATE:
283  smb_conn_srv_ftruncate(ctx, query, query_len);
284  break;
285  case CHMOD:
286  smb_conn_srv_chmod(ctx, query, query_len);
287  break;
288  case UTIMES:
289  smb_conn_srv_utimes(ctx, query, query_len);
290  break;
291  case SETXATTR:
292  smb_conn_srv_setxattr(ctx, query, query_len);
293  break;
294  case GETXATTR:
295  smb_conn_srv_getxattr(ctx, query, query_len);
296  break;
297  case LISTXATTR:
298  smb_conn_srv_listxattr(ctx, query, query_len);
299  break;
300  case REMOVEXATTR:
301  smb_conn_srv_removexattr(ctx, query, query_len);
302  break;
303  default:
304  /* unknown qery ? */
305  goto error;
306  }
307  }
308 
309  error:
310  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
311  exit(EXIT_FAILURE);
312 };
313 
315  enum smb_conn_cmd reply_cmd,
316  int errno_value,
317  void *reply, size_t reply_len){
318 
319  int iov_cnt;
320  struct iovec iov[2];
321  struct smb_conn_reply_hdr header;
322 
323  if (errno_value == 0){
324  if (((reply == NULL) && (reply_len != 0)) ||
325  ((reply != NULL) && (reply_len == 0))) goto error;
326  }else{
327  if ((reply != NULL) || (reply_len != 0)) goto error;
328  }
329 
330  iov_cnt = 1;
331  header.reply_cmd = reply_cmd;
332  header.errno_value = errno_value;
333  header.reply_len = sizeof(struct smb_conn_reply_hdr);
334 
335  iov[0].iov_base = &header;
336  iov[0].iov_len = sizeof(struct smb_conn_reply_hdr);
337 
338  if (reply_len > 0){
339  iov[iov_cnt].iov_base = reply;
340  iov[iov_cnt].iov_len = reply_len;
341  header.reply_len += iov[iov_cnt].iov_len;
342  iov_cnt++;
343  }
344 
345  if (header.reply_len > COMM_BUF_SIZE) goto error;
346  if (writev(ctx->conn_fd, iov, iov_cnt) != (ssize_t) header.reply_len)
347  goto error;
348 
349  return;
350 
351  error:
352  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
353  exit(EXIT_FAILURE);
354 }
355 
357  enum smb_conn_cmd msg_type,
358  int errno_value,
359  int level,
360  const char *msg){
361 
362  ssize_t bytes;
363  struct iovec iov[3];
364  struct smb_conn_reply_hdr reply_header;
365  struct smb_conn_message_req reply;
366 
367  iov[0].iov_base = &reply_header;
368  iov[0].iov_len = sizeof(reply_header);
369  iov[1].iov_base = &reply;
370  iov[1].iov_len = sizeof(reply);
371  iov[2].iov_base = (char*) msg;
372  iov[2].iov_len = strlen(msg) + 1;
373 
374  reply_header.reply_len = iov[0].iov_len + iov[1].iov_len +
375  iov[2].iov_len;
376  reply_header.reply_cmd = msg_type;
377  reply_header.errno_value = errno_value;
378  reply.pid = getpid();
379  reply.debug_level = level;
380  reply.msg_offs = sizeof(reply);
381 
382  if (reply_header.reply_len > COMM_BUF_SIZE) return -1;
383 
384  /* send message */
385  bytes = writev(ctx->conn_fd, iov, 3);
386  if (bytes != (ssize_t) reply_header.reply_len) return -1;
387  return 0;
388 }
389 
391  struct smb_conn_open_query *query, size_t query_len){
392 
393  const char *url;
394  struct smb_conn_srv_fd *state;
395  struct smb_conn_fd_reply reply;
396 
397  if (query_len <= sizeof(struct smb_conn_open_query)) goto error;
398  if ( *(((char *) query) + query_len - 1) != '\0' ) goto error;
399  if (query->url_offs != sizeof(struct smb_conn_open_query)) goto error;
400 
401  url = smb_conn_srv_get_url_from_query(query, query->url_offs);
402  if (query_len != sizeof(struct smb_conn_open_query) + strlen(url) + 1) goto error;
403  if ((url = charset_local2smb(url)) == NULL) goto error;
404 
405  if ((state = malloc(sizeof(struct smb_conn_srv_fd))) == NULL) goto error;
406 
407  state->type = SMB_CONN_FILE;
408  state->offset = (off_t) (-1);
409  state->fd = smbc_open(url, query->flags, query->mode);
410 
411  if (state->fd < 0){
412  int error = errno;
413 
414  free(state);
415  switch(error){
416  case EACCES:
417  case EEXIST:
418  case EFAULT:
419  case EFBIG:
420  case EINTR:
421  case EISDIR:
422  case ELOOP:
423  case EMFILE:
424  case ENAMETOOLONG:
425  case ENFILE:
426  case ENODEV:
427  case ENOENT:
428  case ENOSPC:
429  case ENOTDIR:
430  case EPERM:
431  case EROFS:
432  case ETXTBSY:
433  smb_conn_srv_send_reply(ctx, OPEN, error, NULL, 0);
434  return;
435  default:
436  goto error;
437  }
438  }
439 
440  reply.srv_fd = state;
441  smb_conn_srv_send_reply(ctx, OPEN, 0, &reply, sizeof(reply));
442  return;
443 
444  error:
445  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
446  exit(EXIT_FAILURE);
447 }
448 
450  struct smb_conn_url_mode_query *query, size_t query_len){
451 
452  const char *url;
453  struct smb_conn_srv_fd *state;
454  struct smb_conn_fd_reply reply;
455 
456  if (query_len <= sizeof(struct smb_conn_url_mode_query)) goto error;
457  if ( *(((char *) query) + query_len - 1) != '\0' ) goto error;
458  if (query->url_offs != sizeof(struct smb_conn_url_mode_query)) goto error;
459 
460  url = smb_conn_srv_get_url_from_query(query, query->url_offs);
461  if (query_len != sizeof(struct smb_conn_url_mode_query) + strlen(url) + 1) goto error;
462  if ((url = charset_local2smb(url)) == NULL) goto error;
463 
464  if ((state = malloc(sizeof(struct smb_conn_srv_fd))) == NULL) goto error;
465 
466  state->type = SMB_CONN_FILE;
467  state->offset = (off_t) (-1);
468  state->fd = smbc_creat(url, query->mode);
469 
470  if (state->fd < 0){
471  int error = errno;
472 
473  free(state);
474  switch(error){
475  case EACCES:
476  case EEXIST:
477  case EFAULT:
478  case EFBIG:
479  case EINTR:
480  case EISDIR:
481  case ELOOP:
482  case EMFILE:
483  case ENAMETOOLONG:
484  case ENFILE:
485  case ENODEV:
486  case ENOENT:
487  case ENOSPC:
488  case ENOTDIR:
489  case EPERM:
490  case EROFS:
491  case ETXTBSY:
492  smb_conn_srv_send_reply(ctx, CREAT, error, NULL, 0);
493  return;
494  default:
495  goto error;
496  }
497  }
498 
499  reply.srv_fd = state;
500  smb_conn_srv_send_reply(ctx, CREAT, 0, &reply, sizeof(reply));
501  return;
502 
503  error:
504  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
505  exit(EXIT_FAILURE);
506 }
507 
509  struct smb_conn_rw_query *query, size_t query_len){
510 
511  struct smb_conn_srv_fd *state;
512  struct smb_conn_buf_reply reply;
513 
514  if (query_len != sizeof(struct smb_conn_rw_query)) goto error;
515  if ((query->offset == (off_t) (-1)) ||
516  (query->bufsize > ctx->shmem_size) ||
517  (query->srv_fd == NULL)) goto error;
518 
519  state = query->srv_fd;
520  if ((state->fd < 0) || (state->type != SMB_CONN_FILE)) goto error;
521 
522  if (state->offset != query->offset){
523  off_t pos;
524 
525  pos = smbc_lseek(state->fd, query->offset, SEEK_SET);
526  if (pos != query->offset) goto error;
527  state->offset = query->offset;
528  }
529 
530  reply.bufsize = smbc_read(state->fd, ctx->shmem_ptr, query->bufsize);
531  if (reply.bufsize < 0){
532  switch(errno){
533  case EAGAIN:
534  case EINTR:
535  case EISDIR:
536  state->offset = (off_t) (-1);
537  smb_conn_srv_send_reply(ctx, READ, errno, NULL, 0);
538  return;
539  default:
540  goto error;
541  }
542  }
543 
544  state->offset += reply.bufsize;
545  msync(ctx->shmem_ptr, reply.bufsize, MS_SYNC);
546  smb_conn_srv_send_reply(ctx, READ, 0, &reply, sizeof(reply));
547  return;
548 
549  error:
550  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
551  exit(EXIT_FAILURE);
552 }
553 
555  struct smb_conn_rw_query *query, size_t query_len){
556 
557  struct smb_conn_srv_fd *state;
558  struct smb_conn_buf_reply reply;
559 
560  if (query_len != sizeof(struct smb_conn_rw_query)) goto error;
561  if ((query->offset == (off_t) (-1)) ||
562  (query->bufsize > ctx->shmem_size) ||
563  (query->srv_fd == NULL)) goto error;
564 
565  state = query->srv_fd;
566  if ((state->fd < 0) || (state->type != SMB_CONN_FILE)) goto error;
567 
568  if (state->offset != query->offset){
569  off_t pos;
570 
571  pos = smbc_lseek(state->fd, query->offset, SEEK_SET);
572  if (pos != query->offset) goto error;
573  state->offset = query->offset;
574  }
575 
576  reply.bufsize = smbc_write(state->fd, ctx->shmem_ptr, query->bufsize);
577  if (reply.bufsize < 0){
578  switch(errno){
579  case EAGAIN:
580  case EINTR:
581  case EINVAL:
582  case EIO:
583  case ENOSPC:
584  case EISDIR:
585  state->offset = (off_t) (-1);
586  smb_conn_srv_send_reply(ctx, WRITE, errno, NULL, 0);
587  return;
588  default:
589  goto error;
590  }
591  }
592 
593  state->offset += reply.bufsize;
594  smb_conn_srv_send_reply(ctx, WRITE, 0, &reply, sizeof(reply));
595  return;
596 
597  error:
598  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
599  exit(EXIT_FAILURE);
600 }
601 
603  struct smb_conn_fd_query *query, size_t query_len){
604 
605  struct smb_conn_srv_fd *state;
606 
607  if (query_len != sizeof(struct smb_conn_fd_query)) goto error;
608  if (query->srv_fd == NULL) goto error;
609 
610  state = query->srv_fd;
611  if ((state->fd < 0) || (state->type != SMB_CONN_FILE)) goto error;
612 
613  if (smbc_close(state->fd) < 0){
614  switch(errno){
615  case EINTR:
616  smb_conn_srv_send_reply(ctx, CLOSE, errno, NULL, 0);
617  return;
618  default:
619  goto error;
620  }
621  }
622 
623  free(state);
624  smb_conn_srv_send_reply(ctx, CLOSE, 0, NULL, 0);
625  return;
626 
627  error:
628  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
629  exit(EXIT_FAILURE);
630 }
631 
633  struct smb_conn_url_query *query, size_t query_len){
634 
635  const char *url;
636  struct stat st;
637 
638  if (query_len <= sizeof(struct smb_conn_url_query)) goto error;
639  if ( *(((char *) query) + query_len - 1) != '\0' ) goto error;
640  if (query->url_offs != sizeof(struct smb_conn_url_query)) goto error;
641 
642  url = smb_conn_srv_get_url_from_query(query, query->url_offs);
643  if (query_len != sizeof(struct smb_conn_url_query) + strlen(url) + 1) goto error;
644  if ((url = charset_local2smb(url)) == NULL) goto error;
645 
646  if (smbc_stat(url, &st) < 0){
647  switch(errno){
648  case EACCES:
649  /* try to continue */
650  break;
651  case ELOOP:
652  case ENAMETOOLONG:
653  case ENOENT:
654  case ENOTDIR:
655  smb_conn_srv_send_reply(ctx, UNLINK, errno, NULL, 0);
656  return;
657  default:
658  goto error;
659  }
660  }else{
661  if (!S_ISREG(st.st_mode)){
662  smb_conn_srv_send_reply(ctx, UNLINK, EISDIR, NULL, 0);
663  return;
664  }
665  if ((st.st_mode & S_IWOTH) != S_IWOTH){
666  if (smbc_chmod(url, st.st_mode | S_IWOTH) < 0){
667  switch(errno){
668  case EACCES:
669  case EIO:
670  case EPERM:
671  /* try to continue */
672  break;
673  case ELOOP:
674  case ENAMETOOLONG:
675  case ENOENT:
676  case ENOTDIR:
677  case EROFS:
678  smb_conn_srv_send_reply(ctx, UNLINK, errno, NULL, 0);
679  return;
680  default:
681  goto error;
682  };
683  }
684  }
685  }
686 
687  if (smbc_unlink(url) < 0){
688  switch(errno){
689  case EACCES:
690  case EBUSY:
691  case EIO:
692  case EISDIR:
693  case ELOOP:
694  case ENAMETOOLONG:
695  case ENOENT:
696  case ENOTDIR:
697  case EPERM:
698  case EROFS:
699  smb_conn_srv_send_reply(ctx, UNLINK, errno, NULL, 0);
700  return;
701  default:
702  goto error;
703  }
704  }
705 
706  smb_conn_srv_send_reply(ctx, UNLINK, 0, NULL, 0);
707  return;
708 
709  error:
710  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
711  exit(EXIT_FAILURE);
712 }
713 
715  struct smb_conn_rename_query *query, size_t query_len){
716 
717  int count;
718  const char *old_url;
719  const char *new_url;
720  const char *pos;
721  struct stat old_st;
722  struct stat new_st;
723 
724  if (query_len <= sizeof(struct smb_conn_rename_query)) goto error;
725  if ( *(((char *) query) + query_len - 1) != '\0' ) goto error;
726  if ((query->old_url_offs != sizeof(struct smb_conn_rename_query)) ||
727  (query->new_url_offs <= query->old_url_offs) ||
728  (query->new_url_offs >= query_len - 1)) goto error;
729 
730  old_url = smb_conn_srv_get_url_from_query(query, query->old_url_offs);
731  new_url = smb_conn_srv_get_url_from_query(query, query->new_url_offs);
732 
733  if (new_url != old_url + strlen(old_url) + 1) goto error;
734  if (query_len != sizeof(struct smb_conn_rename_query) +
735  strlen(old_url) + strlen(new_url) + 2) goto error;
736  if ((new_url = charset_local2smb(new_url)) == NULL) goto error;
737  if ((new_url = strdup(new_url)) == NULL) goto error;
738  if ((old_url = charset_local2smb(old_url)) == NULL) goto error;
739 
740  /*
741  * old_url and new_url should point to the same samba share
742  * try find the position of 4-th '/' in "smb://server/share/path" and
743  * compare samba resource names
744  */
745  for(count = 0, pos = old_url; *pos; pos++)
746  if ((*pos == '/') && (++count == 4)) break;
747  if (*pos != '/'){
748  smb_conn_srv_send_reply(ctx, RENAME, EXDEV, NULL, 0);
749  free((char*)new_url);
750  return;
751  }
752  if (strncasecmp(old_url, new_url, pos - old_url + 1) != 0){
753  smb_conn_srv_send_reply(ctx, RENAME, EXDEV, NULL, 0);
754  free((char*)new_url);
755  return;
756  }
757 
758  if (strcasecmp(new_url, old_url) == 0) goto rename;
759 
760  /* check the presence of old_url */
761  if (smbc_stat(old_url, &old_st) < 0){
762  switch(errno){
763  case EACCES:
764  /* try to continue */
765  goto rename;
766  case ELOOP:
767  case ENAMETOOLONG:
768  case ENOENT:
769  case ENOTDIR:
770  smb_conn_srv_send_reply(ctx, RENAME, errno, NULL, 0);
771  free((char*)new_url);
772  return;
773  default:
774  goto error;
775  }
776  }
777 
778  /* check the presence of new_url, delete new_url if necessary */
779  if (smbc_stat(new_url, &new_st) < 0){
780  switch(errno){
781  case EACCES:
782  /* try to continue */
783  goto rename;
784  case ENOENT:
785  /* OK, new path does not exist */
786  goto rename;
787  case ELOOP:
788  case ENAMETOOLONG:
789  case ENOTDIR:
790  smb_conn_srv_send_reply(ctx, RENAME, errno, NULL, 0);
791  free((char*)new_url);
792  return;
793  default:
794  goto error;
795  }
796  }
797 
798  /* rename dir to file is not possible */
799  if (S_ISDIR(old_st.st_mode) && S_ISREG(new_st.st_mode)){
800  smb_conn_srv_send_reply(ctx, RENAME, ENOTDIR, NULL, 0);
801  free((char*)new_url);
802  return;
803  }
804 
805  /* rename dir to dir, if yes, try to delete new_url directory first */
806  if (S_ISDIR(old_st.st_mode) && S_ISDIR(new_st.st_mode)){
807  if (smbc_rmdir(new_url) != 0){
808  switch(errno){
809  case EACCES:
810  case EBUSY:
811  case EPERM:
812  /* try to continue */
813  goto rename;
814  case EINVAL:
815  case ELOOP:
816  case ENAMETOOLONG:
817  case ENOENT:
818  case ENOTDIR:
819  case ENOTEMPTY:
820  case EROFS:
821  smb_conn_srv_send_reply(ctx, RENAME, errno, NULL, 0);
822  free((char*)new_url);
823  return;
824  default:
825  goto error;
826  }
827  }
828  goto rename;
829  }
830 
831  /* rename file to file, if yes, try to delete new_url file first */
832  if (S_ISREG(old_st.st_mode) && S_ISREG(new_st.st_mode)){
833  if ((new_st.st_mode & S_IWOTH) != S_IWOTH){
834  if (smbc_chmod(new_url, new_st.st_mode | S_IWOTH) < 0){
835  switch(errno){
836  case EACCES:
837  case EIO:
838  case EPERM:
839  case ENOENT:
840  case ENOTDIR:
841  /* try to continue */
842  break;
843  case ELOOP:
844  case ENAMETOOLONG:
845  case EROFS:
846  smb_conn_srv_send_reply(ctx, RENAME, errno, NULL, 0);
847  free((char*)new_url);
848  return;
849  default:
850  goto error;
851  };
852  }
853  }
854  if (smbc_unlink(new_url) < 0){
855  switch(errno){
856  case EACCES:
857  case EBUSY:
858  case EIO:
859  case EISDIR:
860  case ENOENT:
861  case ENOTDIR:
862  case EPERM:
863  /* try to continue */
864  break;
865  case ELOOP:
866  case ENAMETOOLONG:
867  case EROFS:
868  smb_conn_srv_send_reply(ctx, UNLINK, errno, NULL, 0);
869  free((char*)new_url);
870  return;
871  default:
872  goto error;
873  }
874  }
875  }
876 
877  rename:
878 
879  if (smbc_rename(old_url, new_url) < 0){
880  switch(errno){
881  case EACCES:
882  case EBUSY:
883  case EINVAL:
884  case EISDIR:
885  case ELOOP:
886  case EMLINK:
887  case ENAMETOOLONG:
888  case ENOENT:
889  case ENOSPC:
890  case ENOTDIR:
891  case ENOTEMPTY:
892  case EEXIST:
893  case EPERM:
894  case EROFS:
895  case EXDEV:
896  smb_conn_srv_send_reply(ctx, RENAME, errno, NULL, 0);
897  free((char*)new_url);
898  return;
899  default:
900  goto error;
901  }
902  }
903 
904  smb_conn_srv_send_reply(ctx, RENAME, 0, NULL, 0);
905  free((char*)new_url);
906  return;
907 
908  error:
909  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
910  exit(EXIT_FAILURE);
911 }
912 
914  struct smb_conn_url_query *query, size_t query_len){
915 
916  const char *url;
917  struct smb_conn_srv_fd *state;
918  struct smb_conn_fd_reply reply;
919 
920  if (query_len <= sizeof(struct smb_conn_url_query)) goto error;
921  if ( *(((char *) query) + query_len - 1) != '\0' ) goto error;
922  if (query->url_offs != sizeof(struct smb_conn_url_query)) goto error;
923 
924  url = smb_conn_srv_get_url_from_query(query, query->url_offs);
925  if (query_len != sizeof(struct smb_conn_url_query) + strlen(url) + 1) goto error;
926  if ((url = charset_local2smb(url)) == NULL) goto error;
927 
928  if ((state = malloc(sizeof(struct smb_conn_srv_fd))) == NULL) goto error;
929 
930  state->type = SMB_CONN_DIR;
931  state->offset = (off_t) (-1);
932  state->fd = smbc_opendir(url);
933 
934  if (state->fd < 0){
935  int error = errno;
936 
937  free(state);
938  switch(error){
939  case EACCES:
940  case EMFILE:
941  case ENOENT:
942  case ENOTDIR:
943  case EPERM:
944  case ENODEV:
945  smb_conn_srv_send_reply(ctx, OPENDIR, error, NULL, 0);
946  return;
947  default:
948  goto error;
949  }
950  }
951 
952  reply.srv_fd = state;
953  smb_conn_srv_send_reply(ctx, OPENDIR, 0, &reply, sizeof(reply));
954  return;
955 
956  error:
957  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
958  exit(EXIT_FAILURE);
959 }
960 
962  struct smb_conn_fd_query *query, size_t query_len){
963 
964  struct smb_conn_srv_fd *state;
965 
966  if (query_len != sizeof(struct smb_conn_fd_query)) goto error;
967  if (query->srv_fd == NULL) goto error;
968 
969  state = query->srv_fd;
970  if ((state->fd < 0) || (state->type != SMB_CONN_DIR)) goto error;
971 
972  if (smbc_closedir(state->fd) < 0) goto error;
973 
974  free(state);
975  smb_conn_srv_send_reply(ctx, CLOSEDIR, 0, NULL, 0);
976  return;
977 
978  error:
979  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
980  exit(EXIT_FAILURE);
981 }
982 
984  struct smb_conn_rw_query *query, size_t query_len){
985 
986  const char *name;
987  struct smbc_dirent *dirent;
988  struct smb_conn_dirent_rec *pos;
989  struct smb_conn_srv_fd *state;
990  struct smb_conn_buf_reply reply;
991 
992 
993  if (query_len != sizeof(struct smb_conn_rw_query)) goto error;
994  if ((query->offset != (off_t) (-1)) ||
995  (query->bufsize > ctx->shmem_size) ||
996  (query->srv_fd == NULL)) goto error;
997 
998  state = query->srv_fd;
999  if ((state->fd < 0) ||
1000  (state->type != SMB_CONN_DIR) ||
1001  (state->offset != (off_t) (-1))) goto error;
1002 
1003  pos = (struct smb_conn_dirent_rec *) ctx->shmem_ptr;
1004  while((char *) (pos + 1) < ctx->shmem_ptr + query->bufsize){
1005  if ((dirent = smbc_readdir(state->fd)) == NULL) break;
1006  if (strcmp(dirent->name, "") == 0) continue;
1007  if (strcmp(dirent->name, ".") == 0) continue;
1008  if (strcmp(dirent->name, "..") == 0) continue;
1009 
1010  name = charset_smb2local(dirent->name);
1011  if (name == NULL){
1012  /* the name can not be converted :-( */
1013  continue;
1014  }
1015  if (strlen(name) + 1 > sizeof(pos->d_name)){
1016  /* the name does not fit to struct smb_dirent_rec :-( */
1017  continue;
1018  }
1019 
1020  pos->smbc_type = dirent->smbc_type;
1021  strcpy(pos->d_name, name);
1022  pos++;
1023  }
1024 
1025  reply.bufsize = ((char *) pos) - ctx->shmem_ptr;
1026  msync(ctx->shmem_ptr, reply.bufsize, MS_SYNC);
1027  smb_conn_srv_send_reply(ctx, READDIR, 0, &reply, sizeof(reply));
1028  return;
1029 
1030  error:
1031  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
1032  exit(EXIT_FAILURE);
1033 }
1034 
1036  struct smb_conn_url_mode_query *query, size_t query_len){
1037 
1038  const char *url;
1039 
1040  if (query_len <= sizeof(struct smb_conn_url_mode_query)) goto error;
1041  if ( *(((char *) query) + query_len - 1) != '\0' ) goto error;
1042  if (query->url_offs != sizeof(struct smb_conn_url_mode_query)) goto error;
1043 
1044  url = smb_conn_srv_get_url_from_query(query, query->url_offs);
1045  if (query_len != sizeof(struct smb_conn_url_mode_query) + strlen(url) + 1) goto error;
1046  if ((url = charset_local2smb(url)) == NULL) goto error;
1047 
1048  if (smbc_mkdir(url, query->mode) < 0){
1049  switch(errno){
1050  case EACCES:
1051  case EEXIST:
1052  case ELOOP:
1053  case ENAMETOOLONG:
1054  case ENOENT:
1055  case ENOSPC:
1056  case ENOTDIR:
1057  case EPERM:
1058  case EROFS:
1059  smb_conn_srv_send_reply(ctx, MKDIR, errno, NULL, 0);
1060  return;
1061  default:
1062  goto error;
1063  }
1064  }
1065 
1066  smb_conn_srv_send_reply(ctx, MKDIR, 0, NULL, 0);
1067  return;
1068 
1069  error:
1070  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
1071  exit(EXIT_FAILURE);
1072 }
1073 
1075  struct smb_conn_url_query *query, size_t query_len){
1076 
1077  const char *url;
1078 
1079  if (query_len <= sizeof(struct smb_conn_url_query)) goto error;
1080  if ( *(((char *) query) + query_len - 1) != '\0' ) goto error;
1081  if (query->url_offs != sizeof(struct smb_conn_url_query)) goto error;
1082 
1083  url = smb_conn_srv_get_url_from_query(query, query->url_offs);
1084  if (query_len != sizeof(struct smb_conn_url_query) + strlen(url) + 1) goto error;
1085  if ((url = charset_local2smb(url)) == NULL) goto error;
1086 
1087  if (smbc_rmdir(url) < 0){
1088  switch(errno){
1089  case EACCES:
1090  case EBUSY:
1091  case EINVAL:
1092  case ELOOP:
1093  case ENAMETOOLONG:
1094  case ENOENT:
1095  case ENOTDIR:
1096  case ENOTEMPTY:
1097  case EPERM:
1098  case EROFS:
1099  smb_conn_srv_send_reply(ctx, RMDIR, errno, NULL, 0);
1100  return;
1101  default:
1102  goto error;
1103  }
1104  }
1105 
1106  smb_conn_srv_send_reply(ctx, RMDIR, 0, NULL, 0);
1107  return;
1108 
1109  error:
1110  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
1111  exit(EXIT_FAILURE);
1112 }
1113 
1115  struct smb_conn_url_query *query, size_t query_len){
1116 
1117  const char *url;
1118  struct smb_conn_stat_reply reply;
1119 
1120  if (query_len <= sizeof(struct smb_conn_url_query)) goto error;
1121  if ( *(((char *) query) + query_len - 1) != '\0' ) goto error;
1122  if (query->url_offs != sizeof(struct smb_conn_url_query)) goto error;
1123 
1124  url = smb_conn_srv_get_url_from_query(query, query->url_offs);
1125  if (query_len != sizeof(struct smb_conn_url_query) + strlen(url) + 1) goto error;
1126  if ((url = charset_local2smb(url)) == NULL) goto error;
1127 
1128  memset(&reply.stat, 0, sizeof(reply.stat));
1129  if (smbc_stat(url, &reply.stat) < 0){
1130  switch(errno){
1131  case EACCES:
1132  case ELOOP:
1133  case ENAMETOOLONG:
1134  case ENOENT:
1135  case ENOTDIR:
1136  smb_conn_srv_send_reply(ctx, STAT, errno, NULL, 0);
1137  return;
1138  default:
1139  goto error;
1140  }
1141  }
1142 
1143  smb_conn_srv_send_reply(ctx, STAT, 0, &reply, sizeof(reply));
1144  return;
1145 
1146  error:
1147  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
1148  exit(EXIT_FAILURE);
1149 }
1150 
1152  struct smb_conn_fd_query *query, size_t query_len){
1153 
1154  struct smb_conn_srv_fd *state;
1155  struct smb_conn_stat_reply reply;
1156 
1157  if (query_len != sizeof(struct smb_conn_fd_query)) goto error;
1158  if (query->srv_fd == NULL) goto error;
1159 
1160  state = query->srv_fd;
1161  if ((state->fd < 0) || (state->type != SMB_CONN_FILE)) goto error;
1162 
1163  memset(&reply.stat, 0, sizeof(reply.stat));
1164  if (smbc_fstat(state->fd, &reply.stat) < 0){
1165  switch(errno){
1166  case EACCES:
1167  case ELOOP:
1168  case ENAMETOOLONG:
1169  case ENOENT:
1170  case ENOTDIR:
1171  state->offset = (off_t) (-1);
1172  smb_conn_srv_send_reply(ctx, FSTAT, errno, NULL, 0);
1173  return;
1174  default:
1175  goto error;
1176  }
1177  }
1178 
1179  smb_conn_srv_send_reply(ctx, FSTAT, 0, &reply, sizeof(reply));
1180  return;
1181 
1182  error:
1183  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
1184  exit(EXIT_FAILURE);
1185 }
1186 
1188  struct smb_conn_ftruncate_query *query, size_t query_len){
1189 
1190  struct smb_conn_srv_fd *state;
1191 
1192  if (query_len != sizeof(struct smb_conn_ftruncate_query)) goto error;
1193  if ((query->offset == (off_t) (-1)) || (query->srv_fd == NULL)) goto error;
1194 
1195  state = query->srv_fd;
1196  if ((state->fd < 0) || (state->type != SMB_CONN_FILE)) goto error;
1197 
1198  if (smbc_ftruncate(state->fd, query->offset) < 0){
1199  switch(errno){
1200  case EACCES:
1201  case EINTR:
1202  case EINVAL:
1203  case EIO:
1204  case EISDIR:
1205  case ELOOP:
1206  case ENAMETOOLONG:
1207  case ENOENT:
1208  case ENOTDIR:
1209  case EPERM:
1210  case EROFS:
1211  case ETXTBSY:
1212  state->offset = (off_t) (-1);
1213  smb_conn_srv_send_reply(ctx, FTRUNCATE, errno, NULL, 0);
1214  return;
1215  default:
1216  goto error;
1217  }
1218  }
1219 
1220  state->offset = (off_t) (-1);
1221  smb_conn_srv_send_reply(ctx, FTRUNCATE, 0, NULL, 0);
1222  return;
1223 
1224  error:
1225  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
1226  exit(EXIT_FAILURE);
1227 }
1228 
1230  struct smb_conn_url_mode_query *query, size_t query_len){
1231 
1232  const char *url;
1233 
1234  if (query_len <= sizeof(struct smb_conn_url_mode_query)) goto error;
1235  if ( *(((char *) query) + query_len - 1) != '\0' ) goto error;
1236  if (query->url_offs != sizeof(struct smb_conn_url_mode_query)) goto error;
1237 
1238  url = smb_conn_srv_get_url_from_query(query, query->url_offs);
1239  if (query_len != sizeof(struct smb_conn_url_mode_query) + strlen(url) + 1) goto error;
1240  if ((url = charset_local2smb(url)) == NULL) goto error;
1241 
1242  if (smbc_chmod(url, query->mode) < 0){
1243  switch(errno){
1244  case EACCES:
1245  case EIO:
1246  case ELOOP:
1247  case ENAMETOOLONG:
1248  case ENOENT:
1249  case ENOTDIR:
1250  case EPERM:
1251  case EROFS:
1252  smb_conn_srv_send_reply(ctx, CHMOD, errno, NULL, 0);
1253  return;
1254  default:
1255  goto error;
1256  }
1257  }
1258 
1259  smb_conn_srv_send_reply(ctx, CHMOD, 0, NULL, 0);
1260  return;
1261 
1262  error:
1263  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
1264  exit(EXIT_FAILURE);
1265 }
1266 
1268  struct smb_conn_utimes_query *query, size_t query_len){
1269 
1270  const char *url;
1271 
1272  if (query_len <= sizeof(struct smb_conn_utimes_query)) goto error;
1273  if ( *(((char *) query) + query_len - 1) != '\0' ) goto error;
1274  if (query->url_offs != sizeof(struct smb_conn_utimes_query)) goto error;
1275 
1276  url = smb_conn_srv_get_url_from_query(query, query->url_offs);
1277  if (query_len != sizeof(struct smb_conn_utimes_query) + strlen(url) + 1) goto error;
1278  if ((url = charset_local2smb(url)) == NULL) goto error;
1279 
1280  if (smbc_utimes(url, query->tbuf) < 0){
1281  switch(errno){
1282  case EACCES:
1283  case ENOENT:
1284  case EPERM:
1285  case EROFS:
1286  smb_conn_srv_send_reply(ctx, UTIMES, errno, NULL, 0);
1287  return;
1288  default:
1289  goto error;
1290  }
1291  }
1292 
1293  smb_conn_srv_send_reply(ctx, UTIMES, 0, NULL, 0);
1294  return;
1295 
1296  error:
1297  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
1298  exit(EXIT_FAILURE);
1299 }
1300 
1302  struct smb_conn_setxattr_query *query, size_t query_len){
1303 
1304  const char *url;
1305  const char *name;
1306 
1307  if (query_len <= sizeof(struct smb_conn_setxattr_query)) goto error;
1308  if ( *(((char *) query) + query_len - 1) != '\0' ) goto error;
1309  if ((query->url_offs != sizeof(struct smb_conn_setxattr_query)) ||
1310  (query->name_offs <= query->url_offs) ||
1311  (query->name_offs >= query_len - 1)) goto error;
1312 
1313  url = smb_conn_srv_get_url_from_query(query, query->url_offs);
1314  name = smb_conn_srv_get_url_from_query(query, query->name_offs);
1315 
1316  if (name != url + strlen(url) + 1) goto error;
1317  if (query_len != sizeof(struct smb_conn_setxattr_query) +
1318  strlen(url) + strlen(name) + 2) goto error;
1319  if ((url = charset_local2smb(url)) == NULL) goto error;
1320 
1321  if (smbc_setxattr(url, name, ctx->shmem_ptr, query->bufsize, query->flags) < 0){
1322  switch(errno){
1323  case EINVAL:
1324  case EEXIST:
1325  case ENOATTR:
1326  case EPERM:
1327  case ENOTSUP:
1328  case ENOSPC:
1329  case EDQUOT:
1330 
1331  case EACCES:
1332  case ELOOP:
1333  case ENAMETOOLONG:
1334  case ENOTDIR:
1335  smb_conn_srv_send_reply(ctx, SETXATTR, errno, NULL, 0);
1336  return;
1337  default:
1338  goto error;
1339  }
1340  }
1341 
1342  smb_conn_srv_send_reply(ctx, SETXATTR, 0, NULL, 0);
1343  return;
1344 
1345  error:
1346  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
1347  exit(EXIT_FAILURE);
1348 }
1349 
1351  struct smb_conn_getxattr_query *query, size_t query_len){
1352 
1353  const char *url;
1354  const char *name;
1355 
1356  if (query_len <= sizeof(struct smb_conn_getxattr_query)) goto error;
1357  if ( *(((char *) query) + query_len - 1) != '\0' ) goto error;
1358  if ((query->url_offs != sizeof(struct smb_conn_getxattr_query)) ||
1359  (query->name_offs <= query->url_offs) ||
1360  (query->name_offs >= query_len - 1)) goto error;
1361 
1362  url = smb_conn_srv_get_url_from_query(query, query->url_offs);
1363  name = smb_conn_srv_get_url_from_query(query, query->name_offs);
1364 
1365  if (name != url + strlen(url) + 1) goto error;
1366  if (query_len != sizeof(struct smb_conn_getxattr_query) +
1367  strlen(url) + strlen(name) + 2) goto error;
1368  if ((url = charset_local2smb(url)) == NULL) goto error;
1369 
1370  if (smbc_getxattr(url, name, ctx->shmem_ptr, query->bufsize) < 0){
1371  switch(errno){
1372  case EINVAL:
1373  case EEXIST:
1374  case ENOATTR:
1375  case EPERM:
1376  case ENOTSUP:
1377  case ERANGE:
1378 
1379  case EACCES:
1380  case ELOOP:
1381  case ENAMETOOLONG:
1382  case ENOTDIR:
1383  smb_conn_srv_send_reply(ctx, GETXATTR, errno, NULL, 0);
1384  return;
1385  default:
1386  goto error;
1387  }
1388  }
1389 
1390  msync(ctx->shmem_ptr, query->bufsize, MS_SYNC);
1391  smb_conn_srv_send_reply(ctx, GETXATTR, 0, NULL, 0);
1392  return;
1393 
1394  error:
1395  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
1396  exit(EXIT_FAILURE);
1397 }
1398 
1400  struct smb_conn_listxattr_query *query, size_t query_len){
1401 
1402  const char *url;
1403 
1404  if (query_len <= sizeof(struct smb_conn_listxattr_query)) goto error;
1405  if ( *(((char *) query) + query_len - 1) != '\0' ) goto error;
1406  if ((query->url_offs != sizeof(struct smb_conn_listxattr_query)) ||
1407  (query->bufsize > ctx->shmem_size)) goto error;
1408 
1409  url = smb_conn_srv_get_url_from_query(query, query->url_offs);
1410  if (query_len != sizeof(struct smb_conn_listxattr_query) + strlen(url) + 1) goto error;
1411  if ((url = charset_local2smb(url)) == NULL) goto error;
1412 
1413  if (smbc_listxattr(url, ctx->shmem_ptr, query->bufsize) < 0){
1414  switch(errno){
1415  case EPERM:
1416  case ENOTSUP:
1417  case ERANGE:
1418 
1419  case EACCES:
1420  case ELOOP:
1421  case ENAMETOOLONG:
1422  case ENOENT:
1423  case ENOTDIR:
1424  smb_conn_srv_send_reply(ctx, LISTXATTR, errno, NULL, 0);
1425  return;
1426  default:
1427  goto error;
1428  }
1429  }
1430 
1431  msync(ctx->shmem_ptr, query->bufsize, MS_SYNC);
1432  smb_conn_srv_send_reply(ctx, LISTXATTR, 0, NULL, 0);
1433  return;
1434 
1435  error:
1436  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
1437  exit(EXIT_FAILURE);
1438 }
1439 
1441  struct smb_conn_removexattr_query *query, size_t query_len){
1442 
1443  const char *url;
1444  const char *name;
1445 
1446  if (query_len <= sizeof(struct smb_conn_removexattr_query)) goto error;
1447  if ( *(((char *) query) + query_len - 1) != '\0' ) goto error;
1448  if ((query->url_offs != sizeof(struct smb_conn_getxattr_query)) ||
1449  (query->name_offs <= query->url_offs) ||
1450  (query->name_offs >= query_len - 1)) goto error;
1451 
1452  url = smb_conn_srv_get_url_from_query(query, query->url_offs);
1453  name = smb_conn_srv_get_url_from_query(query, query->name_offs);
1454 
1455  if (name != url + strlen(url) + 1) goto error;
1456  if (query_len != sizeof(struct smb_conn_getxattr_query) +
1457  strlen(url) + strlen(name) + 2) goto error;
1458  if ((url = charset_local2smb(url)) == NULL) goto error;
1459 
1460  if (smbc_removexattr(url, name) < 0){
1461  switch(errno){
1462  case ENOATTR:
1463  case EPERM:
1464  case ENOTSUP:
1465 
1466  case EACCES:
1467  case ELOOP:
1468  case ENAMETOOLONG:
1469  case ENOTDIR:
1470  smb_conn_srv_send_reply(ctx, REMOVEXATTR, errno, NULL, 0);
1471  return;
1472  default:
1473  goto error;
1474  }
1475  }
1476 
1477  smb_conn_srv_send_reply(ctx, REMOVEXATTR, 0, NULL, 0);
1478  return;
1479 
1480  error:
1481  DSRVDIEMSG(ctx, errno, "errno=%d, %s\n", errno, strerror(errno));
1482  exit(EXIT_FAILURE);
1483 }
char * charset_smb2local_r(const char *src, char *dst, size_t dst_len)
Definition: charset.c:134
char * charset_local2smb(const char *src)
Definition: charset.c:145
int charset_init(const char *local, const char *samba)
Definition: charset.c:14
static char charset_buf[2048]
Definition: charset.c:7
char * charset_smb2local(const char *src)
Definition: charset.c:151
#define CHARSET_BUF_SIZE
Definition: charset.h:6
#define COMM_BUF_SIZE
Definition: smb_conn_proto.h:8
smb_conn_cmd
@ PASSWORD
@ LISTXATTR
@ OPEN
@ CLOSEDIR
@ FSTAT
@ UNLINK
@ DIE_MSG
@ FTRUNCATE
@ WRITE
@ CLOSE
@ SETXATTR
@ REMOVEXATTR
@ OPENDIR
@ CREAT
@ READDIR
@ MKDIR
@ MESSAGE
@ CHMOD
@ RMDIR
@ READ
@ STAT
@ UTIMES
@ RENAME
@ GETXATTR
int smb_conn_srv_send_msg(struct smb_conn_srv_ctx *ctx, enum smb_conn_cmd msg_type, int errno_value, int level, const char *msg)
Definition: smb_conn_srv.c:356
void smb_conn_srv_unlink(struct smb_conn_srv_ctx *ctx, struct smb_conn_url_query *query, size_t query_len)
Definition: smb_conn_srv.c:632
void smb_conn_srv_readdir(struct smb_conn_srv_ctx *ctx, struct smb_conn_rw_query *query, size_t query_len)
Definition: smb_conn_srv.c:983
void smb_conn_srv_chmod(struct smb_conn_srv_ctx *ctx, struct smb_conn_url_mode_query *query, size_t query_len)
void smb_conn_srv_listxattr(struct smb_conn_srv_ctx *ctx, struct smb_conn_listxattr_query *query, size_t query_len)
void smb_conn_srv_rename(struct smb_conn_srv_ctx *ctx, struct smb_conn_rename_query *query, size_t query_len)
Definition: smb_conn_srv.c:714
void smb_conn_srv_ftruncate(struct smb_conn_srv_ctx *ctx, struct smb_conn_ftruncate_query *query, size_t query_len)
static void smb_conn_srv_samba_init(struct smb_conn_srv_ctx *srv_ctx)
Definition: smb_conn_srv.c:164
void smb_conn_srv_close(struct smb_conn_srv_ctx *ctx, struct smb_conn_fd_query *query, size_t query_len)
Definition: smb_conn_srv.c:602
void smb_conn_srv_mkdir(struct smb_conn_srv_ctx *ctx, struct smb_conn_url_mode_query *query, size_t query_len)
void smb_conn_srv_closedir(struct smb_conn_srv_ctx *ctx, struct smb_conn_fd_query *query, size_t query_len)
Definition: smb_conn_srv.c:961
void smb_conn_srv_stat(struct smb_conn_srv_ctx *ctx, struct smb_conn_url_query *query, size_t query_len)
void smb_conn_srv_send_reply(struct smb_conn_srv_ctx *ctx, enum smb_conn_cmd reply_cmd, int errno_value, void *reply, size_t reply_len)
Definition: smb_conn_srv.c:314
void smb_conn_srv_creat(struct smb_conn_srv_ctx *ctx, struct smb_conn_url_mode_query *query, size_t query_len)
Definition: smb_conn_srv.c:449
void smb_conn_srv_fstat(struct smb_conn_srv_ctx *ctx, struct smb_conn_fd_query *query, size_t query_len)
void smb_conn_srv_removexattr(struct smb_conn_srv_ctx *ctx, struct smb_conn_removexattr_query *query, size_t query_len)
void smb_conn_srv_listen(struct smb_conn_srv_ctx *ctx)
Definition: smb_conn_srv.c:185
static void smb_conn_srv_auth_fn(SMBCCTX *ctx, const char *server, const char *share, char *wrkgrp, int wrkgrplen, char *user, int userlen, char *passwd, int passwdlen)
Definition: smb_conn_srv.c:52
void smb_conn_srv_read(struct smb_conn_srv_ctx *ctx, struct smb_conn_rw_query *query, size_t query_len)
Definition: smb_conn_srv.c:508
void smb_conn_srv_setxattr(struct smb_conn_srv_ctx *ctx, struct smb_conn_setxattr_query *query, size_t query_len)
void smb_conn_srv_getxattr(struct smb_conn_srv_ctx *ctx, struct smb_conn_getxattr_query *query, size_t query_len)
void smb_conn_srv_opendir(struct smb_conn_srv_ctx *ctx, struct smb_conn_url_query *query, size_t query_len)
Definition: smb_conn_srv.c:913
void smb_conn_srv_write(struct smb_conn_srv_ctx *ctx, struct smb_conn_rw_query *query, size_t query_len)
Definition: smb_conn_srv.c:554
void smb_conn_srv_rmdir(struct smb_conn_srv_ctx *ctx, struct smb_conn_url_query *query, size_t query_len)
void smb_conn_srv_utimes(struct smb_conn_srv_ctx *ctx, struct smb_conn_utimes_query *query, size_t query_len)
void smb_conn_srv_debug_print(struct smb_conn_srv_ctx *ctx, enum smb_conn_cmd msg_type, int errno_value, int level, int no_fallback, const char *fmt,...)
Definition: smb_conn_srv.c:18
void smb_conn_srv_open(struct smb_conn_srv_ctx *ctx, struct smb_conn_open_query *query, size_t query_len)
Definition: smb_conn_srv.c:390
static const char * smb_conn_srv_get_url_from_query(const void *query, size_t url_offs)
Definition: smb_conn_srv.h:66
#define DSRVPRINTF(ctx, level_value, fmt, args...)
Definition: smb_conn_srv.h:81
@ SMB_CONN_DIR
Definition: smb_conn_srv.h:18
@ SMB_CONN_FILE
Definition: smb_conn_srv.h:17
#define DSRVDIEMSG(ctx, errno_value, fmt, args...)
Definition: smb_conn_srv.h:82
unsigned int smbc_type
smb_conn_srv_fd srv_fd
smb_conn_srv_fd srv_fd
smb_conn_srv_fd srv_fd
enum smb_conn_cmd query_cmd
enum smb_conn_cmd reply_cmd
smb_conn_srv_fd srv_fd
const char * local_charset
const char * samba_charset
enum smb_conn_srv_fd_type type
Definition: smb_conn_srv.h:22
struct timeval tbuf[2]