📄 sysutil.c
字号:
long local_time = vsf_sysutil_get_cached_time_sec(); const char* p_date_format = "%b %d %H:%M"; if (!use_localtime) { p_tm = gmtime(&p_stat->st_mtime); } else { p_tm = localtime(&p_stat->st_mtime); } /* Is this a future or 6 months old date? If so, we drop to year format */ if (p_stat->st_mtime > local_time || (local_time - p_stat->st_mtime) > 60*60*24*182) { p_date_format = "%b %d %Y"; } retval = strftime(datebuf, sizeof(datebuf), p_date_format, p_tm); datebuf[sizeof(datebuf)-1] = '\0'; if (retval == 0) { die("strftime"); } return datebuf;}const char*vsf_sysutil_statbuf_get_numeric_date( const struct vsf_sysutil_statbuf* p_statbuf, int use_localtime){ static char datebuf[15]; const struct stat* p_stat = (const struct stat*) p_statbuf; struct tm* p_tm; int retval; if (!use_localtime) { p_tm = gmtime(&p_stat->st_mtime); } else { p_tm = localtime(&p_stat->st_mtime); } retval = strftime(datebuf, sizeof(datebuf), "%Y%m%d%H%M%S", p_tm); if (retval == 0) { die("strftime"); } return datebuf;}filesize_tvsf_sysutil_statbuf_get_size(const struct vsf_sysutil_statbuf* p_statbuf){ const struct stat* p_stat = (const struct stat*) p_statbuf; if (p_stat->st_size < 0) { die("invalid inode size in vsf_sysutil_statbuf_get_size"); } return p_stat->st_size;}intvsf_sysutil_statbuf_get_uid(const struct vsf_sysutil_statbuf* p_statbuf){ const struct stat* p_stat = (const struct stat*) p_statbuf; return p_stat->st_uid;}intvsf_sysutil_statbuf_get_gid(const struct vsf_sysutil_statbuf* p_statbuf){ const struct stat* p_stat = (const struct stat*) p_statbuf; return p_stat->st_gid;}unsigned intvsf_sysutil_statbuf_get_links(const struct vsf_sysutil_statbuf* p_statbuf){ const struct stat* p_stat = (const struct stat*) p_statbuf; return p_stat->st_nlink;}intvsf_sysutil_statbuf_is_readable_other( const struct vsf_sysutil_statbuf* p_statbuf){ const struct stat* p_stat = (const struct stat*) p_statbuf; if (p_stat->st_mode & S_IROTH) { return 1; } return 0;}const char*vsf_sysutil_statbuf_get_sortkey_mtime( const struct vsf_sysutil_statbuf* p_statbuf){ static char intbuf[32]; const struct stat* p_stat = (const struct stat*) p_statbuf; /* This slight hack function must return a character date format such that * more recent dates appear later in the alphabet! Most notably, we must * make sure we pad to the same length with 0's */ snprintf(intbuf, sizeof(intbuf), "%030ld", (long) p_stat->st_mtime); return intbuf;}voidvsf_sysutil_fchown(const int fd, const int uid, const int gid){ if (fchown(fd, uid, gid) != 0) { die("fchown"); }}voidvsf_sysutil_fchmod(const int fd, unsigned int mode){ mode = mode & 0777; if (fchmod(fd, mode)) { die("fchmod"); }}intvsf_sysutil_chmod(const char* p_filename, unsigned int mode){ /* Safety: mask "mode" to just access permissions, e.g. no suid setting! */ mode = mode & 0777; return chmod(p_filename, mode);}intvsf_sysutil_lock_file_write(int fd){ return lock_internal(fd, F_WRLCK);}intvsf_sysutil_lock_file_read(int fd){ return lock_internal(fd, F_RDLCK);}static intlock_internal(int fd, int lock_type){ struct flock the_lock; int retval; int saved_errno; vsf_sysutil_memclr(&the_lock, sizeof(the_lock)); the_lock.l_type = lock_type; the_lock.l_whence = SEEK_SET; the_lock.l_start = 0; the_lock.l_len = 0; do { retval = fcntl(fd, F_SETLKW, &the_lock); saved_errno = errno; vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0); } while (retval < 0 && saved_errno == EINTR); return retval;}voidvsf_sysutil_unlock_file(int fd){ int retval; struct flock the_lock; vsf_sysutil_memclr(&the_lock, sizeof(the_lock)); the_lock.l_type = F_UNLCK; the_lock.l_whence = SEEK_SET; the_lock.l_start = 0; the_lock.l_len = 0; retval = fcntl(fd, F_SETLK, &the_lock); if (retval != 0) { die("fcntl"); }}intvsf_sysutil_readlink(const char* p_filename, char* p_dest, unsigned int bufsiz){ int retval; if (bufsiz == 0) { return -1; } retval = readlink(p_filename, p_dest, bufsiz - 1); if (retval < 0) { return retval; } /* Ensure buffer is NULL terminated; readlink(2) doesn't do that */ p_dest[retval] = '\0'; return retval;}intvsf_sysutil_retval_is_error(int retval){ if (retval < 0) { return 1; } return 0;}enum EVSFSysUtilErrorvsf_sysutil_get_error(void){ enum EVSFSysUtilError retval = kVSFSysUtilErrUnknown; switch (errno) { case EADDRINUSE: retval = kVSFSysUtilErrADDRINUSE; break; case ENOSYS: retval = kVSFSysUtilErrNOSYS; break; case EINTR: retval = kVSFSysUtilErrINTR; break; case EINVAL: retval = kVSFSysUtilErrINVAL; break; case EOPNOTSUPP: retval = kVSFSysUtilErrOPNOTSUPP; break; } return retval;}intvsf_sysutil_get_ipv4_sock(void){ int retval = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (retval < 0) { die("socket"); } return retval;}intvsf_sysutil_get_ipv6_sock(void){ int retval = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP); if (retval < 0) { die("socket"); } return retval;}struct vsf_sysutil_socketpair_retvalvsf_sysutil_unix_stream_socketpair(void){ struct vsf_sysutil_socketpair_retval retval; int the_sockets[2]; int sys_retval = socketpair(PF_UNIX, SOCK_STREAM, 0, the_sockets); if (sys_retval != 0) { die("socketpair"); } retval.socket_one = the_sockets[0]; retval.socket_two = the_sockets[1]; return retval;}intvsf_sysutil_bind(int fd, const struct vsf_sysutil_sockaddr* p_sockptr){ const struct sockaddr* p_sockaddr = &p_sockptr->u.u_sockaddr; int len = 0; if (p_sockaddr->sa_family == AF_INET) { len = sizeof(struct sockaddr_in); } else if (p_sockaddr->sa_family == AF_INET6) { len = sizeof(struct sockaddr_in6); } else { die("can only support ipv4 and ipv6 currently"); } return bind(fd, p_sockaddr, len);}intvsf_sysutil_listen(int fd, const unsigned int backlog){ int retval = listen(fd, backlog); if (vsf_sysutil_retval_is_error(retval) && vsf_sysutil_get_error() != kVSFSysUtilErrADDRINUSE) { die("listen"); } return retval;}/* Warning: callers of this function assume it does NOT make use of any * non re-entrant calls such as malloc(). */intvsf_sysutil_accept_timeout(int fd, struct vsf_sysutil_sockaddr* p_sockaddr, unsigned int wait_seconds){ struct vsf_sysutil_sockaddr remote_addr; int retval; int saved_errno; fd_set accept_fdset; struct timeval timeout; unsigned int socklen = sizeof(remote_addr); if (p_sockaddr) { vsf_sysutil_memclr(p_sockaddr, sizeof(*p_sockaddr)); } if (wait_seconds > 0) { FD_ZERO(&accept_fdset); FD_SET(fd, &accept_fdset); timeout.tv_sec = wait_seconds; timeout.tv_usec = 0; do { retval = select(fd + 1, &accept_fdset, NULL, NULL, &timeout); saved_errno = errno; vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0); } while (retval < 0 && saved_errno == EINTR); if (retval == 0) { errno = EAGAIN; return -1; } } retval = accept(fd, &remote_addr.u.u_sockaddr, &socklen); vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0); if (retval < 0) { return retval; } /* FreeBSD bug / paranoia: ai32@drexel.edu */ if (socklen == 0) { return -1; } if (remote_addr.u.u_sockaddr.sa_family != AF_INET && remote_addr.u.u_sockaddr.sa_family != AF_INET6) { die("can only support ipv4 and ipv6 currently"); } if (p_sockaddr) { if (remote_addr.u.u_sockaddr.sa_family == AF_INET) { vsf_sysutil_memclr(&remote_addr.u.u_sockaddr_in.sin_zero, sizeof(remote_addr.u.u_sockaddr_in.sin_zero)); vsf_sysutil_memcpy(p_sockaddr, &remote_addr.u.u_sockaddr_in, sizeof(remote_addr.u.u_sockaddr_in)); } else { vsf_sysutil_memcpy(p_sockaddr, &remote_addr.u.u_sockaddr_in6, sizeof(remote_addr.u.u_sockaddr_in6)); } } return retval;}intvsf_sysutil_connect_timeout(int fd, const struct vsf_sysutil_sockaddr* p_addr, unsigned int wait_seconds){ const struct sockaddr* p_sockaddr = &p_addr->u.u_sockaddr; unsigned int addrlen = 0; int retval; int saved_errno; if (p_sockaddr->sa_family == AF_INET) { addrlen = sizeof(p_addr->u.u_sockaddr_in); } else if (p_sockaddr->sa_family == AF_INET6) { addrlen = sizeof(p_addr->u.u_sockaddr_in6); } else { die("can only support ipv4 and ipv6 currently"); } if (wait_seconds > 0) { vsf_sysutil_activate_noblock(fd); } retval = connect(fd, p_sockaddr, addrlen); if (retval < 0 && errno == EINPROGRESS) { fd_set connect_fdset; struct timeval timeout; FD_ZERO(&connect_fdset); FD_SET(fd, &connect_fdset); timeout.tv_sec = wait_seconds; timeout.tv_usec = 0; do { retval = select(fd + 1, NULL, &connect_fdset, NULL, &timeout); saved_errno = errno; vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0); } while (retval < 0 && saved_errno == EINTR); if (retval == 0) { retval = -1; errno = EAGAIN; } else { socklen_t socklen = sizeof(retval); int sockoptret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &retval, &socklen); if (sockoptret != 0) { die("getsockopt"); } } } if (wait_seconds > 0) { vsf_sysutil_deactivate_noblock(fd); } return retval;}voidvsf_sysutil_getsockname(int fd, struct vsf_sysutil_sockaddr** p_sockptr){ struct vsf_sysutil_sockaddr the_addr; int retval; unsigned int socklen = sizeof(the_addr); vsf_sysutil_sockaddr_clear(p_sockptr); retval = getsockname(fd, &the_addr.u.u_sockaddr, &socklen); if (retval != 0) { die("getsockname"); } if (the_addr.u.u_sockaddr.sa_family != AF_INET && the_addr.u.u_sockaddr.sa_family != AF_INET6) { die("can only support ipv4 and ipv6 currently"); } vsf_sysutil_sockaddr_alloc(p_sockptr); if (socklen > sizeof(the_addr)) { socklen = sizeof(the_addr); } vsf_sysutil_memcpy(*p_sockptr, &the_addr, socklen);}voidvsf_sysutil_getpeername(int fd, struct vsf_sysutil_sockaddr** p_sockptr){ struct vsf_sysutil_sockaddr the_addr; int retval; unsigned int socklen = sizeof(the_addr); vsf_sysutil_sockaddr_clear(p_sockptr); retval = getpeername(fd, &the_addr.u.u_sockaddr, &socklen); if (retval != 0) { die("getpeername"); } if (the_addr.u.u_sockaddr.sa_family != AF_INET && the_addr.u.u_sockaddr.sa_family != AF_INET6) { die("can only support ipv4 and ipv6 currently"); } vsf_sysutil_sockaddr_alloc(p_sockptr); if (socklen > sizeof(the_addr)) { socklen = sizeof(the_addr); } vsf_sysutil_memcpy(*p_sockptr, &the_addr, socklen);}voidvsf_sysutil_shutdown_failok(int fd){ /* SHUT_RDWR is a relatively new addition */ #ifndef SHUT_RDWR #define SHUT_RDWR 2 #endif (void) shutdown(fd, SHUT_RDWR);}voidvsf_sysutil_shutdown_read_failok(int fd){ /* SHUT_RD is a relatively new addition */ #ifndef SHUT_RD #define SHUT_RD 0 #endif (void) shutdown(fd, SHUT_RD);}voidvsf_sysutil_sockaddr_clear(struct vsf_sysutil_sockaddr** p_sockptr){ if (*p_sockptr != NULL) { vsf_sysutil_free(*p_sockptr); *p_sockptr = NULL; }}voidvsf_sysutil_sockaddr_alloc(struct vsf_sysutil_sockaddr** p_sockptr){ vsf_sysutil_sockaddr_clear(p_sockptr); *p_sockptr = vsf_sysutil_malloc(sizeof(**p_sockptr)); vsf_sysutil_memclr(*p_sockptr, sizeof(**p_sockptr));}voidvsf_sysutil_sockaddr_alloc_ipv4(struct vsf_sysutil_sockaddr** p_sockptr){ vsf_sysutil_sockaddr_alloc(p_sockptr); (*p_sockptr)->u.u_sockaddr.sa_family = AF_INET;}voidvsf_sysutil_sockaddr_alloc_ipv6(struct vsf_sysutil_sockaddr** p_sockptr){ vsf_sysutil_sockaddr_alloc(p_sockptr); (*p_sockptr)->u.u_sockaddr.sa_family = AF_INET6;}voidvsf_sysutil_sockaddr_clone(struct vsf_sysutil_sockaddr** p_sockptr, const struct vsf_sysutil_sockaddr* p_src){ struct vsf_sysutil_sockaddr* p_sockaddr = 0; vsf_sysutil_sockaddr_alloc(p_sockptr); p_sockaddr = *p_sockptr; if (p_src->u.u_sockaddr.sa_family == AF_INET) { p_sockaddr->u.u_sockaddr.sa_family = AF_INET; vsf_sysutil_memcpy(&p_sockaddr->u.u_sockaddr_in.sin_addr, &p_src->u.u_sockaddr_in.sin_addr, sizeof(p_sockaddr->u.u_sockaddr_in.sin_addr)); } else if (p_src->u.u_sockaddr.sa_family == AF_INET6) { p_sockaddr->u.u_sockaddr.sa_family = AF_INET6; vsf_sysutil_memcpy(&p_sockaddr->u.u_sockaddr_in6.sin6_addr, &p_src->u.u_sockaddr_in6.sin6_addr, sizeof(p_sockaddr->u.u_sockaddr_in6.sin6_addr)); } else { die("can only support ipv4 and ipv6 currently"); }}intvsf_sysutil_sockaddr_addr_equal(const struct vsf_sysutil_sockaddr* p1, const struct vsf_sysutil_sockaddr* p2){ int family1 = p1->u.u_sockaddr.sa_family; int family2 = p2->u.u_sockaddr.sa_family; if (family1 != family2) { if (family1 == AF_INET && family2 == AF_INET6) { const void* p_ipv4_addr = vsf_sysutil_sockaddr_ipv6_v4(p2); if (p_ipv4_addr && !vsf_sysutil_memcmp(p_ipv4_addr, &p1->u.u_sockaddr_in.sin_addr, sizeof(p1->u.u_sockaddr_in.sin_addr))) { return 1; } } else if (family1 == AF_INET6 && family2 == AF_INET) { const void* p_ipv4_addr = vsf_sysutil_sockaddr_ipv6_v4(p1); if (p_ipv4_addr && !vsf_sysutil_memcmp(p_ipv4_addr, &p2->u.u_sockaddr_in.sin_addr, sizeof(p2->u.u_sockaddr_in.sin_addr))) { return 1; } } return 0; } if (family1 == AF_INET) { if (vsf_sysutil_memcmp(&p1->u.u_sockaddr_in.sin_addr, &p2->u.u_sockaddr_in.sin_addr, sizeof(p1->u.u_sockaddr_in.sin_addr)) == 0) { return 1; } } else if (family1 == AF_INET6) { if (vsf_sysutil_memcmp(&p1->u.u_sockaddr_in6.sin6_addr, &p2->u.u_sockaddr_in6.sin6_addr, sizeof(p1->u.u_sockaddr_in6.sin6_addr)) == 0) { return 1; } } return 0;}intvsf_sysutil_sockaddr_is_ipv6(const struct vsf_sysutil_sockaddr* p_sockaddr){ if (p_sockaddr->u.u_sockaddr.sa_family == AF_INET6) { return 1; } return 0;}voidvsf_sysutil_sockaddr_set_ipv4addr(struct vsf_sysutil_sockaddr* p_sockptr, const unsigned char* p_raw){ if (p_sockptr->u.u_sockaddr.sa_family == AF_INET) { vsf_sysutil_memcpy(&p_sockptr->u.u_sockaddr_in.sin_addr, p_raw, sizeof(p_sockptr->u.u_sockaddr_in.sin_addr)); } else if (p_sockptr->u.u_sockaddr.sa_family == AF_INET6) { static struct vsf_sysutil_sockaddr* s_p_sockaddr; vsf_sysutil_sockaddr_alloc_ipv4(&s_p_sockaddr); vsf_sysutil_memcpy(&s_p_sockaddr->u.u_sockaddr_in.sin_addr, p_raw, sizeof(&s_p_sockaddr->u.u_sockaddr_in.sin_addr)); vsf_sysutil_memcpy(&p_sockptr->u.u_sockaddr_in6.sin6_addr, vsf_sysutil_sockaddr_ipv4_v6(s_p_sockaddr), sizeof(p_sockptr->u.u_sockaddr_in6.sin6_addr)); } else { bug("bad family"); }}voidvsf_sysutil_sockaddr_set_ipv6addr(struct vsf_sysutil_sockaddr* p_sockptr, const unsigned char* p_raw){ if (p_sockptr->u.u_sockaddr.sa_family == AF_INET6) { vsf_sysutil_memcpy(&p_sockptr->u.u_sockaddr_in6.sin6_addr, p_raw, sizeof(p_sockptr->u.u_sockaddr_in6.sin6_addr)); } else { bug("bad family"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -