home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1993, 1994 Marc Parmet.
- * This file is part of the Macintosh port of GNU Emacs.
- *
- * GNU Emacs 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.
- */
-
- #if defined(THINK_C)
- #include <MacHeaders>
- #else
- #include <Types.h>
- #include <Memory.h>
- #include <Quickdraw.h>
- #include <Windows.h>
- #include <TextEdit.h>
- #include <Errors.h>
- #include <Resources.h>
- #endif
-
- #include <Script.h>
- #include "errno.h"
- #include "sys/ioctl.h"
- #include "sys/file.h"
- #include "unix-types.h"
- #include "unix-constants.h"
-
- static long
- null_dispatch(long task,long index,long fd,char *p,long n,struct savearea_lomem *lomem)
- {
- switch (task) {
- case unix_read: return 0;
- case unix_write: return 0;
- case unix_close: return 0;
- case unix_fionread: return 0;
- }
- }
-
- static long
- file_dispatch(long task,long index,long fd,char *p,long n,struct savearea_lomem *lomem)
- {
- int i,err;
- int refNum = (**proctable[index].fd[fd].object).u.file.refNum;
-
- switch (task) {
- case unix_read:
- err = FSRead(refNum,&n,p);
- if (err == eofErr) return n;
- if (err) { set_errno(err); return -1; }
- return n;
- case unix_write:
- err = FSWrite(refNum,&n,p);
- if (err) { set_errno(err); return -1; }
- return n;
- case unix_close:
- {
- FCBPBRec pb;
- pb.ioNamePtr = 0L;
- pb.ioRefNum = refNum;
- pb.ioFCBIndx = 0;
- err = PBGetFCBInfo(&pb,0);
- if (err) { set_errno(err); return -1; }
- err = FSClose(refNum);
- if (err) { set_errno(err); return -1; }
- err = FlushVol(0L,pb.ioFCBVRefNum);
- if (err) { set_errno(err); return -1; }
- return 0;
- }
- case unix_fionread:
- return 0;
- }
- }
-
- static int
- has_binary_suffix(unsigned char *s)
- {
- int len = s[0];
- if (len < 4) return 0;
- if (!bcmp(s+len-3,".bin",4)) return 1;
- if (!bcmp(s+len-3,".elc",4)) return 1;
- return 0;
- }
-
- static int
- unix_perm_to_mac_perm(int unix_perm)
- {
- switch (unix_perm) {
- case O_RDONLY: return fsRdPerm;
- case O_WRONLY: return fsWrPerm;
- case O_RDWR: return fsRdWrPerm;
- default: return -1;
- }
- }
-
- static int
- open_internal_file(char *fname,int unix_perm)
- {
- FSSpec spec;
- short refNum;
- int err,fd,mac_perm;
- int file_opened = 0;
- struct unix_object **object;
- int incremented_object_count = 0;
-
- mac_perm = unix_perm_to_mac_perm(unix_perm);
- if (mac_perm == -1) { err = EUNDOC; goto error; }
-
- err = unixfn2FSSpec_internal(fname,&spec,0);
- if (err) goto error;
-
- object = lookup_object(object_flavor_file,(int)&spec);
- if (object == 0L) {
- int translate,binary_suffix = has_binary_suffix(spec.name);
- err = FSpOpenDF(&spec,mac_perm,&refNum);
- if (err) goto error;
- file_opened = 1;
-
- if (binary_suffix)
- translate = 0;
- else {
- unsigned char p[200];
- long i,n = sizeof(p);
- err = FSRead(refNum,&n,p);
- if (err && err != eofErr) goto error;
- err = SetFPos(refNum,fsFromStart,0);
- if (err) goto error;
- translate = 1; /* This way an empty file is translated. */
- for (i = 0; i<n; ++i) {
- if (p[i] == '\012') {
- translate = 0;
- break;
- }
- else if (p[i] == '\015') {
- translate = 1;
- break;
- }
- }
- }
-
- object = add_object(object_flavor_file,translate);
- if (object == 0L) { errno = EUNDOC; goto error; }
- (**object).u.file.spec = spec;
- (**object).u.file.refNum = refNum;
- }
- else
- ++(**object).count;
-
- incremented_object_count = 1;
-
- fd = add_fd(fd_flavor_file,file_dispatch,object);
- if (fd < 0) { err = EUNDOC; goto error; }
- return fd;
-
- error:
- set_errno(err);
- if (file_opened) FSClose(refNum);
- if (incremented_object_count) dec_object_count(object);
- return -1;
- }
-
- static int
- open_internal_dev_null(void)
- {
- int err,fd;
- struct unix_object **object;
-
- object = lookup_object(object_flavor_dev_null,0);
- if (object == 0L) {
- object = add_object(object_flavor_dev_null,0);
- if (object == 0L) { set_errno(EUNDOC); return -1; }
- }
- else
- ++(**object).count;
-
- fd = add_fd(fd_flavor_dev_null,null_dispatch,object);
- if (fd < 0) {
- dec_object_count(object);
- set_errno(EUNDOC);
- return -1;
- }
- else
- return fd;
- }
-
- int
- open_internal(char *fname,int mode)
- {
- int err,fd;
- struct unix_object **object;
-
- if (!strcmp(fname,"/dev/tty"))
- return open_internal_dev_tty();
- else if (!strcmp(fname,"/dev/null"))
- return open_internal_dev_null();
- else
- return open_internal_file(fname,mode);
- }
-
- static int
- copy_rsrc_fork(FSSpec *fromFS,FSSpec *toFS)
- {
- char buffer[512];
- short fromRef,toRef,err;
-
- err = FSpOpenRF(fromFS,fsRdPerm,&fromRef);
- if (err) return err;
- err = FSpOpenRF(toFS,fsWrPerm,&toRef);
- if (err) { FSClose(fromRef); return err; }
-
- while (1) {
- long size = sizeof buffer;
- err = FSRead(fromRef,&size,buffer);
- if (err && err != eofErr) goto abort;
- if (size == 0) break;
- err = FSWrite(toRef,&size,buffer);
- if (err) goto abort;
- }
-
- err = noErr;
-
- abort:
- FSClose(fromRef);
- FSClose(toRef);
- return err;
- }
-
- int
- creat_internal(char *fname,int unix_mode)
- {
- Handle h;
- FSSpec spec;
- short refNum;
- struct unix_object **object;
- int exists,err,fd,binary_suffix,lockup;
-
- err = unixfn2FSSpec_internal(fname,&spec,0);
- if (err && err != fnfErr) { set_errno(err); return -1; }
- exists = (err == noErr);
-
- binary_suffix = has_binary_suffix(spec.name);
- object = lookup_object(object_flavor_file,(int)&spec);
- if (object == 0L) {
- object = add_object(object_flavor_file,!binary_suffix);
- if (object == 0L) { set_errno(EUNDOC); return -1; }
- (**object).u.file.spec = spec;
- }
- else {
- set_errno(EUNDOC);
- return -1;
- }
-
- if (!exists) {
- unsigned char t[256];
- FInfo fromFInfo;
- FSSpec grab;
- int grabbing;
- long creator,type;
-
- // If we are creating a file X, and that file does not already exist,
- // we check to see if there are resources and a creator
- // from a file X~ that we must copy into X. Likewise if creating
- // #X#, then take from X.
-
- grabbing = 0;
-
- // Look for FOO~
- pstrcpy(t,spec.name);
- pstrcat(t,"\p~");
- err = FSMakeFSSpec(spec.vRefNum,spec.parID,t,&grab);
- if (err == noErr)
- // Have FOO~, so FOO grabs from FOO~
- grabbing = 1;
- else {
- // No FOO~. Maybe FOO looks like #FOO#?
- if (spec.name[0] >= 3 && spec.name[1] == '#' && spec.name[spec.name[0]] == '#') {
- // Creating #FOO#, so #FOO# grabs from FOO
- pstrcpy(t,spec.name);
- t[0] = spec.name[0] - 2;
- memcpy(t+1,spec.name+2,t[0]);
- err = FSMakeFSSpec(spec.vRefNum,spec.parID,t,&grab);
- if (err == noErr)
- grabbing = 1;
- }
- }
-
- creator = 'EMAC';
- type = binary_suffix ? 'dELC' : 'TEXT';
- if (grabbing) {
- err = HGetFInfo(grab.vRefNum,grab.parID,grab.name,&fromFInfo);
- if (!err) {
- creator = fromFInfo.fdCreator;
- type = fromFInfo.fdType;
- }
-
- err = FSpCreate(&spec,creator,type,smSystemScript);
- if (err) { dec_object_count(object); set_errno(EUNDOC); return -1; }
- copy_rsrc_fork(&grab,&spec);
- }
- else {
- FSpCreateResFile(&spec,creator,type,smSystemScript);
- err = ResError();
- if (err) { dec_object_count(object); set_errno(EUNDOC); return -1; }
- // Add STR -16396. See IM Vol. VI, p. 9-21.
- h = GetResource('STR ',130);
- if (h != 0L) {
- DetachResource(h);
- refNum = FSpOpenResFile(&spec,fsWrPerm);
- err = ResError();
- if (!err) {
- AddResource(h,'STR ',-16396,0L);
- CloseResFile(refNum);
- }
- }
- }
- }
-
- // Set permissions
- lockup = (unix_mode & 0222) != 0222;
- if (lockup) FSpSetFLock(&spec);
-
- err = FSpOpenDF(&spec,lockup ? fsRdPerm : fsRdWrPerm,&refNum);
- if (err) { dec_object_count(object); set_errno(err); return -1; }
- (**object).u.file.refNum = refNum;
-
- if (exists) {
- err = SetEOF(refNum,0);
- if (err) { dec_object_count(object); set_errno(err); return -1; }
- }
-
- fd = add_fd(fd_flavor_file,file_dispatch,object);
- if (fd < 0) { dec_object_count(object); set_errno(EUNDOC); return -1; }
- return fd;
- }
-