/* Create an IO filename from job parameters and the filename format * sent from client */ char * fname_create(stepd_step_rec_t *job, const char *format, int taskid) { char *name = NULL; char *orig = xstrdup(format); int id; char *esc; if (((id = fname_single_task_io (format)) >= 0) && (taskid != id)) return (xstrdup ("/dev/null")); esc = is_path_escaped(orig); /* If format doesn't specify an absolute pathname, use cwd */ if (orig[0] != '/') { xstrcat(name, job->cwd); if (esc) { xstrcat(name, esc); goto fini; } if (name[strlen(name)-1] != '/') xstrcatchar(name, '/'); } if (esc) { /* esc is malloc */ name = esc; goto fini; } if (job->batch) name = _create_batch_fname(name, orig, job, taskid); else name = _create_step_fname(name, orig, job, taskid); fini: xfree(orig); return name; }
/* * Expand a stdio file name. * * If "filename" is NULL it means that an eio object should be created * for that stdio file rather than a directly connecting it to a file. * * If the "filename" is a valid task number in string form and the * number matches "taskid", then NULL is returned so that an eio * object will be used. If is a valid number, but it does not match * "taskid", then the file descriptor will be connected to /dev/null. */ static char * _expand_stdio_filename(char *filename, int gtaskid, stepd_step_rec_t *job) { int id; if (filename == NULL) return NULL; id = fname_single_task_io(filename); if (id < 0) return fname_create(job, filename, gtaskid); if (id >= job->ntasks) { error("Task ID in filename is invalid"); return NULL; } if (id == gtaskid) return NULL; else return xstrdup("/dev/null"); }
/* Create an IO filename from job parameters and the filename format * sent from client */ char * fname_create(slurmd_job_t *job, const char *format, int taskid) { unsigned int wid = 0; char *name = NULL; char *orig = xstrdup(format); char *p, *q; int id; if (((id = fname_single_task_io (format)) >= 0) && (taskid != id)) return (xstrdup ("/dev/null")); /* If format doesn't specify an absolute pathname, * use cwd */ if (orig[0] != '/') { xstrcat(name, job->cwd); if (name[strlen(name)-1] != '/') xstrcatchar(name, '/'); } q = p = orig; while (*p != '\0') { if (*p == '%') { if (isdigit(*(++p))) { unsigned long in_width = 0; xmemcat(name, q, p - 1); if ((in_width = strtoul(p, &p, 10)) > MAX_WIDTH) wid = MAX_WIDTH; else wid = (unsigned int)in_width; q = p - 1; if (*p == '\0') break; } switch (*p) { case 'a': /* '%a' => array task id */ xmemcat(name, q, p - 1); xstrfmtcat(name, "%0*d", wid, job->array_task_id); q = ++p; break; case 'A': /* '%A' => array master job id */ xmemcat(name, q, p - 1); xstrfmtcat(name, "%0*d", wid, job->array_job_id); q = ++p; break; case 's': /* '%s' => step id */ xmemcat(name, q, p - 1); xstrfmtcat(name, "%0*d", wid, job->stepid); q = ++p; break; case 't': /* '%t' => taskid */ xmemcat(name, q, p - 1); xstrfmtcat(name, "%0*d", wid, taskid); q = ++p; break; case 'n': /* '%n' => nodeid */ xmemcat(name, q, p - 1); xstrfmtcat(name, "%0*d", wid, job->nodeid); q = ++p; break; case 'N': /* '%N' => node name */ xmemcat(name, q, p - 1); xstrfmtcat(name, "%s", conf->hostname); q = ++p; break; case 'J': case 'j': xmemcat(name, q, p - 1); xstrfmtcat(name, "%0*d", wid, job->jobid); if ((*p == 'J') && (job->stepid != NO_VAL)) xstrfmtcat(name, ".%d", job->stepid); q = ++p; break; default: break; } wid = 0; } else p++; } if (q != p) xmemcat(name, q, p); xfree(orig); return name; }