home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 28 / amigaformatcd28.iso / -seriously_amiga- / archivers / mpackppc-wos / src / os2os.c < prev    next >
C/C++ Source or Header  |  1998-04-27  |  10KB  |  442 lines

  1. /* (C) Copyright 1993,1994 by Carnegie Mellon University
  2.  * All Rights Reserved.
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software
  5.  * and its documentation for any purpose is hereby granted without
  6.  * fee, provided that the above copyright notice appear in all copies
  7.  * and that both that copyright notice and this permission notice
  8.  * appear in supporting documentation, and that the name of Carnegie
  9.  * Mellon University not be used in advertising or publicity
  10.  * pertaining to distribution of the software without specific,
  11.  * written prior permission.  Carnegie Mellon University makes no
  12.  * representations about the suitability of this software for any
  13.  * purpose.  It is provided "as is" without express or implied
  14.  * warranty.
  15.  *
  16.  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
  17.  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  18.  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
  19.  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  20.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  21.  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  22.  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  23.  * SOFTWARE.
  24.  */
  25. #define INCL_DOSFILEMGR
  26. #define INCL_DOSERRORS
  27. #include <os2.h>
  28. #include <stdio.h>
  29. #include <io.h>
  30. #include <stdlib.h>
  31. #include <ctype.h>
  32. #include <string.h>
  33. #include <errno.h>
  34. #include <fcntl.h>
  35. #include <sys/types.h>
  36. #include <sys/stat.h>
  37. #include "xmalloc.h"
  38. #include "common.h"
  39.  
  40. #ifdef __EMX__        /* This is for EMX + GCC */
  41.  
  42. #define EACCESS EACCES
  43.  
  44.  
  45.  
  46. #else            /* This is for IBM C++ */
  47.  
  48. #include <direct.h>
  49. #define ENAMETOOLONG EOS2ERR
  50.  
  51. #endif            /* EMX or IBM CSet++ */
  52.  
  53. int overwrite_files = 0;
  54. int didchat;
  55. int mime_eas = 0;
  56.  
  57. /* The name of the file we're writing */
  58. static char *output_fname = 0;
  59.  
  60. /* Characters that can be in filenames */
  61. #define GOODCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" \
  62.                   "0123456789-_^$~!#%&{}@`'()"
  63.  
  64. int my_mkdir(char *filename)
  65. {
  66.     PEAOP2 EABuf;
  67.     APIRET rc;
  68.  
  69.     EABuf = 0;
  70.     rc = DosCreateDir(filename,EABuf);
  71.     
  72.     switch (rc) {
  73.     case NO_ERROR: 
  74.         return 0;
  75.     case ERROR_FILENAME_EXCED_RANGE:
  76.         errno = EACCESS;
  77.         return 1;
  78.     case ERROR_PATH_NOT_FOUND:
  79.         errno = ENOENT;
  80.         return -1;
  81.     default:
  82.         errno = EACCESS;
  83.         return -1;
  84.     }
  85. }
  86.  
  87. void crunch_file(char *p, char **q)
  88. {
  89.     int len, sawdot;
  90.  
  91.     for (*q=p, len=sawdot=0; *p; p++) {
  92.     if (*p == '.') {
  93.         if (!sawdot) {
  94.         *(*q)++ = '.';
  95.         sawdot++;
  96.         len = 0;
  97.         }
  98.     } else if (len < (sawdot ? 3:8)) {
  99.         *(*q)++ = *p;
  100.         len++;
  101.     }
  102.     }
  103.     **q = '\0';
  104. }
  105.  
  106. typedef struct
  107. {
  108.     ULONG cbList;
  109.     ULONG oNext;
  110.     BYTE fEA;
  111.     BYTE cbName;
  112.     USHORT cbValue;
  113.     BYTE NameBuffer[CCHMAXPATH*2+8];
  114. }
  115. FEALST;
  116.  
  117. void EA_attach(int fd, char *name, char *value)
  118. {
  119.     EAOP2 eaop;
  120.     FEALST fealst;
  121.     int len;
  122.  
  123.     eaop.fpFEA2List = (PFEA2LIST) &fealst;
  124.     eaop.fpGEA2List = NULL;
  125.     eaop.oError = 0;
  126.  
  127.     fealst.oNext = 0;
  128.     fealst.fEA = 0;
  129.  
  130.     fealst.cbName = strlen(name) ;
  131.     fealst.cbValue = strlen(value) +4;
  132.  
  133.     len = fealst.cbName +1;
  134.     strcpy(fealst.NameBuffer,name);
  135.  
  136.     *((USHORT *) &(fealst.NameBuffer [len])) = 0xFFFD;
  137.     len += sizeof(USHORT);
  138.     *((USHORT *) &(fealst.NameBuffer [len])) = strlen(value);
  139.     len += sizeof(USHORT);
  140.     strcpy(&(fealst.NameBuffer[len]), value);
  141.  
  142.     fealst.cbList = fealst.cbName+fealst.cbValue+9;
  143.   
  144.     DosSetFileInfo(fd, FIL_QUERYEASIZE, &eaop, sizeof(eaop));
  145. }
  146.  
  147. /* Generate a message-id */
  148. char *os_genid()
  149. {
  150.     static time_t curtime;
  151.     static char *hostname;
  152.     static char *domain;
  153.     char *result;
  154.  
  155.     if (curtime == 0) {
  156.     time(&curtime);
  157.  
  158.     hostname = getenv("HOSTNAME");
  159.     if (!hostname) hostname="random-pc";
  160.     domain = getenv("DOMAINNAME");
  161.     if (!domain) domain="random-domain";
  162.     }
  163.  
  164.     if (strchr(hostname,'.')) {
  165.     result = xmalloc(25+strlen(hostname));
  166.     sprintf(result, "%lu@%s", curtime++, hostname);
  167.     } else {
  168.     if (domain[0] == '.') domain++;
  169.     result = xmalloc(25+strlen(hostname)+strlen(domain));
  170.     sprintf(result, "%lu@%s.%s", curtime++, hostname, domain);
  171.     }
  172.     return result;
  173. }
  174.  
  175. /* Create and return directory for a message-id */
  176. char *os_idtodir(id)
  177. char *id;
  178. {
  179.     static char buf[512];
  180.     int len = 0;
  181.     int cs = 0;
  182.     int rc;
  183.     char *p, *q;
  184.  
  185.     if (p = getenv("TMP")) {
  186.     strncpy(buf, p, 201);
  187.     p[200] = '\0';        /* Ensure sufficiently short */
  188.     }
  189.     else {
  190.     strcpy(buf, "\\tmp");
  191.     (void)my_mkdir(buf);
  192.     }
  193.     if (buf[strlen(buf)-1] != '\\')
  194.     strcat(buf, "\\");
  195.  
  196.     strcat(buf, "parts");
  197.     (void)my_mkdir(buf);
  198.  
  199.     p = buf + strlen(buf);
  200.     *p++ = '\\';
  201.     q = p;
  202.  
  203.     while (*id && len < 200) {
  204.     if (strchr(GOODCHARS, *id)) {
  205.         *p++ = *id;
  206.             len++;
  207.         cs += *id * len;
  208.     }
  209.     id++;
  210.     }
  211.     *p = '\0';
  212.     rc = my_mkdir(buf);
  213.     if (rc == 1) {
  214.     char csarr[] = GOODCHARS;
  215.     /* maybe 8.3 restriction. Take 8 char + 3 checksum */
  216.     p = q;
  217.     len = 0;
  218.     while ( *p && len < 8) { len++; p++; }
  219.     *p++ = '.';
  220.     *p++ = csarr[cs % sizeof(csarr)]; 
  221.     cs = cs / sizeof(csarr);
  222.     *p++ = csarr[cs % sizeof(csarr)]; 
  223.     cs = cs / sizeof(csarr);
  224.     *p++ = csarr[cs % sizeof(csarr)];
  225.     *p = '\0';
  226.     rc = my_mkdir(buf);
  227.     }
  228.     if ((rc == -1) && (errno != EACCESS)) {
  229.     perror(buf);
  230.     return 0;
  231.     }
  232.     *p++ = '\\';
  233.     *p = '\0';
  234.     return buf;
  235. }
  236.  
  237. /*
  238.  * We are done with the directory returned by os_idtodir()
  239.  * Remove it
  240.  */
  241. os_donewithdir(dir)
  242. char *dir;
  243. {
  244.     char *p;
  245.  
  246.     /* Remove trailing slash */
  247.     p = dir + strlen(dir) - 1;
  248.     *p = '\0';
  249.  
  250.     rmdir(dir);
  251. }
  252.  
  253. /*
  254.  * Create a new file, with suggested filename "fname".
  255.  * "fname" may have come from an insecure source, so clean it up first.
  256.  * It may also be null.
  257.  * "contentType" is passed in for use by systems that have typed filesystems.
  258.  * "flags" contains a bit pattern describing attributes of the new file.
  259.  */
  260. FILE *os_newtypedfile(fname, contentType, flags, contentParams)
  261. char *fname;
  262. char *contentType;
  263. int flags;
  264. params contentParams;
  265. {
  266.     char *p, *q, *r;
  267.     int len=0;
  268.     int fd=0;
  269.     int filesuffix=0;
  270.     int uselong=0;
  271.     static int partno=0;
  272.     char buf[256], lbuf[256];
  273.     char *descfname=0;
  274.     FILE *outfile = 0;
  275.     FILESTATUS3 FileInfoBuf;
  276.  
  277.     if (!fname) fname = "";
  278.  
  279.     /* Chop off any drive specifier, convert / to \ */
  280.     if (*fname && fname[1] == ':') fname +=2;
  281.  
  282.     for (p = fname; *p; p++) if (*p == '/') *p = '\\';
  283.  
  284.     /* If absolute path name, chop to tail */
  285.     if (*fname == '\\') {
  286.     p = strrchr(fname, '\\');
  287.     fname = p+1;
  288.     }
  289.  
  290.     /* Clean out bad characters, create directories along path */
  291.     for (p=q=r=fname; *p; p++) {
  292.     if (*p == '\\') {
  293.         if (!strncmp(p, "\\..\\", 4)) {
  294.         p[1] = p[2] = 'X';
  295.         }
  296.         *q = '\0';
  297.         if (my_mkdir(fname) == 1) {
  298.         crunch_file(r,&q);
  299.         (void) my_mkdir(fname);
  300.         }
  301.         *q++ = '\\';
  302.         r = q;
  303.     }
  304.     else if ( (len < 200) && strchr(GOODCHARS ".", *p)) {
  305.         *q++ = *p;
  306.         len++;
  307.     }
  308.     }
  309.     *q = '\0';
  310.  
  311.     if (!fname[0]) {
  312.     sprintf(buf, "part%d",++partno);
  313.     fname = buf;
  314.     }
  315.  
  316.     do {
  317.     errno = 0;
  318.     fd = open(fname, O_CREAT | O_RDWR | (overwrite_files ? O_TRUNC : O_EXCL) | 
  319.            ((flags & FILE_BINARY) ? O_BINARY : O_TEXT), S_IREAD | S_IWRITE);
  320.  
  321.     if ((fd == -1) && (errno == ENAMETOOLONG)) {
  322.         r = strrchr(fname, '\\');
  323.         if (!r) r = fname;
  324.         strcpy(lbuf,r);
  325.         uselong=1;
  326.         crunch_file(r,&q);
  327.         fd = open(fname, O_CREAT | O_RDWR | (overwrite_files ? O_TRUNC : O_EXCL) | 
  328.                ((flags & FILE_BINARY) ? O_BINARY : O_TEXT), S_IREAD | S_IWRITE);
  329.     }
  330.  
  331.     /* simulate sharing violation, if character device found */
  332.  
  333.     if (fd != -1) {
  334.         if (DosQueryFileInfo(fd, FIL_STANDARD, &FileInfoBuf, sizeof(FILESTATUS3))) {
  335.         close(fd);
  336.         fd = -1;
  337.         errno = EACCESS; 
  338.         }
  339.     }
  340.  
  341.     if ((fd == -1) && ((errno == EEXIST) || (errno == EACCESS))) {
  342.         /* chop off suffix */
  343.         if (fname != buf) {
  344.         strcpy(buf,fname);
  345.         fname=buf;
  346.         }
  347.  
  348.         r = strrchr(fname, '\\');
  349.         if (!r) r = fname;
  350.         q = strchr(r, '.');
  351.         if (q) {
  352.         if (*q) *q = '\0';
  353.         }
  354.         q = fname + strlen(fname);
  355.         sprintf(q, ".%d", ++filesuffix);
  356.         errno = 0;
  357.     } 
  358.     } while ((fd == -1) && (!errno));
  359.  
  360.     if (fd == -1) {
  361.     perror(fname);
  362.     } else {
  363.  
  364.     if (uselong) EA_attach(fd,".LONGNAME",lbuf);
  365.     if (mime_eas) EA_attach(fd,"MIME-TYPE",contentType);
  366.     outfile = fdopen(fd, (flags & FILE_BINARY) ? "wb" : "w");
  367.     if (!outfile) {
  368.         close(fd);
  369.         perror(fname);
  370.     }
  371.     }
  372.  
  373.     if (output_fname) free(output_fname);
  374.     output_fname = strsave(fname);
  375.  
  376.     if (strlen(fname) > sizeof(buf)-6) {
  377.     descfname = xmalloc(strlen(fname)+6);
  378.     }
  379.     else {
  380.     descfname = buf;
  381.     }
  382.     strcpy(descfname, fname);
  383.  
  384.     p = strrchr(descfname, '\\');
  385.     if (!p) p = descfname;
  386.     if (p = strrchr(p, '.')) *p = '\0';
  387.  
  388.     strcat(descfname, ".dsc");
  389.     (void) rename(TEMPFILENAME, descfname);
  390.     if (descfname != buf) free(descfname);
  391.     
  392.     fprintf(stdout, "%s (%s)\n", output_fname, contentType);
  393.     didchat = 1;
  394.  
  395.     return outfile;
  396. }
  397.  
  398. /*
  399.  * Close a file opened by os_newTypedFile()
  400.  */
  401. os_closetypedfile(outfile)
  402. FILE *outfile;
  403. {
  404.     fclose(outfile);
  405. }
  406.  
  407. /*
  408.  * (Don't) Handle a BinHex'ed file
  409.  */
  410. int
  411. os_binhex(infile, part, nparts)
  412. FILE *infile;
  413. int part;
  414. int nparts;
  415. {
  416.     return 1;
  417. }
  418.  
  419. /*
  420.  * Warn user that the MD5 digest of the last file created by os_newtypedfile()
  421.  * did not match that supplied in the Content-MD5: header.
  422.  */
  423. os_warnMD5mismatch()
  424. {
  425.     char *warning;
  426.  
  427.     warning = xmalloc(strlen(output_fname) + 100);
  428.     sprintf(warning, "%s was corrupted in transit",
  429.         output_fname);
  430.     warn(warning);
  431.     free(warning);
  432. }
  433.  
  434. /*
  435.  * Report an error (in errno) concerning a filename
  436.  */
  437. os_perror(file)
  438. char *file;
  439. {
  440.     perror(file);
  441. }
  442.