ftp.nice.ch/pub/next/unix/network/system/cap.5.0.s.tar.gz#/cap_5.0/applications/aufs/afpvols.c

This is afpvols.c in view mode; [Download] [Up]

/*
 * $Author: cck $ $Date: 88/05/13 09:22:55 $
 * $Header: afpvols.c,v 1.22 88/05/13 09:22:55 cck Rel $
 * $Revision: 1.22 $
*/

/*
 * afpvols.c - Appletalk Filing Protocol Volume 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.
 *
 */

/*
 * Non OS dependant support routines for:
 *
 *  FPGetVolParms()
 *  FPSetVolParms()
 *  FPOpenVol()
 *  FPCloseVol()
 *  FPFlush()
 *
 */

#include <stdio.h>
#include <sys/param.h>
#ifndef _TYPES
# include <sys/types.h>		/* assume included by param.h */
#endif
#include <netat/appletalk.h>
#include <netat/afp.h>
#include <netat/afpcmd.h>
#include "afps.h"
#include "afpntoh.h"
#include "afpvols.h"
#ifdef USESTRINGDOTH
# include <string.h>
#else
# include <strings.h>
#endif


private VolPtr VolTbl[MAXVOLS];		/* table of VolEntry records */
private int VolCnt = 0;			/* number of volumes */
private VolBitMap VolModBitMap = 0;	/* bitmap of modified volumes */

private PackEntry VolPackR[] = { 	/* Volume Parms Reply */
  PACK(VolPtr,P_WORD,v_bitmap),		/* bitmap specifies below items */
  PACK(VolPtr,P_BMAP,v_bitmap),		/* bitmap specifies below items */
  PAKB(VolPtr,P_WORD,v_attr,VP_ATTR),	/* attributes word */
  PAKB(VolPtr,P_WORD,v_sig,VP_SIG),	/* signature word */
  PAKB(VolPtr,P_TIME,v_cdate,VP_CDATE),	/* creation date */
  PAKB(VolPtr,P_TIME,v_mdate,VP_MDATE),	/* modification date */
  PAKB(VolPtr,P_TIME,v_bdate,VP_BDATE),	/* last back date */
  PAKB(VolPtr,P_WORD,v_volid,VP_VOLID),	/* volume id */
  PAKB(VolPtr,P_DWRD,v_free,VP_FREE),	/* free bytes */
  PAKB(VolPtr,P_DWRD,v_size,VP_SIZE),	/* size in bytes */
  PKSB(VolPtr,P_OSTR,v_name,VP_NAME),	/* name of volume */
  PACKEND()
};

/*
 * void VNew(char *path, char *name, char *pwd)
 *
 * Given a path, volume name, and password string, create a new volume
 * in VolTbl.
 *
 */

void
VNew(path,name,pwd)
char *name;
char *path;
char *pwd;
{
  VolPtr vp;
  char *malloc();

  if ((strlen(name) > MAXVLEN) ||
      (strlen(path) > MAXDLEN) ||
      (strlen(pwd)  > MAXPLEN)) {
	log("VNew: path, name or password too long on path = %s\n",path);
	return;
      }
    
  if (DBVOL)
    printf("Adding vol '%s' on path '%s' pwd='%s'\n",name,path,pwd);

  /* create volume record */
  vp = (VolPtr) malloc(sizeof(VolEntry));
  strcpy(vp->v_name,name);		/* copy the name */
  strcpy(vp->v_path,path);		/*  the path */
  strcpy(vp->v_pwd,pwd);		/*  and the password */
  vp->v_mounted = FALSE;		/* not opened */
  vp->v_volid = VolCnt+1;		/* will be volcnt+1 */
  vp->v_sig = VOL_FIXED_DIRID;		/* signature word */
  vp->v_attr = 0;			/* clear attributes */

  /* Now make sure entry is valid */
  if (OSVolInfo(path,vp,VP_ALL) != noErr) {	/* get volume info */
    free((char *) vp);			/* bad... release storage */
    printf("VNew: No volinfo for %s on path %s\n",name,path);
    return;
  }

  /* This is deferred because I'm not sure how to deallocate :-) */
  /* and isn't needed until we have validated the entry anyway */
  vp->v_rootd = Idirid(path);		/* create directory handle */
  InitDIDVol(vp->v_rootd, VolCnt);	/* initialize volume info for list */
  
  /* Okay, stick it into the table */
  VolTbl[VolCnt++] = vp;		/* set volume record */
}

private char *
spanspace(p)
char *p;
{
  while (*p == ' ' || *p == '\t' || *p == '\n')
    p++;
  return(p);
}

/*
 * char *vskip(char *p)
 *
 * vskip skips to the next field in a line containing volume information
 * as read from the VOLFILE.  The field seperator ":" or the end of line
 * character is set to NULL in order to terminate the field.
 *
 */

private char *
vskip(p)
char *p;
{
  while (*p != '\0' && *p != ':' && *p != '\n')
    p++;
  if (*p != '\0')		/* at end of string? */
    *p++ = '\0';		/* no tie off this field */
  return(p);			/* and return pointer */
}

/*
 * VRdVFile(FILE *fd)
 *
 * Reads a file containing volume information from the specified path.
 * The file descriptor is closed after reading the file
 *
 * VRdVFile is intended to read VOLFILE from the user's home directory
 * after FPLogin.  The information in this file is stored in the VolTbl.
 *
 * Format of VOLFILE:
 *  path:volume name[:optional password][:]
 *
 *  blank lines and lines starting with '#' are ignored.
 *
 */

VRdVFile(fd)
FILE *fd;
{
  char line[MAXLLEN+1];
  char *pathp,*namep,*pswdp,*p,*tilde();
  int origVolCnt;

  origVolCnt = VolCnt;
  while ((p = fgets(line,MAXLLEN,fd)) != NULL) { /* read lines */
    p = spanspace(p);			/* span spaces */
    if (*p == '#' || *p == '\0')	/* comment or blank line? */
      continue;				/* yes, skip it */
    pathp = p; p = vskip(p);		/* save ptr to start of path */
    namep = p; p = vskip(p);		/* start of name */
    pswdp = p; p = vskip(p);		/* save it */
    pathp = tilde(pathp);		/* expand the path */
    VNew(pathp,namep,pswdp);		/* add new entry */
  }
  fclose(fd);				/* close file */
  return(VolCnt != origVolCnt);	        /* return true if found any entries */
}

/*
 * void VInit(char *usr,char *home)
 *
 * VInit adds entries to the table of volumes by reading the user's
 * VOLFILE or VOLFILE1.  If no VOLFILE exists on the path specified by
 * "home" then a default entry entry of path=home and name=usr is
 * setup.
 *
 */

void
VInit(usr,home)
char *usr;
char *home;
{
  char vfn[MAXDLEN+20];			/* afpvols file name */
  FILE *fd;

  if (home == NULL)			/* no home, then nothing to do */
    return;

  strcpy(vfn,home);			/* copy directory */
  strcat(vfn,"/");			/*  terminator */
  strcat(vfn,VOLFILE);			/*  and then the volsfile name */

  if ((fd = fopen(vfn, "r")) == NULL) {
    strcpy(vfn,home);		/* copy directory */
    strcat(vfn,"/");		/*  terminator */
    strcat(vfn,VOLFILE1);	/*  and then the volsfile name */
    if ((fd = fopen(vfn, "r")) == NULL) {
      if (DBVOL)
	printf("VRdVFile: no afpvols or .afpvols in %s\n",home);
      VNew(home,usr,"");	/* if none, then setup home dir */
      return;
    }
  }
  (void)VRdVFile(fd);		/* read vols file from user */
  if (VolCnt == 0)
    VNew(home, usr, "");
}

/*
 * return count of volumes
 *
*/
int
VCount()
{
  return(VolCnt);
}

/*
 * int VMakeVList(VolParm *vp,byte *vpl)
 *
 * Store into vp a number of VolParm entries, one for each volume
 * we know about.  Return in vpl the length of the information.
 * Return the count of volumes.
 * 
 * Used by GetSrvrParms.
 *
 */

int
VMakeVList(r)
byte *r;			/* ptr to place to store */
{
  VolParm vpp;
  int v, len;
  extern PackEntry ProtoGSPRPvol[];

  for (v=0,len=0; v < VolCnt; v++) {
    if (*VolTbl[v]->v_pwd != '\0')
      vpp.volp_flag = SRVRP_PASSWD;	/* is password protected */
    else
      vpp.volp_flag = 0;		/* no flags */
    cpyc2pstr(vpp.volp_name,VolTbl[v]->v_name);
    len += htonPackX(ProtoGSPRPvol, &vpp, r+len);
  }
  return(len);			/* return size used */
}

/*
 * OSErr FPGetVolParms(byte *p,int l,byte *r,int *rl);
 *
 * This call is used to retrieve paramters for a particular volume.
 * The volume is specified by its Volume ID as returned from the
 * FPOpenVol call.
 *
 *
 */

OSErr 
FPGetVolParms(p,l,r,rl)
byte *p,*r;
int *rl,l;
{
  GetVolParmsPkt gvp;			/* cast to packet type */
  int ivol,err;
  VolPtr vp;

  ntohPackX(PsGetVolParms,p,l,(byte *) &gvp); /* decode packet */
  ivol = EtoIVolid(gvp.gvp_volid); 	/* pick up volume id */
  if (ivol < 0)
    return(ivol);			/* unknown volume */
  if (!VolTbl[ivol]->v_mounted)		/* must have called FPOpenVol first */
    return(aeParamErr);			/* not opened */
  vp = VolTbl[ivol];			/* ptr to volume */
  err = OSVolInfo(pathstr(vp->v_rootd),vp,gvp.gvp_bitmap); /* get vol info */

  if (V_BITTST(VolModBitMap,ivol)) {	/* modified since last call? */
    V_BITCLR(VolModBitMap,ivol);	/* yes... clear the flag */
    vp->v_mdate = CurTime();		/* set modify time */
  }

  if (err != noErr)
    return(err);
  vp->v_bitmap = gvp.gvp_bitmap;
  *rl = htonPackX(VolPackR,(byte *) vp,r);
  return(noErr);			/* all ok */
}

/*
 * OSErr FPSetVolParms(byte *p,byte *r,int *rl) [NOOP]
 *
 * This call is used to set the parameters for a particular volume.  The
 * volume is specified by its VolumeID as returned from the FPOpenVol
 * call.
 *
 * In AFP Version 1.0 only the Backup Date field may be set.  Under
 * Unix this is a noop.
 *
 */

/*ARGSUSED*/  
OSErr
FPSetVolParms(p,l,r,rl)
byte *p,*r;
int *rl;
{
  SetVolParmsPkt svp;
  int ivol;

  ntohPackX(PsSetVolParms,p,l,(byte *) &svp); /* unpack */

  ivol = EtoIVolid(svp.svp_volid);
  if (ivol < 0)
    return(aeParamErr);			/* unknown volume */

  if ((svp.svp_bitmap & ~VP_BDATE) != 0)
    return(aeBitMapErr);		/* trying to set unknown parms */

  if (svp.svp_bitmap & VP_BDATE)	/* want to set backup date? */
    VolTbl[ivol]->v_bdate = svp.svp_backdata; /* yes... */

  return(noErr);			/* return ok... */
}

/*
 * OSErr FPOpenVol(byte *p, byte *r, int *rl)
 *
 * This call is used to "mount" a volume.  It must be called before any
 * other call can be made to access objects on the volume.
 *
 */

OSErr 
FPOpenVol(p,l,r,rl)
byte *p;
int l;
byte *r;
int *rl;
{
  OpenVolPkt ovl;
  char pwd[MAXPASSWD+1];		/* null terminated password */
  int v;
  OSErr err;
  VolPtr vp;
  
  ovl.ovl_pass[0] = '\0';		/* zero optional password */
  ntohPackX(PsOpenVol,p,l,(byte *) &ovl); /* decode packet */
  strncpy(pwd,(char *) ovl.ovl_pass,MAXPASSWD);	/* copy optional pwd */
  pwd[MAXPASSWD] = '\0';		/* tie off with a null */

  if (DBVOL)
    printf("FPOpenVol: name=%s, pwd=%s, bm=%d\n",
	   ovl.ovl_name,pwd,ovl.ovl_bitmap);
  
  for (v=0; v < VolCnt; v++)		/* locate the volume */
    if (strcmp(VolTbl[v]->v_name,(char *) ovl.ovl_name) == 0)
      break;

  if (v >= VolCnt)			/* did we find a vol in the scan? */
    return(aeParamErr);			/* no... unknown volume name */

  vp = VolTbl[v];			/* dereference */
  if (*vp->v_pwd != '\0') 	/* password exists on volume? */
    if (strcmp(vp->v_pwd,pwd) != 0) /* yes, check for match */
      return(aeAccessDenied);		/* not the same... return failure */

  if (DBVOL)
    printf("FPOpenVol: name=%s volid=%d\n", vp->v_name,vp->v_volid);

  vp->v_mounted = TRUE;		/* now it is opened... */
  
  /* update volume info */
  if ((err = OSVolInfo(vp->v_path,vp,VP_ALL)) != noErr)
    return(err);

  vp->v_bitmap = ovl.ovl_bitmap;	/* bitmap for packing result */

  *rl = htonPackX(VolPackR,(byte *) vp,r);
  return(noErr);			/* return ok */
}


/*
 * OSErr FPCloseVol(byte *p,byte *r,int *rl)
 *
 * This call is used to "unmount" a volume.
 *
 */

/*ARGSUSED*/
OSErr 
FPCloseVol(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
  CloseVolPkt cv;
  int ivol;

  ntohPackX(PsCloseVol,p,l,(byte *) &cv);
  
  ivol = EtoIVolid(cv.cv_volid); /* convert to internal format */
  if (ivol < 0)			/* error code */
    return(ivol);

  if (DBVOL)
    printf("FPCloseVol %d=%s\n",ivol,VolTbl[ivol]->v_name);

  if (!VolTbl[ivol]->v_mounted)		/* was it mounted? */
    return(aeMiscErr);			/* no... not mounted */

  VolTbl[ivol]->v_mounted = FALSE;	/* indicate no longer mounted */
  return(noErr);			/* and return ok */
}


/*
 * OSErr FPFlush(byte *p,byte *r, int *rl)
 *
 * This call is used to flush to disk any data relating to the specified
 * volume that has been modified by the user.
 *
 */

/*ARGSUSED*/
OSErr
FPFlush(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
  FlushPkt fls;
  int ivol;

  ntohPackX(PsFlush,p,l,(byte *) &fls);

  if (DBVOL)
    printf("FPFLush: ...\n");

  ivol = EtoIVolid(fls.fls_volid);
  if (ivol < 0)
    return(ivol);

  return(OSFlush(ivol));
}

/*
 * IDirP VolRootD(int volid)
 *
 * Return the internal directory pointer for this volumes root directory.
 * Root directory is the volumes mount point, or initial path.
 *
 */

IDirP
VolRootD(volid)
int volid;
{
  if (volid > VolCnt)
    return(NILDIR);
  return(VolTbl[volid]->v_rootd);
}

/*
 * void VolModified(VolBitMap volbm)
 *
 * Indicate that the volumes specified in volbm have been modified.
 *
 */

void
VolModified(volbm)
VolBitMap volbm;
{
  V_BITOR(VolModBitMap,			/* result */
	  VolModBitMap,volbm);		/* is OR of these two */
}


char *
VolName(volid)
{
  if (volid > VolCnt)
    return("");
  return(VolTbl[volid]->v_name);
}


word 
ItoEVolid(iv)
int iv;
{
  return(VolTbl[iv]->v_volid);		/* return volume id */
}

int
EtoIVolid(ev)
word ev;
{
  int iv;
  for (iv=0; iv < VolCnt; iv++)
    if (VolTbl[iv]->v_volid == ev)
      return(iv);
  if (DBVOL)
    printf("EtoIVolid: Bad Volid %d\n",ev);
  return(aeParamErr);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.