/* * access.c - File access routines * * Copyright (C) 1998-2003 Gero Kuhlmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: access.c,v 1.4 2003/01/25 23:29:44 gkminix Exp $ */ #include #include #include "privlib.h" /* * Extract path elements from string */ struct paths { struct paths *next; char *name; }; static struct paths *extractpath(str) char *str; { struct paths *plist = NULL; struct paths *pp; char *cp; size_t len; while (str != NULL) { cp = strchr(str, ':'); len = (cp == NULL) ? strlen(str) : cp - str; if (len > 0) { pp = (struct paths *)nbmalloc(sizeof(struct paths)); pp->name = (char *)nbmalloc(len + 2); strncpy(pp->name, str, len); pp->name[len] = '\0'; pp->next = plist; plist = pp; } if (cp != NULL) cp++; str = cp; } return(plist); } /* * Actually normalize a path */ static struct paths *donorm(pathname, maindir) char *pathname; char *maindir; { struct paths *pathlist, *dirlist, *pp, *dp, *np; struct paths *newlist = NULL; size_t len; /* Extract path elements */ pathlist = extractpath(pathname); dirlist = extractpath(maindir); /* If dirlist is empty, use the local directory as the default */ if (dirlist == NULL) { dirlist = (struct paths *)nbmalloc(sizeof(struct paths)); copystr(&(dirlist->name), "."); dirlist->next = NULL; } /* Make all relative paths absolute to the elements in dirlist */ while (pathlist != NULL) { pp = pathlist; pathlist = pp->next; if (pp->name[0] == '/' || pp->name[0] == '.') { pp->next = newlist; newlist = pp; } else { dp = dirlist; while (dp != NULL) { len = strlen(pp->name) + strlen(dp->name) + 1; np = (struct paths *)nbmalloc(sizeof(struct paths)); np->name = (char *)nbmalloc(len + 2); sprintf(np->name, "%s/%s", dp->name, pp->name); np->next = newlist; newlist = np; dp = dp->next; } free(pp->name); free(pp); } } /* Delete directory list, we don't need it anymore */ while (dirlist != NULL) { dp = dirlist; dirlist = dirlist->next; free(dp->name); free(dp); } /* Normalize all paths which are relative to the netboot directory */ dp = NULL; np = newlist; while (np != NULL) { if (!strncmp(np->name, "//", 2)) { len = strlen(np->name) + strlen(netbootdir) - 1; pp = (struct paths *)nbmalloc(sizeof(struct paths)); pp->name = (char *)nbmalloc(len + 2); sprintf(pp->name, "%s%s", netbootdir, &(np->name[1])); pp->next = np->next; if (dp == NULL) newlist = pp; else dp->next = pp; free(np->name); free(np); np = pp; } dp = np; np = np->next; } return(newlist); } /* * Normalize a path name. */ void setpath(pathname, maindir) char **pathname; char *maindir; { struct paths *pathlist, *pp; size_t retlen; char *newname, *cp; /* Normalize path names */ if (*pathname == NULL || (pathlist = donorm(*pathname, maindir)) == NULL) return; free(*pathname); /* Determine length of return string */ retlen = 0; pp = pathlist; while (pp != NULL) { retlen += strlen(pp->name) + 1; pp = pp->next; } /* Generate return string */ newname = NULL; if (pathlist != NULL) { cp = newname = (char *)nbmalloc(retlen + 1); while (pathlist != NULL) { pp = pathlist; strcpy(cp, pp->name); cp += strlen(pp->name); if (pp->next != NULL) { *(cp++) = ':'; *cp = '\0'; } pathlist = pathlist->next; free(pp->name); free(pp); } } *pathname = newname; } /* * Check if a file is readable, and determine it's normalized path name */ void checkaccess(filename, maindir) char **filename; char *maindir; { struct paths *pathlist, *pp; char *retname; /* Actually normalize the file name */ if (*filename == NULL || (pathlist = donorm(*filename, maindir)) == NULL) return; free(*filename); /* Scan through the normalized file list */ retname = NULL; while (pathlist != NULL) { pp = pathlist; if (retname == NULL && access(pp->name, R_OK) >= 0) copystr(&retname, pp->name); pathlist = pathlist->next; free(pp->name); free(pp); } *filename = retname; }