ftp.nice.ch/pub/next/tools/archiver/Opener.3.4b.Utils.s.tar.gz#/Opener.3.4a.Utils.s/mpack/os2os.c

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

/* (C) Copyright 1993,1994 by Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify, distribute, and sell this software
 * and its documentation for any purpose is hereby granted without
 * fee, provided that the above copyright notice appear in all copies
 * and that both that copyright notice and this permission notice
 * appear in supporting documentation, and that the name of Carnegie
 * Mellon University not be used in advertising or publicity
 * pertaining to distribution of the software without specific,
 * written prior permission.  Carnegie Mellon University makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied
 * warranty.
 *
 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */
#define INCL_DOSFILEMGR
#define INCL_DOSERRORS
#include <os2.h>
#include <stdio.h>
#include <io.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "xmalloc.h"
#include "common.h"

#ifdef __EMX__		/* This is for EMX + GCC */

#define EACCESS EACCES



#else			/* This is for IBM C++ */

#include <direct.h>
#define ENAMETOOLONG EOS2ERR

#endif			/* EMX or IBM CSet++ */

int overwrite_files = 0;
int didchat;
int mime_eas = 0;

/* The name of the file we're writing */
static char *output_fname = 0;

/* Characters that can be in filenames */
#define GOODCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" \
                  "0123456789-_^$~!#%&{}@`'()"

int my_mkdir(char *filename)
{
    PEAOP2 EABuf;
    APIRET rc;

    EABuf = 0;
    rc = DosCreateDir(filename,EABuf);
    
    switch (rc) {
	case NO_ERROR: 
	    return 0;
	case ERROR_FILENAME_EXCED_RANGE:
	    errno = EACCESS;
	    return 1;
	case ERROR_PATH_NOT_FOUND:
	    errno = ENOENT;
	    return -1;
	default:
	    errno = EACCESS;
	    return -1;
    }
}

void crunch_file(char *p, char **q)
{
    int len, sawdot;

    for (*q=p, len=sawdot=0; *p; p++) {
	if (*p == '.') {
	    if (!sawdot) {
		*(*q)++ = '.';
		sawdot++;
		len = 0;
	    }
	} else if (len < (sawdot ? 3:8)) {
	    *(*q)++ = *p;
	    len++;
	}
    }
    **q = '\0';
}

typedef struct
{
    ULONG cbList;
    ULONG oNext;
    BYTE fEA;
    BYTE cbName;
    USHORT cbValue;
    BYTE NameBuffer[CCHMAXPATH*2+8];
}
FEALST;

void EA_attach(int fd, char *name, char *value)
{
    EAOP2 eaop;
    FEALST fealst;
    int len;

    eaop.fpFEA2List = (PFEA2LIST) &fealst;
    eaop.fpGEA2List = NULL;
    eaop.oError = 0;

    fealst.oNext = 0;
    fealst.fEA = 0;

    fealst.cbName = strlen(name) ;
    fealst.cbValue = strlen(value) +4;

    len = fealst.cbName +1;
    strcpy(fealst.NameBuffer,name);

    *((USHORT *) &(fealst.NameBuffer [len])) = 0xFFFD;
    len += sizeof(USHORT);
    *((USHORT *) &(fealst.NameBuffer [len])) = strlen(value);
    len += sizeof(USHORT);
    strcpy(&(fealst.NameBuffer[len]), value);

    fealst.cbList = fealst.cbName+fealst.cbValue+9;
  
    DosSetFileInfo(fd, FIL_QUERYEASIZE, &eaop, sizeof(eaop));
}

/* Generate a message-id */
char *os_genid()
{
    static time_t curtime;
    static char *hostname;
    static char *domain;
    char *result;

    if (curtime == 0) {
	time(&curtime);

	hostname = getenv("HOSTNAME");
	if (!hostname) hostname="random-pc";
	domain = getenv("DOMAINNAME");
	if (!domain) domain="random-domain";
    }

    if (strchr(hostname,'.')) {
	result = xmalloc(25+strlen(hostname));
	sprintf(result, "%lu@%s", curtime++, hostname);
    } else {
	if (domain[0] == '.') domain++;
	result = xmalloc(25+strlen(hostname)+strlen(domain));
	sprintf(result, "%lu@%s.%s", curtime++, hostname, domain);
    }
    return result;
}

/* Create and return directory for a message-id */
char *os_idtodir(id)
char *id;
{
    static char buf[512];
    int len = 0;
    int cs = 0;
    int rc;
    char *p, *q;

    if (p = getenv("TMP")) {
	strncpy(buf, p, 201);
	p[200] = '\0';		/* Ensure sufficiently short */
    }
    else {
	strcpy(buf, "\\tmp");
	(void)my_mkdir(buf);
    }
    if (buf[strlen(buf)-1] != '\\')
	strcat(buf, "\\");

    strcat(buf, "parts");
    (void)my_mkdir(buf);

    p = buf + strlen(buf);
    *p++ = '\\';
    q = p;

    while (*id && len < 200) {
	if (strchr(GOODCHARS, *id)) {
	    *p++ = *id;
            len++;
	    cs += *id * len;
	}
	id++;
    }
    *p = '\0';
    rc = my_mkdir(buf);
    if (rc == 1) {
	char csarr[] = GOODCHARS;
	/* maybe 8.3 restriction. Take 8 char + 3 checksum */
	p = q;
	len = 0;
	while ( *p && len < 8) { len++; p++; }
	*p++ = '.';
	*p++ = csarr[cs % sizeof(csarr)]; 
	cs = cs / sizeof(csarr);
	*p++ = csarr[cs % sizeof(csarr)]; 
	cs = cs / sizeof(csarr);
	*p++ = csarr[cs % sizeof(csarr)];
	*p = '\0';
	rc = my_mkdir(buf);
    }
    if ((rc == -1) && (errno != EACCESS)) {
	perror(buf);
	return 0;
    }
    *p++ = '\\';
    *p = '\0';
    return buf;
}

/*
 * We are done with the directory returned by os_idtodir()
 * Remove it
 */
os_donewithdir(dir)
char *dir;
{
    char *p;

    /* Remove trailing slash */
    p = dir + strlen(dir) - 1;
    *p = '\0';

    rmdir(dir);
}

/*
 * Create a new file, with suggested filename "fname".
 * "fname" may have come from an insecure source, so clean it up first.
 * It may also be null.
 * "contentType" is passed in for use by systems that have typed filesystems.
 * "flags" contains a bit pattern describing attributes of the new file.
 */
FILE *os_newtypedfile(fname, contentType, flags, contentParams)
char *fname;
char *contentType;
int flags;
params contentParams;
{
    char *p, *q, *r;
    int len=0;
    int fd=0;
    int filesuffix=0;
    int uselong=0;
    static int partno=0;
    char buf[256], lbuf[256];
    char *descfname=0;
    FILE *outfile = 0;
    FILESTATUS3 FileInfoBuf;

    if (!fname) fname = "";

    /* Chop off any drive specifier, convert / to \ */
    if (*fname && fname[1] == ':') fname +=2;

    for (p = fname; *p; p++) if (*p == '/') *p = '\\';

    /* If absolute path name, chop to tail */
    if (*fname == '\\') {
	p = strrchr(fname, '\\');
	fname = p+1;
    }

    /* Clean out bad characters, create directories along path */
    for (p=q=r=fname; *p; p++) {
	if (*p == '\\') {
	    if (!strncmp(p, "\\..\\", 4)) {
		p[1] = p[2] = 'X';
	    }
	    *q = '\0';
	    if (my_mkdir(fname) == 1) {
		crunch_file(r,&q);
		(void) my_mkdir(fname);
	    }
	    *q++ = '\\';
	    r = q;
	}
	else if ( (len < 200) && strchr(GOODCHARS ".", *p)) {
	    *q++ = *p;
	    len++;
	}
    }
    *q = '\0';

    if (!fname[0]) {
	sprintf(buf, "part%d",++partno);
	fname = buf;
    }

    do {
	errno = 0;
	fd = open(fname, O_CREAT | O_RDWR | (overwrite_files ? O_TRUNC : O_EXCL) | 
		   ((flags & FILE_BINARY) ? O_BINARY : O_TEXT), S_IREAD | S_IWRITE);

	if ((fd == -1) && (errno == ENAMETOOLONG)) {
	    r = strrchr(fname, '\\');
	    if (!r) r = fname;
	    strcpy(lbuf,r);
	    uselong=1;
	    crunch_file(r,&q);
	    fd = open(fname, O_CREAT | O_RDWR | (overwrite_files ? O_TRUNC : O_EXCL) | 
		       ((flags & FILE_BINARY) ? O_BINARY : O_TEXT), S_IREAD | S_IWRITE);
	}

	/* simulate sharing violation, if character device found */

	if (fd != -1) {
	    if (DosQueryFileInfo(fd, FIL_STANDARD, &FileInfoBuf, sizeof(FILESTATUS3))) {
		close(fd);
		fd = -1;
		errno = EACCESS; 
	    }
	}

	if ((fd == -1) && ((errno == EEXIST) || (errno == EACCESS))) {
	    /* chop off suffix */
	    if (fname != buf) {
		strcpy(buf,fname);
		fname=buf;
	    }

	    r = strrchr(fname, '\\');
	    if (!r) r = fname;
	    q = strchr(r, '.');
	    if (q) {
		if (*q) *q = '\0';
	    }
	    q = fname + strlen(fname);
	    sprintf(q, ".%d", ++filesuffix);
	    errno = 0;
	} 
    } while ((fd == -1) && (!errno));

    if (fd == -1) {
	perror(fname);
    } else {

	if (uselong) EA_attach(fd,".LONGNAME",lbuf);
	if (mime_eas) EA_attach(fd,"MIME-TYPE",contentType);
	outfile = fdopen(fd, (flags & FILE_BINARY) ? "wb" : "w");
	if (!outfile) {
	    close(fd);
	    perror(fname);
	}
    }

    if (output_fname) free(output_fname);
    output_fname = strsave(fname);

    if (strlen(fname) > sizeof(buf)-6) {
	descfname = xmalloc(strlen(fname)+6);
    }
    else {
	descfname = buf;
    }
    strcpy(descfname, fname);

    p = strrchr(descfname, '\\');
    if (!p) p = descfname;
    if (p = strrchr(p, '.')) *p = '\0';

    strcat(descfname, ".dsc");
    (void) rename(TEMPFILENAME, descfname);
    if (descfname != buf) free(descfname);
    
    fprintf(stdout, "%s (%s)\n", output_fname, contentType);
    didchat = 1;

    return outfile;
}

/*
 * Close a file opened by os_newTypedFile()
 */
os_closetypedfile(outfile)
FILE *outfile;
{
    fclose(outfile);
}

/*
 * (Don't) Handle a BinHex'ed file
 */
int
os_binhex(infile, part, nparts)
FILE *infile;
int part;
int nparts;
{
    return 1;
}

/*
 * Warn user that the MD5 digest of the last file created by os_newtypedfile()
 * did not match that supplied in the Content-MD5: header.
 */
os_warnMD5mismatch()
{
    char *warning;

    warning = xmalloc(strlen(output_fname) + 100);
    sprintf(warning, "%s was corrupted in transit",
	    output_fname);
    warn(warning);
    free(warning);
}

/*
 * Report an error (in errno) concerning a filename
 */
os_perror(file)
char *file;
{
    perror(file);
}

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