"Fossies" - the Fresh Open Source Software Archive 
Member "smbnetfs-0.6.3/src/smb_conn_srv.c" (2 Mar 2019, 40451 Bytes) of package /linux/misc/smbnetfs-0.6.3.tar.bz2:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "smb_conn_srv.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
0.6.1_vs_0.6.2.
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
18 void smb_conn_srv_debug_print(struct smb_conn_srv_ctx *ctx,
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
185 void smb_conn_srv_listen(struct smb_conn_srv_ctx *ctx){
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 }
193 smb_conn_srv_samba_init(ctx);
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
314 void smb_conn_srv_send_reply(struct smb_conn_srv_ctx *ctx,
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
356 int smb_conn_srv_send_msg(struct smb_conn_srv_ctx *ctx,
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
390 void smb_conn_srv_open(struct smb_conn_srv_ctx *ctx,
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
449 void smb_conn_srv_creat(struct smb_conn_srv_ctx *ctx,
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
508 void smb_conn_srv_read(struct smb_conn_srv_ctx *ctx,
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
554 void smb_conn_srv_write(struct smb_conn_srv_ctx *ctx,
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
602 void smb_conn_srv_close(struct smb_conn_srv_ctx *ctx,
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
632 void smb_conn_srv_unlink(struct smb_conn_srv_ctx *ctx,
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
714 void smb_conn_srv_rename(struct smb_conn_srv_ctx *ctx,
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
913 void smb_conn_srv_opendir(struct smb_conn_srv_ctx *ctx,
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
961 void smb_conn_srv_closedir(struct smb_conn_srv_ctx *ctx,
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
983 void smb_conn_srv_readdir(struct smb_conn_srv_ctx *ctx,
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
1035 void smb_conn_srv_mkdir(struct smb_conn_srv_ctx *ctx,
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
1074 void smb_conn_srv_rmdir(struct smb_conn_srv_ctx *ctx,
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
1114 void smb_conn_srv_stat(struct smb_conn_srv_ctx *ctx,
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
1151 void smb_conn_srv_fstat(struct smb_conn_srv_ctx *ctx,
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
1187 void smb_conn_srv_ftruncate(struct smb_conn_srv_ctx *ctx,
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
1229 void smb_conn_srv_chmod(struct smb_conn_srv_ctx *ctx,
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
1267 void smb_conn_srv_utimes(struct smb_conn_srv_ctx *ctx,
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
1301 void smb_conn_srv_setxattr(struct smb_conn_srv_ctx *ctx,
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
1350 void smb_conn_srv_getxattr(struct smb_conn_srv_ctx *ctx,
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
1399 void smb_conn_srv_listxattr(struct smb_conn_srv_ctx *ctx,
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
1440 void smb_conn_srv_removexattr(struct smb_conn_srv_ctx *ctx,
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 }