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