/** * @brief * parses the staging file name * syntax: locat_file@hostname:remote_file * on Windows if remote_file is UNC path then * hostname is optional so syntax can be * local_file@remote_unc_file * Note: The arguments local_name, host_name, remote_name are mandatory and * must be allocated with required memory by the caller. * * @param[in] pair - a staged file name pair * @param[in/out] local_name - local file name * @param[in/out] host_name - remote host * @param[in/out] remote_name - remote file namea * * @return int * @retval 0 parsing was successful * @retval 1 error in parsing */ int parse_stage_name(char *pair, char *local_name, char *host_name, char *remote_name) { char *c = NULL; int l_pos = 0; int h_pos = 0; int r_pos = 0; /* Begin the parse */ c = pair; while (isspace(*c)) c++; /* Looking for something before the @ sign */ while (*c != '\0') { if (ISNAMECHAR(*c)) { /* allow whitespace and stop on '@' */ if (l_pos >= MAXPATHLEN) return 1; local_name[l_pos++]=*c; } else break; c++; } if (l_pos == 0) return 1; #ifdef WIN32 if ((*c == '@') && (c+1 != NULL) && (IS_UNCPATH(c+1))) { c++; /* * remote_name is UNC path without host part * so skip parsing of host_name and parse * remote_name */ while (*c != '\0') { if (ISNAMECHAR(*c)) { /* allow whitespace */ if (r_pos >= MAXPATHLEN) return 1; remote_name[r_pos++]=*c; } else break; c++; } } #endif /* Looking for something between the @ and the : */ if (*c == '@') { c++; while (*c != '\0') { if (ISNAMECHAR2(*c)) { /* no whitespace allowed in host */ if (h_pos >= PBS_MAXSERVERNAME) return 1; host_name[h_pos++]=*c; } else break; c++; } if (h_pos == 0) return 1; } #ifdef WIN32 /* * h_pos may be 1 if non-UNC path is given * without host part which is not allowed * so return parsing error * example: -Wstagein=C:\testdir@D:\testdir1 */ if (h_pos == 1) return 1; #endif /* Looking for something after the : */ if (*c == ':') { c++; while (*c != '\0') { if (ISNAMECHAR(*c)) { /* allow whitespace */ if (r_pos >= MAXPATHLEN) return 1; remote_name[r_pos++]=*c; } else break; c++; } } if (r_pos == 0) return 1; if (*c != '\0') return 1; /* set null chars at end of string */ local_name[l_pos] = '\0'; remote_name[r_pos] = '\0'; host_name[h_pos] = '\0'; return (0); }
/** * @brief * parses path and prepares complete path name * * @param[in] path_in - the path name provided as input to be parsed * @param[out] path_out - contains final parsed and prepared path, must * be at least MAXPATHLEN+1 bytes. * * @return int * @retval 0 - success in parsing * @retval nonzero - error encountered in parsing */ int prepare_path(char *path_in, char *path_out) { char *c = NULL; int have_fqdn = 0; /* Initialization with {'\0'} populates entire array */ char host_name[PBS_MAXSERVERNAME + 1] = {'\0'}; /* short host name */ int h_pos = 0; char path_name[MAXPATHLEN + 1] = {'\0'}; size_t path_len; int p_pos = 0; char *host_given = NULL; struct stat statbuf = {0}; dev_t dev = 0; ino_t ino = 0; if (!path_out) return 1; *path_out = '\0'; if (!path_in) return 1; /* Begin the parse */ for (c = path_in; *c; c++) { if (isspace(*c) == 0) break; } if (*c == '\0') return 1; #ifdef WIN32 /* Check for drive letter in Windows */ if (!(isalpha(*c) && (*(c + 1) == ':'))) #endif { /* Looking for a hostname */ if ((host_given = strchr(c, ':')) != NULL) { /* Capture the hostname portion */ for (h_pos = 0; (h_pos < sizeof(host_name)); h_pos++, c++) { if (isalnum(*c) || (*c == '.') || (*c == '-') #ifdef WIN32 /* Underscores are legal in Windows */ || (*c == '_') #endif ) { host_name[h_pos] = *c; } else { break; } } if (*c != ':') return 1; /* Advance past the colon */ c++; } } /* Looking for a posix path */ for (p_pos = 0; p_pos < sizeof(path_name); p_pos++, c++) { if (!isprint(*c)) break; path_name[p_pos] = *c; } /* Should be at end of string */ if (*c != '\0') return 1; path_len = strlen(path_name); if (path_len == 0 && strlen(host_name) == 0) return 1; /* appending a slash in the end to indicate that it is a directory */ if ((path_name[path_len - 1] != '/') && (path_name[path_len - 1] != '\\') && (stat(path_name, &statbuf) == 0) && S_ISDIR(statbuf.st_mode)) { if ((path_len + 1) < sizeof(path_name)) { strcat(path_name, "/"); path_len++; } } #ifdef WIN32 if (IS_UNCPATH(path_name)) { /* * given path is UNC path * so just skip hostname * as UNC path dose not require it */ host_given = NULL; host_name[0] = '\0'; } else #endif { /* get full host name */ if (host_name[0] == '\0') { if (pbs_conf.pbs_output_host_name) { /* use the specified host for returning the file */ snprintf(host_name, sizeof(host_name), "%s", pbs_conf.pbs_output_host_name); have_fqdn = 1; } else { if (gethostname(host_name, sizeof(host_name)) != 0) return 2; host_name[sizeof(host_name) - 1] = '\0'; } } if (have_fqdn == 0) { char host_fqdn[PBS_MAXSERVERNAME + 1] = {'\0'}; /* need to fully qualify the host name */ if (get_fullhostname(host_name, host_fqdn, PBS_MAXSERVERNAME) != 0) return 2; strncpy(path_out, host_fqdn, MAXPATHLEN); /* FQ host name */ } else { strncpy(path_out, host_name, MAXPATHLEN); /* "localhost" or pbs_output_host_name */ } path_out[MAXPATHLEN - 1] = '\0'; /* finish preparing complete host name */ if (strlen(path_out) < MAXPATHLEN) strcat(path_out, ":"); } #ifdef WIN32 if (path_name[0] != '/' && path_name[0] != '\\' && host_given == NULL && strchr(path_name, ':') == NULL ) #else if (path_name[0] != '/' && host_given == NULL) #endif { char cwd[MAXPATHLEN + 1] = {'\0'}; c = getenv("PWD"); /* PWD carries a name that will cause */ if (c != NULL) { /* the NFS to mount */ if (stat(c, &statbuf) < 0) { /* can't stat PWD */ c = NULL; } else { dev = statbuf.st_dev; ino = statbuf.st_ino; if (stat(".", &statbuf) < 0) { perror("prepare_path: cannot stat current directory:"); *path_out = '\0'; return (1); } } if (dev == statbuf.st_dev && ino == statbuf.st_ino) { snprintf(cwd, sizeof(cwd), "%s", c); } else { c = NULL; } } if (c == NULL) { c = getcwd(cwd, MAXPATHLEN); if (c == NULL) { perror("prepare_path: getcwd failed : "); *path_out = '\0'; return (1); } } #ifdef WIN32 /* get UNC path (if available) if it is mapped drive */ get_uncpath(cwd); if (IS_UNCPATH(cwd)) { strcpy(path_out, cwd); if (cwd[strlen(cwd)-1] != '\\') strcat(path_out, "\\"); } else #endif { strncat(path_out, cwd, (MAXPATHLEN + 1) - strlen(path_out)); if (strlen(path_out) < MAXPATHLEN) strcat(path_out, "/"); } } #ifdef WIN32 /* get UNC path (if available) if it is mapped drive */ get_uncpath(path_name); if (IS_UNCPATH(path_name)) strcpy(path_out, path_name); else { /* * check whether given <path_name> is relative path * without drive on localhost and <cwd> is not UNC path? * if yes then do not append drive into <path_out> * otherwise append drive into <path_out> */ if (is_local_host(host_name) && (strchr(path_name, ':') == NULL) && (path_out[strlen(path_out) - 1] != '/') && (!IS_UNCPATH(path_out))) { char drivestr[3] = {'\0'}; char drivestr_unc[MAXPATHLEN + 1] = {'\0'}; drivestr[0] = _getdrive() + 'A' - 1; drivestr[1] = ':'; drivestr[2] = '\0'; /* * check whether <drivestr> is mapped drive? * by calling get_uncpath() * if yes then remove <hostname> part from <path_out> * * This is the case when user submit job * from mapped drive with relative path without drive * in path ex. localhost:err or localhost:out */ snprintf(drivestr_unc, sizeof(drivestr_unc), "%s\\", drivestr); get_uncpath(drivestr_unc); if (IS_UNCPATH(drivestr_unc)) { strncpy(path_out, drivestr_unc, MAXPATHLEN); } else { strncat(path_out, drivestr, MAXPATHLEN - strlen(path_out)); } } strncat(path_out, path_name, MAXPATHLEN - strlen(path_out)); } back2forward_slash(path_out); /* "\" translate to "/" for path */ strcpy(path_out, replace_space(path_out, "\\ ")); path_out[MAXPATHLEN - 1] = '\0'; #else strncat(path_out, path_name, (MAXPATHLEN + 1) - strlen(path_out)); #endif return (0); }
int parse_stage_list(char *list) { char *b = NULL; char *c = NULL; char *s = NULL; char *l = NULL; int comma = 0; char local[MAXPATHLEN+1] = {'\0'}; char host[PBS_MAXSERVERNAME] = {'\0'}; char remote[MAXPATHLEN+1] = {'\0'}; if (strlen(list) == 0) return (1); if ((l = (char *)malloc(strlen(list)+1)) == NULL) { fprintf(stderr, "Out of memory.\n"); return 1; } memset(l, 0, strlen(list)+1); strcpy(l, list); c = l; while (*c != '\0') { /* Drop leading white space */ while (isspace((int) * c)) c++; /* Find the next comma */ s = c; while (*c != '\0') { if (*c == ',' && (s != c) && *(c - 1) != '\\') break; c++; } /* Drop any trailing blanks */ comma = (*c == ','); *c = '\0'; b = c - 1; while (isspace((int) * b)) *b-- = '\0'; /* Parse the individual list item */ if (parse_stage_name(s, local, host, remote)) { (void) free(l); return 1; } /* Make sure all parts of the item are present */ if (strlen(local) == 0) { (void) free(l); return 1; } #ifdef WIN32 if ((strlen(host) == 0) && (strlen(remote) > 0) && (!IS_UNCPATH(remote))) #else if (strlen(host) == 0) #endif { (void) free(l); return 1; } if (strlen(remote) == 0) { (void) free(l); return 1; } if (comma) { c++; } } if (comma) { (void)free(l); return 1; } (void)free(l); return 0; }