1 /*
2 * Part of Very Secure FTPd
3 * Licence: GPL v2
4 * Author: Chris Evans
5 *
6 * sysutil.c
7 *
8 * Routines to make the libc/syscall API more pleasant to use. Long term,
9 * more libc/syscalls will go in here to reduce the number of .c files with
10 * dependencies on libc or syscalls.
11 */
12
13 #define PRIVATE_HANDS_OFF_syscall_retval syscall_retval
14 #define PRIVATE_HANDS_OFF_exit_status exit_status
15 #include "sysutil.h"
16 #include "utility.h"
17 #include "tunables.h"
18 #include "sysdeputil.h"
19
20 /* Activate 64-bit file support on Linux/32bit plus others */
21 #define _FILE_OFFSET_BITS 64
22 #define _LARGEFILE_SOURCE 1
23 #define _LARGEFILE64_SOURCE 1
24 #define _LARGE_FILES 1
25
26 /* For Linux, this adds nothing :-) */
27 #include "port/porting_junk.h"
28
29 #include <signal.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <sys/mman.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <netinet/in.h>
39 #include <stdio.h>
40 #include <dirent.h>
41 #include <time.h>
42 #include <arpa/inet.h>
43 #include <errno.h>
44 #include <pwd.h>
45 #include <grp.h>
46 #include <ctype.h>
47 #include <sys/wait.h>
48 #include <sys/time.h>
49 /* Must be before netinet/ip.h. Found on FreeBSD, Solaris */
50 #include <netinet/in_systm.h>
51 #include <netinet/ip.h>
52 #include <netinet/tcp.h>
53 #include <limits.h>
54 #include <syslog.h>
55 #include <utime.h>
56 #include <netdb.h>
57 #include <sys/resource.h>
58
59 /* Private variables to this file */
60 /* Current umask() */
61 static unsigned int s_current_umask;
62 /* Cached time */
63 static struct timeval s_current_time;
64 /* Current pid */
65 static int s_current_pid = -1;
66 /* Exit function */
67 static exitfunc_t s_exit_func;
68 /* Difference in timezone from GMT in seconds */
69 static long s_timezone;
70
71 /* Our internal signal handling implementation details */
72 static struct vsf_sysutil_sig_details
73 {
74 vsf_sighandle_t sync_sig_handler;
75 void* p_private;
76 volatile sig_atomic_t pending;
77 int running;
78 int use_alarm;
79 } s_sig_details[NSIG];
80
81 static vsf_context_io_t s_io_handler;
82 static void* s_p_io_handler_private;
83 static int s_io_handler_running;
84
85 struct vsf_sysutil_sockaddr
86 {
87 union
88 {
89 struct sockaddr u_sockaddr;
90 struct sockaddr_in u_sockaddr_in;
91 struct sockaddr_in6 u_sockaddr_in6;
92 } u;
93 };
94
95 /* File locals */
96 static void vsf_sysutil_common_sighandler(int signum);
97 static void vsf_sysutil_alrm_sighandler(int signum);
98 static int vsf_sysutil_translate_sig(const enum EVSFSysUtilSignal sig);
99 static void vsf_sysutil_set_sighandler(int sig, void (*p_handlefunc)(int));
100 static int vsf_sysutil_translate_memprot(
101 const enum EVSFSysUtilMapPermission perm);
102 static int vsf_sysutil_translate_openmode(
103 const enum EVSFSysUtilOpenMode mode);
104 static void vsf_sysutil_alloc_statbuf(struct vsf_sysutil_statbuf** p_ptr);
105 void vsf_sysutil_sockaddr_alloc(struct vsf_sysutil_sockaddr** p_sockptr);
106 static int lock_internal(int fd, int lock_type);
107
108 static void
vsf_sysutil_alrm_sighandler(int signum)109 vsf_sysutil_alrm_sighandler(int signum)
110 {
111 (void) signum;
112 alarm(1);
113 }
114
115 static void
vsf_sysutil_common_sighandler(int signum)116 vsf_sysutil_common_sighandler(int signum)
117 {
118 if (signum < 0 || signum >= NSIG)
119 {
120 /* "cannot happen" */
121 return;
122 }
123 if (s_sig_details[signum].sync_sig_handler)
124 {
125 s_sig_details[signum].pending = 1;
126 /* Since this synchronous signal framework has a small race (signal coming
127 * in just before we start a blocking call), there's the option to fire an
128 * alarm repeatedly until the signal is handled.
129 */
130 if (s_sig_details[signum].use_alarm)
131 {
132 alarm(1);
133 }
134 }
135 }
136
137 /* Notes. This signal check is evaluated after potentially blocking system
138 * calls, i.e. at highly defined points in the code. Since we only interrupt
139 * at these definite locations, the signal handlers can be non-trivial
140 * without us having to worry about re-entrancy.
141 *
142 * We guarantee that a handler for a given signal is not re-entrant. This
143 * is taken care of by the "running" flag.
144 *
145 * This call itself can only be re-entered once we dereference the actual
146 * hander function pointer, so we are safe with respect to races modifying
147 * the "running" flag.
148 */
149 void
vsf_sysutil_check_pending_actions(const enum EVSFSysUtilInterruptContext context,int retval,int fd)150 vsf_sysutil_check_pending_actions(
151 const enum EVSFSysUtilInterruptContext context, int retval, int fd)
152 {
153 unsigned int i;
154 /* Check the i/o handler before the signal handlers */
155 if (s_io_handler && !s_io_handler_running && context == kVSFSysUtilIO)
156 {
157 s_io_handler_running = 1;
158 (*s_io_handler)(retval, fd, s_p_io_handler_private);
159 s_io_handler_running = 0;
160 }
161 for (i=0; i < NSIG; ++i)
162 {
163 if (s_sig_details[i].pending && !s_sig_details[i].running)
164 {
165 s_sig_details[i].running = 1;
166 if (s_sig_details[i].use_alarm)
167 {
168 alarm(0);
169 }
170 if (s_sig_details[i].sync_sig_handler)
171 {
172 s_sig_details[i].pending = 0;
173 (*(s_sig_details[i].sync_sig_handler))(s_sig_details[i].p_private);
174 }
175 s_sig_details[i].running = 0;
176 }
177 }
178 }
179
180 static int
vsf_sysutil_translate_sig(const enum EVSFSysUtilSignal sig)181 vsf_sysutil_translate_sig(const enum EVSFSysUtilSignal sig)
182 {
183 int realsig = 0;
184 switch (sig)
185 {
186 case kVSFSysUtilSigALRM:
187 realsig = SIGALRM;
188 break;
189 case kVSFSysUtilSigTERM:
190 realsig = SIGTERM;
191 break;
192 case kVSFSysUtilSigCHLD:
193 realsig = SIGCHLD;
194 break;
195 case kVSFSysUtilSigPIPE:
196 realsig = SIGPIPE;
197 break;
198 case kVSFSysUtilSigURG:
199 realsig = SIGURG;
200 break;
201 case kVSFSysUtilSigHUP:
202 realsig = SIGHUP;
203 break;
204 case kVSFSysUtilSigUSR1:
205 realsig = SIGUSR1;
206 break;
207 default:
208 bug("unknown signal in vsf_sysutil_translate_sig");
209 break;
210 }
211 if (realsig < 0 || realsig >= NSIG)
212 {
213 bug("signal out of range in vsf_sysutil_translate_sig");
214 }
215 return realsig;
216 }
217
218 void
vsf_sysutil_install_sighandler(const enum EVSFSysUtilSignal sig,vsf_sighandle_t handler,void * p_private,int use_alarm)219 vsf_sysutil_install_sighandler(const enum EVSFSysUtilSignal sig,
220 vsf_sighandle_t handler,
221 void* p_private,
222 int use_alarm)
223 {
224 int realsig = vsf_sysutil_translate_sig(sig);
225 s_sig_details[realsig].p_private = p_private;
226 s_sig_details[realsig].sync_sig_handler = handler;
227 s_sig_details[realsig].use_alarm = use_alarm;
228 vsf_sysutil_set_sighandler(realsig, vsf_sysutil_common_sighandler);
229 if (use_alarm && realsig != SIGALRM)
230 {
231 vsf_sysutil_set_sighandler(SIGALRM, vsf_sysutil_alrm_sighandler);
232 }
233 }
234
235 void
vsf_sysutil_default_sig(const enum EVSFSysUtilSignal sig)236 vsf_sysutil_default_sig(const enum EVSFSysUtilSignal sig)
237 {
238 int realsig = vsf_sysutil_translate_sig(sig);
239 vsf_sysutil_set_sighandler(realsig, SIG_DFL);
240 s_sig_details[realsig].p_private = NULL;
241 s_sig_details[realsig].sync_sig_handler = NULL;
242 }
243
244 void
vsf_sysutil_install_null_sighandler(const enum EVSFSysUtilSignal sig)245 vsf_sysutil_install_null_sighandler(const enum EVSFSysUtilSignal sig)
246 {
247 int realsig = vsf_sysutil_translate_sig(sig);
248 s_sig_details[realsig].p_private = NULL;
249 s_sig_details[realsig].sync_sig_handler = NULL;
250 vsf_sysutil_set_sighandler(realsig, vsf_sysutil_common_sighandler);
251 }
252
253 void
vsf_sysutil_install_async_sighandler(const enum EVSFSysUtilSignal sig,vsf_async_sighandle_t handler)254 vsf_sysutil_install_async_sighandler(const enum EVSFSysUtilSignal sig,
255 vsf_async_sighandle_t handler)
256 {
257 int realsig = vsf_sysutil_translate_sig(sig);
258 s_sig_details[realsig].p_private = NULL;
259 s_sig_details[realsig].sync_sig_handler = NULL;
260 vsf_sysutil_block_sig(sig);
261 vsf_sysutil_set_sighandler(realsig, handler);
262 }
263
264 static void
vsf_sysutil_set_sighandler(int sig,void (* p_handlefunc)(int))265 vsf_sysutil_set_sighandler(int sig, void (*p_handlefunc)(int))
266 {
267 int retval;
268 struct sigaction sigact;
269 vsf_sysutil_memclr(&sigact, sizeof(sigact));
270 sigact.sa_handler = p_handlefunc;
271 retval = sigfillset(&sigact.sa_mask);
272 if (retval != 0)
273 {
274 die("sigfillset");
275 }
276 retval = sigaction(sig, &sigact, NULL);
277 if (retval != 0)
278 {
279 die("sigaction");
280 }
281 }
282
283 void
vsf_sysutil_block_sig(const enum EVSFSysUtilSignal sig)284 vsf_sysutil_block_sig(const enum EVSFSysUtilSignal sig)
285 {
286 sigset_t sset;
287 int retval;
288 int realsig = vsf_sysutil_translate_sig(sig);
289 retval = sigemptyset(&sset);
290 if (retval != 0)
291 {
292 die("sigemptyset");
293 }
294 retval = sigaddset(&sset, realsig);
295 if (retval != 0)
296 {
297 die("sigaddset");
298 }
299 retval = sigprocmask(SIG_BLOCK, &sset, NULL);
300 if (retval != 0)
301 {
302 die("sigprocmask");
303 }
304 }
305
306 void
vsf_sysutil_unblock_sig(const enum EVSFSysUtilSignal sig)307 vsf_sysutil_unblock_sig(const enum EVSFSysUtilSignal sig)
308 {
309 sigset_t sset;
310 int retval;
311 int realsig = vsf_sysutil_translate_sig(sig);
312 retval = sigemptyset(&sset);
313 if (retval != 0)
314 {
315 die("sigemptyset");
316 }
317 retval = sigaddset(&sset, realsig);
318 if (retval != 0)
319 {
320 die("sigaddset");
321 }
322 retval = sigprocmask(SIG_UNBLOCK, &sset, NULL);
323 if (retval != 0)
324 {
325 die("sigprocmask");
326 }
327 }
328 void
vsf_sysutil_install_io_handler(vsf_context_io_t handler,void * p_private)329 vsf_sysutil_install_io_handler(vsf_context_io_t handler, void* p_private)
330 {
331 if (s_io_handler != NULL)
332 {
333 bug("double register of i/o handler");
334 }
335 s_io_handler = handler;
336 s_p_io_handler_private = p_private;
337 }
338
339 void
vsf_sysutil_uninstall_io_handler(void)340 vsf_sysutil_uninstall_io_handler(void)
341 {
342 if (s_io_handler == NULL)
343 {
344 bug("no i/o handler to unregister!");
345 }
346 s_io_handler = NULL;
347 s_p_io_handler_private = NULL;
348 }
349
350 void
vsf_sysutil_set_alarm(const unsigned int trigger_seconds)351 vsf_sysutil_set_alarm(const unsigned int trigger_seconds)
352 {
353 (void) alarm(trigger_seconds);
354 }
355
356 void
vsf_sysutil_clear_alarm(void)357 vsf_sysutil_clear_alarm(void)
358 {
359 vsf_sysutil_set_alarm(0);
360 }
361
362 int
vsf_sysutil_read(const int fd,void * p_buf,const unsigned int size)363 vsf_sysutil_read(const int fd, void* p_buf, const unsigned int size)
364 {
365 while (1)
366 {
367 int retval = read(fd, p_buf, size);
368 int saved_errno = errno;
369 vsf_sysutil_check_pending_actions(kVSFSysUtilIO, retval, fd);
370 if (retval < 0 && saved_errno == EINTR)
371 {
372 continue;
373 }
374 return retval;
375 }
376 }
377
378 int
vsf_sysutil_write(const int fd,const void * p_buf,const unsigned int size)379 vsf_sysutil_write(const int fd, const void* p_buf, const unsigned int size)
380 {
381 while (1)
382 {
383 int retval = write(fd, p_buf, size);
384 int saved_errno = errno;
385 vsf_sysutil_check_pending_actions(kVSFSysUtilIO, retval, fd);
386 if (retval < 0 && saved_errno == EINTR)
387 {
388 continue;
389 }
390 return retval;
391 }
392 }
393
394 int
vsf_sysutil_read_loop(const int fd,void * p_buf,unsigned int size)395 vsf_sysutil_read_loop(const int fd, void* p_buf, unsigned int size)
396 {
397 int retval;
398 int num_read = 0;
399 if (size > INT_MAX)
400 {
401 die("size too big in vsf_sysutil_read_loop");
402 }
403 while (1)
404 {
405 retval = vsf_sysutil_read(fd, (char*)p_buf + num_read, size);
406 if (retval < 0)
407 {
408 return retval;
409 }
410 else if (retval == 0)
411 {
412 /* Read all we're going to read.. */
413 return num_read;
414 }
415 if ((unsigned int) retval > size)
416 {
417 die("retval too big in vsf_sysutil_read_loop");
418 }
419 num_read += retval;
420 size -= (unsigned int) retval;
421 if (size == 0)
422 {
423 /* Hit the read target, cool. */
424 return num_read;
425 }
426 }
427 }
428
429 int
vsf_sysutil_write_loop(const int fd,const void * p_buf,unsigned int size)430 vsf_sysutil_write_loop(const int fd, const void* p_buf, unsigned int size)
431 {
432 int retval;
433 int num_written = 0;
434 if (size > INT_MAX)
435 {
436 die("size too big in vsf_sysutil_write_loop");
437 }
438 while (1)
439 {
440 retval = vsf_sysutil_write(fd, (const char*)p_buf + num_written, size);
441 if (retval < 0)
442 {
443 /* Error */
444 return retval;
445 }
446 else if (retval == 0)
447 {
448 /* Written all we're going to write.. */
449 return num_written;
450 }
451 if ((unsigned int) retval > size)
452 {
453 die("retval too big in vsf_sysutil_write_loop");
454 }
455 num_written += retval;
456 size -= (unsigned int) retval;
457 if (size == 0)
458 {
459 /* Hit the write target, cool. */
460 return num_written;
461 }
462 }
463 }
464
465 filesize_t
vsf_sysutil_get_file_offset(const int file_fd)466 vsf_sysutil_get_file_offset(const int file_fd)
467 {
468 filesize_t retval = lseek(file_fd, 0, SEEK_CUR);
469 if (retval < 0)
470 {
471 die("lseek");
472 }
473 return retval;
474 }
475
476 void
vsf_sysutil_lseek_to(const int fd,filesize_t seek_pos)477 vsf_sysutil_lseek_to(const int fd, filesize_t seek_pos)
478 {
479 filesize_t retval;
480 if (seek_pos < 0)
481 {
482 die("negative seek_pos in vsf_sysutil_lseek_to");
483 }
484 retval = lseek(fd, seek_pos, SEEK_SET);
485 if (retval < 0)
486 {
487 die("lseek");
488 }
489 }
490
491 void
vsf_sysutil_lseek_end(const int fd)492 vsf_sysutil_lseek_end(const int fd)
493 {
494 filesize_t retval;
495 retval = lseek(fd, 0, SEEK_END);
496 if (retval < 0)
497 {
498 die("lseek");
499 }
500 }
501
502 void
vsf_sysutil_fillbuff(void * buff,unsigned int size,char chr)503 vsf_sysutil_fillbuff(void* buff, unsigned int size, char chr)
504 {
505 if (size == 0 || size > INT_MAX || buff == NULL)
506 {
507 return;
508 }
509 while (size != 0)
510 {
511 *(char*)buff = chr;
512 buff++;
513 size--;
514 }
515 return;
516 }
517
518 void*
vsf_sysutil_malloc(unsigned int size)519 vsf_sysutil_malloc(unsigned int size)
520 {
521 void* p_ret;
522 /* Paranoia - what if we got an integer overflow/underflow? */
523 if (size == 0 || size > INT_MAX)
524 {
525 bug("zero or big size in vsf_sysutil_malloc");
526 }
527 p_ret = malloc(size);
528 if (p_ret == NULL)
529 {
530 die("malloc");
531 }
532 return p_ret;
533 }
534
535 void*
vsf_sysutil_malloc_zero(unsigned int size)536 vsf_sysutil_malloc_zero(unsigned int size)
537 {
538 void* p_ret;
539 p_ret = vsf_sysutil_malloc(size);
540 vsf_sysutil_fillbuff(p_ret, size, 0);
541 return p_ret;
542 }
543
544 void*
vsf_sysutil_realloc(void * p_ptr,unsigned int size)545 vsf_sysutil_realloc(void* p_ptr, unsigned int size)
546 {
547 void* p_ret;
548 if (size == 0 || size > INT_MAX)
549 {
550 bug("zero or big size in vsf_sysutil_realloc");
551 }
552 p_ret = realloc(p_ptr, size);
553 if (p_ret == NULL)
554 {
555 die("realloc");
556 }
557 return p_ret;
558 }
559
560 void
vsf_sysutil_free(void * p_ptr)561 vsf_sysutil_free(void* p_ptr)
562 {
563 if (p_ptr == NULL)
564 {
565 bug("vsf_sysutil_free got a null pointer");
566 }
567 free(p_ptr);
568 }
569
570 unsigned int
vsf_sysutil_getpid(void)571 vsf_sysutil_getpid(void)
572 {
573 if (s_current_pid == -1)
574 {
575 s_current_pid = vsf_sysutil_getpid_nocache();
576 }
577 return (unsigned int) s_current_pid;
578 }
579
580 unsigned int
vsf_sysutil_getppid(void)581 vsf_sysutil_getppid(void)
582 {
583 return (unsigned int)getppid();
584 }
585
586 int
vsf_sysutil_fork(void)587 vsf_sysutil_fork(void)
588 {
589 /* Child does NOT inherit exit function */
590 exitfunc_t curr_func = s_exit_func;
591 int retval;
592 s_exit_func = 0;
593 retval = vsf_sysutil_fork_failok();
594 if (retval != 0)
595 {
596 s_exit_func = curr_func;
597 }
598 if (retval < 0)
599 {
600 die("fork");
601 }
602 return retval;
603 }
604
605 int
vsf_sysutil_fork_failok(void)606 vsf_sysutil_fork_failok(void)
607 {
608 int retval;
609 retval = fork();
610 if (retval == 0)
611 {
612 vsf_sysutil_post_fork();
613 }
614 return retval;
615 }
616
617 void
vsf_sysutil_set_exit_func(exitfunc_t exitfunc)618 vsf_sysutil_set_exit_func(exitfunc_t exitfunc)
619 {
620 s_exit_func = exitfunc;
621 }
622
623 void
vsf_sysutil_exit(int exit_code)624 vsf_sysutil_exit(int exit_code)
625 {
626 if (s_exit_func)
627 {
628 exitfunc_t curr_func = s_exit_func;
629 /* Prevent recursion */
630 s_exit_func = 0;
631 (*curr_func)();
632 }
633 _exit(exit_code);
634 }
635
636 struct vsf_sysutil_wait_retval
vsf_sysutil_wait(void)637 vsf_sysutil_wait(void)
638 {
639 struct vsf_sysutil_wait_retval retval;
640 vsf_sysutil_memclr(&retval, sizeof(retval));
641 while (1)
642 {
643 int sys_ret = wait(&retval.exit_status);
644 if (sys_ret < 0 && errno == EINTR)
645 {
646 vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
647 continue;
648 }
649 retval.syscall_retval = sys_ret;
650 return retval;
651 }
652 }
653
654 int
vsf_sysutil_wait_reap_one(void)655 vsf_sysutil_wait_reap_one(void)
656 {
657 int retval = waitpid(-1, NULL, WNOHANG);
658 if (retval == 0 || (retval < 0 && errno == ECHILD))
659 {
660 /* No more children */
661 return 0;
662 }
663 if (retval < 0)
664 {
665 die("waitpid");
666 }
667 /* Got one */
668 return retval;
669 }
670
671 int
vsf_sysutil_wait_get_retval(const struct vsf_sysutil_wait_retval * p_waitret)672 vsf_sysutil_wait_get_retval(const struct vsf_sysutil_wait_retval* p_waitret)
673 {
674 return p_waitret->syscall_retval;
675 }
676
677 int
vsf_sysutil_wait_exited_normally(const struct vsf_sysutil_wait_retval * p_waitret)678 vsf_sysutil_wait_exited_normally(
679 const struct vsf_sysutil_wait_retval* p_waitret)
680 {
681 int status = ((struct vsf_sysutil_wait_retval*) p_waitret)->exit_status;
682 return WIFEXITED(status);
683 }
684
685 int
vsf_sysutil_wait_get_exitcode(const struct vsf_sysutil_wait_retval * p_waitret)686 vsf_sysutil_wait_get_exitcode(const struct vsf_sysutil_wait_retval* p_waitret)
687 {
688 int status;
689 if (!vsf_sysutil_wait_exited_normally(p_waitret))
690 {
691 bug("not a normal exit in vsf_sysutil_wait_get_exitcode");
692 }
693 status = ((struct vsf_sysutil_wait_retval*) p_waitret)->exit_status;
694 return WEXITSTATUS(status);
695 }
696
697 void
vsf_sysutil_activate_keepalive(int fd)698 vsf_sysutil_activate_keepalive(int fd)
699 {
700 int keepalive = 1;
701 int retval = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
702 sizeof(keepalive));
703 if (retval != 0)
704 {
705 die("setsockopt: keepalive");
706 }
707 }
708
709 void
vsf_sysutil_activate_reuseaddr(int fd)710 vsf_sysutil_activate_reuseaddr(int fd)
711 {
712 int reuseaddr = 1;
713 int retval = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
714 sizeof(reuseaddr));
715 if (retval != 0)
716 {
717 die("setsockopt: reuseaddr");
718 }
719 }
720
721 void
vsf_sysutil_set_nodelay(int fd)722 vsf_sysutil_set_nodelay(int fd)
723 {
724 int nodelay = 1;
725 int retval = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &nodelay,
726 sizeof(nodelay));
727 if (retval != 0)
728 {
729 die("setsockopt: nodelay");
730 }
731 }
732
733 void
vsf_sysutil_activate_sigurg(int fd)734 vsf_sysutil_activate_sigurg(int fd)
735 {
736 int retval = fcntl(fd, F_SETOWN, vsf_sysutil_getpid());
737 if (retval != 0)
738 {
739 die("fcntl");
740 }
741 }
742
743 void
vsf_sysutil_activate_oobinline(int fd)744 vsf_sysutil_activate_oobinline(int fd)
745 {
746 int oob_inline = 1;
747 int retval = setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &oob_inline,
748 sizeof(oob_inline));
749 if (retval != 0)
750 {
751 die("setsockopt: oobinline");
752 }
753 }
754
755 void
vsf_sysutil_set_iptos_throughput(int fd)756 vsf_sysutil_set_iptos_throughput(int fd)
757 {
758 int tos = IPTOS_THROUGHPUT;
759 /* Ignore failure to set (maybe this IP stack demands privilege for this) */
760 (void) setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
761 }
762
763 void
vsf_sysutil_activate_linger(int fd)764 vsf_sysutil_activate_linger(int fd)
765 {
766 int retval;
767 struct linger the_linger;
768 vsf_sysutil_memclr(&the_linger, sizeof(the_linger));
769 the_linger.l_onoff = 1;
770 the_linger.l_linger = 60 * 10;
771 retval = setsockopt(fd, SOL_SOCKET, SO_LINGER, &the_linger,
772 sizeof(the_linger));
773 if (retval != 0)
774 {
775 die("setsockopt: linger");
776 }
777 }
778
779 void
vsf_sysutil_deactivate_linger_failok(int fd)780 vsf_sysutil_deactivate_linger_failok(int fd)
781 {
782 struct linger the_linger;
783 the_linger.l_onoff = 0;
784 the_linger.l_linger = 0;
785 (void) setsockopt(fd, SOL_SOCKET, SO_LINGER, &the_linger, sizeof(the_linger));
786 }
787
788 void
vsf_sysutil_activate_noblock(int fd)789 vsf_sysutil_activate_noblock(int fd)
790 {
791 int retval;
792 int curr_flags = fcntl(fd, F_GETFL);
793 if (vsf_sysutil_retval_is_error(curr_flags))
794 {
795 die("fcntl");
796 }
797 curr_flags |= O_NONBLOCK;
798 retval = fcntl(fd, F_SETFL, curr_flags);
799 if (retval != 0)
800 {
801 die("fcntl");
802 }
803 }
804
805 void
vsf_sysutil_deactivate_noblock(int fd)806 vsf_sysutil_deactivate_noblock(int fd)
807 {
808 int retval;
809 int curr_flags = fcntl(fd, F_GETFL);
810 if (vsf_sysutil_retval_is_error(curr_flags))
811 {
812 die("fcntl");
813 }
814 curr_flags &= ~O_NONBLOCK;
815 retval = fcntl(fd, F_SETFL, curr_flags);
816 if (retval != 0)
817 {
818 die("fcntl");
819 }
820 }
821
822 int
vsf_sysutil_recv_peek(const int fd,void * p_buf,unsigned int len)823 vsf_sysutil_recv_peek(const int fd, void* p_buf, unsigned int len)
824 {
825 while (1)
826 {
827 int retval = recv(fd, p_buf, len, MSG_PEEK);
828 int saved_errno = errno;
829 vsf_sysutil_check_pending_actions(kVSFSysUtilIO, retval, fd);
830 if (retval < 0 && saved_errno == EINTR)
831 {
832 continue;
833 }
834 return retval;
835 }
836 }
837
838 int
vsf_sysutil_atoi(const char * p_str)839 vsf_sysutil_atoi(const char* p_str)
840 {
841 return atoi(p_str);
842 }
843
844 filesize_t
vsf_sysutil_a_to_filesize_t(const char * p_str)845 vsf_sysutil_a_to_filesize_t(const char* p_str)
846 {
847 /* atoll() is C99 standard - but even modern FreeBSD, OpenBSD don't have
848 * it, so we'll supply our own
849 */
850 filesize_t result = 0;
851 filesize_t mult = 1;
852 unsigned int len = vsf_sysutil_strlen(p_str);
853 unsigned int i;
854 /* Bail if the number is excessively big (petabytes!) */
855 if (len > 15)
856 {
857 return 0;
858 }
859 for (i=0; i<len; ++i)
860 {
861 char the_char = p_str[len-(i+1)];
862 filesize_t val;
863 if (the_char < '0' || the_char > '9')
864 {
865 return 0;
866 }
867 val = the_char - '0';
868 val *= mult;
869 result += val;
870 mult *= 10;
871 }
872 return result;
873 }
874
875 const char*
vsf_sysutil_ulong_to_str(unsigned long the_ulong)876 vsf_sysutil_ulong_to_str(unsigned long the_ulong)
877 {
878 static char ulong_buf[32];
879 (void) snprintf(ulong_buf, sizeof(ulong_buf), "%lu", the_ulong);
880 return ulong_buf;
881 }
882
883 const char*
vsf_sysutil_ulong_to_hex(unsigned long the_ulong)884 vsf_sysutil_ulong_to_hex(unsigned long the_ulong)
885 {
886 static char ulong_buf[32];
887 (void) snprintf(ulong_buf, sizeof(ulong_buf), "%.8lx", the_ulong);
888 return ulong_buf;
889 }
890
891 const char*
vsf_sysutil_filesize_t_to_str(filesize_t the_filesize)892 vsf_sysutil_filesize_t_to_str(filesize_t the_filesize)
893 {
894 static char filesize_buf[32];
895 if (sizeof(long) == 8)
896 {
897 /* Avoid using non-standard %ll if we can */
898 (void) snprintf(filesize_buf, sizeof(filesize_buf), "%ld",
899 (long) the_filesize);
900 }
901 else
902 {
903 (void) snprintf(filesize_buf, sizeof(filesize_buf), "%lld", the_filesize);
904 }
905 return filesize_buf;
906 }
907
908 const char*
vsf_sysutil_double_to_str(double the_double)909 vsf_sysutil_double_to_str(double the_double)
910 {
911 static char double_buf[32];
912 (void) snprintf(double_buf, sizeof(double_buf), "%.2f", the_double);
913 return double_buf;
914 }
915
916 const char*
vsf_sysutil_uint_to_octal(unsigned int the_uint)917 vsf_sysutil_uint_to_octal(unsigned int the_uint)
918 {
919 static char octal_buf[32];
920 if (the_uint == 0)
921 {
922 octal_buf[0] = '0';
923 octal_buf[1] = '\0';
924 }
925 else
926 {
927 (void) snprintf(octal_buf, sizeof(octal_buf), "0%o", the_uint);
928 }
929 return octal_buf;
930 }
931
932 unsigned int
vsf_sysutil_octal_to_uint(const char * p_str)933 vsf_sysutil_octal_to_uint(const char* p_str)
934 {
935 /* NOTE - avoiding using sscanf() parser */
936 unsigned int result = 0;
937 int seen_non_zero_digit = 0;
938 while (*p_str != '\0')
939 {
940 int digit = *p_str;
941 if (!isdigit(digit) || digit > '7')
942 {
943 break;
944 }
945 if (digit != '0')
946 {
947 seen_non_zero_digit = 1;
948 }
949 if (seen_non_zero_digit)
950 {
951 result <<= 3;
952 result += (digit - '0');
953 }
954 p_str++;
955 }
956 return result;
957 }
958
959 int
vsf_sysutil_toupper(int the_char)960 vsf_sysutil_toupper(int the_char)
961 {
962 return toupper((unsigned char) the_char);
963 }
964
965 int
vsf_sysutil_isspace(int the_char)966 vsf_sysutil_isspace(int the_char)
967 {
968 return isspace((unsigned char) the_char);
969 }
970
971 int
vsf_sysutil_isprint(int the_char)972 vsf_sysutil_isprint(int the_char)
973 {
974 /* From Solar - we know better than some libc's! Don't let any potential
975 * control chars through
976 */
977 unsigned char uc = (unsigned char) the_char;
978 if (uc <= 31)
979 {
980 return 0;
981 }
982 if (uc == 177)
983 {
984 return 0;
985 }
986 if (uc >= 128 && uc <= 159)
987 {
988 return 0;
989 }
990 return isprint(the_char);
991 }
992
993 int
vsf_sysutil_isalnum(int the_char)994 vsf_sysutil_isalnum(int the_char)
995 {
996 return isalnum((unsigned char) the_char);
997 }
998
999 int
vsf_sysutil_isdigit(int the_char)1000 vsf_sysutil_isdigit(int the_char)
1001 {
1002 return isdigit((unsigned char) the_char);
1003 }
1004
1005 char*
vsf_sysutil_getcwd(char * p_dest,const unsigned int buf_size)1006 vsf_sysutil_getcwd(char* p_dest, const unsigned int buf_size)
1007 {
1008 char* p_retval;
1009 if (buf_size == 0) {
1010 return p_dest;
1011 }
1012 p_retval = getcwd(p_dest, buf_size);
1013 p_dest[buf_size - 1] = '\0';
1014 return p_retval;
1015 }
1016
1017 int
vsf_sysutil_mkdir(const char * p_dirname,const unsigned int mode)1018 vsf_sysutil_mkdir(const char* p_dirname, const unsigned int mode)
1019 {
1020 return mkdir(p_dirname, mode);
1021 }
1022
1023 int
vsf_sysutil_rmdir(const char * p_dirname)1024 vsf_sysutil_rmdir(const char* p_dirname)
1025 {
1026 return rmdir(p_dirname);
1027 }
1028
1029 int
vsf_sysutil_chdir(const char * p_dirname)1030 vsf_sysutil_chdir(const char* p_dirname)
1031 {
1032 return chdir(p_dirname);
1033 }
1034
1035 int
vsf_sysutil_rename(const char * p_from,const char * p_to)1036 vsf_sysutil_rename(const char* p_from, const char* p_to)
1037 {
1038 return rename(p_from, p_to);
1039 }
1040
1041 struct vsf_sysutil_dir*
vsf_sysutil_opendir(const char * p_dirname)1042 vsf_sysutil_opendir(const char* p_dirname)
1043 {
1044 return (struct vsf_sysutil_dir*) opendir(p_dirname);
1045 }
1046
1047 void
vsf_sysutil_closedir(struct vsf_sysutil_dir * p_dir)1048 vsf_sysutil_closedir(struct vsf_sysutil_dir* p_dir)
1049 {
1050 DIR* p_real_dir = (DIR*) p_dir;
1051 int retval = closedir(p_real_dir);
1052 if (retval != 0)
1053 {
1054 die("closedir");
1055 }
1056 }
1057
1058 const char*
vsf_sysutil_next_dirent(struct vsf_sysutil_dir * p_dir)1059 vsf_sysutil_next_dirent(struct vsf_sysutil_dir* p_dir)
1060 {
1061 DIR* p_real_dir = (DIR*) p_dir;
1062 struct dirent* p_dirent = readdir(p_real_dir);
1063 if (p_dirent == NULL)
1064 {
1065 return NULL;
1066 }
1067 return p_dirent->d_name;
1068 }
1069
1070 unsigned int
vsf_sysutil_strlen(const char * p_text)1071 vsf_sysutil_strlen(const char* p_text)
1072 {
1073 size_t ret = strlen(p_text);
1074 /* A defense in depth measure. */
1075 if (ret > INT_MAX / 8)
1076 {
1077 die("string suspiciously long");
1078 }
1079 return (unsigned int) ret;
1080 }
1081
1082 char*
vsf_sysutil_strdup(const char * p_str)1083 vsf_sysutil_strdup(const char* p_str)
1084 {
1085 return strdup(p_str);
1086 }
1087
1088 char*
vsf_sysutil_strndup(const char * p_str,unsigned int p_len)1089 vsf_sysutil_strndup(const char* p_str, unsigned int p_len)
1090 {
1091 char *new = (char *)malloc(p_len+1);
1092
1093 if (new == NULL)
1094 return NULL;
1095
1096 new[p_len]='\0';
1097 return (char *)memcpy(new, p_str, p_len);
1098 }
1099
1100 void
vsf_sysutil_memclr(void * p_dest,unsigned int size)1101 vsf_sysutil_memclr(void* p_dest, unsigned int size)
1102 {
1103 /* Safety */
1104 if (size == 0)
1105 {
1106 return;
1107 }
1108 memset(p_dest, '\0', size);
1109 }
1110
1111 void
vsf_sysutil_memcpy(void * p_dest,const void * p_src,const unsigned int size)1112 vsf_sysutil_memcpy(void* p_dest, const void* p_src, const unsigned int size)
1113 {
1114 /* Safety */
1115 if (size == 0)
1116 {
1117 return;
1118 }
1119 /* Defense in depth */
1120 if (size > INT_MAX)
1121 {
1122 die("possible negative value to memcpy?");
1123 }
1124 memcpy(p_dest, p_src, size);
1125 }
1126
1127 void
vsf_sysutil_strcpy(char * p_dest,const char * p_src,unsigned int maxsize)1128 vsf_sysutil_strcpy(char* p_dest, const char* p_src, unsigned int maxsize)
1129 {
1130 if (maxsize == 0)
1131 {
1132 return;
1133 }
1134 strncpy(p_dest, p_src, maxsize);
1135 p_dest[maxsize - 1] = '\0';
1136 }
1137
1138 int
vsf_sysutil_memcmp(const void * p_src1,const void * p_src2,unsigned int size)1139 vsf_sysutil_memcmp(const void* p_src1, const void* p_src2, unsigned int size)
1140 {
1141 /* Safety */
1142 if (size == 0)
1143 {
1144 return 0;
1145 }
1146 return memcmp(p_src1, p_src2, size);
1147 }
1148
1149 int
vsf_sysutil_strcmp(const char * p_src1,const char * p_src2)1150 vsf_sysutil_strcmp(const char* p_src1, const char* p_src2)
1151 {
1152 return strcmp(p_src1, p_src2);
1153 }
1154
1155 unsigned int
vsf_sysutil_getpagesize(void)1156 vsf_sysutil_getpagesize(void)
1157 {
1158 static unsigned int s_page_size;
1159 if (s_page_size == 0)
1160 {
1161 s_page_size = getpagesize();
1162 if (s_page_size == 0)
1163 {
1164 die("getpagesize");
1165 }
1166 }
1167 return s_page_size;
1168 }
1169
1170 static int
vsf_sysutil_translate_memprot(const enum EVSFSysUtilMapPermission perm)1171 vsf_sysutil_translate_memprot(const enum EVSFSysUtilMapPermission perm)
1172 {
1173 int retval = 0;
1174 switch (perm)
1175 {
1176 case kVSFSysUtilMapProtReadOnly:
1177 retval = PROT_READ;
1178 break;
1179 case kVSFSysUtilMapProtNone:
1180 retval = PROT_NONE;
1181 break;
1182 default:
1183 bug("bad value in vsf_sysutil_translate_memprot");
1184 break;
1185 }
1186 return retval;
1187 }
1188
1189 void
vsf_sysutil_memprotect(void * p_addr,unsigned int len,const enum EVSFSysUtilMapPermission perm)1190 vsf_sysutil_memprotect(void* p_addr, unsigned int len,
1191 const enum EVSFSysUtilMapPermission perm)
1192 {
1193 int prot = vsf_sysutil_translate_memprot(perm);
1194 int retval = mprotect(p_addr, len, prot);
1195 if (retval != 0)
1196 {
1197 die("mprotect");
1198 }
1199 }
1200
1201 void
vsf_sysutil_memunmap(void * p_start,unsigned int length)1202 vsf_sysutil_memunmap(void* p_start, unsigned int length)
1203 {
1204 int retval = munmap(p_start, length);
1205 if (retval != 0)
1206 {
1207 die("munmap");
1208 }
1209 }
1210
1211 static int
vsf_sysutil_translate_openmode(const enum EVSFSysUtilOpenMode mode)1212 vsf_sysutil_translate_openmode(const enum EVSFSysUtilOpenMode mode)
1213 {
1214 int retval = 0;
1215 switch (mode)
1216 {
1217 case kVSFSysUtilOpenReadOnly:
1218 retval = O_RDONLY;
1219 break;
1220 case kVSFSysUtilOpenWriteOnly:
1221 retval = O_WRONLY;
1222 break;
1223 case kVSFSysUtilOpenReadWrite:
1224 retval = O_RDWR;
1225 break;
1226 default:
1227 bug("bad mode in vsf_sysutil_translate_openmode");
1228 break;
1229 }
1230 return retval;
1231 }
1232
1233 int
vsf_sysutil_open_file(const char * p_filename,const enum EVSFSysUtilOpenMode mode)1234 vsf_sysutil_open_file(const char* p_filename,
1235 const enum EVSFSysUtilOpenMode mode)
1236 {
1237 return open(p_filename, vsf_sysutil_translate_openmode(mode) | O_NONBLOCK);
1238 }
1239
1240 int
vsf_sysutil_create_file_exclusive(const char * p_filename)1241 vsf_sysutil_create_file_exclusive(const char* p_filename)
1242 {
1243 /* umask() also contributes to end mode */
1244 return open(p_filename, O_CREAT | O_EXCL | O_WRONLY | O_APPEND,
1245 tunable_file_open_mode);
1246 }
1247
1248 int
vsf_sysutil_create_or_open_file(const char * p_filename,unsigned int mode)1249 vsf_sysutil_create_or_open_file(const char* p_filename, unsigned int mode)
1250 {
1251 return open(p_filename, O_CREAT | O_WRONLY | O_NONBLOCK, mode);
1252 }
1253
1254 int
vsf_sysutil_create_or_open_file_append(const char * p_filename,unsigned int mode)1255 vsf_sysutil_create_or_open_file_append(const char* p_filename,
1256 unsigned int mode)
1257 {
1258 return open(p_filename, O_CREAT | O_WRONLY | O_NONBLOCK | O_APPEND, mode);
1259 }
1260
1261 void
vsf_sysutil_dupfd2(int old_fd,int new_fd)1262 vsf_sysutil_dupfd2(int old_fd, int new_fd)
1263 {
1264 int retval;
1265 if (old_fd == new_fd)
1266 {
1267 return;
1268 }
1269 retval = dup2(old_fd, new_fd);
1270 if (retval != new_fd)
1271 {
1272 die("dup2");
1273 }
1274 }
1275
1276 void
vsf_sysutil_close(int fd)1277 vsf_sysutil_close(int fd)
1278 {
1279 while (1)
1280 {
1281 int retval = close(fd);
1282 if (retval != 0)
1283 {
1284 if (errno == EINTR)
1285 {
1286 vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
1287 continue;
1288 }
1289 die("close");
1290 }
1291 return;
1292 }
1293 }
1294
1295 int
vsf_sysutil_close_failok(int fd)1296 vsf_sysutil_close_failok(int fd)
1297 {
1298 return close(fd);
1299 }
1300
1301 int
vsf_sysutil_unlink(const char * p_dead)1302 vsf_sysutil_unlink(const char* p_dead)
1303 {
1304 return unlink(p_dead);
1305 }
1306
1307 int
vsf_sysutil_write_access(const char * p_filename)1308 vsf_sysutil_write_access(const char* p_filename)
1309 {
1310 int retval = access(p_filename, W_OK);
1311 return (retval == 0);
1312 }
1313
1314 static void
vsf_sysutil_alloc_statbuf(struct vsf_sysutil_statbuf ** p_ptr)1315 vsf_sysutil_alloc_statbuf(struct vsf_sysutil_statbuf** p_ptr)
1316 {
1317 if (*p_ptr == NULL)
1318 {
1319 *p_ptr = vsf_sysutil_malloc(sizeof(struct stat));
1320 }
1321 }
1322
1323 void
vsf_sysutil_fstat(int fd,struct vsf_sysutil_statbuf ** p_ptr)1324 vsf_sysutil_fstat(int fd, struct vsf_sysutil_statbuf** p_ptr)
1325 {
1326 int retval;
1327 vsf_sysutil_alloc_statbuf(p_ptr);
1328 retval = fstat(fd, (struct stat*) (*p_ptr));
1329 if (retval != 0)
1330 {
1331 die("fstat");
1332 }
1333 }
1334
1335 int
vsf_sysutil_stat(const char * p_name,struct vsf_sysutil_statbuf ** p_ptr)1336 vsf_sysutil_stat(const char* p_name, struct vsf_sysutil_statbuf** p_ptr)
1337 {
1338 vsf_sysutil_alloc_statbuf(p_ptr);
1339 return stat(p_name, (struct stat*) (*p_ptr));
1340 }
1341
1342 int
vsf_sysutil_lstat(const char * p_name,struct vsf_sysutil_statbuf ** p_ptr)1343 vsf_sysutil_lstat(const char* p_name, struct vsf_sysutil_statbuf** p_ptr)
1344 {
1345 vsf_sysutil_alloc_statbuf(p_ptr);
1346 return lstat(p_name, (struct stat*) (*p_ptr));
1347 }
1348
1349 void
vsf_sysutil_dir_stat(const struct vsf_sysutil_dir * p_dir,struct vsf_sysutil_statbuf ** p_ptr)1350 vsf_sysutil_dir_stat(const struct vsf_sysutil_dir* p_dir,
1351 struct vsf_sysutil_statbuf** p_ptr)
1352 {
1353 int fd = dirfd((DIR*) p_dir);
1354 vsf_sysutil_fstat(fd, p_ptr);
1355 }
1356
1357 int
vsf_sysutil_statbuf_is_regfile(const struct vsf_sysutil_statbuf * p_stat)1358 vsf_sysutil_statbuf_is_regfile(const struct vsf_sysutil_statbuf* p_stat)
1359 {
1360 const struct stat* p_realstat = (const struct stat*) p_stat;
1361 return S_ISREG(p_realstat->st_mode);
1362 }
1363
1364 int
vsf_sysutil_statbuf_is_symlink(const struct vsf_sysutil_statbuf * p_stat)1365 vsf_sysutil_statbuf_is_symlink(const struct vsf_sysutil_statbuf* p_stat)
1366 {
1367 const struct stat* p_realstat = (const struct stat*) p_stat;
1368 return S_ISLNK(p_realstat->st_mode);
1369 }
1370
1371 int
vsf_sysutil_statbuf_is_socket(const struct vsf_sysutil_statbuf * p_stat)1372 vsf_sysutil_statbuf_is_socket(const struct vsf_sysutil_statbuf* p_stat)
1373 {
1374 const struct stat* p_realstat = (const struct stat*) p_stat;
1375 return S_ISSOCK(p_realstat->st_mode);
1376 }
1377
1378 int
vsf_sysutil_statbuf_is_dir(const struct vsf_sysutil_statbuf * p_stat)1379 vsf_sysutil_statbuf_is_dir(const struct vsf_sysutil_statbuf* p_stat)
1380 {
1381 const struct stat* p_realstat = (const struct stat*) p_stat;
1382 return S_ISDIR(p_realstat->st_mode);
1383 }
1384
1385 const char*
vsf_sysutil_statbuf_get_perms(const struct vsf_sysutil_statbuf * p_statbuf)1386 vsf_sysutil_statbuf_get_perms(const struct vsf_sysutil_statbuf* p_statbuf)
1387 {
1388 static char perms[11];
1389 int i;
1390 const struct stat* p_stat = (const struct stat*) p_statbuf;
1391 for (i=0; i<10; i++)
1392 {
1393 perms[i] = '-';
1394 }
1395 perms[0] = '?';
1396 switch (p_stat->st_mode & S_IFMT)
1397 {
1398 case S_IFREG: perms[0] = '-'; break;
1399 case S_IFDIR: perms[0] = 'd'; break;
1400 case S_IFLNK: perms[0] = 'l'; break;
1401 case S_IFIFO: perms[0] = 'p'; break;
1402 case S_IFSOCK: perms[0] = 's'; break;
1403 case S_IFCHR: perms[0] = 'c'; break;
1404 case S_IFBLK: perms[0] = 'b'; break;
1405 default: break;
1406 }
1407 if (p_stat->st_mode & S_IRUSR) perms[1] = 'r';
1408 if (p_stat->st_mode & S_IWUSR) perms[2] = 'w';
1409 if (p_stat->st_mode & S_IXUSR) perms[3] = 'x';
1410 if (p_stat->st_mode & S_IRGRP) perms[4] = 'r';
1411 if (p_stat->st_mode & S_IWGRP) perms[5] = 'w';
1412 if (p_stat->st_mode & S_IXGRP) perms[6] = 'x';
1413 if (p_stat->st_mode & S_IROTH) perms[7] = 'r';
1414 if (p_stat->st_mode & S_IWOTH) perms[8] = 'w';
1415 if (p_stat->st_mode & S_IXOTH) perms[9] = 'x';
1416 if (p_stat->st_mode & S_ISUID) perms[3] = (perms[3] == 'x') ? 's' : 'S';
1417 if (p_stat->st_mode & S_ISGID) perms[6] = (perms[6] == 'x') ? 's' : 'S';
1418 if (p_stat->st_mode & S_ISVTX) perms[9] = (perms[9] == 'x') ? 't' : 'T';
1419 perms[10] = '\0';
1420 return perms;
1421 }
1422
1423 long
vsf_sysutil_statbuf_get_filedate(const struct vsf_sysutil_statbuf * p_statbuf)1424 vsf_sysutil_statbuf_get_filedate(const struct vsf_sysutil_statbuf* p_statbuf)
1425 {
1426 const struct stat* p_stat = (const struct stat*) p_statbuf;
1427 return p_stat->st_mtime;
1428 }
1429
1430 const char*
vsf_sysutil_statbuf_get_date(const struct vsf_sysutil_statbuf * p_statbuf,int use_localtime,long curr_time)1431 vsf_sysutil_statbuf_get_date(const struct vsf_sysutil_statbuf* p_statbuf,
1432 int use_localtime, long curr_time)
1433 {
1434 static char datebuf[64];
1435 int retval;
1436 struct tm* p_tm;
1437 const struct stat* p_stat = (const struct stat*) p_statbuf;
1438 const char* p_date_format = "%b %d %H:%M";
1439 if (!use_localtime)
1440 {
1441 p_tm = gmtime(&p_stat->st_mtime);
1442 }
1443 else
1444 {
1445 p_tm = localtime(&p_stat->st_mtime);
1446 }
1447 /* Is this a future or 6 months old date? If so, we drop to year format */
1448 if (p_stat->st_mtime > curr_time ||
1449 (curr_time - p_stat->st_mtime) > 60*60*24*182)
1450 {
1451 p_date_format = "%b %d %Y";
1452 }
1453 retval = strftime(datebuf, sizeof(datebuf), p_date_format, p_tm);
1454 datebuf[sizeof(datebuf)-1] = '\0';
1455 if (retval == 0)
1456 {
1457 die("strftime");
1458 }
1459 return datebuf;
1460 }
1461
1462 const char*
vsf_sysutil_statbuf_get_numeric_date(const struct vsf_sysutil_statbuf * p_statbuf,int use_localtime)1463 vsf_sysutil_statbuf_get_numeric_date(
1464 const struct vsf_sysutil_statbuf* p_statbuf,
1465 int use_localtime)
1466 {
1467 static char datebuf[15];
1468 const struct stat* p_stat = (const struct stat*) p_statbuf;
1469 struct tm* p_tm;
1470 int retval;
1471 if (!use_localtime)
1472 {
1473 p_tm = gmtime(&p_stat->st_mtime);
1474 }
1475 else
1476 {
1477 p_tm = localtime(&p_stat->st_mtime);
1478 }
1479 retval = strftime(datebuf, sizeof(datebuf), "%Y%m%d%H%M%S", p_tm);
1480 if (retval == 0)
1481 {
1482 die("strftime");
1483 }
1484 return datebuf;
1485 }
1486
1487 filesize_t
vsf_sysutil_statbuf_get_size(const struct vsf_sysutil_statbuf * p_statbuf)1488 vsf_sysutil_statbuf_get_size(const struct vsf_sysutil_statbuf* p_statbuf)
1489 {
1490 const struct stat* p_stat = (const struct stat*) p_statbuf;
1491 if (p_stat->st_size < 0)
1492 {
1493 die("invalid inode size in vsf_sysutil_statbuf_get_size");
1494 }
1495 return p_stat->st_size;
1496 }
1497
1498 int
vsf_sysutil_statbuf_get_uid(const struct vsf_sysutil_statbuf * p_statbuf)1499 vsf_sysutil_statbuf_get_uid(const struct vsf_sysutil_statbuf* p_statbuf)
1500 {
1501 const struct stat* p_stat = (const struct stat*) p_statbuf;
1502 return p_stat->st_uid;
1503 }
1504
1505 int
vsf_sysutil_statbuf_get_gid(const struct vsf_sysutil_statbuf * p_statbuf)1506 vsf_sysutil_statbuf_get_gid(const struct vsf_sysutil_statbuf* p_statbuf)
1507 {
1508 const struct stat* p_stat = (const struct stat*) p_statbuf;
1509 return p_stat->st_gid;
1510 }
1511
1512 unsigned int
vsf_sysutil_statbuf_get_links(const struct vsf_sysutil_statbuf * p_statbuf)1513 vsf_sysutil_statbuf_get_links(const struct vsf_sysutil_statbuf* p_statbuf)
1514 {
1515 const struct stat* p_stat = (const struct stat*) p_statbuf;
1516 return p_stat->st_nlink;
1517 }
1518
1519 int
vsf_sysutil_statbuf_is_readable_other(const struct vsf_sysutil_statbuf * p_statbuf)1520 vsf_sysutil_statbuf_is_readable_other(
1521 const struct vsf_sysutil_statbuf* p_statbuf)
1522 {
1523 const struct stat* p_stat = (const struct stat*) p_statbuf;
1524 if (p_stat->st_mode & S_IROTH)
1525 {
1526 return 1;
1527 }
1528 return 0;
1529 }
1530
1531 const char*
vsf_sysutil_statbuf_get_sortkey_mtime(const struct vsf_sysutil_statbuf * p_statbuf)1532 vsf_sysutil_statbuf_get_sortkey_mtime(
1533 const struct vsf_sysutil_statbuf* p_statbuf)
1534 {
1535 static char intbuf[32];
1536 const struct stat* p_stat = (const struct stat*) p_statbuf;
1537 /* This slight hack function must return a character date format such that
1538 * more recent dates appear later in the alphabet! Most notably, we must
1539 * make sure we pad to the same length with 0's
1540 */
1541 snprintf(intbuf, sizeof(intbuf), "%030ld", (long) p_stat->st_mtime);
1542 return intbuf;
1543 }
1544
1545 void
vsf_sysutil_fchown(const int fd,const int uid,const int gid)1546 vsf_sysutil_fchown(const int fd, const int uid, const int gid)
1547 {
1548 if (fchown(fd, uid, gid) != 0)
1549 {
1550 die("fchown");
1551 }
1552 }
1553
1554 void
vsf_sysutil_fchmod(const int fd,unsigned int mode)1555 vsf_sysutil_fchmod(const int fd, unsigned int mode)
1556 {
1557 mode = mode & 0777;
1558 if (fchmod(fd, mode))
1559 {
1560 die("fchmod");
1561 }
1562 }
1563
1564 int
vsf_sysutil_chmod(const char * p_filename,unsigned int mode)1565 vsf_sysutil_chmod(const char* p_filename, unsigned int mode)
1566 {
1567 /* Safety: mask "mode" to just access permissions, e.g. no suid setting! */
1568 mode = mode & 0777;
1569 return chmod(p_filename, mode);
1570 }
1571
1572 int
vsf_sysutil_lock_file_write(int fd)1573 vsf_sysutil_lock_file_write(int fd)
1574 {
1575 return lock_internal(fd, F_WRLCK);
1576 }
1577
1578 int
vsf_sysutil_lock_file_read(int fd)1579 vsf_sysutil_lock_file_read(int fd)
1580 {
1581 return lock_internal(fd, F_RDLCK);
1582 }
1583
1584 static int
lock_internal(int fd,int lock_type)1585 lock_internal(int fd, int lock_type)
1586 {
1587 struct flock the_lock;
1588 int retval;
1589 int saved_errno;
1590 vsf_sysutil_memclr(&the_lock, sizeof(the_lock));
1591 the_lock.l_type = lock_type;
1592 the_lock.l_whence = SEEK_SET;
1593 the_lock.l_start = 0;
1594 the_lock.l_len = 0;
1595 do
1596 {
1597 retval = fcntl(fd, F_SETLKW, &the_lock);
1598 saved_errno = errno;
1599 vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
1600 }
1601 while (retval < 0 && saved_errno == EINTR);
1602 return retval;
1603 }
1604
1605 void
vsf_sysutil_unlock_file(int fd)1606 vsf_sysutil_unlock_file(int fd)
1607 {
1608 int retval;
1609 struct flock the_lock;
1610 vsf_sysutil_memclr(&the_lock, sizeof(the_lock));
1611 the_lock.l_type = F_UNLCK;
1612 the_lock.l_whence = SEEK_SET;
1613 the_lock.l_start = 0;
1614 the_lock.l_len = 0;
1615 retval = fcntl(fd, F_SETLK, &the_lock);
1616 if (retval != 0)
1617 {
1618 die("fcntl");
1619 }
1620 }
1621
1622 int
vsf_sysutil_readlink(const char * p_filename,char * p_dest,unsigned int bufsiz)1623 vsf_sysutil_readlink(const char* p_filename, char* p_dest, unsigned int bufsiz)
1624 {
1625 int retval;
1626 if (bufsiz == 0) {
1627 return -1;
1628 }
1629 retval = readlink(p_filename, p_dest, bufsiz - 1);
1630 if (retval < 0)
1631 {
1632 return retval;
1633 }
1634 /* Ensure buffer is NULL terminated; readlink(2) doesn't do that */
1635 p_dest[retval] = '\0';
1636 return retval;
1637 }
1638
1639 int
vsf_sysutil_retval_is_error(int retval)1640 vsf_sysutil_retval_is_error(int retval)
1641 {
1642 if (retval < 0)
1643 {
1644 return 1;
1645 }
1646 return 0;
1647 }
1648
1649 enum EVSFSysUtilError
vsf_sysutil_get_error(void)1650 vsf_sysutil_get_error(void)
1651 {
1652 enum EVSFSysUtilError retval = kVSFSysUtilErrUnknown;
1653 switch (errno)
1654 {
1655 case EADDRINUSE:
1656 retval = kVSFSysUtilErrADDRINUSE;
1657 break;
1658 case ENOSYS:
1659 retval = kVSFSysUtilErrNOSYS;
1660 break;
1661 case EINTR:
1662 retval = kVSFSysUtilErrINTR;
1663 break;
1664 case EINVAL:
1665 retval = kVSFSysUtilErrINVAL;
1666 break;
1667 case EOPNOTSUPP:
1668 retval = kVSFSysUtilErrOPNOTSUPP;
1669 break;
1670 case EACCES:
1671 retval = kVSFSysUtilErrACCES;
1672 break;
1673 case ENOENT:
1674 retval = kVSFSysUtilErrNOENT;
1675 break;
1676 default:
1677 break;
1678 }
1679 return retval;
1680 }
1681
1682 int
vsf_sysutil_get_ipv4_sock(void)1683 vsf_sysutil_get_ipv4_sock(void)
1684 {
1685 int retval = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
1686 if (retval < 0)
1687 {
1688 die("socket");
1689 }
1690 return retval;
1691 }
1692
1693 int
vsf_sysutil_get_ipv6_sock(void)1694 vsf_sysutil_get_ipv6_sock(void)
1695 {
1696 int retval = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
1697 if (retval < 0)
1698 {
1699 die("socket");
1700 }
1701 return retval;
1702 }
1703
1704 struct vsf_sysutil_socketpair_retval
vsf_sysutil_unix_stream_socketpair(void)1705 vsf_sysutil_unix_stream_socketpair(void)
1706 {
1707 struct vsf_sysutil_socketpair_retval retval;
1708 int the_sockets[2];
1709 int sys_retval = socketpair(PF_UNIX, SOCK_STREAM, 0, the_sockets);
1710 if (sys_retval != 0)
1711 {
1712 die("socketpair");
1713 }
1714 retval.socket_one = the_sockets[0];
1715 retval.socket_two = the_sockets[1];
1716 return retval;
1717 }
1718
1719 int
vsf_sysutil_bind(int fd,const struct vsf_sysutil_sockaddr * p_sockptr)1720 vsf_sysutil_bind(int fd, const struct vsf_sysutil_sockaddr* p_sockptr)
1721 {
1722 const struct sockaddr* p_sockaddr = &p_sockptr->u.u_sockaddr;
1723 int len = 0;
1724 if (p_sockaddr->sa_family == AF_INET)
1725 {
1726 len = sizeof(struct sockaddr_in);
1727 }
1728 else if (p_sockaddr->sa_family == AF_INET6)
1729 {
1730 len = sizeof(struct sockaddr_in6);
1731 }
1732 else
1733 {
1734 die("can only support ipv4 and ipv6 currently");
1735 }
1736 return bind(fd, p_sockaddr, len);
1737 }
1738
1739 int
vsf_sysutil_listen(int fd,const unsigned int backlog)1740 vsf_sysutil_listen(int fd, const unsigned int backlog)
1741 {
1742 int retval = listen(fd, backlog);
1743 if (vsf_sysutil_retval_is_error(retval) &&
1744 vsf_sysutil_get_error() != kVSFSysUtilErrADDRINUSE)
1745 {
1746 die("listen");
1747 }
1748 return retval;
1749 }
1750
1751 /* Warning: callers of this function assume it does NOT make use of any
1752 * non re-entrant calls such as malloc().
1753 */
1754 int
vsf_sysutil_accept_timeout(int fd,struct vsf_sysutil_sockaddr * p_sockaddr,unsigned int wait_seconds)1755 vsf_sysutil_accept_timeout(int fd, struct vsf_sysutil_sockaddr* p_sockaddr,
1756 unsigned int wait_seconds)
1757 {
1758 struct vsf_sysutil_sockaddr remote_addr;
1759 int retval;
1760 int saved_errno;
1761 fd_set accept_fdset;
1762 struct timeval timeout;
1763 socklen_t socklen = sizeof(remote_addr);
1764 if (p_sockaddr)
1765 {
1766 vsf_sysutil_memclr(p_sockaddr, sizeof(*p_sockaddr));
1767 }
1768 if (wait_seconds > 0)
1769 {
1770 FD_ZERO(&accept_fdset);
1771 FD_SET(fd, &accept_fdset);
1772 timeout.tv_sec = wait_seconds;
1773 timeout.tv_usec = 0;
1774 do
1775 {
1776 retval = select(fd + 1, &accept_fdset, NULL, NULL, &timeout);
1777 saved_errno = errno;
1778 vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
1779 }
1780 while (retval < 0 && saved_errno == EINTR);
1781 if (retval <= 0)
1782 {
1783 if (retval == 0)
1784 {
1785 errno = EAGAIN;
1786 }
1787 return -1;
1788 }
1789 }
1790 retval = accept(fd, &remote_addr.u.u_sockaddr, &socklen);
1791 vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
1792 if (retval < 0)
1793 {
1794 return retval;
1795 }
1796 /* FreeBSD bug / paranoia: ai32@drexel.edu */
1797 if (socklen == 0)
1798 {
1799 return -1;
1800 }
1801 if (remote_addr.u.u_sockaddr.sa_family != AF_INET &&
1802 remote_addr.u.u_sockaddr.sa_family != AF_INET6)
1803 {
1804 die("can only support ipv4 and ipv6 currently");
1805 }
1806 if (p_sockaddr)
1807 {
1808 if (remote_addr.u.u_sockaddr.sa_family == AF_INET)
1809 {
1810 vsf_sysutil_memclr(&remote_addr.u.u_sockaddr_in.sin_zero,
1811 sizeof(remote_addr.u.u_sockaddr_in.sin_zero));
1812 vsf_sysutil_memcpy(p_sockaddr, &remote_addr.u.u_sockaddr_in,
1813 sizeof(remote_addr.u.u_sockaddr_in));
1814 }
1815 else
1816 {
1817 vsf_sysutil_memcpy(p_sockaddr, &remote_addr.u.u_sockaddr_in6,
1818 sizeof(remote_addr.u.u_sockaddr_in6));
1819 }
1820 }
1821 return retval;
1822 }
1823
1824 int
vsf_sysutil_connect_timeout(int fd,const struct vsf_sysutil_sockaddr * p_addr,unsigned int wait_seconds)1825 vsf_sysutil_connect_timeout(int fd, const struct vsf_sysutil_sockaddr* p_addr,
1826 unsigned int wait_seconds)
1827 {
1828 const struct sockaddr* p_sockaddr = &p_addr->u.u_sockaddr;
1829 unsigned int addrlen = 0;
1830 int retval;
1831 int saved_errno;
1832 if (p_sockaddr->sa_family == AF_INET)
1833 {
1834 addrlen = sizeof(p_addr->u.u_sockaddr_in);
1835 }
1836 else if (p_sockaddr->sa_family == AF_INET6)
1837 {
1838 addrlen = sizeof(p_addr->u.u_sockaddr_in6);
1839 }
1840 else
1841 {
1842 die("can only support ipv4 and ipv6 currently");
1843 }
1844 if (wait_seconds > 0)
1845 {
1846 vsf_sysutil_activate_noblock(fd);
1847 }
1848 retval = connect(fd, p_sockaddr, addrlen);
1849 if (retval < 0 && errno == EINPROGRESS)
1850 {
1851 fd_set connect_fdset;
1852 struct timeval timeout;
1853 FD_ZERO(&connect_fdset);
1854 FD_SET(fd, &connect_fdset);
1855 timeout.tv_sec = wait_seconds;
1856 timeout.tv_usec = 0;
1857 do
1858 {
1859 retval = select(fd + 1, NULL, &connect_fdset, NULL, &timeout);
1860 saved_errno = errno;
1861 vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
1862 }
1863 while (retval < 0 && saved_errno == EINTR);
1864 if (retval <= 0)
1865 {
1866 if (retval == 0)
1867 {
1868 errno = EAGAIN;
1869 }
1870 retval = -1;
1871 }
1872 else
1873 {
1874 socklen_t socklen = sizeof(retval);
1875 int sockoptret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &retval, &socklen);
1876 if (sockoptret != 0)
1877 {
1878 die("getsockopt");
1879 }
1880 if (retval != 0)
1881 {
1882 errno = retval;
1883 retval = -1;
1884 }
1885 }
1886 }
1887 if (wait_seconds > 0)
1888 {
1889 vsf_sysutil_deactivate_noblock(fd);
1890 }
1891 return retval;
1892 }
1893
1894 void
vsf_sysutil_getsockname(int fd,struct vsf_sysutil_sockaddr ** p_sockptr)1895 vsf_sysutil_getsockname(int fd, struct vsf_sysutil_sockaddr** p_sockptr)
1896 {
1897 struct vsf_sysutil_sockaddr the_addr;
1898 int retval;
1899 socklen_t socklen = sizeof(the_addr);
1900 vsf_sysutil_sockaddr_clear(p_sockptr);
1901 retval = getsockname(fd, &the_addr.u.u_sockaddr, &socklen);
1902 if (retval != 0)
1903 {
1904 die("getsockname");
1905 }
1906 if (the_addr.u.u_sockaddr.sa_family != AF_INET &&
1907 the_addr.u.u_sockaddr.sa_family != AF_INET6)
1908 {
1909 die("can only support ipv4 and ipv6 currently");
1910 }
1911 vsf_sysutil_sockaddr_alloc(p_sockptr);
1912 if (socklen > sizeof(the_addr))
1913 {
1914 socklen = sizeof(the_addr);
1915 }
1916 vsf_sysutil_memcpy(*p_sockptr, &the_addr, socklen);
1917 }
1918
1919 void
vsf_sysutil_getpeername(int fd,struct vsf_sysutil_sockaddr ** p_sockptr)1920 vsf_sysutil_getpeername(int fd, struct vsf_sysutil_sockaddr** p_sockptr)
1921 {
1922 struct vsf_sysutil_sockaddr the_addr;
1923 int retval;
1924 socklen_t socklen = sizeof(the_addr);
1925 vsf_sysutil_sockaddr_clear(p_sockptr);
1926 retval = getpeername(fd, &the_addr.u.u_sockaddr, &socklen);
1927 if (retval != 0)
1928 {
1929 die("getpeername");
1930 }
1931 if (the_addr.u.u_sockaddr.sa_family != AF_INET &&
1932 the_addr.u.u_sockaddr.sa_family != AF_INET6)
1933 {
1934 die("can only support ipv4 and ipv6 currently");
1935 }
1936 vsf_sysutil_sockaddr_alloc(p_sockptr);
1937 if (socklen > sizeof(the_addr))
1938 {
1939 socklen = sizeof(the_addr);
1940 }
1941 vsf_sysutil_memcpy(*p_sockptr, &the_addr, socklen);
1942 }
1943
1944 void
vsf_sysutil_shutdown_failok(int fd)1945 vsf_sysutil_shutdown_failok(int fd)
1946 {
1947 /* SHUT_RDWR is a relatively new addition */
1948 #ifndef SHUT_RDWR
1949 #define SHUT_RDWR 2
1950 #endif
1951 (void) shutdown(fd, SHUT_RDWR);
1952 }
1953
1954 void
vsf_sysutil_shutdown_read_failok(int fd)1955 vsf_sysutil_shutdown_read_failok(int fd)
1956 {
1957 /* SHUT_RD is a relatively new addition */
1958 #ifndef SHUT_RD
1959 #define SHUT_RD 0
1960 #endif
1961 (void) shutdown(fd, SHUT_RD);
1962 }
1963
1964 void
vsf_sysutil_sockaddr_clear(struct vsf_sysutil_sockaddr ** p_sockptr)1965 vsf_sysutil_sockaddr_clear(struct vsf_sysutil_sockaddr** p_sockptr)
1966 {
1967 if (*p_sockptr != NULL)
1968 {
1969 vsf_sysutil_free(*p_sockptr);
1970 *p_sockptr = NULL;
1971 }
1972 }
1973
1974 void
vsf_sysutil_sockaddr_alloc(struct vsf_sysutil_sockaddr ** p_sockptr)1975 vsf_sysutil_sockaddr_alloc(struct vsf_sysutil_sockaddr** p_sockptr)
1976 {
1977 vsf_sysutil_sockaddr_clear(p_sockptr);
1978 *p_sockptr = vsf_sysutil_malloc(sizeof(**p_sockptr));
1979 vsf_sysutil_memclr(*p_sockptr, sizeof(**p_sockptr));
1980 }
1981
1982 void
vsf_sysutil_sockaddr_alloc_ipv4(struct vsf_sysutil_sockaddr ** p_sockptr)1983 vsf_sysutil_sockaddr_alloc_ipv4(struct vsf_sysutil_sockaddr** p_sockptr)
1984 {
1985 vsf_sysutil_sockaddr_alloc(p_sockptr);
1986 (*p_sockptr)->u.u_sockaddr.sa_family = AF_INET;
1987 }
1988
1989 void
vsf_sysutil_sockaddr_alloc_ipv6(struct vsf_sysutil_sockaddr ** p_sockptr)1990 vsf_sysutil_sockaddr_alloc_ipv6(struct vsf_sysutil_sockaddr** p_sockptr)
1991 {
1992 vsf_sysutil_sockaddr_alloc(p_sockptr);
1993 (*p_sockptr)->u.u_sockaddr.sa_family = AF_INET6;
1994 }
1995
1996 void
vsf_sysutil_sockaddr_clone(struct vsf_sysutil_sockaddr ** p_sockptr,const struct vsf_sysutil_sockaddr * p_src)1997 vsf_sysutil_sockaddr_clone(struct vsf_sysutil_sockaddr** p_sockptr,
1998 const struct vsf_sysutil_sockaddr* p_src)
1999 {
2000 struct vsf_sysutil_sockaddr* p_sockaddr = 0;
2001 vsf_sysutil_sockaddr_alloc(p_sockptr);
2002 p_sockaddr = *p_sockptr;
2003 if (p_src->u.u_sockaddr.sa_family == AF_INET)
2004 {
2005 p_sockaddr->u.u_sockaddr.sa_family = AF_INET;
2006 vsf_sysutil_memcpy(&p_sockaddr->u.u_sockaddr_in.sin_addr,
2007 &p_src->u.u_sockaddr_in.sin_addr,
2008 sizeof(p_sockaddr->u.u_sockaddr_in.sin_addr));
2009 }
2010 else if (p_src->u.u_sockaddr.sa_family == AF_INET6)
2011 {
2012 p_sockaddr->u.u_sockaddr.sa_family = AF_INET6;
2013 vsf_sysutil_memcpy(&p_sockaddr->u.u_sockaddr_in6.sin6_addr,
2014 &p_src->u.u_sockaddr_in6.sin6_addr,
2015 sizeof(p_sockaddr->u.u_sockaddr_in6.sin6_addr));
2016 p_sockaddr->u.u_sockaddr_in6.sin6_scope_id =
2017 p_src->u.u_sockaddr_in6.sin6_scope_id;
2018 }
2019 else
2020 {
2021 die("can only support ipv4 and ipv6 currently");
2022 }
2023 }
2024
2025 int
vsf_sysutil_sockaddr_addr_equal(const struct vsf_sysutil_sockaddr * p1,const struct vsf_sysutil_sockaddr * p2)2026 vsf_sysutil_sockaddr_addr_equal(const struct vsf_sysutil_sockaddr* p1,
2027 const struct vsf_sysutil_sockaddr* p2)
2028 {
2029 int family1 = p1->u.u_sockaddr.sa_family;
2030 int family2 = p2->u.u_sockaddr.sa_family;
2031 if (family1 != family2)
2032 {
2033 if (family1 == AF_INET && family2 == AF_INET6)
2034 {
2035 const void* p_ipv4_addr = vsf_sysutil_sockaddr_ipv6_v4(p2);
2036 if (p_ipv4_addr &&
2037 !vsf_sysutil_memcmp(p_ipv4_addr, &p1->u.u_sockaddr_in.sin_addr,
2038 sizeof(p1->u.u_sockaddr_in.sin_addr)))
2039 {
2040 return 1;
2041 }
2042 }
2043 else if (family1 == AF_INET6 && family2 == AF_INET)
2044 {
2045 const void* p_ipv4_addr = vsf_sysutil_sockaddr_ipv6_v4(p1);
2046 if (p_ipv4_addr &&
2047 !vsf_sysutil_memcmp(p_ipv4_addr, &p2->u.u_sockaddr_in.sin_addr,
2048 sizeof(p2->u.u_sockaddr_in.sin_addr)))
2049 {
2050 return 1;
2051 }
2052 }
2053 return 0;
2054 }
2055 if (family1 == AF_INET)
2056 {
2057 if (vsf_sysutil_memcmp(&p1->u.u_sockaddr_in.sin_addr,
2058 &p2->u.u_sockaddr_in.sin_addr,
2059 sizeof(p1->u.u_sockaddr_in.sin_addr)) == 0)
2060 {
2061 return 1;
2062 }
2063 }
2064 else if (family1 == AF_INET6)
2065 {
2066 if (vsf_sysutil_memcmp(&p1->u.u_sockaddr_in6.sin6_addr,
2067 &p2->u.u_sockaddr_in6.sin6_addr,
2068 sizeof(p1->u.u_sockaddr_in6.sin6_addr)) == 0)
2069 {
2070 return 1;
2071 }
2072 }
2073 return 0;
2074 }
2075
2076 int
vsf_sysutil_sockaddr_is_ipv6(const struct vsf_sysutil_sockaddr * p_sockaddr)2077 vsf_sysutil_sockaddr_is_ipv6(const struct vsf_sysutil_sockaddr* p_sockaddr)
2078 {
2079 if (p_sockaddr->u.u_sockaddr.sa_family == AF_INET6)
2080 {
2081 return 1;
2082 }
2083 return 0;
2084 }
2085
2086 void
vsf_sysutil_sockaddr_set_ipv4addr(struct vsf_sysutil_sockaddr * p_sockptr,const unsigned char * p_raw)2087 vsf_sysutil_sockaddr_set_ipv4addr(struct vsf_sysutil_sockaddr* p_sockptr,
2088 const unsigned char* p_raw)
2089 {
2090 if (p_sockptr->u.u_sockaddr.sa_family == AF_INET)
2091 {
2092 vsf_sysutil_memcpy(&p_sockptr->u.u_sockaddr_in.sin_addr, p_raw,
2093 sizeof(p_sockptr->u.u_sockaddr_in.sin_addr));
2094 }
2095 else if (p_sockptr->u.u_sockaddr.sa_family == AF_INET6)
2096 {
2097 static struct vsf_sysutil_sockaddr* s_p_sockaddr;
2098 vsf_sysutil_sockaddr_alloc_ipv4(&s_p_sockaddr);
2099 vsf_sysutil_memcpy(&s_p_sockaddr->u.u_sockaddr_in.sin_addr, p_raw,
2100 sizeof(s_p_sockaddr->u.u_sockaddr_in.sin_addr));
2101 vsf_sysutil_memcpy(&p_sockptr->u.u_sockaddr_in6.sin6_addr,
2102 vsf_sysutil_sockaddr_ipv4_v6(s_p_sockaddr),
2103 sizeof(p_sockptr->u.u_sockaddr_in6.sin6_addr));
2104 }
2105 else
2106 {
2107 bug("bad family");
2108 }
2109 }
2110
2111 void
vsf_sysutil_sockaddr_set_ipv6addr(struct vsf_sysutil_sockaddr * p_sockptr,const unsigned char * p_raw)2112 vsf_sysutil_sockaddr_set_ipv6addr(struct vsf_sysutil_sockaddr* p_sockptr,
2113 const unsigned char* p_raw)
2114 {
2115 if (p_sockptr->u.u_sockaddr.sa_family == AF_INET6)
2116 {
2117 vsf_sysutil_memcpy(&p_sockptr->u.u_sockaddr_in6.sin6_addr, p_raw,
2118 sizeof(p_sockptr->u.u_sockaddr_in6.sin6_addr));
2119 }
2120 else
2121 {
2122 bug("bad family");
2123 }
2124 }
2125
2126 void
vsf_sysutil_sockaddr_set_mask(struct vsf_sysutil_sockaddr * p_sockptr,short int mask)2127 vsf_sysutil_sockaddr_set_mask(struct vsf_sysutil_sockaddr* p_sockptr,
2128 short int mask)
2129 {
2130 static unsigned char raw[16];
2131 unsigned int i = 0;
2132 vsf_sysutil_fillbuff(&raw, sizeof(raw), 0);
2133
2134 while ((i < sizeof(raw)) && (mask > 0))
2135 {
2136 raw[i++] = ((1 << (8 - ((mask > 8) ? 8 : mask))) - 1) ^ 0xFF;
2137 mask -= 8;
2138 }
2139 if (p_sockptr->u.u_sockaddr.sa_family == AF_INET)
2140 {
2141 vsf_sysutil_sockaddr_set_ipv4addr(p_sockptr, (const unsigned char*)&raw);
2142 }
2143 else if (p_sockptr->u.u_sockaddr.sa_family == AF_INET6)
2144 {
2145 vsf_sysutil_sockaddr_set_ipv6addr(p_sockptr, (const unsigned char*)&raw);
2146 }
2147 else
2148 {
2149 bug("bad family");
2150 }
2151 }
2152
2153 int
vsf_sysutil_sockaddr_get_ipv6scope(struct vsf_sysutil_sockaddr * p_sockptr)2154 vsf_sysutil_sockaddr_get_ipv6scope(struct vsf_sysutil_sockaddr* p_sockptr)
2155 {
2156 return p_sockptr->u.u_sockaddr_in6.sin6_scope_id;
2157 }
2158
2159 void
vsf_sysutil_sockaddr_set_ipv6scope(struct vsf_sysutil_sockaddr * p_sockptr,const int scope_id)2160 vsf_sysutil_sockaddr_set_ipv6scope(struct vsf_sysutil_sockaddr* p_sockptr,
2161 const int scope_id)
2162 {
2163 p_sockptr->u.u_sockaddr_in6.sin6_scope_id = scope_id;
2164 }
2165
2166 const void*
vsf_sysutil_sockaddr_ipv6_v4(const struct vsf_sysutil_sockaddr * p_addr)2167 vsf_sysutil_sockaddr_ipv6_v4(const struct vsf_sysutil_sockaddr* p_addr)
2168 {
2169 static unsigned char pattern[12] =
2170 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF };
2171 const unsigned char* p_addr_start;
2172 if (p_addr->u.u_sockaddr.sa_family != AF_INET6)
2173 {
2174 return 0;
2175 }
2176 if (vsf_sysutil_memcmp(pattern, &p_addr->u.u_sockaddr_in6.sin6_addr, 12))
2177 {
2178 return 0;
2179 }
2180 p_addr_start = (const unsigned char*)&p_addr->u.u_sockaddr_in6.sin6_addr;
2181 return &p_addr_start[12];
2182 }
2183
2184 const void*
vsf_sysutil_sockaddr_ipv4_v6(const struct vsf_sysutil_sockaddr * p_addr)2185 vsf_sysutil_sockaddr_ipv4_v6(const struct vsf_sysutil_sockaddr* p_addr)
2186 {
2187 static unsigned char ret[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF };
2188 if (p_addr->u.u_sockaddr.sa_family != AF_INET)
2189 {
2190 return 0;
2191 }
2192 vsf_sysutil_memcpy(&ret[12], &p_addr->u.u_sockaddr_in.sin_addr, 4);
2193 return ret;
2194 }
2195
2196 void*
vsf_sysutil_sockaddr_get_raw_addr(struct vsf_sysutil_sockaddr * p_sockptr)2197 vsf_sysutil_sockaddr_get_raw_addr(struct vsf_sysutil_sockaddr* p_sockptr)
2198 {
2199 if (p_sockptr->u.u_sockaddr.sa_family == AF_INET)
2200 {
2201 return &p_sockptr->u.u_sockaddr_in.sin_addr;
2202 }
2203 else if (p_sockptr->u.u_sockaddr.sa_family == AF_INET6)
2204 {
2205 return &p_sockptr->u.u_sockaddr_in6.sin6_addr;
2206 }
2207 else
2208 {
2209 bug("bad family");
2210 }
2211 return 0;
2212 }
2213
2214 unsigned int
vsf_sysutil_get_ipaddr_size(void)2215 vsf_sysutil_get_ipaddr_size(void)
2216 {
2217 struct vsf_sysutil_sockaddr addr;
2218 unsigned int size = sizeof(addr.u.u_sockaddr_in.sin_addr);
2219 unsigned int size2 = sizeof(addr.u.u_sockaddr_in6.sin6_addr);
2220 if (size2 > size)
2221 {
2222 size = size2;
2223 }
2224 return size;
2225 }
2226
2227 int
vsf_sysutil_get_ipsock(const struct vsf_sysutil_sockaddr * p_addr)2228 vsf_sysutil_get_ipsock(const struct vsf_sysutil_sockaddr* p_addr)
2229 {
2230 if (p_addr->u.u_sockaddr.sa_family == AF_INET)
2231 {
2232 return vsf_sysutil_get_ipv4_sock();
2233 }
2234 else if (p_addr->u.u_sockaddr.sa_family == AF_INET6)
2235 {
2236 return vsf_sysutil_get_ipv6_sock();
2237 }
2238 else
2239 {
2240 bug("bad family");
2241 }
2242 return -1;
2243 }
2244
2245 void
vsf_sysutil_sockaddr_set_any(struct vsf_sysutil_sockaddr * p_sockaddr)2246 vsf_sysutil_sockaddr_set_any(struct vsf_sysutil_sockaddr* p_sockaddr)
2247 {
2248 if (p_sockaddr->u.u_sockaddr.sa_family == AF_INET)
2249 {
2250 vsf_sysutil_memclr(&p_sockaddr->u.u_sockaddr_in.sin_addr,
2251 sizeof(p_sockaddr->u.u_sockaddr_in.sin_addr));
2252 }
2253 else if (p_sockaddr->u.u_sockaddr.sa_family == AF_INET6)
2254 {
2255 vsf_sysutil_memclr(&p_sockaddr->u.u_sockaddr_in6.sin6_addr,
2256 sizeof(p_sockaddr->u.u_sockaddr_in6.sin6_addr));
2257 }
2258 else
2259 {
2260 bug("bad family");
2261 }
2262 }
2263
2264 int
vsf_sysutil_sockaddr_in_mask(struct vsf_sysutil_sockaddr * p_src,struct vsf_sysutil_sockaddr * p_dst,struct vsf_sysutil_sockaddr * p_mask)2265 vsf_sysutil_sockaddr_in_mask(struct vsf_sysutil_sockaddr* p_src,
2266 struct vsf_sysutil_sockaddr* p_dst,
2267 struct vsf_sysutil_sockaddr* p_mask)
2268 {
2269 static struct vsf_sysutil_sockaddr* p_addr;
2270 int ret = 0, i = 0;
2271 unsigned char src_raw[16], mask_raw[16];
2272
2273 if (p_src->u.u_sockaddr.sa_family != p_dst->u.u_sockaddr.sa_family &&
2274 p_src->u.u_sockaddr.sa_family != p_mask->u.u_sockaddr.sa_family)
2275 {
2276 bug("incompatible family");
2277 }
2278 vsf_sysutil_sockaddr_clone(&p_addr, p_mask);
2279
2280 if (p_src->u.u_sockaddr.sa_family == AF_INET)
2281 {
2282 vsf_sysutil_memcpy(&src_raw, &p_src->u.u_sockaddr_in.sin_addr, 4);
2283 vsf_sysutil_memcpy(&mask_raw, &p_mask->u.u_sockaddr_in.sin_addr, 4);
2284 while (i < 4)
2285 {
2286 src_raw[i] &= mask_raw[i];
2287 i++;
2288 }
2289 vsf_sysutil_sockaddr_set_ipv4addr(p_addr, (const unsigned char*)&src_raw);
2290 ret = vsf_sysutil_sockaddr_addr_equal(p_addr, p_dst);
2291 }
2292 else if (p_src->u.u_sockaddr.sa_family == AF_INET6)
2293 {
2294 vsf_sysutil_memcpy(&src_raw, &p_src->u.u_sockaddr_in6.sin6_addr, 16);
2295 vsf_sysutil_memcpy(&mask_raw, &p_mask->u.u_sockaddr_in6.sin6_addr, 16);
2296 while (i < 16)
2297 {
2298 src_raw[i] &= mask_raw[i];
2299 i++;
2300 }
2301 vsf_sysutil_sockaddr_set_ipv6addr(p_addr, (const unsigned char*)&src_raw);
2302 ret = vsf_sysutil_sockaddr_addr_equal(p_addr, p_dst);
2303 }
2304 else
2305 {
2306 bug("bad family");
2307 }
2308
2309 vsf_sysutil_sockaddr_clear(&p_addr);
2310 return ret;
2311 }
2312
2313
2314 int
vsf_sysutil_sockaddr_is_any(struct vsf_sysutil_sockaddr * p_sockaddr)2315 vsf_sysutil_sockaddr_is_any(struct vsf_sysutil_sockaddr* p_sockaddr)
2316 {
2317 static struct vsf_sysutil_sockaddr* p_any;
2318 int ret = 0;
2319
2320 vsf_sysutil_sockaddr_clone(&p_any, p_sockaddr);
2321 vsf_sysutil_sockaddr_set_any(p_any);
2322 ret = vsf_sysutil_sockaddr_addr_equal(p_any, p_sockaddr);
2323 vsf_sysutil_sockaddr_clear(&p_any);
2324 return ret;
2325 }
2326
2327 unsigned short
vsf_sysutil_sockaddr_get_port(const struct vsf_sysutil_sockaddr * p_sockptr)2328 vsf_sysutil_sockaddr_get_port(const struct vsf_sysutil_sockaddr* p_sockptr)
2329 {
2330 if (p_sockptr->u.u_sockaddr.sa_family == AF_INET)
2331 {
2332 return ntohs(p_sockptr->u.u_sockaddr_in.sin_port);
2333 }
2334 else if (p_sockptr->u.u_sockaddr.sa_family == AF_INET6)
2335 {
2336 return ntohs(p_sockptr->u.u_sockaddr_in6.sin6_port);
2337 }
2338 else
2339 {
2340 bug("bad family");
2341 }
2342 /* NOTREACHED */
2343 return 0;
2344 }
2345
2346 void
vsf_sysutil_sockaddr_set_port(struct vsf_sysutil_sockaddr * p_sockptr,unsigned short the_port)2347 vsf_sysutil_sockaddr_set_port(struct vsf_sysutil_sockaddr* p_sockptr,
2348 unsigned short the_port)
2349 {
2350 if (p_sockptr->u.u_sockaddr.sa_family == AF_INET)
2351 {
2352 p_sockptr->u.u_sockaddr_in.sin_port = htons(the_port);
2353 }
2354 else if (p_sockptr->u.u_sockaddr.sa_family == AF_INET6)
2355 {
2356 p_sockptr->u.u_sockaddr_in6.sin6_port = htons(the_port);
2357 }
2358 else
2359 {
2360 bug("bad family");
2361 }
2362 }
2363
2364 int
vsf_sysutil_is_port_reserved(unsigned short the_port)2365 vsf_sysutil_is_port_reserved(unsigned short the_port)
2366 {
2367 if (the_port < IPPORT_RESERVED)
2368 {
2369 return 1;
2370 }
2371 return 0;
2372 }
2373
2374 const char*
vsf_sysutil_inet_ntop(const struct vsf_sysutil_sockaddr * p_sockptr)2375 vsf_sysutil_inet_ntop(const struct vsf_sysutil_sockaddr* p_sockptr)
2376 {
2377 const struct sockaddr* p_sockaddr = &p_sockptr->u.u_sockaddr;
2378 if (p_sockaddr->sa_family == AF_INET)
2379 {
2380 return inet_ntoa(p_sockptr->u.u_sockaddr_in.sin_addr);
2381 }
2382 else if (p_sockaddr->sa_family == AF_INET6)
2383 {
2384 static char inaddr_buf[64];
2385 const char* p_ret = inet_ntop(AF_INET6,
2386 &p_sockptr->u.u_sockaddr_in6.sin6_addr,
2387 inaddr_buf, sizeof(inaddr_buf));
2388 inaddr_buf[sizeof(inaddr_buf) - 1] = '\0';
2389 if (p_ret == NULL)
2390 {
2391 inaddr_buf[0] = '\0';
2392 }
2393 return inaddr_buf;
2394 }
2395 else
2396 {
2397 die("can only support ipv4 and ipv6 currently");
2398 return 0;
2399 }
2400 }
2401
2402 const char*
vsf_sysutil_inet_ntoa(const void * p_raw_addr)2403 vsf_sysutil_inet_ntoa(const void* p_raw_addr)
2404 {
2405 return inet_ntoa(*((struct in_addr*)p_raw_addr));
2406 }
2407
2408 int
vsf_sysutil_inet_aton(const char * p_text,struct vsf_sysutil_sockaddr * p_addr)2409 vsf_sysutil_inet_aton(const char* p_text, struct vsf_sysutil_sockaddr* p_addr)
2410 {
2411 static char sin_addr[sizeof(struct in6_addr)];
2412 if (inet_pton(p_addr->u.u_sockaddr.sa_family, p_text, &sin_addr))
2413 {
2414 if (p_addr->u.u_sockaddr.sa_family == AF_INET)
2415 vsf_sysutil_memcpy(&p_addr->u.u_sockaddr_in.sin_addr,
2416 &sin_addr, sizeof(p_addr->u.u_sockaddr_in.sin_addr));
2417 else
2418 if (p_addr->u.u_sockaddr.sa_family == AF_INET6)
2419 vsf_sysutil_memcpy(&p_addr->u.u_sockaddr_in6.sin6_addr,
2420 &sin_addr, sizeof(p_addr->u.u_sockaddr_in6.sin6_addr));
2421 return 1;
2422 }
2423 else
2424 {
2425 return 0;
2426 }
2427 }
2428
2429 void
vsf_sysutil_dns_resolve(struct vsf_sysutil_sockaddr ** p_sockptr,const char * p_name)2430 vsf_sysutil_dns_resolve(struct vsf_sysutil_sockaddr** p_sockptr,
2431 const char* p_name)
2432 {
2433 struct hostent* hent = gethostbyname(p_name);
2434 if (hent == NULL)
2435 {
2436 die2("cannot resolve host:", p_name);
2437 }
2438 vsf_sysutil_sockaddr_clear(p_sockptr);
2439 if (hent->h_addrtype == AF_INET)
2440 {
2441 unsigned int len = hent->h_length;
2442 if (len > sizeof((*p_sockptr)->u.u_sockaddr_in.sin_addr))
2443 {
2444 len = sizeof((*p_sockptr)->u.u_sockaddr_in.sin_addr);
2445 }
2446 vsf_sysutil_sockaddr_alloc_ipv4(p_sockptr);
2447 vsf_sysutil_memcpy(&(*p_sockptr)->u.u_sockaddr_in.sin_addr,
2448 hent->h_addr_list[0], len);
2449 }
2450 else if (hent->h_addrtype == AF_INET6)
2451 {
2452 unsigned int len = hent->h_length;
2453 if (len > sizeof((*p_sockptr)->u.u_sockaddr_in6.sin6_addr))
2454 {
2455 len = sizeof((*p_sockptr)->u.u_sockaddr_in6.sin6_addr);
2456 }
2457 vsf_sysutil_sockaddr_alloc_ipv6(p_sockptr);
2458 vsf_sysutil_memcpy(&(*p_sockptr)->u.u_sockaddr_in6.sin6_addr,
2459 hent->h_addr_list[0], len);
2460 }
2461 else
2462 {
2463 die("gethostbyname(): neither IPv4 nor IPv6");
2464 }
2465 }
2466
2467 int
vsf_sysutil_inet_addr_to_int(struct vsf_sysutil_sockaddr * p_addr)2468 vsf_sysutil_inet_addr_to_int(struct vsf_sysutil_sockaddr* p_addr)
2469 {
2470 struct in_addr sin_addr;
2471 vsf_sysutil_memcpy(&sin_addr, &p_addr->u.u_sockaddr_in.sin_addr,
2472 sizeof(p_addr->u.u_sockaddr_in.sin_addr));
2473 return (int)sin_addr.s_addr;
2474 }
2475
2476 struct vsf_sysutil_user*
vsf_sysutil_getpwuid(const int uid)2477 vsf_sysutil_getpwuid(const int uid)
2478 {
2479 if (uid < 0)
2480 {
2481 bug("negative uid in vsf_sysutil_getpwuid");
2482 }
2483 return (struct vsf_sysutil_user*) getpwuid((unsigned int) uid);
2484 }
2485
2486 struct vsf_sysutil_user*
vsf_sysutil_getpwnam(const char * p_user)2487 vsf_sysutil_getpwnam(const char* p_user)
2488 {
2489 return (struct vsf_sysutil_user*) getpwnam(p_user);
2490 }
2491
2492 const char*
vsf_sysutil_user_getname(const struct vsf_sysutil_user * p_user)2493 vsf_sysutil_user_getname(const struct vsf_sysutil_user* p_user)
2494 {
2495 const struct passwd* p_passwd = (const struct passwd*) p_user;
2496 return p_passwd->pw_name;
2497 }
2498
2499 const char*
vsf_sysutil_user_get_homedir(const struct vsf_sysutil_user * p_user)2500 vsf_sysutil_user_get_homedir(const struct vsf_sysutil_user* p_user)
2501 {
2502 const struct passwd* p_passwd = (const struct passwd*) p_user;
2503 return p_passwd->pw_dir;
2504 }
2505
2506 int
vsf_sysutil_user_getuid(const struct vsf_sysutil_user * p_user)2507 vsf_sysutil_user_getuid(const struct vsf_sysutil_user* p_user)
2508 {
2509 const struct passwd* p_passwd = (const struct passwd*) p_user;
2510 return p_passwd->pw_uid;
2511 }
2512
2513 int
vsf_sysutil_user_getgid(const struct vsf_sysutil_user * p_user)2514 vsf_sysutil_user_getgid(const struct vsf_sysutil_user* p_user)
2515 {
2516 const struct passwd* p_passwd = (const struct passwd*) p_user;
2517 return p_passwd->pw_gid;
2518 }
2519
2520 struct vsf_sysutil_group*
vsf_sysutil_getgrgid(const int gid)2521 vsf_sysutil_getgrgid(const int gid)
2522 {
2523 if (gid < 0)
2524 {
2525 die("negative gid in vsf_sysutil_getgrgid");
2526 }
2527 return (struct vsf_sysutil_group*) getgrgid((unsigned int) gid);
2528 }
2529
2530 const char*
vsf_sysutil_group_getname(const struct vsf_sysutil_group * p_group)2531 vsf_sysutil_group_getname(const struct vsf_sysutil_group* p_group)
2532 {
2533 const struct group* p_grp = (const struct group*) p_group;
2534 return p_grp->gr_name;
2535 }
2536
2537 unsigned char
vsf_sysutil_get_random_byte(void)2538 vsf_sysutil_get_random_byte(void)
2539 {
2540 static int seeded;
2541 unsigned int uint_res;
2542 unsigned char c1, c2, c3, c4;
2543 if (!seeded)
2544 {
2545 struct timeval tv;
2546 int retval = gettimeofday(&tv, NULL);
2547 if (retval != 0)
2548 {
2549 die("gettimeofday");
2550 }
2551 srand((unsigned)tv.tv_usec);
2552 seeded = 1;
2553 }
2554 uint_res = rand();
2555 c1 = uint_res & 0x000000ff;
2556 c2 = (uint_res >> 8) & 0x000000ff;
2557 c3 = (uint_res >> 16) & 0x000000ff;
2558 c4 = (uint_res >> 24) & 0x000000ff;
2559 return c1 ^ c2 ^ c3 ^ c4;
2560 }
2561
2562 int
vsf_sysutil_running_as_root(void)2563 vsf_sysutil_running_as_root(void)
2564 {
2565 return (getuid() == 0);
2566 }
2567
2568 void
vsf_sysutil_setuid(const struct vsf_sysutil_user * p_user)2569 vsf_sysutil_setuid(const struct vsf_sysutil_user* p_user)
2570 {
2571 const struct passwd* p_passwd = (const struct passwd*) p_user;
2572 vsf_sysutil_setuid_numeric(p_passwd->pw_uid);
2573 }
2574
2575 void
vsf_sysutil_setuid_numeric(int uid)2576 vsf_sysutil_setuid_numeric(int uid)
2577 {
2578 int retval = setuid(uid);
2579 if (retval != 0)
2580 {
2581 die("setuid");
2582 }
2583 }
2584
2585 void
vsf_sysutil_setgid(const struct vsf_sysutil_user * p_user)2586 vsf_sysutil_setgid(const struct vsf_sysutil_user* p_user)
2587 {
2588 const struct passwd* p_passwd = (const struct passwd*) p_user;
2589 vsf_sysutil_setgid_numeric(p_passwd->pw_gid);
2590 }
2591
2592 void
vsf_sysutil_setgid_numeric(int gid)2593 vsf_sysutil_setgid_numeric(int gid)
2594 {
2595 int retval = setgid(gid);
2596 if (retval != 0)
2597 {
2598 die("setgid");
2599 }
2600 }
2601
2602 int
vsf_sysutil_geteuid(void)2603 vsf_sysutil_geteuid(void)
2604 {
2605 int retval = geteuid();
2606 if (retval < 0)
2607 {
2608 die("geteuid");
2609 }
2610 return retval;
2611 }
2612
2613 int
vsf_sysutil_getegid(void)2614 vsf_sysutil_getegid(void)
2615 {
2616 int retval = getegid();
2617 if (retval < 0)
2618 {
2619 die("getegid");
2620 }
2621 return retval;
2622 }
2623
2624 void
vsf_sysutil_seteuid(const struct vsf_sysutil_user * p_user)2625 vsf_sysutil_seteuid(const struct vsf_sysutil_user* p_user)
2626 {
2627 const struct passwd* p_passwd = (const struct passwd*) p_user;
2628 vsf_sysutil_seteuid_numeric(p_passwd->pw_uid);
2629 }
2630
2631 void
vsf_sysutil_setegid(const struct vsf_sysutil_user * p_user)2632 vsf_sysutil_setegid(const struct vsf_sysutil_user* p_user)
2633 {
2634 const struct passwd* p_passwd = (const struct passwd*) p_user;
2635 vsf_sysutil_setegid_numeric(p_passwd->pw_gid);
2636 }
2637
2638 void
vsf_sysutil_seteuid_numeric(int uid)2639 vsf_sysutil_seteuid_numeric(int uid)
2640 {
2641 /* setreuid() would seem to be more portable than seteuid() */
2642 int retval = setreuid(-1, uid);
2643 if (retval != 0)
2644 {
2645 die("seteuid");
2646 }
2647 }
2648
2649 void
vsf_sysutil_setegid_numeric(int gid)2650 vsf_sysutil_setegid_numeric(int gid)
2651 {
2652 /* setregid() would seem to be more portable than setegid() */
2653 int retval = setregid(-1, gid);
2654 if (retval != 0)
2655 {
2656 die("setegid");
2657 }
2658 }
2659
2660 void
vsf_sysutil_clear_supp_groups(void)2661 vsf_sysutil_clear_supp_groups(void)
2662 {
2663 int retval = setgroups(0, NULL);
2664 if (retval != 0)
2665 {
2666 die("setgroups");
2667 }
2668 }
2669
2670 void
vsf_sysutil_initgroups(const struct vsf_sysutil_user * p_user)2671 vsf_sysutil_initgroups(const struct vsf_sysutil_user* p_user)
2672 {
2673 const struct passwd* p_passwd = (const struct passwd*) p_user;
2674 int retval = initgroups(p_passwd->pw_name, p_passwd->pw_gid);
2675 if (retval != 0)
2676 {
2677 die("initgroups");
2678 }
2679 }
2680
2681 void
vsf_sysutil_chroot(const char * p_root_path)2682 vsf_sysutil_chroot(const char* p_root_path)
2683 {
2684 int retval = chroot(p_root_path);
2685 if (retval != 0)
2686 {
2687 die("chroot");
2688 }
2689 }
2690
2691 unsigned int
vsf_sysutil_get_umask(void)2692 vsf_sysutil_get_umask(void)
2693 {
2694 return s_current_umask;
2695 }
2696
2697 void
vsf_sysutil_set_umask(unsigned int new_umask)2698 vsf_sysutil_set_umask(unsigned int new_umask)
2699 {
2700 s_current_umask = (new_umask & 0777);
2701 (void) umask(s_current_umask);
2702 }
2703
2704 void
vsf_sysutil_make_session_leader(void)2705 vsf_sysutil_make_session_leader(void)
2706 {
2707 /* This makes us the leader if we are not already */
2708 (void) setsid();
2709 /* Check we're the leader */
2710 if ((int) vsf_sysutil_getpid() != getpgrp())
2711 {
2712 die("not session leader");
2713 }
2714 }
2715
2716 void
vsf_sysutil_reopen_standard_fds(void)2717 vsf_sysutil_reopen_standard_fds(void)
2718 {
2719 /* This reopens STDIN, STDOUT and STDERR to /dev/null */
2720 int fd;
2721 if ((fd = open("/dev/null", O_RDWR, 0)) < 0)
2722 {
2723 goto error;
2724 }
2725 vsf_sysutil_dupfd2(fd, STDIN_FILENO);
2726 vsf_sysutil_dupfd2(fd, STDOUT_FILENO);
2727 vsf_sysutil_dupfd2(fd, STDERR_FILENO);
2728 if ( fd > 2 )
2729 {
2730 vsf_sysutil_close(fd);
2731 }
2732 return;
2733
2734 error:
2735 die("reopening standard file descriptors to /dev/null failed");
2736 }
2737
2738 void
vsf_sysutil_tzset(void)2739 vsf_sysutil_tzset(void)
2740 {
2741 int retval;
2742 char tzbuf[sizeof("+HHMM!")];
2743 time_t the_time = time(NULL);
2744 struct tm* p_tm;
2745 tzset();
2746 p_tm = localtime(&the_time);
2747 if (p_tm == NULL)
2748 {
2749 die("localtime");
2750 }
2751 /* Set our timezone in the TZ environment variable to cater for the fact
2752 * that modern glibc does not cache /etc/localtime (which becomes inaccessible
2753 * when we chroot().
2754 */
2755 retval = strftime(tzbuf, sizeof(tzbuf), "%z", p_tm);
2756 tzbuf[sizeof(tzbuf) - 1] = '\0';
2757 if (retval == 5)
2758 {
2759 /* Static because putenv() does not copy the string. */
2760 static char envtz[sizeof("TZ=UTC-hh:mm")];
2761 /* Insert a colon so we have e.g. -05:00 instead of -0500 */
2762 tzbuf[5] = tzbuf[4];
2763 tzbuf[4] = tzbuf[3];
2764 tzbuf[3] = ':';
2765 /* Invert the sign - we just got the offset _from_ UTC but for TZ, we need
2766 * the offset _to_ UTC.
2767 */
2768 if (tzbuf[0] == '+')
2769 {
2770 tzbuf[0] = '-';
2771 }
2772 else
2773 {
2774 tzbuf[0] = '+';
2775 }
2776 snprintf(envtz, sizeof(envtz), "TZ=UTC%s", tzbuf);
2777 putenv(envtz);
2778 s_timezone = ((tzbuf[1] - '0') * 10 + (tzbuf[2] - '0')) * 60 * 60;
2779 s_timezone += ((tzbuf[4] - '0') * 10 + (tzbuf[5] - '0')) * 60;
2780 if (tzbuf[0] == '-')
2781 {
2782 s_timezone *= -1;
2783 }
2784 }
2785 /* Call in to the time subsystem again now that TZ is set, trying to force
2786 * caching of the actual zoneinfo for the timezone.
2787 */
2788 p_tm = localtime(&the_time);
2789 if (p_tm == NULL)
2790 {
2791 die("localtime #2");
2792 }
2793 p_tm = gmtime(&the_time);
2794 if (p_tm == NULL)
2795 {
2796 die("gmtime");
2797 }
2798 }
2799
2800 const char*
vsf_sysutil_get_current_date(int use_localtime)2801 vsf_sysutil_get_current_date(int use_localtime)
2802 {
2803 static char datebuf[64];
2804 time_t curr_time;
2805 const struct tm* p_tm;
2806 int i = 0;
2807 curr_time = vsf_sysutil_get_time_sec();
2808 if (!use_localtime) {
2809 p_tm = gmtime(&curr_time);
2810 } else {
2811 p_tm = localtime(&curr_time);
2812 }
2813 if (strftime(datebuf, sizeof(datebuf), "%a %b!%d %H:%M:%S %Y", p_tm) == 0)
2814 {
2815 die("strftime");
2816 }
2817 datebuf[sizeof(datebuf) - 1] = '\0';
2818 /* This hack is because %e in strftime() isn't so portable */
2819 while (datebuf[i] != '!' && datebuf[i] != '\0')
2820 {
2821 ++i;
2822 }
2823 if (datebuf[i] == '!')
2824 {
2825 datebuf[i] = ' ';
2826 if (datebuf[i+1] == '0')
2827 {
2828 datebuf[i+1] = ' ';
2829 }
2830 }
2831 return datebuf;
2832 }
2833
2834 const char*
vsf_sysutil_get_datetimefmt(int use_localtime,long curr_time,const char * fmt)2835 vsf_sysutil_get_datetimefmt(int use_localtime, long curr_time, const char* fmt)
2836 {
2837 static char datebuf[64];
2838 const struct tm* p_tm;
2839 int i = 0;
2840 if (!use_localtime) {
2841 p_tm = gmtime(&curr_time);
2842 } else {
2843 p_tm = localtime(&curr_time);
2844 }
2845 if (strftime(datebuf, sizeof(datebuf), fmt, p_tm) == 0)
2846 {
2847 die("strftime");
2848 }
2849 datebuf[sizeof(datebuf) - 1] = '\0';
2850 /* This hack is because %e in strftime() isn't so portable */
2851 while (datebuf[i] != '!' && datebuf[i] != '\0')
2852 {
2853 ++i;
2854 }
2855 if (datebuf[i] == '!')
2856 {
2857 datebuf[i] = ' ';
2858 if (datebuf[i+1] == '0')
2859 {
2860 datebuf[i+1] = ' ';
2861 }
2862 }
2863 return datebuf;
2864 }
2865
2866 const char*
vsf_sysutil_get_datetime(int use_localtime,long curr_time)2867 vsf_sysutil_get_datetime(int use_localtime, long curr_time)
2868 {
2869 if (!use_localtime) {
2870 return vsf_sysutil_get_datetimefmt(use_localtime, curr_time, "%a,!%d %b %H:%M:%S %Y %Z");
2871 } else {
2872 return vsf_sysutil_get_datetimefmt(use_localtime, curr_time, "%a,!%d %b %H:%M:%S %Y");
2873 }
2874 }
2875
2876 const char*
vsf_sysutil_get_date(int use_localtime,long curr_time)2877 vsf_sysutil_get_date(int use_localtime, long curr_time)
2878 {
2879 return vsf_sysutil_get_datetimefmt(use_localtime, curr_time, "%a,!%d %b %Y");
2880 }
2881
2882 const char*
vsf_sysutil_get_sdate(int use_localtime,long curr_time)2883 vsf_sysutil_get_sdate(int use_localtime, long curr_time)
2884 {
2885 return vsf_sysutil_get_datetimefmt(use_localtime, curr_time, "%d.%m.%Y");
2886 }
2887
2888 const char*
vsf_sysutil_get_time(int use_localtime,long curr_time)2889 vsf_sysutil_get_time(int use_localtime, long curr_time)
2890 {
2891 if (!use_localtime) {
2892 return vsf_sysutil_get_datetimefmt(use_localtime, curr_time, "%H:%M:%S %Z");
2893 } else {
2894 return vsf_sysutil_get_datetimefmt(use_localtime, curr_time, "%H:%M:%S");
2895 }
2896 }
2897
2898 long
vsf_sysutil_get_time_sec(void)2899 vsf_sysutil_get_time_sec(void)
2900 {
2901 if (gettimeofday(&s_current_time, NULL) != 0)
2902 {
2903 die("gettimeofday");
2904 }
2905 return s_current_time.tv_sec;
2906 }
2907
2908 long
vsf_sysutil_get_time_usec(void)2909 vsf_sysutil_get_time_usec(void)
2910 {
2911 return s_current_time.tv_usec;
2912 }
2913
2914 void
vsf_sysutil_qsort(void * p_base,unsigned int num_elem,unsigned int elem_size,int (* p_compar)(const void *,const void *))2915 vsf_sysutil_qsort(void* p_base, unsigned int num_elem, unsigned int elem_size,
2916 int (*p_compar)(const void *, const void *))
2917 {
2918 qsort(p_base, num_elem, elem_size, p_compar);
2919 }
2920
2921 void
vsf_sysutil_sleep(double seconds)2922 vsf_sysutil_sleep(double seconds)
2923 {
2924 int retval;
2925 int saved_errno;
2926 double fractional;
2927 time_t secs;
2928 struct timespec ts;
2929 secs = (time_t) seconds;
2930 fractional = seconds - (double) secs;
2931 ts.tv_sec = secs;
2932 ts.tv_nsec = (long) (fractional * (double) 1000000000);
2933 do
2934 {
2935 retval = nanosleep(&ts, &ts);
2936 saved_errno = errno;
2937 vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
2938 } while (retval == -1 && saved_errno == EINTR);
2939 }
2940
2941 char*
vsf_sysutil_getenv(const char * p_var)2942 vsf_sysutil_getenv(const char* p_var)
2943 {
2944 return getenv(p_var);
2945 }
2946
2947 void
vsf_sysutil_openlog(int force)2948 vsf_sysutil_openlog(int force)
2949 {
2950 int facility = LOG_DAEMON;
2951 int option = LOG_PID;
2952 if (!force)
2953 {
2954 option |= LOG_NDELAY;
2955 }
2956 #ifdef LOG_FTP
2957 facility = LOG_FTP;
2958 #endif
2959 openlog("vsftpd", option, facility);
2960 }
2961
2962 void
vsf_sysutil_closelog(void)2963 vsf_sysutil_closelog(void)
2964 {
2965 closelog();
2966 }
2967
2968 void
vsf_sysutil_syslog(const char * p_text,int severe)2969 vsf_sysutil_syslog(const char* p_text, int severe)
2970 {
2971 int prio = LOG_INFO;
2972 if (severe)
2973 {
2974 prio = LOG_WARNING;
2975 }
2976 syslog(prio, "%s", p_text);
2977 }
2978
2979 long
vsf_sysutil_parse_time(const char * p_text)2980 vsf_sysutil_parse_time(const char* p_text)
2981 {
2982 struct tm the_time;
2983 unsigned int len = vsf_sysutil_strlen(p_text);
2984 vsf_sysutil_memclr(&the_time, sizeof(the_time));
2985 if (len >= 8)
2986 {
2987 char yr[5];
2988 char mon[3];
2989 char day[3];
2990 vsf_sysutil_strcpy(yr, p_text, 5);
2991 vsf_sysutil_strcpy(mon, p_text + 4, 3);
2992 vsf_sysutil_strcpy(day, p_text + 6, 3);
2993 the_time.tm_year = vsf_sysutil_atoi(yr) - 1900;
2994 the_time.tm_mon = vsf_sysutil_atoi(mon) - 1;
2995 the_time.tm_mday = vsf_sysutil_atoi(day);
2996 }
2997 if (len >= 14)
2998 {
2999 char hr[3];
3000 char mins[3];
3001 char sec[3];
3002 vsf_sysutil_strcpy(hr, p_text + 8, 3);
3003 vsf_sysutil_strcpy(mins, p_text + 10, 3);
3004 vsf_sysutil_strcpy(sec, p_text + 12, 3);
3005 the_time.tm_hour = vsf_sysutil_atoi(hr);
3006 the_time.tm_min = vsf_sysutil_atoi(mins);
3007 the_time.tm_sec = vsf_sysutil_atoi(sec);
3008 }
3009 return mktime(&the_time);
3010 }
3011
3012 int
vsf_sysutil_setmodtime(const char * p_file,long the_time,int is_localtime)3013 vsf_sysutil_setmodtime(const char* p_file, long the_time, int is_localtime)
3014 {
3015 struct utimbuf new_times;
3016 if (!is_localtime)
3017 {
3018 the_time -= s_timezone;
3019 }
3020 vsf_sysutil_memclr(&new_times, sizeof(new_times));
3021 new_times.actime = the_time;
3022 new_times.modtime = the_time;
3023 return utime(p_file, &new_times);
3024 }
3025
3026 void
vsf_sysutil_ftruncate(int fd)3027 vsf_sysutil_ftruncate(int fd)
3028 {
3029 int ret = ftruncate(fd, 0);
3030 if (ret != 0)
3031 {
3032 die("ftruncate");
3033 }
3034 }
3035
3036 int
vsf_sysutil_getuid(void)3037 vsf_sysutil_getuid(void)
3038 {
3039 return getuid();
3040 }
3041
3042 void
vsf_sysutil_set_address_space_limit(unsigned long bytes)3043 vsf_sysutil_set_address_space_limit(unsigned long bytes)
3044 {
3045 /* Unfortunately, OpenBSD is missing RLIMIT_AS. */
3046 #ifdef RLIMIT_AS
3047 int ret;
3048 struct rlimit rlim;
3049 rlim.rlim_cur = bytes;
3050 rlim.rlim_max = bytes;
3051 ret = setrlimit(RLIMIT_AS, &rlim);
3052 /* Permit EPERM as this could indicate that the shell launching vsftpd already
3053 * has a lower limit.
3054 */
3055 if (ret != 0 && errno != EPERM)
3056 {
3057 die("setrlimit");
3058 }
3059 #endif /* RLIMIT_AS */
3060 (void) bytes;
3061 }
3062
3063 void
vsf_sysutil_set_no_fds()3064 vsf_sysutil_set_no_fds()
3065 {
3066 int ret;
3067 struct rlimit rlim;
3068 rlim.rlim_cur = 0;
3069 rlim.rlim_max = 0;
3070 ret = setrlimit(RLIMIT_NOFILE, &rlim);
3071 if (ret != 0)
3072 {
3073 die("setrlimit NOFILE");
3074 }
3075 }
3076
3077 void
vsf_sysutil_set_no_procs()3078 vsf_sysutil_set_no_procs()
3079 {
3080 #ifdef RLIMIT_NPROC
3081 int ret;
3082 struct rlimit rlim;
3083 rlim.rlim_cur = 0;
3084 rlim.rlim_max = 0;
3085 ret = setrlimit(RLIMIT_NPROC, &rlim);
3086 if (ret != 0)
3087 {
3088 die("setrlimit NPROC");
3089 }
3090 #endif
3091 }
3092
3093 void
vsf_sysutil_post_fork()3094 vsf_sysutil_post_fork()
3095 {
3096 int i;
3097 /* Don't inherit any exit function. */
3098 s_exit_func = NULL;
3099 /* Uncached the current PID. */
3100 s_current_pid = -1;
3101 /* Don't inherit anything relating to the synchronous signal system */
3102 s_io_handler = NULL;
3103 for (i=0; i < NSIG; ++i)
3104 {
3105 s_sig_details[i].sync_sig_handler = NULL;
3106 }
3107 for (i=0; i < NSIG; ++i)
3108 {
3109 s_sig_details[i].pending = 0;
3110 }
3111 }
3112
3113 static struct sigaction sigalr, sigusr1;
3114
3115 void
vsf_sysutil_sigaction(const enum EVSFSysUtilSignal sig,void (* p_handlefunc)(int))3116 vsf_sysutil_sigaction(const enum EVSFSysUtilSignal sig, void (*p_handlefunc)(int))
3117 {
3118 int realsig = vsf_sysutil_translate_sig(sig);
3119 int retval;
3120 struct sigaction sigact, *origsigact=NULL;
3121 if (realsig==SIGALRM)
3122 {
3123 origsigact = &sigalr;
3124 }
3125 else if (realsig==SIGUSR1)
3126 {
3127 origsigact = &sigusr1;
3128 }
3129 vsf_sysutil_memclr(&sigact, sizeof(sigact));
3130 if (p_handlefunc != NULL)
3131 {
3132 sigact.sa_handler = p_handlefunc;
3133 retval = sigfillset(&sigact.sa_mask);
3134 if (retval != 0)
3135 {
3136 die("sigfillset");
3137 }
3138 retval = sigaction(realsig, &sigact, origsigact);
3139 }
3140 else
3141 {
3142 retval = sigaction(realsig, origsigact, NULL);
3143 }
3144 if (retval != 0)
3145 {
3146 die("sigaction");
3147 }
3148 }
3149
3150 int
vsf_sysutil_kill(int pid,int sig)3151 vsf_sysutil_kill(int pid, int sig)
3152 {
3153 int realsig = vsf_sysutil_translate_sig(sig);
3154 return kill(pid, realsig);
3155 }
3156
3157 int
vsf_sysutil_pause()3158 vsf_sysutil_pause()
3159 {
3160 return pause();
3161 }
3162
3163