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

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

/*
 * $Author: cck $ $Date: 88/02/23 17:16:11 $
 * $Header: afpfork.c,v 1.23 88/02/23 17:16:11 cck Rel $
 * $Revision: 1.23 $
*/

/*
 * afpfork.c - Appletalk Filing Protocol Fork Level 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:
 *
 *  FPGetForkParms()
 *  FPSetForkParms()
 *  FPOpenFork()
 *  FPCloseFork()
 *  FPRead()
 *  FPWrite() 
 *  FPFlushFork()
 *  FPByteRangeLock()
 * 
 */

#include <stdio.h>
#include <sys/param.h>
#ifndef _TYPES
 /* assume included by param.h */
# include <sys/types.h>
#endif
#include <netat/appletalk.h>
#include <netat/afp.h>
#include <netat/afpcmd.h>
#include "afps.h"
#include "afpntoh.h"
#include "afposncs.h"
 

typedef struct {
  int ofn_fd;			/* file descriptor */
  sdword ofn_pos;		/* file position */
  IDirP ofn_ipdir;
  int ofn_ivol;
  int ofn_efn;			/* external file number */
  char ofn_fnam[MAXUFLEN];	/* file name */
  int ofn_mode;
  int ofn_type;			/* data or rsrc */
  int ofn_flgs;			/* file flags */
#define OF_EOF  0x020		/*  eof on file */
#define OF_NOTOPEN   0x02	/* to support non-existent files */
#define OF_INUSE 0x04		/* OFN is in use */
  int ofn_trans_table;		/* Translation table if any */
} OFN;

#define MaxOFN 30

private OFN OFNTBL[MaxOFN];

private int oinit = FALSE;

private
iniofn()
{
  int i;

  for (i=0; i < MaxOFN; i++) {
    OFNTBL[i].ofn_flgs = 0;
    OFNTBL[i].ofn_trans_table = -1; /* no index */
    OFNTBL[i].ofn_efn = i+1;
  }
  oinit = TRUE;
}

private word
ItoEOFN(o)
OFN *o;
{
  return(o->ofn_efn);
}

private OFN *
EtoIOFN(i)
int i;
{
  i = i-1;
  if (i > MaxOFN || i < 0) {
    printf("EtoIOFN: bad file number\n");
    return(NULL);
  }
  if (!oinit || (OFNTBL[i].ofn_flgs & OF_INUSE) == 0)	/* ofn assigned? */
    return(NULL);		/* no, mark as bad */
  return(&OFNTBL[i]);
}

private void
relofn(ofn)
OFN *ofn;
{
  ofn->ofn_flgs = 0;
  ofn->ofn_trans_table = -1;	/* delete */
}

private OFN *
asnofn()
{
  int i;
  if (!oinit)
    iniofn();
  for (i=0; i < MaxOFN; i++)
    if ((OFNTBL[i].ofn_flgs & OF_INUSE) == 0) {
      OFNTBL[i].ofn_trans_table = -1; /* paranoia: no index */
      OFNTBL[i].ofn_flgs = OF_INUSE;
      return(&OFNTBL[i]);
    }
  return(0);
}

/*
 * This is a horrible hack that is necessary to ensure that renames
 * get reflected back.  Really, really, points to the need for internal
 * directory of names....  Can't use fstat because file name is required
 * to return some of the information (from finderinfo).  Sigh...
 *
*/
OFNFIXUP(oipdir, ofile, nipdir, nfile)
IDirP oipdir;
char *ofile;
IDirP nipdir;
char *nfile;
{
  OFN *ofn;
  if (!oinit)
    return;

  for (ofn = OFNTBL; ofn < OFNTBL+MaxOFN; ofn++)
    if (ofn->ofn_flgs & OF_INUSE) {
      if (ofn->ofn_ipdir == oipdir && strcmp(ofn->ofn_fnam, ofile) == 0) {
	ofn->ofn_ipdir = nipdir; /* remember new directory */
	strcpy(ofn->ofn_fnam, nfile); /* remember new file */
      }
    }
  return(0);
}


/*
 * OSErr FPGetForkParms(...)
 *
 * This call is used to retrieve parameters for a file associated with
 * a particular open fork.
 *
 * Inputs:
 *   refnum	Open fork refnum
 *   bitmap	Bitmap describing which parameters are to be retrieved.
 *		This field is the same as the FPGetFileDirParms call.
 *
 * Outputs:
 *   Same as FPGetFileDirParms.
 *
 * Errors:
 *   ParamErr, BitMapErr, AccessDenied.
 *
 * The fork must be open for read.
 *
 */

OSErr 
FPGetForkParms(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
  GetForkParmsPkt gfp;
  FileDirParm fdp;
  int err;
  OFN *ofn;

  ntohPackX(PsGetForkParms,p,l,(byte *) &gfp);
  if ((ofn = EtoIOFN(gfp.gfp_refnum)) == NULL)
    return(aeParamErr);
  
  fdp.fdp_pdirid = ItoEdirid(ofn->ofn_ipdir,ofn->ofn_ivol);
  fdp.fdp_dbitmap = 0;
  fdp.fdp_fbitmap = gfp.gfp_bitmap;
  fdp.fdp_zero = 0;
  err = OSFileDirInfo(ofn->ofn_ipdir,NILDIR,ofn->ofn_fnam,&fdp,ofn->ofn_ivol);
  if (err != noErr)
    return(err);
  PackWord(gfp.gfp_bitmap,r);
  *rl = 2;
  *rl += htonPackX(FilePackR,(byte *) &fdp,r+(*rl));
  return(noErr);
}

/*
 * OSErr FPSetForkParms(...)
 *
 * Inputs:
 *
 *   refnum	Open fork refnum.
 *   bitmap	Bitmap describing which params are to be set.
 *
 * Output:
 *   Function Result.
 *
 * Errors:
 *   ParamErr, BitMapErr, DiskFull, LockErr, AccessDenied.
 *
 * The bitmap is the same as FPSetFileDirParms, however in AFP 1.1
 * only the fork length may be set.
 *
 * The fork must be opened for write.
 *
 */ 

/*ARGSUSED*/
OSErr 
FPSetForkParms(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
  SetForkParmsPkt sfkp;
  OFN *ofn;
  sdword len;

  ntohPackX(PsSetForkParms,p,l,(byte *) &sfkp);
  if ((ofn = EtoIOFN(sfkp.sfkp_refnum)) == NULL)
    return(aeParamErr);
  
  if (DBFRK)
    printf("FPSetForkParms: ofn=%d\n",sfkp.sfkp_refnum);

  if ((sfkp.sfkp_bitmap & ~(FP_DFLEN|FP_RFLEN)) != 0 || sfkp.sfkp_bitmap==0) {
    printf("FPSetForkParms: bad bitmap %x\n",sfkp.sfkp_bitmap);
    return(aeBitMapErr);
  }

  len = (sfkp.sfkp_bitmap & FP_DFLEN) ? sfkp.sfkp_dflen  : sfkp.sfkp_rflen;
  /* can only set fork length for now */
  return((ofn->ofn_flgs&OF_NOTOPEN) ? noErr : OSSetForklen(ofn->ofn_fd, len));
}


OSErr 
FPOpenFork(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
  OpenForkPkt ofk;
  OpenForkReplyPkt ofr;
  FileDirParm fdp;
  int ivol,err,err1,flg,fhdl,len, ttidx;
  IDirP idir,ipdir;
  char file[MAXUFLEN];
  byte finderinfo[FINFOLEN];
  OFN *ofn;
  extern PackEntry ProtoOFkRP[];

  ntohPackX(PsOpenFork,p,l,(byte *) &ofk);

  err = EtoIfile(file,&idir,&ipdir,&ivol,ofk.ofk_dirid,
		 ofk.ofk_volid,ofk.ofk_ptype,ofk.ofk_path);
  if (err != noErr)
    return(err);

  if (DBFRK) 
    printf("OpenFork: rdflg=%d, mode=%d, path=%s file=%s\n",
	   ofk.ofk_rdflg,ofk.ofk_mode,pathstr(ipdir),file);

  flg = (ofk.ofk_rdflg == 0) ? F_DATA : F_RSRC;

  err = OSOpenFork(ipdir,file,ofk.ofk_mode,flg,&fhdl);
  if (err != noErr && !(flg == F_RSRC && err == aeObjectNotFound))
    return(err);
  
  /* now, if data fork exists and resource open failed, allow go ahead */
  if (err == aeObjectNotFound) {
#ifdef notdef
    /* why did I do this? */
    if (ofk.ofk_mode & OFK_MWR)	/* don't allow write access */
      return(aeAccessDenied);
#endif
    if (OSFileExists(ipdir, file, F_DATA) != noErr)
      return(aeObjectNotFound);
    else {
      if (DBFRK)
	printf("Allowing fake access to resource fork\n");
    }
  }

  ofn = asnofn();
  if (ofn == 0) {
    if (err == noErr)
      OSClose(fhdl);
    return(aeTooManyFilesOpen);
  }
  ofn->ofn_fd = fhdl;
  ofn->ofn_mode = ofk.ofk_mode;
  ofn->ofn_type = flg;
  ofn->ofn_ipdir = ipdir;
  ofn->ofn_ivol = ivol;

  if (err == aeObjectNotFound)
    ofn->ofn_flgs |= OF_NOTOPEN;

  if (flg == F_DATA) {
    /* Never translate resource fork */
    OSGetFNDR(ipdir, file, finderinfo); /* check file type */
    if ((ttidx = ncs_istrans(finderinfo, file)) >= 0) {
      ofn->ofn_trans_table = ttidx;
      if (DBFRK)
	printf("Open fork: translation table: %s\n", ncs_tt_name(ttidx));
    }
  }

  strcpy(ofn->ofn_fnam,file);	/* remember file name (UGH!!!!) */

  fdp.fdp_fbitmap = ofk.ofk_bitmap;
  fdp.fdp_dbitmap = 0;
  if ((err1 = OSFileDirInfo(ipdir,NILDIR,file,&fdp,ivol)) != noErr) {
    if (err != noErr)
      OSClose(fhdl);
    relofn(ofn);
    return(err1);
  }
  ofr.ofkr_bitmap = ofk.ofk_bitmap;
  ofr.ofkr_refnum = ItoEOFN(ofn);
  len = htonPackX(ProtoOFkRP, &ofr, r);	/* pack away */
  *rl = len + htonPackX(FilePackR,(byte *) &fdp,r+len);
  return(noErr);
}

/*ARGSUSED*/
OSErr 
FPCloseFork(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
  CloseForkPkt cfk;
  OFN *ofn;
  int err;

  ntohPackX(PsCloseFork,p,l,(byte *) &cfk);
  if (DBFRK)
    printf("CloseFork: refnum=%d\n",cfk.cfk_refnum);
  if ((ofn = EtoIOFN(cfk.cfk_refnum)) == NULL)
    return(aeParamErr);

  if ((ofn->ofn_mode & OFK_MWR) != 0)	/* if opened for write */
    VolModified(ofn->ofn_ivol);		/*  then set volume modification dt */
  
  err = (ofn->ofn_flgs & OF_NOTOPEN) ? noErr : OSClose(ofn->ofn_fd);
  relofn(ofn);
  return(err);
}


/*
 * 
 * FPRead(...)
 *
 * The fork is read starting offset bytes from the beginning of the fork
 * and terminating at the first newline-char encountered.
 *
 */
 
OSErr 
FPRead(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
  ReadPkt rp;
  OFN *ofn;
  extern int sqs;		/* get max send quantum size */

  ntohPackX(PsRead,p,l,(byte *) &rp);
  if (DBFRK)
    printf("Read: ofn=%d, offset=%d, reqcnt=%d, flg=%d, nlc=%c\n",
	   rp.rdf_refnum,rp.rdf_offset,rp.rdf_reqcnt,
	   rp.rdf_flag,rp.rdf_nlchar);

  if ((ofn = EtoIOFN(rp.rdf_refnum)) == NULL)
    return(aeParamErr);

  if (ofn->ofn_flgs & OF_NOTOPEN) {
    *rl = 0;
    return(aeEOFErr);
  }

  return(OSRead(ofn->ofn_fd,rp.rdf_offset,
		min(rp.rdf_reqcnt,sqs),
		rp.rdf_flag,rp.rdf_nlchar,r,rl,&ofn->ofn_pos,
		ofn->ofn_trans_table));
}

OSErr 
FPWrite(p,l,r,rl,cno,reqref)
byte *p,*r;
int l,*rl;
int cno;
ReqRefNumType reqref;
{
  WritePkt wrt;
  int rcvlen;
  int comp,err;
  OFN *ofn;
  extern int n_rrpkts;

  ntohPackX(PsWrite,p,l,(byte *) &wrt);
  if ((ofn = EtoIOFN(wrt.wrt_refnum)) == NULL)
    return(aeParamErr);
  if (DBFRK)
    printf("FPWrite: ofn=%d, flg=%d, offs=%d, req=%d\n",
	   wrt.wrt_refnum,wrt.wrt_flag,wrt.wrt_offset,wrt.wrt_reqcnt);
  if (ofn->ofn_flgs & OF_NOTOPEN) {
    if (wrt.wrt_reqcnt != 0)	/* allow zero length requests */
      return(aeAccessDenied);
  }

  err = SPWrtContinue(cno,reqref,r,n_rrpkts*atpMaxData,&rcvlen,-1,&comp);
  if (err != noErr)
    return(err);
  do { abSleep(4,TRUE); } while (comp > 0);    
  if (comp < 0)
    return(comp);
  err = OSWrite(ofn->ofn_fd,r,(sdword) rcvlen,
		wrt.wrt_offset,wrt.wrt_flag,&ofn->ofn_pos,
		ofn->ofn_trans_table);
  if (err != noErr)		
    return(err);
  PackDWord(ofn->ofn_pos,r);
  *rl = sizeof(ofn->ofn_pos);
  return(noErr);
} 

/*ARGSUSED*/
OSErr 
FPFlushFork(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
  OFN *ofn;
  FlushForkPkt flf;

  ntohPackX(PsFlush, p, l, (byte *)&flf);
  if ((ofn = EtoIOFN(flf.flf_refnum)) == NULL)
    return(aeParamErr);
  if (DBFRK)
    printf("FLFlush: ofn=%d\n", flf.flf_refnum);
  return((ofn->ofn_flgs & OF_NOTOPEN) ? noErr : OSFlushFork(ofn->ofn_fd));
}

/*ARGSUSED*/
OSErr 
FPByteRangeLock(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
  OFN *ofn;
  ByteRangeLockPkt brl;
  OSErr err;

  ntohPackX(PsByteRangeLock, p, l, (byte *)&brl);
  if ((ofn = EtoIOFN(brl.brl_refnum)) == NULL)
    return(aeParamErr);
  if (DBFRK)
    printf("Byte Range Lock: ofn=%d (file %s)\n",ofn->ofn_fd,ofn->ofn_fnam);
  if (ofn->ofn_flgs & OF_NOTOPEN)
    ofn->ofn_pos = brl.brl_offset;
  else {
    err = OSByteRangeLock(ofn->ofn_fd, brl.brl_offset, brl.brl_length,
			  brl.brl_flg, &ofn->ofn_pos);
    if (err != noErr)
      return(err);
  }
  PackDWord(ofn->ofn_pos,r);
  *rl = sizeof(ofn->ofn_pos);
  return(noErr);
}

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