If str points to a valid hostspec, return allocated memory containing the * [USER@]HOST part of the string, and set the path_start_ptr to the part of * the string after the host part. Otherwise, return NULL. If port_ptr is * non-NULL, we must be parsing an rsync:// URL hostname, and we will set * *port_ptr if a port number is found. Note that IPv6 IPs will have their * (required for parsin
| 3071 | * *port_ptr if a port number is found. Note that IPv6 IPs will have their |
| 3072 | * (required for parsing) [ and ] chars elided from the returned string. */ |
| 3073 | static char *parse_hostspec(char *str, char **path_start_ptr, int *port_ptr) |
| 3074 | { |
| 3075 | char *s, *host_start = str; |
| 3076 | int hostlen = 0, userlen = 0; |
| 3077 | char *ret; |
| 3078 | |
| 3079 | for (s = str; ; s++) { |
| 3080 | if (!*s) { |
| 3081 | /* It is only OK if we run out of string with rsync:// */ |
| 3082 | if (!port_ptr) |
| 3083 | return NULL; |
| 3084 | if (!hostlen) |
| 3085 | hostlen = s - host_start; |
| 3086 | break; |
| 3087 | } |
| 3088 | if (*s == ':' || *s == '/') { |
| 3089 | if (!hostlen) |
| 3090 | hostlen = s - host_start; |
| 3091 | if (*s++ == '/') { |
| 3092 | if (!port_ptr) |
| 3093 | return NULL; |
| 3094 | } else if (port_ptr) { |
| 3095 | *port_ptr = atoi(s); |
| 3096 | while (isDigit(s)) s++; |
| 3097 | if (*s && *s++ != '/') |
| 3098 | return NULL; |
| 3099 | } |
| 3100 | break; |
| 3101 | } |
| 3102 | if (*s == '@') { |
| 3103 | userlen = s - str + 1; |
| 3104 | host_start = s + 1; |
| 3105 | } else if (*s == '[') { |
| 3106 | if (s != host_start++) |
| 3107 | return NULL; |
| 3108 | while (*s && *s != ']' && *s != '/') s++; /*SHARED ITERATOR*/ |
| 3109 | hostlen = s - host_start; |
| 3110 | if (*s != ']' || (s[1] && s[1] != '/' && s[1] != ':') || !hostlen) |
| 3111 | return NULL; |
| 3112 | } |
| 3113 | } |
| 3114 | |
| 3115 | *path_start_ptr = s; |
| 3116 | ret = new_array(char, userlen + hostlen + 1); |
| 3117 | if (userlen) |
| 3118 | strlcpy(ret, str, userlen + 1); |
| 3119 | strlcpy(ret + userlen, host_start, hostlen + 1); |
| 3120 | return ret; |
| 3121 | } |
| 3122 | |
| 3123 | /* Look for a HOST specification of the form "HOST:PATH", "HOST::PATH", or |
| 3124 | * "rsync://HOST:PORT/PATH". If found, *host_ptr will be set to some allocated |
no test coverage detected