CAP/applications/aufs/afpdid.c

1191 lines
30 KiB
C

/*
* $Author: djh $ $Date: 1996/04/27 12:03:04 $
* $Header: /mac/src/cap60/applications/aufs/RCS/afpdid.c,v 2.13 1996/04/27 12:03:04 djh Rel djh $
* $Revision: 2.13 $
*
*/
/*
* afpdid.c - Directory id routines
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* March 1987 Schilit Created.
* December 1990 djh tidy up for AFP 2.0
*
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/param.h>
#ifndef _TYPES
/* assume included by param.h */
# include <sys/types.h>
#endif _TYPES
#include <sys/stat.h>
#include <netat/appletalk.h>
#include <netat/afp.h>
#include "afps.h"
#ifdef USEDIRENT
# include <dirent.h>
#else USEDIRENT
# ifdef xenix5
# include <sys/ndir.h>
# else xenix5
# include <sys/dir.h>
# endif xenix5
#endif USEDIRENT
#ifdef USESTRINGDOTH
# include <string.h>
#else USESTRINGDOTH
# include <strings.h>
#endif USESTRINGDOTH
/*
*
* EtoIdirid() - external to internal translation of directory id.
* ItoEdirid() - internal to external translation of directory id.
* EtoIfile() - return info on file
* Idirid() - given a path, return an internal directory id.
* Ipdirid() - given a directory id, return parent's directory id.
* Idndirid() - given a directory id and a directory name, return
* the directory id of the "directory", creating did if
* non-existant
* Idrdirid() - remove the specified directory
* pathstr() - given a directory id, return a path.
* ppathstr() - given a "root" dirid and dirid, return a path relative
* to root dirid
* InitDID() - called once to init this module.
* InitDIDVol - mark the volume of a dirid
* ItoEName() - translate internal to external name
* EtoIName() - translate external to internal name
* ENameLen() - figure length of interal file name in external terms
* EModified() - mark dirid as modified
*
*/
#define TRUE 1
#define FALSE 0
private IDirP rootd;
#ifdef FIXED_DIRIDS
/*
* We use a separate database and server to provide persistant
* external numbers. This allows the external ids to be
* common accross several instances of aufs - coincidental ones
* as well as repeated calls by the same user. The database
* is read-only from this program - a separate aufsExt server
* is used to create new entries etc. Some backup functions in
* the library allow for when the server or database are (for
* some reason) absent or not responding. However, these should
* not be used normally. The scheme below is preferable if you
* don't wish to have the server running.
*
*/
#include "../../lib/afp/afpidaufs.h"
#else FIXED_DIRIDS
/*
* ExtDir structure maps external directory numbers into internal (IDir)
* pointers. It is not a good idea to simply pass back the IDir pointer
* since the mac expects forever constant ids and will remember these
* ids between logins to the server.
*
* Although we can't generate forever constant ids the ExtDir table will
* at least verify that we are not looking at a random pointer address.
*
* Failure from the table lookup generates a aeParamErr which is usually
* handled ok the mac by restarting the selection process at root dir.
*
*/
struct { /* Maps external to internal safely */
int xd_base; /* base edir number */
int xd_count; /* number in use */
IDirP *xd_idirs; /* pointers to the internal dirids */
int xd_idsize; /* size of idirs array */
} ExtDir;
#endif FIXED_DIRIDS
private char *ipathstr();
private sdword NewEDirid();
/*
* nfind scans and finds whether a particular directory "dir" has a
* subdirectory by the name "nam"
*
* use a simple hash of "nam" to avoid multiple strcmp() calls
*
*/
private IDirP
nfind(dir,nam)
IDirP dir;
char *nam;
{
register long hash;
register char *p;
p = nam;
hash = 0;
while (*p) {
hash <<= 2;
hash += *p++;
}
for ( ; dir != (IDirP)0; dir = dir->next) {
if (dir->hash != hash)
continue;
if (strcmp(dir->name, nam) == 0)
break;
}
return(dir);
}
/*
* Create a new directory entry under the specified parent
* (Should we check existance?)
*
*/
private IDirP
mkdirset(parent,name)
IDirP parent;
char *name;
{
IDirP dir;
register long hash;
register char *p, *t;
dir = (IDirP)malloc(sizeof(IDir));
t = dir->name = (char *)malloc((unsigned) strlen(p = name)+1);
hash = 0;
while (*p) {
hash <<= 2;
hash += (*t++ = *p++); /* copy string while making hash */
}
*t = '\0';
dir->hash = hash; /* remember name hash value */
dir->pdir = parent; /* set pointer to parent in node */
dir->subs = NILDIR; /* no children */
if (parent != NILDIR) { /* if parent different than root */
V_COPY(dir->volbm,parent->volbm); /* duplicate info... */
dir->next = parent->subs; /* make us a sub dir of parent */
parent->subs = dir; /* ... */
} else { /* if no parent then */
V_ZERO(dir->volbm); /* no ownership */
dir->next = NILDIR; /* no siblings */
}
dir->flags = 0; /* no flags yet */
dir->modified = 0;
dir->eceidx = NOECIDX; /* no index for enum cache */
dir->edirid = -1; /* create new external dirid */
OSValidateDIDDirInfo(dir); /* validate directory info */
if (parent && (dir->flags & DID_DATA) == 0) {
parent->subs = dir->next; /* unlink it */
free(dir->name); /* nada */
free(dir); /* nada */
return(NILDIR);
}
if (parent)
OSValidateDIDDirInfo(parent); /* revalidate parent */
return(dir);
}
IDirP
Ipdirid(dir)
IDirP dir;
{
return(dir->pdir); /* return parent */
}
IDirP lastcd = NILDIR;
/*
* return an absolute path
*
*/
char *
pathstr(cd)
IDirP cd;
{
static char paths[MAXPATHLEN];
if (lastcd == cd) /* same as last request? */
return(paths); /* yes.. just return old paths */
lastcd = cd; /* else set new dir */
(void)ipathstr(cd,paths); /* and do the work... */
return(paths); /* return new path */
}
private char *
ipathstr(cd,p)
IDirP cd;
register char *p;
{
register char *t;
/* check for root directory */
if (cd == rootd) {
/* init path */
*p++ = '/';
*p = '\0';
return(p);
}
/* recurse on parent until root */
p = ipathstr(cd->pdir, p);
/* insert new path component */
if (cd->pdir != rootd)
*p++ = '/';
t = cd->name;
while (*t)
*p++ = *t++;
*p = '\0';
/* return a pointer */
return(p);
}
#ifdef FIXED_DIRIDS
/*
* dir path and filename concatanated
*
*/
private char *
filpathstr(cd, name)
IDirP cd;
char *name;
{
char *p;
int len;
p = pathstr(cd); /* get dir path */
len = strlen(p);
if (p[len-1] != '/') /* add / if needs */
p[len++] = '/';
strcpy(p+len, name); /* add given name */
lastcd = NILDIR; /* have corrupted cd area */
return p;
}
#endif FIXED_DIRIDS
/*
* return a path relative to vroot
*
*/
char *
ppathstr(vrootd,cd)
IDirP vrootd,cd;
{
static char path[MAXPATHLEN];
int len;
if (cd == vrootd) /* check for root directory */
strcpy(path,""); /* at top of tree, init path */
else {
(void) ppathstr(vrootd,cd->pdir); /* recurse on parent until root */
len = strlen(path);
if (cd->pdir != vrootd) /* ... */
path[len++] = '/'; /* add path component */
strcpy(path+len, cd->name); /* concatenate current dir to path */
}
return(path);
}
/*
* void printtree(dir,start)
*
* Print the directory tree starting from dir, start is a copy
* of dir.
*
*/
private void
printtree(dir,start)
IDirP dir,start;
{
if (dir == NILDIR)
return;
printf("Path %s Idirid = 0x%x = %d\n",pathstr(dir),dir,dir);
printtree(dir->subs,start);
if (dir != start)
printtree(dir->next,start);
}
/*
* void InitDID()
*
* Called once to initialize directory id mechanism.
*
* Create root directory in rootd.
*
*/
void
InitDID()
{
#ifdef FIXED_DIRIDS
aufsExtInit();
#else FIXED_DIRIDS
ExtDir.xd_count = 0; /* no known external dirs */
ExtDir.xd_base = 320; /* anything will do above EROOTD */
ExtDir.xd_idsize = 100; /* inital size of table */
ExtDir.xd_idirs = (IDirP *) malloc(sizeof(IDirP)*100);
#endif FIXED_DIRIDS
rootd = mkdirset(NILDIR,""); /* allocate root directory */
}
/*
* InitDIDVol(dirid)
*/
InitDIDVol(dirid, volid)
IDirP dirid;
int volid;
{
V_BITSET(dirid->volbm,volid); /* remember ownership */
}
/*
* IDirP Idirid(char *path,char *dn)
*
* Make sure path is valid
*
*/
IDirP
Idirid(path)
char *path;
{
char c, *p;
IDirP cd, ncd;
int len;
if (*path == '\0') { /* any argument specified? */
logit(0, "internal error: Idirid has a bad arg count\n");
return(NILDIR);
}
/* scan down path, creating dirids as necessary */
if (*path != '/') { /* check if root is starting point? */
if (DBDIR)
logit(0, "internal error: Idirid has bad starting point %s\n",path);
}
len = strlen(path); /* get length of path */
while ((len-1) && path[len-1] == '/') /* chew off trailing /s */
len--;
cd = rootd;
do {
while (*path == '/') /* step to start of component */
path++,len--;
/* find end */
for (p = path; *p != '/' && len; p++, len--)
/* NULL */;
c = *p; /* remember char here */
*p = '\0'; /* change to null */
ncd = nfind(cd->subs, path); /* find component if it exists */
if (ncd == NILDIR)
cd = mkdirset(cd, path); /* create new */
else
cd = ncd;
*p = c; /* set back to org. */
path = p;
} while (len && cd != NILDIR);
return(cd); /* final point */
}
/*
*
* IDirP Idndirid(IDirP idirid,char *dn)
*
* Return an internal directory ID for the directory "path/dn" --
* where path specifies the parent path and dn the directory name.
* The string dn may be null in which case a directory id for path
* is returned.
*
* This routine always returns an internal directory id, creating a
* new IDir node if necessary. One of only two routine which causes
* the creation of new IDir nodes.
*
* WILL RETURN NULL IF PATH IS BAD
*/
IDirP
Idndirid(parent,dn)
IDirP parent;
char *dn;
{
IDirP dp;
#ifdef SHORT_NAMES
if (DBDIR && parent != NULL)
printf("Idndirid parent->name %s dn %s\n",parent->name,
(dn == NULL) ? "<null>" : dn);
#endif SHORT_NAMES
if (dn == NULL || *dn == '\0') /* is the name specified? */
return(parent); /* no, so return parent */
dp = nfind(parent->subs,dn); /* see if already present */
if (dp != NILDIR) /* yes... */
return(dp); /* return info */
return(mkdirset(parent,dn)); /* create new directory */
}
/*
* Idname(pdir, dirid)
*
* return name of directory dirid in directory pdir
*
* MODIFY return value at your own risk!
*
*/
char *
Idname(pdir, dirid)
IDirP pdir;
IDirP dirid;
{
register IDirP p = pdir->subs;
#ifdef SHORT_NAMES
if (DBDIR && dirid != NULL && pdir != NULL)
printf("Idname pdir->name %s, dirid->name %s\n",pdir->name,dirid->name);
#endif SHORT_NAMES
do {
if (p == dirid)
return(p->name);
p = p->next;
} while (p != NILDIR);
return(NULL);
}
/*
* sdword NewEDirid(IDirP idir)
*
* Allocate a new unique external directory id for a newly created
* directory. The id is is used as an index into a table of internal
* directory ids. The returned external id is this index plus some
* random base number to map past EROOTD (2).
*
* If the table of internal directory pointers overgrows its bounds
* then realloc the table at a larger size.
*
*/
#ifdef FIXED_DIRIDS
sdword
Edirid(idir)
IDirP idir;
{
if (idir == rootd) /* shortcut */
return(rootEid);
else {
if (idir->edirid == -1)
idir->edirid = NewEDirid(idir);
return(idir->edirid);
}
}
#endif FIXED_DIRIDS
private sdword
NewEDirid(idir)
IDirP idir;
{
#ifdef SHORT_NAMES
if (DBDIR && idir != NULL)
printf("NewEDirid idir->name %s\n",idir->name);
#endif SHORT_NAMES
#ifdef FIXED_DIRIDS
if (idir == rootd)
return(rootEid); /* root has no parent! */
return(aufsExtEDirId(Edirid(idir->pdir), idir->name));
#else FIXED_DIRIDS
{
sdword edir;
if (ExtDir.xd_count >= ExtDir.xd_idsize) {
ExtDir.xd_idirs = (IDirP *) /* realloc larger table */
realloc((char *) ExtDir.xd_idirs,
sizeof(IDirP)*((unsigned) ExtDir.xd_idsize+100));
ExtDir.xd_idsize += 100; /* larger table now */
if (DBDIR)
printf("NewEDirid: Realloc occured.\n");
}
edir = ExtDir.xd_count; /* current counter is idx */
ExtDir.xd_count++; /* increment count */
ExtDir.xd_idirs[edir] = idir; /* save new handle */
return(ExtDir.xd_base+edir); /* return base + idx */
}
#endif FIXED_DIRIDS
}
/*
* IDirP GetIDirid(sdword edir)
*
* Given an external ID check to see if we know about the external->internal
* mapping by verifying the edir as an index into a table.
*
* If no known mapping then return NILDIR.
*
*/
private IDirP
GetIDirid(edir)
sdword edir;
{
#ifdef SHORT_NAMES
if (DBDIR)
printf("GetIDirid: edir:%d\n",edir);
#endif SHORT_NAMES
#ifdef FIXED_DIRIDS
{
char *path;
path = aufsExtPath(edir);
if (DBDIR)
printf("GetIDirid gave '%s' for %d\n", path, edir);
if (path)
return(Idirid(path));
if (DBDIR)
printf("GetIDirid: Bad directory idx %d\n", edir);
return(NILDIR);
}
#else FIXED_DIRIDS
edir -= ExtDir.xd_base; /* subtract base */
if (edir < 0 || /* below base? */
edir > ExtDir.xd_count-1) { /* or above count? */
if (DBDIR) /* then invalid */
printf("GetIDirid: Bad directory idx %d, highest is %d\n",
edir,ExtDir.xd_count-1);
return(NILDIR); /* yes... not allocated */
}
return(ExtDir.xd_idirs[edir]); /* return handle */
#endif FIXED_DIRIDS
}
/*
* IDirP EtoIdirid(sdword dirid,word volid)
*
* Convert an external directory id (dirid) to an internal directory
* id.
*
* Internal directory ids are pointers of type IDir into the directory
* tree built and maintained by these procedures. There is only one
* directory tree, and each AFP volume contains a root id which is the
* mount point for that volume (which may be different from the
* directory trees root of "/").
*
* There are two special external directory IDs, EROOTD (1) and
* EPROOTD (2), for the volume's root directory and parent of root
* directory.
*
* If the external id is neither of these call GetIDirid to
* do the real work.
*
*/
IDirP
EtoIdirid(dirid,volid)
sdword dirid;
int volid;
{
IDirP VolRootD(),idir;
if (DBDIR)
printf("EtoIdirid: volid %d dirid:%d \n",volid,dirid);
if (dirid == EROOTD) /* check for root id */
return(VolRootD(volid)); /* yes, so return volumes root */
if (dirid == EPROOTD) /* check for parent of root */
return(Ipdirid(VolRootD(volid))); /* yes, so return that too... */
idir = GetIDirid(dirid); /* get internal dirid */
if (idir != NILDIR && /* if directory exists and */
V_BITTST(idir->volbm,volid)) /* is on specified volume... */
return(idir); /* then return dirid */
return(NILDIR); /* else return nil directory */
}
/*
* sdword ItoEdirid(IDirP dirid, word volid)
*
* Convert an internal directory id to an external directory id.
*
* See EtoIdirid() above.
*
*/
sdword
ItoEdirid(dirid,volid)
IDirP dirid;
int volid;
{
IDirP rd,VolRootD();
#ifdef SHORT_NAMES
if (DBDIR && dirid != NULL)
printf("ItoEdirid: dirid->name %s, volid %d\n",dirid->name,volid);
#endif SHORT_NAMES
rd = VolRootD(volid); /* fetch volumes root directory id */
if (dirid == rd) /* converting root id? */
return(EROOTD); /* yes, return special code */
if (dirid == Ipdirid(rd)) /* converting parent of root? */
return(EPROOTD); /* yes, return code for that too */
if (DBDIR && !V_BITTST(dirid->volbm,volid)) /* know this ownership? */
printf("ItoEdirid: bad volid for %s\n",pathstr(dirid));
if (dirid->edirid == -1) {
if (DBDIR)
printf("ItoEdirid: calling NewEDirid\n");
dirid->edirid = NewEDirid(dirid);
if (DBDIR)
printf("ItoEdirid: NewEDirid returns %d\n", dirid->edirid);
}
if ((dirid->flags & DID_VALID) == 0) /* validate info if invalid */
OSValidateDIDDirInfo(dirid);
return(dirid->edirid); /* else return external form */
}
/*
* OSErr EtoIFile(char *file, IDirP *idir, IDirP *ipdir, int *ivol
* sdword edir, word evol, byte eptype, byte *epath);
*
* Convert external arguments which specify a file/dir into internal
* handles.
*
* edir, evol, eptype and epath are the external ancestor directory
* id, the external volume id, the path type and the external path.
*
* Returned values are file (the last component of the path), idir,
* the directory handle if file is a directory, ipdir, the ancestor
* handle, and ivol the internal volume id.
*
* This is the major routine for converting volume, dir, path type,
* and path into unix form and proceeds as follows:
*
* Convert volume and ancestor directory (ivol, ipdir from evol and edir).
*
* For each component in the path, convert the component name to internal
* form and locate the component in the IDir tree.
*
* Return the last component name in file, and if this component exists
* in the IDir tree, return the handle in idir. Set ipdir to be the
* ancestor of the file.
*
* Only allow the volume root directory (dirid EROOTD) in the volume
* root parent directory (dirid EPROOTD)
*
*/
OSErr
EtoIfile(file,idir,ipdir,ivol,edir,evol,eptype,epath)
char *file;
IDirP *idir,*ipdir;
int *ivol;
sdword edir;
word evol;
byte eptype;
byte *epath;
{
int pl;
byte efn[MAXLFLEN+1],*fn;
char c,lc;
OSErr err;
IDirP id;
IDirP iprootd, irootd; /* has parent of root and root respectively */
if (DBDIR) {
int i = 1;
pl = *epath;
printf("EtoIfile: ivol = %d, epath = ", *ivol);
while (pl--) {
printf("(%c)", *(epath+i));
i++;
}
printf("\n");
}
*ivol = EtoIVolid(evol); /* set internal volid */
if (*ivol < 0)
return(*ivol); /* error */
id = EtoIdirid(edir,*ivol); /* fetch internal id */
if (id == NILDIR) /* exists? */
return(aeParamErr); /* no.... */
irootd = VolRootD(*ivol); /* get root directory internal id */
/* assert(irootd != NULL) */
iprootd = Ipdirid(irootd); /* and then its parent */
pl = *epath++; /* pascal string length */
lc = ' '; /* non-null last char */
for (fn=efn; pl-- > 0;) {
c = *fn++ = *epath++; /* copy the char */
if (c == '\0') { /* found a component separator? */
if (lc == '\0') { /* yes.... was last char also null? */
/* yes... then want parent since we have "null,null" */
if (id == iprootd) /* can't go above here! */
return(aeObjectNotFound);
id = Ipdirid(id); /* okay, move to parent */
} else /* otherwise */
if (*efn != '\0') { /* check if we have a component */
if (id == iprootd) {
/* only possible subdir */
#ifdef SHORT_NAMES
if (eptype == 0x02) {
if (strcmp((char *)efn, (char *)VolName(*ivol)) != 0)
return(aeObjectNotFound);
} else {
if (strcmp((char *)efn, (char *)VolSName(*ivol)) != 0)
return(aeObjectNotFound);
}
#else SHORT_NAMES
if (strcmp((char *)efn, (char *)VolName(*ivol)) != 0)
return(aeObjectNotFound);
#endif SHORT_NAMES
id = irootd;
} else {
#ifdef SHORT_NAMES
if (DBDIR)
printf("EtoIfile, eptype 0x%x\n",eptype);
if (eptype == 0x02) {
if ((err=EtoIName(efn,file)) != noErr) /*convert e to i */
return(err);
}
else { /*shortname*/
if ((err=EtoIName_Short(id,efn,file)) != noErr)
return(err);
}
#else SHORT_NAMES
if ((err=EtoIName(efn,file)) != noErr) /* convert e to i */
return(err);
#endif SHORT_NAMES
id = Idndirid(id,file); /* and move to new */
}
}
fn = efn; /* init ptr for next component */
}
lc = c; /* remember last char */
if (id == NILDIR) { /* did we hit something bad? */
printf("No such component %s\n",fn);
return(aeParamErr);
}
}
*fn = '\0'; /* tie off with a null */
if (id == iprootd && *efn != '\0') { /* special check */
#ifdef SHORT_NAMES
if (eptype == 0x02) {
if (strcmp((char *)efn, (char *)VolName(*ivol)) != 0)
return(aeObjectNotFound);
} else {
if (strcmp((char *)efn, (char *)VolSName(*ivol)) != 0)
return(aeObjectNotFound);
}
#else SHORT_NAMES
if (strcmp((char *)efn, (char *)VolName(*ivol)) != 0)
return(aeObjectNotFound);
#endif SHORT_NAMES
*file = '\0';
id = irootd;
} else {
#ifdef SHORT_NAMES
if (DBDIR)
printf("EtoIfile, eptype 0x%x\n",eptype);
if (eptype == 0x2) {
if ((err=EtoIName(efn,file)) != noErr) /* convert last file component */
return(err);
}
else {
if ((err=EtoIName_Short(id,efn,file)) != noErr) /* shortname */
return(err);
}
#else SHORT_NAMES
if ((err=EtoIName(efn,file)) != noErr) /* convert last file component */
return(err);
#endif SHORT_NAMES
}
if (*file == '\0') { /* did we have a file name? */
strcpy(file, id->name);
if (id == iprootd) /* tch, tch - don't want above here */
return(aeObjectNotFound);
*idir = id; /* set directory name */
*ipdir = Ipdirid(id); /* set parent id */
} else {
/* disallow "." or ".." */
if (file[0] == '.' &&
(file[1] == '\0' || (file[1] == '.' && file[2] == '\0')))
return(aeObjectNotFound);
*ipdir = id; /* else parent is dir itself */
*idir = Idndirid(id,file); /* and dir is possibly the file */
/* can only access "rootd" in parent of root directory */
if (id == iprootd && *idir != irootd)
return(aeObjectNotFound);
}
return(noErr);
}
/*
* dir_link(IDirP pdir, IDirP dir)
*
* Make the directory dir a subdirectory of parent pdir.
*
*/
private void
dir_link(pdir,dir)
IDirP pdir,dir;
{
#ifdef SHORT_NAMES
if (DBDIR && pdir != NULL && dir != NULL)
printf("dir_link pdir->name %s, dir->name %s\n",pdir->name,dir->name);
#endif SHORT_NAMES
dir->pdir = pdir; /* set parent */
dir->next = pdir->subs; /* link to front */
pdir->subs = dir;
}
/*
* dir_unlink(IDirP pdir, IDirP dir)
*
* Remove the directory dir from it's parent pdir.
*
*/
private void
dir_unlink(pdir,dir)
IDirP pdir,dir;
{
IDirP prev,this;
#ifdef SHORT_NAMES
if (DBDIR && pdir != NULL && dir != NULL)
printf("dir_unlink pdir->name %s, dir->name %s\n",pdir->name, dir->name);
#endif SHORT_NAMES
for (prev = NILDIR, this = pdir->subs;
this != NILDIR && this != dir;
prev = this, this = this->next);
if (this == NILDIR) { /* moby trouble */
printf("dir_unlink: dir %s not found\n",this);
return;
}
if (prev == NILDIR) /* first on the list? */
pdir->subs = this->next; /* yes... link to parent */
else
prev->next = this->next; /* else link to prev */
this->next = NILDIR; /* next no longer valid */
this->pdir = NILDIR; /* parent no longer known */
}
Idrdirid(ipdir, idir)
IDirP ipdir, idir;
{
/* simple solution - simply unlink from extdir list and "mark" */
/* it is as invalid - set the idir's extdir bad and when used */
/* we will "revalidate" it. Sufficient checking is done to */
/* prevent returnning "bad" info anyway. Basically, the whole */
/* point is to prevent mac side from getting to entries which aren't */
/* valid - this will simply eliminate work */
#ifdef FIXED_DIRIDS
if (idir->edirid == -1)
aufsExtDel(pathstr(idir));
else
aufsExtDelId(idir->edirid);
#else FIXED_DIRIDS
ExtDir.xd_idirs[idir->edirid - ExtDir.xd_base] = NILDIR;
#endif FIXED_DIRIDS
idir->edirid = -1;
idir->flags &= ~DID_VALID;
#ifdef SHORT_NAMES
if (DBDIR && ipdir != NULL && idir != NULL)
printf("Idrdirid ipdir->name %s, idir->name %s\n",ipdir->name,idir->name);
#endif SHORT_NAMES
#ifdef notdef
/* until problem of "old" ones is figured out */
/* the fix is to make all things that "stash" dirids check validity */
/* possibly store a refcnt in it to figure when we may kill off */
dir_unlink(ipdir, idir); /* unlink from the tree */
ExtDir.xd_idirs[idir->edirid - ExtDir.xd_base] = NILDIR; /* set to nil */
/* would like to delete space, but bad thing to do */
idir->flags &= ~DID_VALID; /* mark as not valid */
idir->subs = NILDIR; /* make sure not valid (shouldn't be) */
#endif notdef
}
/*
* Idmove(IDirP fpdir, char *from, IDirP tpdir, char *to)
*
* Maintains consistency in internal structures when a directory
* is renamed or moved.
*
* The directory "from" in parent fpdir is being renamed to be
* "to" in the parent tpdir. Because directory ids may not
* change we must modify the tree instead of recreating nodes.
*
*/
void
Idmove(fpdir,from,tpdir,to)
IDirP fpdir,tpdir;
char *from,*to;
{
IDirP fdir;
#ifdef FIXED_DIRIDS
sdword toEid;
char *orig_name = NULL;
#endif FIXED_DIRIDS
#ifdef SHORT_NAMES
if (DBFIL && fpdir != NULL)
printf("Idmove fpdir->name %s, tpdir->name %s, from %s, to %s\n",fpdir->name, tpdir->name, from, to);
#endif SHORT_NAMES
if (DBFIL) {
printf("Idmove: changing path=%s, file=%s",pathstr(fpdir),from);
if (tpdir == fpdir)
printf(" to new name %s\n",to);
else
printf(" to path=%s, file=%s\n",pathstr(tpdir),to);
}
fdir = nfind(fpdir->subs,from); /* locate source dir */
if (fdir == NILDIR) {
printf("Idmove: no known directory %s\n",from);
return;
}
#ifdef FIXED_DIRIDS
if (fdir->edirid == -1) /* will need full name later */
orig_name = string_copy(pathstr(fdir));
#endif FIXED_DIRIDS
if (strcmp(from,to) != 0) { /* if different names then... */
register long hash;
register char *p, *t;
free(fdir->name); /* release the old name */
t = fdir->name = (char *)malloc((unsigned) strlen(p = to)+1);
hash = 0;
while (*p) {
hash <<= 2;
hash += (*t++ = *p++); /* copy string while making hash */
}
*t = '\0';
/* record hash */
fdir->hash = hash;
}
if (fpdir != tpdir) { /* if different parents then... */
if (nfind(tpdir->subs,to) != NILDIR)
printf("Idmove: name already exists %s\n",to);
else {
dir_unlink(fpdir,fdir); /* unlink from old parent */
dir_link(tpdir,fdir); /* relink into new parent */
#ifdef FIXED_DIRIDS
toEid = Edirid(tpdir);
if (fdir->edirid == -1)
aufsExtMoveId(orig_name, toEid, to);
else
aufsExtMoveIds(fdir->edirid, toEid, to);
#endif FIXED_DIRIDS
}
}
#ifdef FIXED_DIRIDS
else { /* effectively a rename */
if (fdir->edirid == -1)
aufsExtRename(orig_name, to);
else
aufsExtRenameId(fdir->edirid, to);
}
if (orig_name != NULL)
free(orig_name);
#endif FIXED_DIRIDS
lastcd = NILDIR; /* names have changed */
}
static char *hexdigits = "0123456789abcdef";
/* problem with length of enp */
#ifdef SHORT_NAMES
byte *
ItoEName_Short(idir,in,enp)
IDirP *idir;
char *in;
byte *enp;
{
char c,c2;
char *cp,*cp2;
byte *en = enp;
if (in[0] != '\0')
Get_name(idir,in,0,en);
else
*en++ = '\0';
return(enp);
}
#endif SHORT_NAMES
byte *
ItoEName(in,enp)
register char *in;
byte *enp;
{
byte c,c2;
char *cp,*cp2;
byte *en = enp;
#ifdef ISO_TRANSLATE
extern u_char ISO2Mac[];
#endif ISO_TRANSLATE
while ((c = *in++) != '\0') {
if (c != ':') {
#if defined (ISO_TRANSLATE) & defined (ISO_FILENAMES)
*en++ = (c & 0x80) ? ((c2 = ISO2Mac[c]) ? c2 : 0x3f) : c;
#else /* ISO_TRANSLATE & ISO_FILENAMES */
*en++ = c;
#endif /* ISO_TRANSLATE & ISO_FILENAMES */
} else {
/* must convert to external form */
if ((c = *in++) == '\0' || (c2 = *in++) == '\0') {
*en++ = '|';
if (c != '\0')
*en++ = (c == ':') ? '|' : c; /* found null, deposit c or | */
break; /* done with while */
}
if ((cp = index(hexdigits,c)) == NULL ||
(cp2 = index(hexdigits,c2)) == NULL)
{
*en++ = '|'; /* deposit initial | */
*en++ = (c == ':') ? '|' : c; /* deposit c or | */
*en++ = (c2 == ':') ? '|' : c2; /* deposit c2 or | */
continue; /* continue with while */
}
#ifndef hpux
*en++ = ((cp-hexdigits) << 4) | (cp2-hexdigits);
#else /* hpux */
/* hpux compiler barfs on the above */
*en = ((cp-hexdigits) << 4);
*en |= (cp2-hexdigits);
en++;
#endif /*hpux*/
}
}
*en++ = '\0';
return(enp);
}
#ifdef SHORT_NAMES
OSErr
EtoIName_Short(idir,en,inp)
IDirP idir;
register byte *en; /* max is 31 or so */
char *inp;
{
byte c; /* unsigned char */
register char *in = inp;
register int cnt = 0;
if ((*en) != '\0')
Get_name(idir,en,1,in);
else
*in++ = '\0';
return(noErr);
}
#endif SHORT_NAMES
OSErr
EtoIName(en,inp)
register byte *en; /* max is 31 or so */
char *inp;
{
byte c; /* unsigned char */
register u_char *in = (u_char *)inp;
register int cnt = 0;
#ifdef ISO_TRANSLATE
extern u_char Mac2ISO[];
#endif ISO_TRANSLATE
while ((c = *en++) != '\0') {
if (isascii(c) && !iscntrl(c) && isprint(c) && c != '/') {
*in++ = c;
cnt++;
} else {
#if defined (ISO_TRANSLATE) & defined (ISO_FILENAMES)
if ((c & 0x80) && (*in = Mac2ISO[c])) {
cnt += 1;
in++;
} else
#endif /* ISO_TRANSLATE & ISO_FILENAMES */
{
/* must convert to 3 char external form */
*in++ = ':'; /* : */
*in++ = hexdigits[(c >> 4) & 0xf];
*in++ = hexdigits[(c & 0xf)];
cnt += 3;
}
}
}
*in++ = '\0';
if (cnt > MAXNAMLEN)
return(aeAccessDenied); /* bogus */
return(noErr);
}
/*
* Given an internal file name, compute the length of the external
* file name
*/
int
ENameLen(in)
register char *in;
{
register int len = 0;
register char c;
register char c2;
while ((c = *in++) != '\0') {
if (c != ':')
len++;
else {
/* must convert to external form */
if ((c = *in++) == '\0' || (c2 = *in++) == '\0') {
len++;
if (c != '\0')
len++;
break; /* done with while */
}
if (index(hexdigits,c) == NULL || index(hexdigits,c2) == NULL)
len += 3;
else
len++;
}
}
return(len);
}
void
EModified(dirid)
IDirP dirid;
{
/* what to do on overflow of 2^35-1? */
dirid->modified++; /* push the modified flag */
VolModified(dirid->volbm); /* and here too! */
}