(FILECREATED "18-Dec-84 23:09:57" {ERIS}<LISPCORE>SOURCES>NSFILINGPATCH.;1 15891 changes to: (VARS NSFILINGPATCHCOMS)) (* Copyright (c) 1984 by Xerox Corporation. All rights reserved.) (PRETTYCOMPRINT NSFILINGPATCHCOMS) (RPAQQ NSFILINGPATCHCOMS ((FNS \NSFILING.GENERATEFILES \NSFILING.CLOSEFILE \NSFILING.CONNECT \NSFILING.MAYBE.CREATE))) (DEFINEQ (\NSFILING.GENERATEFILES [LAMBDA (DEVICE PATTERN DESIREDPROPS OPTIONS) (* bvm: "18-Dec-84 21:48") (PROG (CONNECTION BULKSTREAM RESULT) [SETQ RESULT (RESETLST (PROG ((STAR "*") HOST NAME VERSION DIRECTORY FILTERLIST SCOPELIST INFINITE.DEPTH N) (for TAIL on (UNPACKFILENAME.STRING PATTERN) by (CDDR TAIL) do (SELECTQ (CAR TAIL) (HOST (SETQ HOST (CADR TAIL))) (DIRECTORY (SETQ DIRECTORY (CADR TAIL))) (NAME (SETQ NAME (CADR TAIL))) [EXTENSION (COND ((NOT (CADR TAIL)) NIL) [(NOT (STREQUAL (CADR TAIL) STAR)) (SETQ NAME (CONCAT NAME "." (CADR TAIL] ((NEQ (NTHCHARCODE NAME -1) (CHARCODE *)) (SETQ NAME (CONCAT NAME STAR] [VERSION (SETQ VERSION (MKATOM (CADR TAIL] NIL)) [COND ((SETQ N (STRPOS (QUOTE *) DIRECTORY)) (* Wild card in directory part is hard. Get as far down in the tree as possible, then enumerate everything) (bind (BROKET ← 0) X while (AND (SETQ X (STRPOS (QUOTE >) DIRECTORY (ADD1 BROKET))) (ILESSP X N)) do (SETQ BROKET X) finally (SETQ NAME (SUBSTRING DIRECTORY (ADD1 BROKET) N)) (SETQ DIRECTORY (AND (NEQ BROKET 0) (SUBSTRING DIRECTORY 1 (SUB1 BROKET] (SETQ CONNECTION (OR (\GETFILINGCONNECTION DEVICE) (RETURN NIL))) (RESETSAVE NIL (LIST (FUNCTION \NSFILING.CLOSE.IF.ERROR) CONNECTION)) (RETURN (COND ((\NSFILING.CONNECT CONNECTION DIRECTORY T) [COND ((SETQ DESIREDPROPS (for PROP in DESIREDPROPS when (SETQ PROP (\FILING.ATTRIBUTE.TYPE (OR (CADR (ASSOC PROP \LISP.TO.NSFILING.ATTRIBUTES)) PROP) T)) collect PROP)) (* make sure there are no duplicates, since File server can object to that) (SETQ DESIREDPROPS (INTERSECTION DESIREDPROPS DESIREDPROPS] (SETQ DESIREDPROPS (CONS [COND [(EQ (fetch FSPROTOCOLNAME of CONNECTION) (QUOTE FILING)) (CONSTANT (\FILING.ATTRIBUTE.TYPE (QUOTE PATHNAME] (T (CONSTANT (\FILING.ATTRIBUTE.TYPE (QUOTE NAME] (APPEND [CONSTANT (\FILING.ATTRIBUTE.TYPE.SEQUENCE (QUOTE (VERSION IS.DIRECTORY] DESIREDPROPS))) [COND [(STRPOS (QUOTE *) NAME) (* Enumerate entire directory, matching against any wild cards.) (COND ((NOT (STREQUAL NAME STAR)) (* The following doesn't quite work because the fileserver won't match against subdirectory names. So we always enumerate the whole directory, regardless of the pattern.) (push FILTERLIST (BQUOTE (MATCHES (NAME , NAME] (T (* Only enumerate versions.) (push FILTERLIST (BQUOTE (= , (COURIER.CREATE (FILING . FILTER.ATTRIBUTE) ATTRIBUTE ←(LIST (QUOTE NAME) NAME) INTERPRETATION ←( QUOTE STRING] [COND ((FIXP VERSION) (push FILTERLIST (BQUOTE (= , (COURIER.CREATE (FILING . FILTER.ATTRIBUTE) ATTRIBUTE ←(LIST (QUOTE VERSION) VERSION) INTERPRETATION ←(QUOTE CARDINAL] [COND (FILTERLIST (push SCOPELIST (LIST (QUOTE FILTER) (COND ((CDR FILTERLIST) (LIST (QUOTE AND) FILTERLIST)) (T (CAR FILTERLIST] [COND ((AND FILING.ENUMERATION.DEPTH DIRECTORY (EQ (fetch FSPROTOCOLNAME of CONNECTION) (QUOTE FILING))) (* Controls how many levels in hierarchy to show. If FILING.ENUMERATION.DEPTH is infinite, then let's also ignore the "files" that are subdirectories) (push SCOPELIST (BQUOTE (DEPTH , (OR (SMALLP FILING.ENUMERATION.DEPTH) (PROGN (SETQ INFINITE.DEPTH T) 65535] (SETQ BULKSTREAM (FILING.CALL CONNECTION (QUOTE LIST) (fetch FSCURRENTDIRECTORY of CONNECTION) DESIREDPROPS SCOPELIST NIL (fetch FSSESSIONHANDLE of CONNECTION))) (create FILEGENOBJ NEXTFILEFN ←(FUNCTION \NSFILING.NEXTFILE) FILEINFOFN ←(FUNCTION \NSFILING.FILEINFOFN) GENFILESTATE ←(create \NSFILING.GENFILESTATE NSGENERATOR ←( BULKDATA.GENERATOR BULKSTREAM (QUOTE FILING) (QUOTE ATTRIBUTE.SEQUENCE)) NSFILTER ←( DIRECTORY.MATCH.SETUP PATTERN) NSCONNECTION ← CONNECTION NSIGNOREDIRECTORIES ← INFINITE.DEPTH] (COND ((NULL CONNECTION)) ((EQMEMB (QUOTE RESETLST) OPTIONS) (RESETSAVE NIL (LIST (FUNCTION [LAMBDA (CONNECTION STREAM) (CLOSEF STREAM) (\CLOSEFILINGCONNECTION CONNECTION RESETSTATE]) CONNECTION BULKSTREAM))) ((NULL BULKSTREAM) (\CLOSEFILINGCONNECTION CONNECTION))) (RETURN (OR RESULT (\NULLFILEGENERATOR]) (\NSFILING.CLOSEFILE [LAMBDA (FILESTREAM OPTIONS) (* bvm: "18-Dec-84 23:05") (RESETLST (PROG ((ABORTFLG (EQMEMB (QUOTE ABORT) OPTIONS)) NEWHANDLE HANDLE CONNECTION INFO) [COND ((AND (SETQ NEWHANDLE (\BULK.DATA.CLOSE FILESTREAM ABORTFLG)) (NEQ (CAR NEWHANDLE) (QUOTE ERROR))) (SETQ HANDLE NEWHANDLE)) (T (SETQ HANDLE (fetch NSFILING.HANDLE of FILESTREAM] (* Get the handle from the result of the STORE (for OUTPUT) or from the handle already given to RETRIEVE or REPLACE) (OR (SETQ CONNECTION (fetch NSFILING.CONNECTION of FILESTREAM)) (RETURN)) (RESETSAVE NIL (LIST (FUNCTION \NSFILING.RESETCLOSE) CONNECTION)) (COND [(EQ (CAR NEWHANDLE) (QUOTE ERROR)) (COND ((AND (WRITEABLE FILESTREAM) (NOT ABORTFLG)) (ERROR (CONCAT "CLOSEF: File not written " (CADR NEWHANDLE) " -- " (CADDR NEWHANDLE)) (fetch FULLFILENAME of FILESTREAM] ((AND HANDLE (SPP.OPENP (fetch FSCOURIERSTREAM of CONNECTION))) (NLSETQ (* errorset protect this because SPP.OPENP can lie, if we have not blocked recently) [COND ([AND NEWHANDLE (SETQ INFO (FILING.CALL CONNECTION (QUOTE GET.ATTRIBUTES) NEWHANDLE \NSFILING.USEFUL.ATTRIBUTE.TYPES (fetch FSSESSIONHANDLE of CONNECTION) (QUOTE NOERROR] (* Save attributes in case caller wants to look at newly created file) (replace NSCACHE of (fetch DEVICEINFO of (fetch DEVICE of FILESTREAM)) with (CONS (LIST (QUOTE FULLNAME) (fetch FULLFILENAME of FILESTREAM)) INFO] (\NSFILING.CLOSE.HANDLE CONNECTION HANDLE) (replace NSFILING.HANDLE of FILESTREAM with NIL]) (\NSFILING.CONNECT [LAMBDA (CONNECTION PATHNAME REALREQUIRED CREATE?) (* bvm: "18-Dec-84 22:33") (* Follow the list of directories in PATHNAME and cache the handle for the final one in the connection record. The special case when PATHNAME is NIL is equivalent to connecting to the root directory. Uses cached current path to avoid useless reconnecting. WARNING: this may fail if there is ever more than one version of the same subdirectory name. To fix this we could use the same hack that's in \NSFILING.GETFILE : first enumerate the versions (also requiring the IS.DIRECTORY attribute) and then use the unique FILE.ID, but since it hasn't been a problem yet, we don't bother.) (PROG ((NEW.DIRLIST (OR (LISTP PATHNAME) (\PATHNAME.TO.DIRECTORY.LIST PATHNAME))) (OLD.DIRLIST (fetch FSCURRENTPATH of CONNECTION)) (SESSIONHANDLE (fetch FSSESSIONHANDLE of CONNECTION)) (OLD.HANDLE (fetch FSCURRENTDIRECTORY of CONNECTION)) NEW.HANDLE ADDITIONAL.DIRLIST NSPATHNAME) (COND ((AND (EQUAL NEW.DIRLIST OLD.DIRLIST) (OR NEW.DIRLIST (NOT REALREQUIRED) (NEQ OLD.HANDLE \NSFILING.NULL.HANDLE))) (* Nothing needs to be done because we're already connected to this path.) (RETURN T))) (COND ((AND (CDR NEW.DIRLIST) (EQ (fetch FSPROTOCOLNAME of CONNECTION) (QUOTE FILING))) [SETQ NSPATHNAME (CONCATLIST (CDR (for DIR in NEW.DIRLIST join (LIST (QUOTE /) DIR] (SETQ NEW.HANDLE (FILING.CALL CONNECTION (QUOTE OPEN) (BQUOTE ((PATHNAME , NSPATHNAME))) \NSFILING.NULL.HANDLE NIL SESSIONHANDLE (QUOTE RETURNERRORS))) (SELECTQ (CAR NEW.HANDLE) (NIL (RETURN)) [ERROR (COND ((AND (EQ (CADDR NEW.HANDLE) (QUOTE FileNotFound)) (SETQ NEW.HANDLE (\NSFILING.MAYBE.CREATE CREATE? NEW.DIRLIST (CAR (LAST NEW.DIRLIST) ) CONNECTION))) (* Successfully created) ) (T (RETURN] NIL) (UNINTERRUPTABLY (SETQ OLD.HANDLE (fetch FSCURRENTDIRECTORY of CONNECTION)) (* Need to do this because recursive call to \NSFILING.CONNECT might have changed it) (replace FSCURRENTDIRECTORY of CONNECTION with NEW.HANDLE) (replace FSCURRENTPATH of CONNECTION with NEW.DIRLIST)) (COND ((NEQ OLD.HANDLE \NSFILING.NULL.HANDLE) (* Close the old handle we're not using any more) (FILING.CALL CONNECTION (QUOTE CLOSE) OLD.HANDLE SESSIONHANDLE))) (RETURN T))) [COND ([AND (CDR NEW.DIRLIST) (SETQ ADDITIONAL.DIRLIST NEW.DIRLIST) (for OLD.DIR in OLD.DIRLIST always (STREQUAL OLD.DIR (pop ADDITIONAL.DIRLIST] (* We're currently connected to a prefix of the desired path, so we can save some remote calls.) (SETQ NEW.DIRLIST ADDITIONAL.DIRLIST)) (T (* We need to start again from the root. If we kept open the handles of all directories in the current path, we would only have to go back to the nearest common ancestor, but it's probably not worth it.) (COND ((NEQ OLD.HANDLE \NSFILING.NULL.HANDLE) (FILING.CALL CONNECTION (QUOTE CLOSE) (PROG1 OLD.HANDLE (UNINTERRUPTABLY (replace FSCURRENTDIRECTORY of CONNECTION with (SETQ OLD.HANDLE \NSFILING.NULL.HANDLE)) (replace FSCURRENTPATH of CONNECTION with NIL))) SESSIONHANDLE))) (COND ((AND REALREQUIRED (NULL NEW.DIRLIST)) (* Caller wants handle of the root of the file system, and can't use the "null handle" constant) (replace FSCURRENTDIRECTORY of CONNECTION with (SETQ OLD.HANDLE (FILING.CALL CONNECTION (QUOTE OPEN) NIL \NSFILING.NULL.HANDLE NIL SESSIONHANDLE (QUOTE NOERROR] (RETURN (for TAIL on NEW.DIRLIST do (COND ((SETQ NEW.HANDLE (FILING.CALL CONNECTION (QUOTE OPEN) [BQUOTE ((NAME , (SETQ NEW.DIR (CAR TAIL] OLD.HANDLE NIL SESSIONHANDLE (QUOTE RETURNERRORS))) [COND ((EQ (CAR (LISTP NEW.HANDLE)) (QUOTE ERROR)) (COND [(AND (NULL (CDR TAIL)) (EQ (CADDR NEW.HANDLE) (QUOTE FileNotFound)) (SETQ NEW.HANDLE (\NSFILING.MAYBE.CREATE CREATE? NEW.DIRLIST NEW.DIR CONNECTION T] (T (RETURN] (UNINTERRUPTABLY (replace FSCURRENTDIRECTORY of CONNECTION with NEW.HANDLE) (replace FSCURRENTPATH of CONNECTION with (APPEND (fetch FSCURRENTPATH of CONNECTION) (LIST NEW.DIR)))) (COND ((NEQ OLD.HANDLE \NSFILING.NULL.HANDLE) (* Close the old handle we're not using any more) (FILING.CALL CONNECTION (QUOTE CLOSE) OLD.HANDLE SESSIONHANDLE))) (SETQ OLD.HANDLE NEW.HANDLE)) (T (RETURN))) finally (RETURN T]) (\NSFILING.MAYBE.CREATE [LAMBDA (CREATE? DIRLST NEW.DIR CONNECTION CONNECTED) (* bvm: "18-Dec-84 22:27") (* * Called to possibly create a nonexistent subdirectory. DIRLST is a list of directories down to the final NEW.DIR. CONNECTED is true if CONNECTION is already connected to the penultimate dir) (AND (SELECTQ CREATE? [ASK (EQ (QUOTE Y) (ASKUSER DWIMWAIT (QUOTE Y) (CONCAT "Create subdirectory {" (fetch FSNAMESTRING of CONNECTION) "}<" [CONCATLIST (for DIR in DIRLST join (LIST DIR (QUOTE >] "? "] (NIL NIL) T) (OR CONNECTED (\NSFILING.CONNECT CONNECTION (for TAIL on DIRLST collect (CAR TAIL) while (CDR TAIL)) T T)) (FILING.CALL CONNECTION (QUOTE CREATE) (fetch FSCURRENTDIRECTORY of CONNECTION) (BQUOTE ((NAME , NEW.DIR) (IS.DIRECTORY T) (FILE.TYPE 1))) NIL (fetch FSSESSIONHANDLE of CONNECTION) (QUOTE NOERROR]) ) (PUTPROPS NSFILINGPATCH COPYRIGHT ("Xerox Corporation" 1984)) (DECLARE: DONTCOPY (FILEMAP (NIL (374 15807 (\NSFILING.GENERATEFILES 384 . 6483) (\NSFILING.CLOSEFILE 6485 . 8767) ( \NSFILING.CONNECT 8769 . 14678) (\NSFILING.MAYBE.CREATE 14680 . 15805))))) STOP