/* * MKDIRPATH.C * * (c)Copyright 2015, Matthew Dillon, All Rights Reserved. See the COPYRIGHT * file at the base of the distribution. */ #include "defs.h" /* * Default path is "$RUNEDATA/$prog/rune_%s.map". * * $prog is set to the project directive. If there is no project directive * $prog is set to the base program name. * * If RUNEDATA exists we use $RUNEDATA/$prog/rune_*.map else if uid == 0 we * use /var/rune/$prog/rune_*.map else if HOME we use * $HOME/.rune/$prog/rune_*.map else if USER we use * /tmp/$USER/$prog/rune_*.map else we use /tmp/$prog/rune_*.map * * If sg->sg_Project begins with a '/' it overrides all possible directory * prefixes except RUNEDATA. RUNEDATA is always an absolute override, and an * absolute sg_Project will be tacked on as a sub-directory to it. */ char * getprojectpath(Declaration *d) { char idbuf[RUNE_IDTOSTR_LEN]; const char *prog; runeid_t id; char *path; char *base; int plen; prog = NULL; id = d->d_Id; runeid_sym(id, idbuf); if (d->d_ScopeFlags & SCOPE_SHARED) { SemGroup *sg = d->d_MyGroup; while (prog == NULL && sg) { prog = sg->sg_Project; sg = sg->sg_Parent; } } base = getenv("RUNEDATA"); if (prog == NULL) { prog = getprogname(); if (strrchr(prog, '/')) prog = strrchr(prog, '/'); if (strrchr(prog, '.')) plen = strrchr(prog, '.') - prog; else plen = (int)strlen(prog); if (plen > 2 && prog[plen - 2] == '.') plen -= 2; } else { plen = strlen(prog); } if (base) { asprintf(&path, "%s/%*.*s/rune_%s.map", base, plen, plen, prog, idbuf); } else if (plen && prog[0] == '/') { asprintf(&path, "%*.*s/rune_%s.map", plen, plen, prog, idbuf); } else if (getuid() == 0) { asprintf(&path, "/var/rune/%*.*s/rune_%s.map", plen, plen, prog, idbuf); } else if ((base = getenv("HOME")) != NULL) { asprintf(&path, "%s/.rune/%*.*s/rune_%s.map", base, plen, plen, prog, idbuf); } else if ((base = getenv("USER")) != NULL) { asprintf(&path, "/tmp/%s/%*.*s/rune_%s.map", base, plen, plen, prog, idbuf); } else { asprintf(&path, "/tmp/%*.*s/rune_%s.map", plen, plen, prog, idbuf); } return path; } /* * Create missing directory path components, including the last path element * if specified. Intermediate directory path components are allowed to exist * and may contain softlinks. */ void mkdirpath(const char *path, int lastcomp) { const char *stop; const char *next; char *sub; struct stat st; stop = path; while (*stop == '/') ++stop; while (*stop) { if ((next = strchr(stop, '/')) == NULL) stop += strlen(stop); else stop = next; next = stop; while (*next == '/') ++next; if (lastcomp == 0 && *next == 0) break; sub = malloc(stop - path + 1); bcopy(path, sub, stop - path); sub[stop - path] = 0; if (stat(sub, &st) < 0) { if (errno != ENOENT) break; if (mkdir(sub, 0755) < 0) { if (errno != EEXIST) break; } } free(sub); stop = next; } }