sysutil.c
上传用户:ig0539
上传日期:2022-05-21
资源大小:181k
文件大小:60k
源码类别:

Ftp客户端

开发平台:

C/C++

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