home *** CD-ROM | disk | FTP | other *** search
/ MacGames Sampler / PHT MacGames Bundle.iso / MacSource Folder / Samples from the CD / Editors / emacs / Emacs-1.14b1-sources / sources / unix-emulation-src / creat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-30  |  7.6 KB  |  336 lines  |  [TEXT/EMAC]

  1. /*
  2.  * Copyright (C) 1993, 1994 Marc Parmet.
  3.  * This file is part of the Macintosh port of GNU Emacs.
  4.  *
  5.  * GNU Emacs is distributed in the hope that it will be useful,
  6.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  7.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  8.  * GNU General Public License for more details.
  9.  */
  10.  
  11. #if defined(THINK_C)
  12. #include <MacHeaders>
  13. #else
  14. #include <Types.h>
  15. #include <Memory.h>
  16. #include <Quickdraw.h>
  17. #include <Windows.h>
  18. #include <TextEdit.h>
  19. #include <Errors.h>
  20. #include <Resources.h>
  21. #endif
  22.  
  23. #include <Script.h>
  24. #include "errno.h"
  25. #include "sys/ioctl.h"
  26. #include "sys/file.h"
  27. #include "unix-types.h"
  28. #include "unix-constants.h"
  29.  
  30. static long
  31. null_dispatch(long task,long index,long fd,char *p,long n,struct savearea_lomem *lomem)
  32. {
  33.     switch (task) {
  34.     case unix_read:        return 0;
  35.     case unix_write:    return 0;
  36.     case unix_close:    return 0;
  37.     case unix_fionread:    return 0;
  38.     }
  39. }
  40.  
  41. static long
  42. file_dispatch(long task,long index,long fd,char *p,long n,struct savearea_lomem *lomem)
  43. {
  44.     int i,err;
  45.     int refNum = (**proctable[index].fd[fd].object).u.file.refNum;
  46.     
  47.     switch (task) {
  48.     case unix_read:
  49.         err = FSRead(refNum,&n,p);
  50.         if (err == eofErr) return n;
  51.         if (err) { set_errno(err); return -1; }
  52.         return n;
  53.     case unix_write:
  54.         err = FSWrite(refNum,&n,p);
  55.         if (err) { set_errno(err); return -1; }
  56.         return n;
  57.     case unix_close:
  58.     {
  59.         FCBPBRec pb;
  60.         pb.ioNamePtr = 0L;
  61.         pb.ioRefNum = refNum;
  62.         pb.ioFCBIndx = 0;
  63.         err = PBGetFCBInfo(&pb,0);
  64.         if (err) { set_errno(err); return -1; }
  65.         err = FSClose(refNum);
  66.         if (err) { set_errno(err); return -1; }
  67.         err = FlushVol(0L,pb.ioFCBVRefNum);
  68.         if (err) { set_errno(err); return -1; }
  69.         return 0;
  70.     }
  71.     case unix_fionread:
  72.         return 0;
  73.     }
  74. }
  75.  
  76. static int
  77. has_binary_suffix(unsigned char *s)
  78. {
  79.     int len = s[0];
  80.     if (len < 4) return 0;
  81.     if (!bcmp(s+len-3,".bin",4)) return 1;
  82.     if (!bcmp(s+len-3,".elc",4)) return 1;
  83.     return 0;
  84. }
  85.  
  86. static int
  87. unix_perm_to_mac_perm(int unix_perm)
  88. {
  89.     switch (unix_perm) {
  90.     case O_RDONLY:    return fsRdPerm;
  91.     case O_WRONLY:    return fsWrPerm;
  92.     case O_RDWR:    return fsRdWrPerm;
  93.     default:        return -1;
  94.     }
  95. }
  96.  
  97. static int
  98. open_internal_file(char *fname,int unix_perm)
  99. {
  100.     FSSpec spec;
  101.     short refNum;
  102.     int err,fd,mac_perm;
  103.     int file_opened = 0;
  104.     struct unix_object **object;
  105.     int incremented_object_count = 0;
  106.  
  107.     mac_perm = unix_perm_to_mac_perm(unix_perm);
  108.     if (mac_perm == -1) { err = EUNDOC; goto error; }
  109.     
  110.     err = unixfn2FSSpec_internal(fname,&spec,0);
  111.     if (err) goto error;
  112.  
  113.     object = lookup_object(object_flavor_file,(int)&spec);
  114.     if (object == 0L) {
  115.         int translate,binary_suffix = has_binary_suffix(spec.name);
  116.         err = FSpOpenDF(&spec,mac_perm,&refNum);
  117.         if (err) goto error;
  118.         file_opened = 1;
  119.  
  120.         if (binary_suffix)
  121.             translate = 0;
  122.         else {
  123.             unsigned char p[200];
  124.             long i,n = sizeof(p);
  125.             err = FSRead(refNum,&n,p);
  126.             if (err && err != eofErr) goto error;
  127.             err = SetFPos(refNum,fsFromStart,0);
  128.             if (err) goto error;
  129.             translate = 1; /* This way an empty file is translated. */
  130.             for (i = 0; i<n; ++i) {
  131.                 if (p[i] == '\012') {
  132.                     translate = 0;
  133.                     break;
  134.                 }
  135.                 else if (p[i] == '\015') {
  136.                     translate = 1;
  137.                     break;
  138.                 }
  139.             }
  140.         }
  141.  
  142.         object = add_object(object_flavor_file,translate);
  143.         if (object == 0L) { errno = EUNDOC; goto error; }
  144.         (**object).u.file.spec = spec;
  145.         (**object).u.file.refNum = refNum;
  146.     }
  147.     else
  148.         ++(**object).count;
  149.     
  150.     incremented_object_count = 1;
  151.     
  152.     fd = add_fd(fd_flavor_file,file_dispatch,object);
  153.     if (fd < 0) { err = EUNDOC; goto error; }
  154.     return fd;
  155.     
  156.     error:
  157.     set_errno(err);
  158.     if (file_opened) FSClose(refNum);
  159.     if (incremented_object_count) dec_object_count(object);
  160.     return -1;
  161. }
  162.  
  163. static int
  164. open_internal_dev_null(void)
  165. {
  166.     int err,fd;
  167.     struct unix_object **object;
  168.  
  169.     object = lookup_object(object_flavor_dev_null,0);
  170.     if (object == 0L) {
  171.         object = add_object(object_flavor_dev_null,0);
  172.         if (object == 0L) { set_errno(EUNDOC); return -1; }
  173.     }
  174.     else
  175.         ++(**object).count;
  176.     
  177.     fd = add_fd(fd_flavor_dev_null,null_dispatch,object);
  178.     if (fd < 0) {
  179.         dec_object_count(object);
  180.         set_errno(EUNDOC);
  181.         return -1;
  182.     }
  183.     else
  184.         return fd;
  185. }
  186.  
  187. int
  188. open_internal(char *fname,int mode)
  189. {
  190.     int err,fd;
  191.     struct unix_object **object;
  192.  
  193.     if (!strcmp(fname,"/dev/tty"))
  194.         return open_internal_dev_tty();
  195.     else if (!strcmp(fname,"/dev/null"))
  196.         return open_internal_dev_null();
  197.     else
  198.         return open_internal_file(fname,mode);
  199. }
  200.  
  201. static int
  202. copy_rsrc_fork(FSSpec *fromFS,FSSpec *toFS)
  203. {
  204.     char buffer[512];
  205.     short fromRef,toRef,err;
  206.     
  207.     err = FSpOpenRF(fromFS,fsRdPerm,&fromRef);
  208.     if (err) return err;
  209.     err = FSpOpenRF(toFS,fsWrPerm,&toRef);
  210.     if (err) { FSClose(fromRef); return err; }
  211.     
  212.     while (1) {
  213.         long size = sizeof buffer;
  214.         err = FSRead(fromRef,&size,buffer);
  215.         if (err && err != eofErr) goto abort;
  216.         if (size == 0) break;
  217.         err = FSWrite(toRef,&size,buffer);
  218.         if (err) goto abort;
  219.     }
  220.         
  221.     err = noErr;
  222.     
  223.     abort:
  224.     FSClose(fromRef);
  225.     FSClose(toRef);
  226.     return err;
  227. }
  228.  
  229. int
  230. creat_internal(char *fname,int unix_mode)
  231. {
  232.     Handle h;
  233.     FSSpec spec;
  234.     short refNum;
  235.     struct unix_object **object;
  236.     int exists,err,fd,binary_suffix,lockup;
  237.  
  238.     err = unixfn2FSSpec_internal(fname,&spec,0);
  239.     if (err && err != fnfErr) { set_errno(err); return -1; }
  240.     exists = (err == noErr);
  241.  
  242.     binary_suffix = has_binary_suffix(spec.name);
  243.     object = lookup_object(object_flavor_file,(int)&spec);
  244.     if (object == 0L) {
  245.         object = add_object(object_flavor_file,!binary_suffix);
  246.         if (object == 0L) { set_errno(EUNDOC); return -1; }
  247.         (**object).u.file.spec = spec;
  248.     }
  249.     else {
  250.         set_errno(EUNDOC);
  251.         return -1;
  252.     }
  253.  
  254.     if (!exists) {
  255.         unsigned char t[256];
  256.         FInfo fromFInfo;
  257.         FSSpec grab;
  258.         int grabbing;
  259.         long creator,type;
  260.  
  261.         // If we are creating a file X, and that file does not already exist,
  262.         // we check to see if there are resources and a creator
  263.         // from a file X~ that we must copy into X.  Likewise if creating
  264.         // #X#, then take from X.
  265.         
  266.         grabbing = 0;
  267.         
  268.         // Look for FOO~
  269.         pstrcpy(t,spec.name);
  270.         pstrcat(t,"\p~");
  271.         err = FSMakeFSSpec(spec.vRefNum,spec.parID,t,&grab);
  272.         if (err == noErr)
  273.             // Have FOO~, so FOO grabs from FOO~
  274.             grabbing = 1;
  275.         else {
  276.             // No FOO~.  Maybe FOO looks like #FOO#?
  277.             if (spec.name[0] >= 3 && spec.name[1] == '#' && spec.name[spec.name[0]] == '#') {
  278.                 // Creating #FOO#, so #FOO# grabs from FOO
  279.                 pstrcpy(t,spec.name);
  280.                 t[0] = spec.name[0] - 2;
  281.                 memcpy(t+1,spec.name+2,t[0]);
  282.                 err = FSMakeFSSpec(spec.vRefNum,spec.parID,t,&grab);
  283.                 if (err == noErr)
  284.                     grabbing = 1;
  285.             }
  286.         }
  287.     
  288.         creator = 'EMAC';
  289.         type = binary_suffix ? 'dELC' : 'TEXT';
  290.         if (grabbing) {
  291.             err = HGetFInfo(grab.vRefNum,grab.parID,grab.name,&fromFInfo);
  292.             if (!err) {
  293.                 creator = fromFInfo.fdCreator;
  294.                 type = fromFInfo.fdType;
  295.             }
  296.             
  297.             err = FSpCreate(&spec,creator,type,smSystemScript);
  298.             if (err) { dec_object_count(object); set_errno(EUNDOC); return -1; }
  299.             copy_rsrc_fork(&grab,&spec);
  300.         }
  301.         else {
  302.             FSpCreateResFile(&spec,creator,type,smSystemScript);
  303.             err = ResError();
  304.             if (err) { dec_object_count(object); set_errno(EUNDOC); return -1; }
  305.             // Add STR -16396.  See IM Vol. VI, p. 9-21.
  306.             h = GetResource('STR ',130);
  307.             if (h != 0L) {
  308.                 DetachResource(h);
  309.                 refNum = FSpOpenResFile(&spec,fsWrPerm);
  310.                 err = ResError();
  311.                 if (!err) {
  312.                     AddResource(h,'STR ',-16396,0L);
  313.                     CloseResFile(refNum);
  314.                 }
  315.             }
  316.         }
  317.     }
  318.     
  319.     // Set permissions
  320.     lockup = (unix_mode & 0222) != 0222;
  321.     if (lockup) FSpSetFLock(&spec);
  322.     
  323.     err = FSpOpenDF(&spec,lockup ? fsRdPerm : fsRdWrPerm,&refNum);
  324.     if (err) { dec_object_count(object); set_errno(err); return -1; }
  325.     (**object).u.file.refNum = refNum;
  326.     
  327.     if (exists) {
  328.         err = SetEOF(refNum,0);
  329.         if (err) { dec_object_count(object); set_errno(err); return -1; }
  330.     }
  331.  
  332.     fd = add_fd(fd_flavor_file,file_dispatch,object);
  333.     if (fd < 0) { dec_object_count(object); set_errno(EUNDOC); return -1; }
  334.     return fd;
  335. }
  336.