⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sysutil.c

📁 文件传输协议linux 下vsftpd2.1.0.tar.gz
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Part of Very Secure FTPd * Licence: GPL v2 * Author: Chris Evans *  * sysutil.c * * Routines to make the libc/syscall API more pleasant to use. Long term, * more libc/syscalls will go in here to reduce the number of .c files with * dependencies on libc or syscalls. */#define PRIVATE_HANDS_OFF_syscall_retval syscall_retval#define PRIVATE_HANDS_OFF_exit_status exit_status#include "sysutil.h"#include "utility.h"#include "tunables.h"/* Activate 64-bit file support on Linux/32bit plus others */#define _FILE_OFFSET_BITS 64#define _LARGEFILE_SOURCE 1#define _LARGEFILE64_SOURCE 1#define _LARGE_FILES 1/* For Linux, this adds nothing :-) */#include "port/porting_junk.h"#include <signal.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/mman.h>#include <sys/stat.h>#include <fcntl.h>#include <netinet/in.h>#include <stdio.h>#include <dirent.h>#include <time.h>#include <arpa/inet.h>#include <errno.h>#include <pwd.h>#include <grp.h>#include <ctype.h>#include <sys/wait.h>#include <sys/time.h>/* Must be before netinet/ip.h. Found on FreeBSD, Solaris */#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/tcp.h>#include <limits.h>#include <syslog.h>#include <utime.h>#include <netdb.h>#include <sys/resource.h>/* Private variables to this file *//* Current umask() */static unsigned int s_current_umask;/* Cached time */static struct timeval s_current_time;/* Current pid */static int s_current_pid = -1;/* Exit function */static exitfunc_t s_exit_func;/* Difference in timezone from GMT in seconds */static long s_timezone;/* Our internal signal handling implementation details */static struct vsf_sysutil_sig_details{  vsf_sighandle_t sync_sig_handler;  void* p_private;  int pending;  int running;  int use_alarm;} s_sig_details[NSIG];static vsf_context_io_t s_io_handler;static void* s_p_io_handler_private;static int s_io_handler_running;struct vsf_sysutil_sockaddr{  union  {    struct sockaddr u_sockaddr;    struct sockaddr_in u_sockaddr_in;    struct sockaddr_in6 u_sockaddr_in6;  } u;};/* File locals */static void vsf_sysutil_common_sighandler(int signum);static void vsf_sysutil_alrm_sighandler(int signum);static int vsf_sysutil_translate_sig(const enum EVSFSysUtilSignal sig);static void vsf_sysutil_set_sighandler(int sig, void (*p_handlefunc)(int));static int vsf_sysutil_translate_memprot(  const enum EVSFSysUtilMapPermission perm);static int vsf_sysutil_translate_openmode(  const enum EVSFSysUtilOpenMode mode);static void vsf_sysutil_alloc_statbuf(struct vsf_sysutil_statbuf** p_ptr);void vsf_sysutil_sockaddr_alloc(struct vsf_sysutil_sockaddr** p_sockptr);static int lock_internal(int fd, int lock_type);static voidvsf_sysutil_alrm_sighandler(int signum){  (void) signum;  alarm(1);}static voidvsf_sysutil_common_sighandler(int signum){  if (signum < 0 || signum >= NSIG)  {    // bug() is not async safe but this check really is a "cannot happen"    // debug aid.    bug("signal out of range in vsf_sysutil_common_sighandler");  }  if (s_sig_details[signum].sync_sig_handler)  {    s_sig_details[signum].pending = 1;    /* Since this synchronous signal framework has a small race (signal coming     * in just before we start a blocking call), there's the option to fire an     * alarm repeatedly until the signal is handled.     */    if (s_sig_details[signum].use_alarm)    {      alarm(1);    }  }}/* Notes. This signal check is evaluated after potentially blocking system * calls, i.e. at highly defined points in the code. Since we only interrupt * at these definite locations, the signal handlers can be non-trivial * without us having to worry about re-entrancy. * * We guarantee that a handler for a given signal is not re-entrant. This * is taken care of by the "running" flag. * * This call itself can only be re-entered once we dereference the actual * hander function pointer, so we are safe with respect to races modifying * the "running" flag. */voidvsf_sysutil_check_pending_actions(  const enum EVSFSysUtilInterruptContext context, int retval, int fd){  unsigned int i;  /* Check the i/o handler before the signal handlers */  if (s_io_handler && !s_io_handler_running && context == kVSFSysUtilIO)  {    s_io_handler_running = 1;    (*s_io_handler)(retval, fd, s_p_io_handler_private);    s_io_handler_running = 0;  }  for (i=0; i < NSIG; ++i)  {    if (s_sig_details[i].pending && !s_sig_details[i].running)    {      s_sig_details[i].running = 1;      if (s_sig_details[i].use_alarm)      {        alarm(0);      }      if (s_sig_details[i].sync_sig_handler)      {        s_sig_details[i].pending = 0;        (*(s_sig_details[i].sync_sig_handler))(s_sig_details[i].p_private);      }      s_sig_details[i].running = 0;    }  }}static intvsf_sysutil_translate_sig(const enum EVSFSysUtilSignal sig){  int realsig = 0;  switch (sig)  {    case kVSFSysUtilSigALRM:      realsig = SIGALRM;      break;    case kVSFSysUtilSigTERM:      realsig = SIGTERM;      break;    case kVSFSysUtilSigCHLD:      realsig = SIGCHLD;      break;    case kVSFSysUtilSigPIPE:      realsig = SIGPIPE;      break;    case kVSFSysUtilSigURG:      realsig = SIGURG;      break;    case kVSFSysUtilSigHUP:      realsig = SIGHUP;      break;    default:      bug("unknown signal in vsf_sysutil_translate_sig");      break;  }  if (realsig < 0 || realsig >= NSIG)  {    bug("signal out of range in vsf_sysutil_translate_sig");  }  return realsig;}voidvsf_sysutil_install_sighandler(const enum EVSFSysUtilSignal sig,                               vsf_sighandle_t handler,                               void* p_private,                               int use_alarm){  int realsig = vsf_sysutil_translate_sig(sig);  s_sig_details[realsig].p_private = p_private;  s_sig_details[realsig].sync_sig_handler = handler;  s_sig_details[realsig].use_alarm = use_alarm;  vsf_sysutil_set_sighandler(realsig, vsf_sysutil_common_sighandler);  if (use_alarm && realsig != SIGALRM)  {    vsf_sysutil_set_sighandler(SIGALRM, vsf_sysutil_alrm_sighandler);  }}voidvsf_sysutil_default_sig(const enum EVSFSysUtilSignal sig){  int realsig = vsf_sysutil_translate_sig(sig);  vsf_sysutil_set_sighandler(realsig, SIG_DFL);  s_sig_details[realsig].p_private = NULL;  s_sig_details[realsig].sync_sig_handler = NULL;}voidvsf_sysutil_install_null_sighandler(const enum EVSFSysUtilSignal sig){  int realsig = vsf_sysutil_translate_sig(sig);  s_sig_details[realsig].p_private = NULL;  s_sig_details[realsig].sync_sig_handler = NULL;  vsf_sysutil_set_sighandler(realsig, vsf_sysutil_common_sighandler);}voidvsf_sysutil_install_async_sighandler(const enum EVSFSysUtilSignal sig,                                     vsf_async_sighandle_t handler){  int realsig = vsf_sysutil_translate_sig(sig);  s_sig_details[realsig].p_private = NULL;  s_sig_details[realsig].sync_sig_handler = NULL;  vsf_sysutil_block_sig(sig);  vsf_sysutil_set_sighandler(realsig, handler);}static voidvsf_sysutil_set_sighandler(int sig, void (*p_handlefunc)(int)){  int retval;  struct sigaction sigact;  vsf_sysutil_memclr(&sigact, sizeof(sigact));  sigact.sa_handler = p_handlefunc;  retval = sigfillset(&sigact.sa_mask);  if (retval != 0)  {    die("sigfillset");  }  retval = sigaction(sig, &sigact, NULL);  if (retval != 0)  {    die("sigaction");  }}voidvsf_sysutil_block_sig(const enum EVSFSysUtilSignal sig){  sigset_t sset;  int retval;  int realsig = vsf_sysutil_translate_sig(sig);  retval = sigemptyset(&sset);  if (retval != 0)  {    die("sigemptyset");  }  retval = sigaddset(&sset, realsig);  if (retval != 0)  {    die("sigaddset");  }  retval = sigprocmask(SIG_BLOCK, &sset, NULL);  if (retval != 0)  {    die("sigprocmask");  }}voidvsf_sysutil_unblock_sig(const enum EVSFSysUtilSignal sig){  sigset_t sset;  int retval;  int realsig = vsf_sysutil_translate_sig(sig);  retval = sigemptyset(&sset);  if (retval != 0)  {    die("sigemptyset");  }  retval = sigaddset(&sset, realsig);  if (retval != 0)  {    die("sigaddset");  }  retval = sigprocmask(SIG_UNBLOCK, &sset, NULL);  if (retval != 0)  {    die("sigprocmask");  }}voidvsf_sysutil_install_io_handler(vsf_context_io_t handler, void* p_private){  if (s_io_handler != NULL)  {    bug("double register of i/o handler");  }  s_io_handler = handler;  s_p_io_handler_private = p_private;}voidvsf_sysutil_uninstall_io_handler(void){  if (s_io_handler == NULL)  {    bug("no i/o handler to unregister!");  }  s_io_handler = NULL;  s_p_io_handler_private = NULL;}voidvsf_sysutil_set_alarm(const unsigned int trigger_seconds){  (void) alarm(trigger_seconds);}voidvsf_sysutil_clear_alarm(void){  vsf_sysutil_set_alarm(0);}intvsf_sysutil_read(const int fd, void* p_buf, const unsigned int size){  while (1)  {    int retval = read(fd, p_buf, size);    int saved_errno = errno;    vsf_sysutil_check_pending_actions(kVSFSysUtilIO, retval, fd);    if (retval < 0 && saved_errno == EINTR)    {      continue;    }    return retval;  }}intvsf_sysutil_write(const int fd, const void* p_buf, const unsigned int size){  while (1)  {    int retval = write(fd, p_buf, size);    int saved_errno = errno;    vsf_sysutil_check_pending_actions(kVSFSysUtilIO, retval, fd);    if (retval < 0 && saved_errno == EINTR)    {      continue;    }    return retval;  }}intvsf_sysutil_read_loop(const int fd, void* p_buf, unsigned int size){  int retval;  int num_read = 0;  if (size > INT_MAX)  {    die("size too big in vsf_sysutil_read_loop");  }  while (1)  {    retval = vsf_sysutil_read(fd, (char*)p_buf + num_read, size);    if (retval < 0)    {      return retval;    }    else if (retval == 0)    {      /* Read all we're going to read.. */      return num_read;     }    if ((unsigned int) retval > size)    {      die("retval too big in vsf_sysutil_read_loop");    }    num_read += retval;    size -= (unsigned int) retval;    if (size == 0)    {      /* Hit the read target, cool. */      return num_read;    }  }}intvsf_sysutil_write_loop(const int fd, const void* p_buf, unsigned int size){  int retval;  int num_written = 0;  if (size > INT_MAX)  {    die("size too big in vsf_sysutil_write_loop");  }  while (1)  {    retval = vsf_sysutil_write(fd, (const char*)p_buf + num_written, size);    if (retval < 0)    {      /* Error */      return retval;    }    else if (retval == 0)    {      /* Written all we're going to write.. */      return num_written;    }    if ((unsigned int) retval > size)    {      die("retval too big in vsf_sysutil_read_loop");    }    num_written += retval;    size -= (unsigned int) retval;    if (size == 0)    {      /* Hit the write target, cool. */      return num_written;    }  }}filesize_tvsf_sysutil_get_file_offset(const int file_fd){  filesize_t retval = lseek(file_fd, 0, SEEK_CUR);  if (retval < 0)  {    die("lseek");  }  return retval;}voidvsf_sysutil_lseek_to(const int fd, filesize_t seek_pos){  filesize_t retval;  if (seek_pos < 0)  {    die("negative seek_pos in vsf_sysutil_lseek_to");  }  retval = lseek(fd, seek_pos, SEEK_SET);  if (retval < 0)  {    die("lseek");  }}void*vsf_sysutil_malloc(unsigned int size){  void* p_ret;  /* Paranoia - what if we got an integer overflow/underflow? */  if (size == 0 || size > INT_MAX)  {    bug("zero or big size in vsf_sysutil_malloc");  }    p_ret = malloc(size);  if (p_ret == NULL)  {    die("malloc");  }  return p_ret;}void*vsf_sysutil_realloc(void* p_ptr, unsigned int size){  void* p_ret;  if (size == 0 || size > INT_MAX)  {    bug("zero or big size in vsf_sysutil_realloc");  }  p_ret = realloc(p_ptr, size);  if (p_ret == NULL)  {    die("realloc");  }  return p_ret;}voidvsf_sysutil_free(void* p_ptr){  if (p_ptr == NULL)  {    bug("vsf_sysutil_free got a null pointer");  }  free(p_ptr);}unsigned intvsf_sysutil_getpid(void){  if (s_current_pid == -1)  {    s_current_pid = getpid();  }  return (unsigned int) s_current_pid;}intvsf_sysutil_fork(void){  /* Child does NOT inherit exit function */  exitfunc_t curr_func = s_exit_func;  int retval;  s_exit_func = 0;  retval = vsf_sysutil_fork_failok();  if (retval != 0)  {    s_exit_func = curr_func;  }  if (retval < 0)  {    die("fork");  }  return retval;}intvsf_sysutil_fork_failok(void){  int retval = fork();  if (retval == 0)  {    s_current_pid = -1;  }  return retval;}voidvsf_sysutil_set_exit_func(exitfunc_t exitfunc){  s_exit_func = exitfunc;}voidvsf_sysutil_exit(int exit_code){  if (s_exit_func)  {    exitfunc_t curr_func = s_exit_func;    /* Prevent recursion */    s_exit_func = 0;    (*curr_func)();  }  _exit(exit_code);}struct vsf_sysutil_wait_retvalvsf_sysutil_wait(void){  struct vsf_sysutil_wait_retval retval;  vsf_sysutil_memclr(&retval, sizeof(retval));  while (1)  {    int sys_ret = wait(&retval.exit_status);    if (sys_ret < 0 && errno == EINTR)    {      vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);      continue;    }    retval.syscall_retval = sys_ret;    return retval;  }}intvsf_sysutil_wait_reap_one(void){  int retval = waitpid(-1, NULL, WNOHANG);  if (retval == 0 || (retval < 0 && errno == ECHILD))  {    /* No more children */    return 0;  }  if (retval < 0)  {    die("waitpid");  }  /* Got one */  return retval;}intvsf_sysutil_wait_get_retval(const struct vsf_sysutil_wait_retval* p_waitret){  return p_waitret->syscall_retval;}intvsf_sysutil_wait_exited_normally(  const struct vsf_sysutil_wait_retval* p_waitret){  int status = ((struct vsf_sysutil_wait_retval*) p_waitret)->exit_status;  return WIFEXITED(status);}intvsf_sysutil_wait_get_exitcode(const struct vsf_sysutil_wait_retval* p_waitret){  int status;  if (!vsf_sysutil_wait_exited_normally(p_waitret))  {    bug("not a normal exit in vsf_sysutil_wait_get_exitcode");  }  status = ((struct vsf_sysutil_wait_retval*) p_waitret)->exit_status;  return WEXITSTATUS(status);}voidvsf_sysutil_activate_keepalive(int fd){  int keepalive = 1;  int retval = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive,                          sizeof(keepalive));  if (retval != 0)  {    die("setsockopt: keepalive");  }}voidvsf_sysutil_activate_reuseaddr(int fd){  int reuseaddr = 1;  int retval = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,                          sizeof(reuseaddr));  if (retval != 0)  {    die("setsockopt: reuseaddr");  }}voidvsf_sysutil_set_nodelay(int fd){  int nodelay = 1;  int retval = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &nodelay,                          sizeof(nodelay));  if (retval != 0)  {    die("setsockopt: nodelay");  }}voidvsf_sysutil_activate_sigurg(int fd){  int retval = fcntl(fd, F_SETOWN, getpid());  if (retval != 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -