home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
TELECOM
/
xyz.lzh
/
ftdisk.c
< prev
next >
Wrap
Text File
|
1995-08-18
|
20KB
|
719 lines
/*
Printed form of this source is Copyright (C) 1995 Coriolis
Group, Inc. All rights reserved. Individual users may
make printed copies for their own personal use.
All other forms are Copyright (C) 1995 Tim Kientzle. All
rights reserved.
Redistribution in source or binary form is permitted only under
the following conditions:
1. If you own a copy of `The Working Programmer's Guide To Serial
Protocols,' then you may redistribute this code as part of
a complete application program under the conditions
described in that book. (See pages xiv, xv.) In any case,
you must abide by terms 4-7 below.
2. Otherwise, if you have received this code as a part of an
application program, it may only be redistributed with the
complete source of that program, under whatever conditions
apply to redistribution of that program as a whole.
3. If you have received this source code by some other means,
you may not redistribute it without explicit written
permission from Tim Kientzle.
4. All advertising materials mentioning features or use of this
software must prominently display the following acknowledgement:
This product is partially based on source code appearing in
`The Working Programmer's Guide to Serial Protocols,'
Copyright (C) 1995 Coriolis Group, Inc. and Tim Kientzle.
5. All programs using this source code must display the above
acknowledgement prominently in the program documentation
and user interface.
6. Neither the name of the Tim Kientzle nor the Coriolis Group, Inc.,
may be used to endorse or promote products derived from this
software without specific prior written permission.
7. Any redistribution in source form must retain the above copyright
notice, this list of conditions, and the disclaimer below.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL TIM KIENTZLE OR THE CORIOLIS GROUP BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define debugWarn (1)
#define debugDisk (1024)
#define StsRet(expr) \
do{ \
int tmpErrorVal= (expr); \
if(tmpErrorVal!=diskOK)return StsWarn(tmpErrorVal); \
}while(FALSE)
#define StsWarn(s)DiskDebugWarn(pF,(s),__FILE__,__LINE__)
#define DiskWriteEOL_CR(f)putc(CR,(f))
#define DiskWriteEOL_LF(f)putc(LF,(f))
#define DiskWriteEOL_CRLF(f)putc(CR,(f));putc(LF,(f)) \
#define DiskWriteEOL(f)DiskWriteEOL_CR(f) \
#include <stddef.h>
#include <direct.h>
#include <ctype.h>
#include <time.h>
#include <stdio.h>
#ifdef _UCC
#include <string.h>
#include <stdlib.h>
#else
#include <strings.h>
#endif
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef NULL
#define NULL ((void *)0)
#endif
#define STATIC static
#define FileExists(fname) (access(fname,0)==0)
int access (const char *name, int mode);
#include "ftdisk.h"
#define BUFFERSIZE 4096
#define SHORTBUFF 1100
#define C_NULL 0x00
#define TAB 0x09
#define LF 0x0a
#define CR 0x0d
#define SUB 0x1a
typedef struct {
FILE *f;
DEBUG debug;
int fileType;
long fileMode;
struct tm fileDate;
long fileSize;
char *fileName;
char lastChar;
char *buffer;
unsigned bufferSize;
unsigned bufferLimit;
unsigned bufferBegin;
unsigned bufferEnd;
} DISKFILE_PRIVATE;
STATIC int DiskDebugWarn
(DISKFILE_PRIVATE *pF, int s, const char *file, int line) {
const char *msg = NULL;
if (!pF->debug)
return s;
if (s != diskOK) {
DebugBeginInternal (pF->debug, debugWarn, file, line);
DebugString (pF->debug, "?!?!?!:");
}
switch (s) {
case diskOK:
return diskOK;;
case diskError:
msg = "diskError";
break;
case diskFatal:
msg = "diskFatal";
break;
case diskNoSuchFile:
msg = "diskNoSuchFile";
break;
case diskCantRead:
msg = "diskCantRead";
break;
case diskEOF:
msg = "diskEOF";
break;
}
if (msg != NULL)
DebugString (pF->debug, msg);
else {
DebugString (pF->debug, "Disk Error ");
DebugInt (pF->debug, s);
}
DebugEnd (pF->debug);
return s;
}
STATIC void DiskConvertName
(char *resultName, const char *initialName) {
char *p = resultName;
const char *q = initialName;
if (!isalpha (*q)) {
*p++ = 'x';
*p++ = '_';
}
for (; *q != '\0'; q++) {
*p = isupper (*q) ? tolower (*q) : *q;
if (!isalpha (*p) && !isdigit (*p) && (*p != '.'))
*p = '_';
p++;
}
while (*--p == '_') ;
*(++p) = '\0';
resultName[26] = '\0';
}
STATIC int DiskMakeNameUnique
(DISKFILE_PRIVATE *pF, char *fname) {
char *p;
char *dot = NULL;
for (p = fname; *p; p++) {
if (*p == '.')
dot = p;
}
p--;
while (FileExists (fname)) {
if (!dot || !isdigit (*p)) {
if (!dot) {
*++p = '.';
dot = p;
}
while (p - dot < 3)
*++p = '0';
*p = '1';
p[1] = 0;
} else {
char *p1 = p;
while ((*p1 == '9') && (p1 > fname))
*(p1--) = '0';
if ((*p1 == '.') && (p1 > fname))
p1--;
while ((*p1 == '9') && (p1 > fname))
*(p1--) = '0';
if ((*p1 == '.') && (p1 > fname))
p1--;
if ((p1 == fname) && ((*p1 == '.') || (*p1 == '9')))
return StsWarn (diskError);
if (!isdigit (*p1))
*p1 = '1';
else
(*p1)++;
}
}
return diskOK;
}
STATIC int DiskGuessType
(const char *buff, unsigned long size) {
int i;
const char *p;
register int c;
if (size == 0)
return diskFileBinary;
p = buff;
i = size;
c = ((int) *p) & 0xFF;
if ((c == C_NULL) || (c == SUB))
return diskFileBinary;
while (i-- > 0) {
c = *p++ & 0xff;
if ((c >= 0x7f)
|| ((c < 0x20) && (c != CR) && (c != LF)
&& (c != TAB) && (c != SUB) && (c != C_NULL)))
return diskFileBinary;
}
p = buff;
i = size;
while ((i > 0) && ((c = *p++) != SUB) && (c != C_NULL)) {
i--;
}
while ((i > 0) && (*p++ == c)) {
i--;
}
if (i > 0)
return diskFileBinary;
return diskFileText;
}
STATIC int DiskWriteText
(DISKFILE fPublic) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
char *p = pF->buffer;
long num = pF->bufferEnd;
char lastChar = pF->lastChar;
register int c;
for (; num; --num) {
c = *p++;
if ((c) && (c != LF) && (c != SUB) && (c != CR))
putc (c, pF->f);
else if (c == CR) {
DiskWriteEOL (pF->f);
} else if ((c == LF) && (lastChar != CR)) {
DiskWriteEOL (pF->f);
}
lastChar = c;
}
pF->lastChar = lastChar;
return diskOK;
}
STATIC int DiskWriteFlush
(DISKFILE fPublic) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
int returnVal = diskOK;
if (pF->bufferEnd == 0)
return (diskOK);
if (pF->fileType == diskFileUnknown)
pF->fileType = DiskGuessType (pF->buffer, pF->bufferEnd);
if (pF->debug) {
DebugBegin (pF->debug, debugDisk);
DebugString (pF->debug, "Flushing ");
DebugString (pF->debug, (pF->fileType >= diskFileText) ? "Text" : "Binary");
DebugString (pF->debug, " file ``");
DebugString (pF->debug, pF->fileName);
DebugString (pF->debug, "'' to disk: ");
DebugInt (pF->debug, pF->bufferEnd);
DebugString (pF->debug, "bytes.");
DebugEnd (pF->debug);
}
switch (pF->fileType) {
case diskFileBinary:
case diskFileUnknown:
if (fwrite (pF->buffer, 1, pF->bufferEnd, pF->f) != pF->bufferEnd)
returnVal = StsWarn (diskFatal);
break;
case diskFileText:
case diskFileAscii:
case diskFileLatin1:
returnVal = StsWarn (DiskWriteText (pF));
break;
default:
returnVal = StsWarn (DiskWriteText (pF));
break;
}
pF->bufferEnd = 0;
pF->bufferLimit = pF->bufferSize;
return returnVal;
}
int DiskWriteInit
(DISKFILE *pFPublic, DEBUG debug) {
DISKFILE_PRIVATE *pF;
*pFPublic = NULL;
pF = malloc (sizeof (*pF));
if (pF == NULL)
return StsWarn (diskFatal);
memset (pF, 0, sizeof (*pF));
pF->buffer = malloc (BUFFERSIZE);
if (pF->buffer == NULL) {
free (pF);
return StsWarn (diskFatal);
} {
time_t t = time (NULL);
pF->fileDate = *localtime (&t);
}
pF->fileType = diskFileUnknown;
pF->fileMode = 0;
pF->fileSize = 0;
pF->bufferSize = BUFFERSIZE;
pF->bufferLimit = SHORTBUFF;
pF->bufferBegin = pF->bufferEnd = 0;
pF->debug = debug;
*pFPublic = pF;
return diskOK;
}
int DiskWriteName
(DISKFILE fPublic, const char *preferredName) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
char fileName[256];
if (pF->debug) {
DebugBegin (pF->debug, debugDisk);
DebugString (pF->debug, "DiskWriteName(``");
DebugString (pF->debug, preferredName);
DebugString (pF->debug, "'')");
DebugEnd (pF->debug);
}
DiskConvertName (fileName, preferredName);
pF->fileName = malloc (strlen (fileName) + 1);
if (pF->fileName == NULL) {
return StsWarn (diskFatal);
}
strcpy (pF->fileName, fileName);
return diskOK;
}
int DiskWriteSize
(DISKFILE fPublic, long fileSize) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
if (pF->debug) {
DebugBegin (pF->debug, debugDisk);
DebugString (pF->debug, "DiskWriteSize(");
DebugInt (pF->debug, fileSize);
DebugString (pF->debug, ")");
DebugEnd (pF->debug);
}
pF->fileSize = fileSize;
return diskOK;
}
int DiskWriteDate
(DISKFILE fPublic, struct tm *pFileDate) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
if (pF->debug) {
DebugBegin (pF->debug, debugDisk);
DebugString (pF->debug, "DiskWriteDate");
DebugEnd (pF->debug);
}
pF->fileDate = *pFileDate;
return diskOK;
}
int DiskWriteMode
(DISKFILE fPublic, long fileMode) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
if (pF->debug) {
DebugBegin (pF->debug, debugDisk);
DebugString (pF->debug, "DiskWriteMode(");
DebugIntHex (pF->debug, fileMode);
DebugString (pF->debug, ")");
DebugEnd (pF->debug);
}
pF->fileMode = fileMode;
return diskOK;
}
int DiskWriteType
(DISKFILE fPublic, int fileType) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
if (pF->debug) {
DebugBegin (pF->debug, debugDisk);
DebugString (pF->debug, "DiskWriteType(");
DebugInt (pF->debug, fileType);
DebugString (pF->debug, ")");
DebugEnd (pF->debug);
}
pF->fileType = fileType;
return diskOK;
}
int DiskWriteOpen
(DISKFILE fPublic) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
char fileName[256];
strcpy (fileName, pF->fileName);
StsRet (DiskMakeNameUnique (pF, fileName));
free (pF->fileName);
pF->fileName = malloc (strlen (fileName) + 1);
if (pF->fileName == NULL) {
free (pF->buffer);
free (pF);
return StsWarn (diskFatal);
}
strcpy (pF->fileName, fileName);
if (pF->debug) {
DebugBegin (pF->debug, debugDisk);
DebugString (pF->debug, "DiskWriteOpen: opening ``");
DebugString (pF->debug, pF->fileName);
DebugString (pF->debug, "''");
DebugEnd (pF->debug);
}
return DiskReplaceOpen (fPublic);
}
int DiskReplaceOpen
(DISKFILE fPublic) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
if (pF->debug) {
DebugBegin (pF->debug, debugDisk);
DebugString (pF->debug, "DiskReplaceOpen: replacing ``");
DebugString (pF->debug, pF->fileName);
DebugString (pF->debug, "''");
DebugEnd (pF->debug);
}
pF->f = fopen (pF->fileName, "w");
if (pF->f == NULL) {
free (pF->buffer);
free (pF->fileName);
free (pF);
return StsWarn (diskError);
}
return diskOK;
}
int DiskAppendOpen
(DISKFILE fPublic) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
if (pF->debug) {
DebugBegin (pF->debug, debugDisk);
DebugString (pF->debug, "DiskAppendOpen: opening ``");
DebugString (pF->debug, pF->fileName);
DebugString (pF->debug, "''");
DebugEnd (pF->debug);
}
pF->f = fopen (pF->fileName, "w+");
if (pF->f == NULL) {
free (pF->buffer);
free (pF->fileName);
free (pF);
return StsWarn (diskError);
}
return diskOK;
}
int DiskWrite
(DISKFILE fPublic, const void *buff, unsigned long cnt) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
const char *pSource = (const char *) buff;
unsigned long size;
while (cnt > 0) {
if ((pF->bufferEnd + cnt) > pF->bufferLimit)
StsRet (DiskWriteFlush (pF));
if ((pF->bufferEnd + cnt) > pF->bufferLimit)
size = pF->bufferLimit - pF->bufferEnd - 1;
else
size = cnt;
memcpy (pF->buffer + pF->bufferEnd, pSource, size);
cnt -= size;
pSource += size;
pF->bufferEnd += size;
}
return diskOK;
}
int DiskWriteClose
(DISKFILE fPublic) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
int returnVal = diskOK;
returnVal = StsWarn (DiskWriteFlush (pF));
if (pF->debug) {
DebugBegin (pF->debug, debugDisk);
DebugString (pF->debug, "DiskWriteClose: closing ``");
DebugString (pF->debug, pF->fileName);
DebugString (pF->debug, "''");
DebugEnd (pF->debug);
}
if ((returnVal == diskOK) && (fclose (pF->f)))
returnVal = StsWarn (diskError);
if (pF->buffer != NULL)
free (pF->buffer);
if (pF->fileName != NULL)
free (pF->fileName);
free (pF);
return returnVal;
}
STATIC void DiskCopyText
(char *dest, unsigned *pDestSize,
const char *source, unsigned sourceSize,
char *pLastChar) {
char lastChar = *pLastChar;
const char *p = source;
char *q = dest;
int c;
for (; sourceSize; --sourceSize) {
c = *p++;
if ((c) && (c != LF) && (c != SUB) && (c != CR))
*q++ = c;
else if (c == CR) {
*q++ = CR;
*q++ = LF;
} else if ((c == LF) && (lastChar != CR)) {
*q++ = CR;
*q++ = LF;
}
lastChar = c;
}
*pLastChar = lastChar;
*pDestSize = q - dest;
}
STATIC char diskReadBuff[BUFFERSIZE];
STATIC int DiskReadFillBuffer
(DISKFILE fPublic) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
if (pF->fileType >= diskFileText) {
unsigned sizeRead;
sizeRead = fread (diskReadBuff, 1, pF->bufferSize / 2, pF->f);
pF->bufferBegin = 0;
if (sizeRead == 0) {
pF->bufferEnd = 0;
return diskEOF;
} else {
DiskCopyText (pF->buffer, &(pF->bufferEnd), diskReadBuff, sizeRead,
&(pF->lastChar));
}
} else {
pF->bufferEnd = fread (pF->buffer, 1, pF->bufferSize, pF->f);
pF->bufferBegin = 0;
if (pF->bufferEnd == 0)
return diskEOF;
}
return diskOK;
}
int DiskReadOpen
(DISKFILE *pFPublic, const char *name, int fileType) {
DISKFILE_PRIVATE *pF;
*pFPublic = NULL;
pF = malloc (sizeof (*pF));
if (pF == NULL)
return StsWarn (diskFatal);
memset (pF, 0, sizeof (*pF));
pF->buffer = malloc (BUFFERSIZE);
if (pF->buffer == NULL) {
free (pF);
return StsWarn (diskFatal);
}
pF->bufferSize = BUFFERSIZE;
pF->bufferLimit = SHORTBUFF;
pF->bufferBegin = pF->bufferEnd = 0;
pF->f = fopen (name, "r");
if (pF->f == NULL) {
free (pF);
return StsWarn (diskNoSuchFile);
}
pF->fileMode = -1;
pF->fileSize = -1;
{
time_t t = time (NULL);
pF->fileDate = *localtime (&t);
}
pF->fileName = malloc (strlen (name) + 1);
if (pF->fileName == NULL) {
free (pF);
return StsWarn (diskFatal);
}
strcpy (pF->fileName, name);
pF->fileType = fileType;
if (pF->fileType == diskFileUnknown) {
unsigned sizeRead;
sizeRead = fread (diskReadBuff, 1, pF->bufferSize / 2, pF->f);
pF->fileType = DiskGuessType (diskReadBuff, sizeRead);
pF->lastChar = 0;
if (pF->fileType >= diskFileText)
DiskCopyText (pF->buffer, &(pF->bufferEnd), diskReadBuff, sizeRead,
&(pF->lastChar));
else {
memcpy (pF->buffer, diskReadBuff, sizeRead);
pF->bufferEnd = sizeRead;
}
} {
int _gs_gfd (int path, struct fildes *buffer, int count);
struct fildes fd;
_gs_gfd (fileno (pF->f), &fd, sizeof (fd));
{
unsigned char *p = (unsigned char *) fd.fd_fsize;
pF->fileSize = *p++;
pF->fileSize = pF->fileSize * 256 + *p++;
pF->fileSize = pF->fileSize * 256 + *p++;
pF->fileSize = pF->fileSize * 256 + *p++;
}
{
pF->fileDate.tm_year = fd.fd_date[0];
pF->fileDate.tm_mon = fd.fd_date[1] - 1;
pF->fileDate.tm_mday = fd.fd_date[2];
pF->fileDate.tm_hour = fd.fd_date[3];
pF->fileDate.tm_min = fd.fd_date[4];
pF->fileDate.tm_sec = fd.fd_date[5];
}
pF->fileMode = (fd.fd_att & 070 >> 3)
| ((fd.fd_att & 070))
| ((fd.fd_att & 070) << 3);
}
*pFPublic = pF;
return diskOK;
}
int DiskRead
(DISKFILE fPublic, void *buff,
unsigned long requestedSize, unsigned long *pSizeRead) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
char *cbuff = buff;
int err;
*pSizeRead = 0;
if (requestedSize == 0)
return diskOK;
while (requestedSize > 0) {
unsigned bufferSize = pF->bufferEnd - pF->bufferBegin;
if (requestedSize >= bufferSize) {
memcpy (cbuff, pF->buffer + pF->bufferBegin, bufferSize);
requestedSize -= bufferSize;
*pSizeRead += bufferSize;
cbuff += bufferSize;
err = DiskReadFillBuffer (pF);
if (err == diskEOF)
break;
if (err != diskOK)
return err;
} else {
memcpy (cbuff, pF->buffer + pF->bufferBegin, requestedSize);
*pSizeRead += requestedSize;
pF->bufferBegin += requestedSize;
requestedSize = 0;
}
}
if (*pSizeRead == 0)
return diskEOF;
return diskOK;
}
int DiskReadClose
(DISKFILE fPublic) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
int returnVal = diskOK;
if (pF->f != NULL)
if (fclose (pF->f))
returnVal = StsWarn (diskError);
if (pF->buffer != NULL)
free (pF->buffer);
if (pF->fileName != NULL)
free (pF->fileName);
free (pF);
return returnVal;
}
int DiskFileType
(DISKFILE fPublic, int *pType) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
*pType = pF->fileType;
return 0;
}
int DiskFileMode
(DISKFILE fPublic, long *pMode) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
*pMode = pF->fileMode;
return 0;
}
int DiskFileDate
(DISKFILE fPublic, struct tm *pTm) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
*pTm = pF->fileDate;
return 0;
}
int DiskFileSize
(DISKFILE fPublic, long *pSize) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
*pSize = pF->fileSize;
return 0;
}
int DiskFileName
(DISKFILE fPublic, const char **pName) {
DISKFILE_PRIVATE *pF = (DISKFILE_PRIVATE *) fPublic;
*pName = pF->fileName;
return 0;
}