/*
* access.c - File access routines
*
* Copyright (C) 1998-2003 Gero Kuhlmann <gero@gkminix.han.de>
*
* 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 <common.h>
#include <nblib.h>
#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;
}
syntax highlighted by Code2HTML, v. 0.9.1