X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fsocket-util.c;h=4965b63af4d1cce7e5b62e38579efe26834fb68f;hb=3bcf3e33e9cfb7fd837086bfa8e627110d84dce8;hp=912c47e097f8e80c807cabf3cfddcab343594184;hpb=02dd3123a0e312f1d33403e744af52dd6096f12d;p=openvswitch diff --git a/lib/socket-util.c b/lib/socket-util.c index 912c47e0..4965b63a 100644 --- a/lib/socket-util.c +++ b/lib/socket-util.c @@ -292,55 +292,79 @@ guess_netmask(uint32_t ip) : htonl(0)); /* ??? */ } -/* Opens a non-blocking IPv4 socket of the specified 'style' and connects to - * 'target', which should be a string in the format "[:]". - * is required. If 'default_port' is nonzero then is optional and - * defaults to 'default_port'. +/* Parses 'target', which should be a string in the format "[:]". + * is required. If 'default_port' is nonzero then is optional + * and defaults to 'default_port'. * - * 'style' should be SOCK_STREAM (for TCP) or SOCK_DGRAM (for UDP). - * - * On success, returns 0 (indicating connection complete) or EAGAIN (indicating - * connection in progress), in which case the new file descriptor is stored - * into '*fdp'. On failure, returns a positive errno value other than EAGAIN - * and stores -1 into '*fdp'. - * - * If 'sinp' is non-null, then on success the target address is stored into - * '*sinp'. */ -int -inet_open_active(int style, const char *target_, uint16_t default_port, - struct sockaddr_in *sinp, int *fdp) + * On success, returns true and stores the parsed remote address into '*sinp'. + * On failure, logs an error, stores zeros into '*sinp', and returns false. */ +bool +inet_parse_active(const char *target_, uint16_t default_port, + struct sockaddr_in *sinp) { char *target = xstrdup(target_); char *save_ptr = NULL; const char *host_name; const char *port_string; - struct sockaddr_in sin; - int fd = -1; - int error; + bool ok = false; /* Defaults. */ - memset(&sin, 0, sizeof sin); - sin.sin_family = AF_INET; - sin.sin_port = htons(default_port); + sinp->sin_family = AF_INET; + sinp->sin_port = htons(default_port); /* Tokenize. */ host_name = strtok_r(target, ":", &save_ptr); port_string = strtok_r(NULL, ":", &save_ptr); if (!host_name) { - ovs_error(0, "%s: bad peer name format", target_); - error = EAFNOSUPPORT; + VLOG_ERR("%s: bad peer name format", target_); goto exit; } /* Look up IP, port. */ - error = lookup_ip(host_name, &sin.sin_addr); - if (error) { + if (lookup_ip(host_name, &sinp->sin_addr)) { goto exit; } if (port_string && atoi(port_string)) { - sin.sin_port = htons(atoi(port_string)); + sinp->sin_port = htons(atoi(port_string)); } else if (!default_port) { VLOG_ERR("%s: port number must be specified", target_); + goto exit; + } + + ok = true; + +exit: + if (!ok) { + memset(sinp, 0, sizeof *sinp); + } + free(target); + return ok; +} + +/* Opens a non-blocking IPv4 socket of the specified 'style' and connects to + * 'target', which should be a string in the format "[:]". + * is required. If 'default_port' is nonzero then is optional and + * defaults to 'default_port'. + * + * 'style' should be SOCK_STREAM (for TCP) or SOCK_DGRAM (for UDP). + * + * On success, returns 0 (indicating connection complete) or EAGAIN (indicating + * connection in progress), in which case the new file descriptor is stored + * into '*fdp'. On failure, returns a positive errno value other than EAGAIN + * and stores -1 into '*fdp'. + * + * If 'sinp' is non-null, then on success the target address is stored into + * '*sinp'. */ +int +inet_open_active(int style, const char *target, uint16_t default_port, + struct sockaddr_in *sinp, int *fdp) +{ + struct sockaddr_in sin; + int fd = -1; + int error; + + /* Parse. */ + if (!inet_parse_active(target, default_port, &sin)) { error = EAFNOSUPPORT; goto exit; } @@ -348,7 +372,7 @@ inet_open_active(int style, const char *target_, uint16_t default_port, /* Create non-blocking socket. */ fd = socket(AF_INET, style, 0); if (fd < 0) { - VLOG_ERR("%s: socket: %s", target_, strerror(errno)); + VLOG_ERR("%s: socket: %s", target, strerror(errno)); error = errno; goto exit; } @@ -379,7 +403,6 @@ exit: } else { *fdp = -1; } - free(target); return error; } @@ -588,3 +611,31 @@ fsync_parent_dir(const char *file_name) return error; } + +/* Obtains the modification time of the file named 'file_name' to the greatest + * supported precision. If successful, stores the mtime in '*mtime' and + * returns 0. On error, returns a positive errno value and stores zeros in + * '*mtime'. */ +int +get_mtime(const char *file_name, struct timespec *mtime) +{ + struct stat s; + + if (!stat(file_name, &s)) { + mtime->tv_sec = s.st_mtime; + +#if HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC + mtime->tv_nsec = s.st_mtim.tv_nsec; +#elif HAVE_STRUCT_STAT_ST_MTIMENSEC + mtime->tv_nsec = s.st_mtimensec; +#else + mtime->tv_nsec = 0; +#endif + + return 0; + } else { + mtime->tv_sec = mtime->tv_nsec = 0; + return errno; + } +} +