src/runtime/Files.Mod: Rewrote parts of it for avoding buffer overflows, or

safely terminating in this case ...
bootstrap/*/Files.c: 'bootstrapped' files because of the modifications in
    'src/runtime/Files.Mod' ...
This commit is contained in:
runkharr 2018-04-13 08:24:28 +02:00
parent fc9911e5f2
commit e54927e49e
6 changed files with 1113 additions and 386 deletions

View file

@ -60,6 +60,7 @@ export ADDRESS *Files_FileDesc__typ;
export ADDRESS *Files_BufDesc__typ; export ADDRESS *Files_BufDesc__typ;
export ADDRESS *Files_Rider__typ; export ADDRESS *Files_Rider__typ;
static void Files_AppendStr (CHAR *src, ADDRESS src__len, CHAR *dest, ADDRESS dest__len, INT32 *dx, BOOLEAN *done);
static void Files_Assert (BOOLEAN truth); static void Files_Assert (BOOLEAN truth);
export Files_File Files_Base (Files_Rider *r, ADDRESS *r__typ); export Files_File Files_Base (Files_Rider *r, ADDRESS *r__typ);
static Files_File Files_CacheEntry (Platform_FileIdentity identity); static Files_File Files_CacheEntry (Platform_FileIdentity identity);
@ -70,6 +71,7 @@ static void Files_Create (Files_File f);
export void Files_Delete (CHAR *name, ADDRESS name__len, INT16 *res); export void Files_Delete (CHAR *name, ADDRESS name__len, INT16 *res);
static void Files_Deregister (CHAR *name, ADDRESS name__len); static void Files_Deregister (CHAR *name, ADDRESS name__len);
static void Files_Err (CHAR *s, ADDRESS s__len, Files_File f, INT16 errcode); static void Files_Err (CHAR *s, ADDRESS s__len, Files_File f, INT16 errcode);
static void Files_ErrBO (CHAR *where, ADDRESS where__len, CHAR *culprit, ADDRESS culprit__len);
static void Files_Finalize (SYSTEM_PTR o); static void Files_Finalize (SYSTEM_PTR o);
static void Files_FlipBytes (SYSTEM_BYTE *src, ADDRESS src__len, SYSTEM_BYTE *dest, ADDRESS dest__len); static void Files_FlipBytes (SYSTEM_BYTE *src, ADDRESS src__len, SYSTEM_BYTE *dest, ADDRESS dest__len);
static void Files_Flush (Files_Buffer buf); static void Files_Flush (Files_Buffer buf);
@ -77,10 +79,12 @@ export void Files_GetDate (Files_File f, INT32 *t, INT32 *d);
export void Files_GetName (Files_File f, CHAR *name, ADDRESS name__len); export void Files_GetName (Files_File f, CHAR *name, ADDRESS name__len);
static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len); static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len);
static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len); static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len);
static void Files_IntToStr (INT32 n, CHAR *buffer, ADDRESS buffer__len);
export INT32 Files_Length (Files_File f); export INT32 Files_Length (Files_File f);
static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len); static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len);
export Files_File Files_New (CHAR *name, ADDRESS name__len); export Files_File Files_New (CHAR *name, ADDRESS name__len);
export Files_File Files_Old (CHAR *name, ADDRESS name__len); export Files_File Files_Old (CHAR *name, ADDRESS name__len);
static void Files_Peek (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x);
export INT32 Files_Pos (Files_Rider *r, ADDRESS *r__typ); export INT32 Files_Pos (Files_Rider *r, ADDRESS *r__typ);
export void Files_Purge (Files_File f); export void Files_Purge (Files_File f);
export void Files_Read (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x); export void Files_Read (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x);
@ -147,27 +151,87 @@ static void Files_Err (CHAR *s, ADDRESS s__len, Files_File f, INT16 errcode)
__DEL(s); __DEL(s);
} }
static void Files_ErrBO (CHAR *where, ADDRESS where__len, CHAR *culprit, ADDRESS culprit__len)
{
INT32 ix;
__DUP(where, where__len, CHAR);
__DUP(culprit, culprit__len, CHAR);
Out_Ln();
Out_String((CHAR*)"-- Files.", 10);
Out_String(where, where__len);
Out_String((CHAR*)": Buffer overflow (", 20);
Out_String(culprit, culprit__len);
Out_String((CHAR*)"|<", 3);
Out_String((CHAR*)")", 2);
Out_Ln();
__HALT(99);
__DEL(where);
__DEL(culprit);
}
static void Files_AppendStr (CHAR *src, ADDRESS src__len, CHAR *dest, ADDRESS dest__len, INT32 *dx, BOOLEAN *done)
{
INT32 sx;
__DUP(src, src__len, CHAR);
sx = 0;
while (src[sx] != 0x00) {
if (*dx >= dest__len - 1) {
*done = 0;
__DEL(src);
return;
}
dest[*dx] = src[sx];
*dx += 1;
sx += 1;
}
*done = 1;
__DEL(src);
}
static void Files_IntToStr (INT32 n, CHAR *buffer, ADDRESS buffer__len)
{
INT32 bx;
BOOLEAN sign;
sign = 0;
if (n < 0) {
n = -n;
sign = 1;
}
bx = buffer__len;
bx -= 1;
buffer[bx] = 0x00;
do {
if (bx > 0) {
bx -= 1;
buffer[bx] = (CHAR)((int)__MOD(n, 10) + 48);
n = __DIV(n, 10);
}
} while (!(n == 0));
if ((sign && bx > 0)) {
bx -= 1;
buffer[bx] = '-';
}
__MOVE(((ADDRESS)buffer) + bx, (ADDRESS)buffer, buffer__len - bx);
}
static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len) static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len)
{ {
INT16 i, j; INT32 i;
BOOLEAN done;
__DUP(dir, dir__len, CHAR); __DUP(dir, dir__len, CHAR);
__DUP(name, name__len, CHAR); __DUP(name, name__len, CHAR);
i = 0; i = 0;
j = 0; Files_AppendStr(dir, dir__len, (void*)dest, dest__len, &i, &done);
while (dir[i] != 0x00) { if ((done && dest[i - 1] != '/')) {
dest[i] = dir[i]; Files_AppendStr((CHAR*)"/", 2, (void*)dest, dest__len, &i, &done);
i += 1;
} }
if (dest[i - 1] != '/') { if (done) {
dest[i] = '/'; Files_AppendStr(name, name__len, (void*)dest, dest__len, &i, &done);
i += 1;
}
while (name[j] != 0x00) {
dest[i] = name[j];
i += 1;
j += 1;
} }
dest[i] = 0x00; dest[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"MakeFileName", 13, dest, dest__len);
}
__DEL(dir); __DEL(dir);
__DEL(name); __DEL(name);
} }
@ -175,50 +239,42 @@ static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS
static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len) static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len)
{ {
INT32 n, i, j; INT32 n, i, j;
CHAR numBuffer[40];
BOOLEAN done;
__DUP(finalName, finalName__len, CHAR); __DUP(finalName, finalName__len, CHAR);
Files_tempno += 1; Files_tempno += 1;
n = Files_tempno; n = Files_tempno;
i = 0; i = 0;
done = 1;
if (finalName[0] != '/') { if (finalName[0] != '/') {
while (Platform_CWD[i] != 0x00) { Files_AppendStr(Platform_CWD, 256, (void*)name, name__len, &i, &done);
name[i] = Platform_CWD[i]; if ((done && name[i - 1] != '/')) {
i += 1; Files_AppendStr((CHAR*)"/", 2, (void*)name, name__len, &i, &done);
}
if (Platform_CWD[i - 1] != '/') {
name[i] = '/';
i += 1;
} }
} }
j = 0; if (done) {
while (finalName[j] != 0x00) { Files_AppendStr(finalName, finalName__len, (void*)name, name__len, &i, &done);
name[i] = finalName[j];
i += 1;
j += 1;
} }
if (done) {
i -= 1; i -= 1;
while (name[i] != '/') { while (name[i] != '/') {
i -= 1; i -= 1;
} }
name[i + 1] = '.';
name[i + 2] = 't';
name[i + 3] = 'm';
name[i + 4] = 'p';
name[i + 5] = '.';
i += 6;
while (n > 0) {
name[i] = (CHAR)((int)__MOD(n, 10) + 48);
n = __DIV(n, 10);
i += 1; i += 1;
Files_AppendStr((CHAR*)".tmp.", 6, (void*)name, name__len, &i, &done);
} }
name[i] = '.'; if (done) {
i += 1; Files_IntToStr(Files_tempno, (void*)numBuffer, 40);
n = Platform_PID; Files_AppendStr(numBuffer, 40, (void*)name, name__len, &i, &done);
while (n > 0) { }
name[i] = (CHAR)((int)__MOD(n, 10) + 48); if (done) {
n = __DIV(n, 10); Files_IntToStr(Platform_PID, (void*)numBuffer, 40);
i += 1; Files_AppendStr(numBuffer, 40, (void*)name, name__len, &i, &done);
} }
name[i] = 0x00; name[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"GetTempName", 12, name, name__len);
}
__DEL(finalName); __DEL(finalName);
} }
@ -349,13 +405,15 @@ Files_File Files_New (CHAR *name, ADDRESS name__len)
static void Files_ScanPath (INT16 *pos, CHAR *dir, ADDRESS dir__len) static void Files_ScanPath (INT16 *pos, CHAR *dir, ADDRESS dir__len)
{ {
INT16 i; INT32 i;
INT16 pos1;
CHAR ch; CHAR ch;
BOOLEAN done;
i = 0; i = 0;
done = 1;
if (Files_SearchPath == NIL) { if (Files_SearchPath == NIL) {
if (*pos == 0) { if (*pos == 0) {
dir[0] = '.'; Files_AppendStr((CHAR*)".", 2, (void*)dir, dir__len, &i, &done);
i = 1;
*pos += 1; *pos += 1;
} }
} else { } else {
@ -367,27 +425,35 @@ static void Files_ScanPath (INT16 *pos, CHAR *dir, ADDRESS dir__len)
if (ch == '~') { if (ch == '~') {
*pos += 1; *pos += 1;
ch = (Files_SearchPath->data)[*pos]; ch = (Files_SearchPath->data)[*pos];
while (Files_HOME[i] != 0x00) { Files_AppendStr(Files_HOME, 1024, (void*)dir, dir__len, &i, &done);
dir[i] = Files_HOME[i]; if ((((((((done && ch != '/')) && ch != 0x00)) && ch != ';')) && ch != ' ')) {
i += 1;
}
if ((((((ch != '/' && ch != 0x00)) && ch != ';')) && ch != ' ')) {
while ((i > 0 && dir[i - 1] != '/')) { while ((i > 0 && dir[i - 1] != '/')) {
i -= 1; i -= 1;
} }
} }
} }
while ((ch != 0x00 && ch != ';')) { if (done) {
while ((((done && ch != 0x00)) && ch != ';')) {
if (i >= dir__len - 1) {
done = 0;
} else {
dir[i] = ch; dir[i] = ch;
i += 1; i += 1;
*pos += 1; *pos += 1;
ch = (Files_SearchPath->data)[*pos]; ch = (Files_SearchPath->data)[*pos];
} }
}
if (done) {
while ((i > 0 && dir[i - 1] == ' ')) { while ((i > 0 && dir[i - 1] == ' ')) {
i -= 1; i -= 1;
} }
} }
}
}
dir[i] = 0x00; dir[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"ScanPath", 9, dir, dir__len);
}
} }
static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len) static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len)
@ -634,6 +700,30 @@ void Files_Read (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x)
} }
} }
static void Files_Peek (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x)
{
INT32 offset;
Files_Buffer buf = NIL;
buf = (*r).buf;
offset = (*r).offset;
if ((*r).org != buf->org) {
Files_Set(&*r, r__typ, buf->f, (*r).org + offset);
buf = (*r).buf;
offset = (*r).offset;
}
Files_Assert(offset <= buf->size);
if (offset < buf->size) {
*x = buf->data[offset];
} else if ((*r).org + offset < buf->f->len) {
Files_Set(&*r, r__typ, (*r).buf->f, (*r).org + offset);
*x = (*r).buf->data[0];
(*r).offset = 0;
} else {
*x = 0x00;
(*r).eof = 1;
}
}
void Files_ReadBytes (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x, ADDRESS x__len, INT32 n) void Files_ReadBytes (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x, ADDRESS x__len, INT32 n)
{ {
INT32 xpos, min, restInBuf, offset; INT32 xpos, min, restInBuf, offset;
@ -897,27 +987,47 @@ void Files_ReadString (Files_Rider *R, ADDRESS *R__typ, CHAR *x, ADDRESS x__len)
{ {
INT16 i; INT16 i;
CHAR ch; CHAR ch;
BOOLEAN done;
i = 0; i = 0;
do { done = 1;
Files_Read(&*R, R__typ, (void*)&ch); Files_Read(&*R, R__typ, (void*)&ch);
do {
if (i >= x__len - 1) {
done = 0;
}
x[i] = ch; x[i] = ch;
i += 1; i += 1;
} while (!(ch == 0x00)); Files_Read(&*R, R__typ, (void*)&ch);
} while (!(!done || ch == 0x00));
x[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"ReadString", 11, x, x__len);
}
} }
void Files_ReadLine (Files_Rider *R, ADDRESS *R__typ, CHAR *x, ADDRESS x__len) void Files_ReadLine (Files_Rider *R, ADDRESS *R__typ, CHAR *x, ADDRESS x__len)
{ {
INT16 i; INT16 i;
CHAR ch;
i = 0; i = 0;
if (x__len < 2) {
Files_ErrBO((CHAR*)"ReadLine", 9, (CHAR*)"*buffer too short*", 19);
}
do { do {
Files_Read(&*R, R__typ, (void*)&x[i]); Files_Read(&*R, R__typ, (void*)&ch);
x[i] = ch;
i += 1; i += 1;
} while (!(x[i - 1] == 0x00 || x[i - 1] == 0x0a)); } while (!((i >= x__len - 1 || ch == 0x00) || ch == 0x0a));
if (x[i - 1] == 0x0a) { if (x[i - 1] == 0x0d) {
if (i >= x__len - 1) {
Files_Peek(&*R, R__typ, (void*)&ch);
if (ch == 0x0a) {
i -= 1;
Files_Read(&*R, R__typ, (void*)&ch);
}
} else {
i -= 1; i -= 1;
} }
if ((i > 0 && x[i - 1] == 0x0d)) {
i -= 1;
} }
x[i] = 0x00; x[i] = 0x00;
} }

View file

@ -60,6 +60,7 @@ export ADDRESS *Files_FileDesc__typ;
export ADDRESS *Files_BufDesc__typ; export ADDRESS *Files_BufDesc__typ;
export ADDRESS *Files_Rider__typ; export ADDRESS *Files_Rider__typ;
static void Files_AppendStr (CHAR *src, ADDRESS src__len, CHAR *dest, ADDRESS dest__len, INT32 *dx, BOOLEAN *done);
static void Files_Assert (BOOLEAN truth); static void Files_Assert (BOOLEAN truth);
export Files_File Files_Base (Files_Rider *r, ADDRESS *r__typ); export Files_File Files_Base (Files_Rider *r, ADDRESS *r__typ);
static Files_File Files_CacheEntry (Platform_FileIdentity identity); static Files_File Files_CacheEntry (Platform_FileIdentity identity);
@ -70,6 +71,7 @@ static void Files_Create (Files_File f);
export void Files_Delete (CHAR *name, ADDRESS name__len, INT16 *res); export void Files_Delete (CHAR *name, ADDRESS name__len, INT16 *res);
static void Files_Deregister (CHAR *name, ADDRESS name__len); static void Files_Deregister (CHAR *name, ADDRESS name__len);
static void Files_Err (CHAR *s, ADDRESS s__len, Files_File f, INT16 errcode); static void Files_Err (CHAR *s, ADDRESS s__len, Files_File f, INT16 errcode);
static void Files_ErrBO (CHAR *where, ADDRESS where__len, CHAR *culprit, ADDRESS culprit__len);
static void Files_Finalize (SYSTEM_PTR o); static void Files_Finalize (SYSTEM_PTR o);
static void Files_FlipBytes (SYSTEM_BYTE *src, ADDRESS src__len, SYSTEM_BYTE *dest, ADDRESS dest__len); static void Files_FlipBytes (SYSTEM_BYTE *src, ADDRESS src__len, SYSTEM_BYTE *dest, ADDRESS dest__len);
static void Files_Flush (Files_Buffer buf); static void Files_Flush (Files_Buffer buf);
@ -77,10 +79,12 @@ export void Files_GetDate (Files_File f, INT32 *t, INT32 *d);
export void Files_GetName (Files_File f, CHAR *name, ADDRESS name__len); export void Files_GetName (Files_File f, CHAR *name, ADDRESS name__len);
static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len); static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len);
static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len); static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len);
static void Files_IntToStr (INT32 n, CHAR *buffer, ADDRESS buffer__len);
export INT32 Files_Length (Files_File f); export INT32 Files_Length (Files_File f);
static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len); static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len);
export Files_File Files_New (CHAR *name, ADDRESS name__len); export Files_File Files_New (CHAR *name, ADDRESS name__len);
export Files_File Files_Old (CHAR *name, ADDRESS name__len); export Files_File Files_Old (CHAR *name, ADDRESS name__len);
static void Files_Peek (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x);
export INT32 Files_Pos (Files_Rider *r, ADDRESS *r__typ); export INT32 Files_Pos (Files_Rider *r, ADDRESS *r__typ);
export void Files_Purge (Files_File f); export void Files_Purge (Files_File f);
export void Files_Read (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x); export void Files_Read (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x);
@ -147,27 +151,87 @@ static void Files_Err (CHAR *s, ADDRESS s__len, Files_File f, INT16 errcode)
__DEL(s); __DEL(s);
} }
static void Files_ErrBO (CHAR *where, ADDRESS where__len, CHAR *culprit, ADDRESS culprit__len)
{
INT32 ix;
__DUP(where, where__len, CHAR);
__DUP(culprit, culprit__len, CHAR);
Out_Ln();
Out_String((CHAR*)"-- Files.", 10);
Out_String(where, where__len);
Out_String((CHAR*)": Buffer overflow (", 20);
Out_String(culprit, culprit__len);
Out_String((CHAR*)"|<", 3);
Out_String((CHAR*)")", 2);
Out_Ln();
__HALT(99);
__DEL(where);
__DEL(culprit);
}
static void Files_AppendStr (CHAR *src, ADDRESS src__len, CHAR *dest, ADDRESS dest__len, INT32 *dx, BOOLEAN *done)
{
INT32 sx;
__DUP(src, src__len, CHAR);
sx = 0;
while (src[sx] != 0x00) {
if (*dx >= dest__len - 1) {
*done = 0;
__DEL(src);
return;
}
dest[*dx] = src[sx];
*dx += 1;
sx += 1;
}
*done = 1;
__DEL(src);
}
static void Files_IntToStr (INT32 n, CHAR *buffer, ADDRESS buffer__len)
{
INT32 bx;
BOOLEAN sign;
sign = 0;
if (n < 0) {
n = -n;
sign = 1;
}
bx = buffer__len;
bx -= 1;
buffer[bx] = 0x00;
do {
if (bx > 0) {
bx -= 1;
buffer[bx] = (CHAR)((int)__MOD(n, 10) + 48);
n = __DIV(n, 10);
}
} while (!(n == 0));
if ((sign && bx > 0)) {
bx -= 1;
buffer[bx] = '-';
}
__MOVE(((ADDRESS)buffer) + bx, (ADDRESS)buffer, buffer__len - bx);
}
static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len) static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len)
{ {
INT16 i, j; INT32 i;
BOOLEAN done;
__DUP(dir, dir__len, CHAR); __DUP(dir, dir__len, CHAR);
__DUP(name, name__len, CHAR); __DUP(name, name__len, CHAR);
i = 0; i = 0;
j = 0; Files_AppendStr(dir, dir__len, (void*)dest, dest__len, &i, &done);
while (dir[i] != 0x00) { if ((done && dest[i - 1] != '/')) {
dest[i] = dir[i]; Files_AppendStr((CHAR*)"/", 2, (void*)dest, dest__len, &i, &done);
i += 1;
} }
if (dest[i - 1] != '/') { if (done) {
dest[i] = '/'; Files_AppendStr(name, name__len, (void*)dest, dest__len, &i, &done);
i += 1;
}
while (name[j] != 0x00) {
dest[i] = name[j];
i += 1;
j += 1;
} }
dest[i] = 0x00; dest[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"MakeFileName", 13, dest, dest__len);
}
__DEL(dir); __DEL(dir);
__DEL(name); __DEL(name);
} }
@ -175,50 +239,42 @@ static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS
static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len) static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len)
{ {
INT32 n, i, j; INT32 n, i, j;
CHAR numBuffer[40];
BOOLEAN done;
__DUP(finalName, finalName__len, CHAR); __DUP(finalName, finalName__len, CHAR);
Files_tempno += 1; Files_tempno += 1;
n = Files_tempno; n = Files_tempno;
i = 0; i = 0;
done = 1;
if (finalName[0] != '/') { if (finalName[0] != '/') {
while (Platform_CWD[i] != 0x00) { Files_AppendStr(Platform_CWD, 256, (void*)name, name__len, &i, &done);
name[i] = Platform_CWD[i]; if ((done && name[i - 1] != '/')) {
i += 1; Files_AppendStr((CHAR*)"/", 2, (void*)name, name__len, &i, &done);
}
if (Platform_CWD[i - 1] != '/') {
name[i] = '/';
i += 1;
} }
} }
j = 0; if (done) {
while (finalName[j] != 0x00) { Files_AppendStr(finalName, finalName__len, (void*)name, name__len, &i, &done);
name[i] = finalName[j];
i += 1;
j += 1;
} }
if (done) {
i -= 1; i -= 1;
while (name[i] != '/') { while (name[i] != '/') {
i -= 1; i -= 1;
} }
name[i + 1] = '.';
name[i + 2] = 't';
name[i + 3] = 'm';
name[i + 4] = 'p';
name[i + 5] = '.';
i += 6;
while (n > 0) {
name[i] = (CHAR)((int)__MOD(n, 10) + 48);
n = __DIV(n, 10);
i += 1; i += 1;
Files_AppendStr((CHAR*)".tmp.", 6, (void*)name, name__len, &i, &done);
} }
name[i] = '.'; if (done) {
i += 1; Files_IntToStr(Files_tempno, (void*)numBuffer, 40);
n = Platform_PID; Files_AppendStr(numBuffer, 40, (void*)name, name__len, &i, &done);
while (n > 0) { }
name[i] = (CHAR)((int)__MOD(n, 10) + 48); if (done) {
n = __DIV(n, 10); Files_IntToStr(Platform_PID, (void*)numBuffer, 40);
i += 1; Files_AppendStr(numBuffer, 40, (void*)name, name__len, &i, &done);
} }
name[i] = 0x00; name[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"GetTempName", 12, name, name__len);
}
__DEL(finalName); __DEL(finalName);
} }
@ -349,13 +405,15 @@ Files_File Files_New (CHAR *name, ADDRESS name__len)
static void Files_ScanPath (INT16 *pos, CHAR *dir, ADDRESS dir__len) static void Files_ScanPath (INT16 *pos, CHAR *dir, ADDRESS dir__len)
{ {
INT16 i; INT32 i;
INT16 pos1;
CHAR ch; CHAR ch;
BOOLEAN done;
i = 0; i = 0;
done = 1;
if (Files_SearchPath == NIL) { if (Files_SearchPath == NIL) {
if (*pos == 0) { if (*pos == 0) {
dir[0] = '.'; Files_AppendStr((CHAR*)".", 2, (void*)dir, dir__len, &i, &done);
i = 1;
*pos += 1; *pos += 1;
} }
} else { } else {
@ -367,27 +425,35 @@ static void Files_ScanPath (INT16 *pos, CHAR *dir, ADDRESS dir__len)
if (ch == '~') { if (ch == '~') {
*pos += 1; *pos += 1;
ch = (Files_SearchPath->data)[*pos]; ch = (Files_SearchPath->data)[*pos];
while (Files_HOME[i] != 0x00) { Files_AppendStr(Files_HOME, 1024, (void*)dir, dir__len, &i, &done);
dir[i] = Files_HOME[i]; if ((((((((done && ch != '/')) && ch != 0x00)) && ch != ';')) && ch != ' ')) {
i += 1;
}
if ((((((ch != '/' && ch != 0x00)) && ch != ';')) && ch != ' ')) {
while ((i > 0 && dir[i - 1] != '/')) { while ((i > 0 && dir[i - 1] != '/')) {
i -= 1; i -= 1;
} }
} }
} }
while ((ch != 0x00 && ch != ';')) { if (done) {
while ((((done && ch != 0x00)) && ch != ';')) {
if (i >= dir__len - 1) {
done = 0;
} else {
dir[i] = ch; dir[i] = ch;
i += 1; i += 1;
*pos += 1; *pos += 1;
ch = (Files_SearchPath->data)[*pos]; ch = (Files_SearchPath->data)[*pos];
} }
}
if (done) {
while ((i > 0 && dir[i - 1] == ' ')) { while ((i > 0 && dir[i - 1] == ' ')) {
i -= 1; i -= 1;
} }
} }
}
}
dir[i] = 0x00; dir[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"ScanPath", 9, dir, dir__len);
}
} }
static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len) static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len)
@ -634,6 +700,30 @@ void Files_Read (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x)
} }
} }
static void Files_Peek (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x)
{
INT32 offset;
Files_Buffer buf = NIL;
buf = (*r).buf;
offset = (*r).offset;
if ((*r).org != buf->org) {
Files_Set(&*r, r__typ, buf->f, (*r).org + offset);
buf = (*r).buf;
offset = (*r).offset;
}
Files_Assert(offset <= buf->size);
if (offset < buf->size) {
*x = buf->data[offset];
} else if ((*r).org + offset < buf->f->len) {
Files_Set(&*r, r__typ, (*r).buf->f, (*r).org + offset);
*x = (*r).buf->data[0];
(*r).offset = 0;
} else {
*x = 0x00;
(*r).eof = 1;
}
}
void Files_ReadBytes (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x, ADDRESS x__len, INT32 n) void Files_ReadBytes (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x, ADDRESS x__len, INT32 n)
{ {
INT32 xpos, min, restInBuf, offset; INT32 xpos, min, restInBuf, offset;
@ -897,27 +987,47 @@ void Files_ReadString (Files_Rider *R, ADDRESS *R__typ, CHAR *x, ADDRESS x__len)
{ {
INT16 i; INT16 i;
CHAR ch; CHAR ch;
BOOLEAN done;
i = 0; i = 0;
do { done = 1;
Files_Read(&*R, R__typ, (void*)&ch); Files_Read(&*R, R__typ, (void*)&ch);
do {
if (i >= x__len - 1) {
done = 0;
}
x[i] = ch; x[i] = ch;
i += 1; i += 1;
} while (!(ch == 0x00)); Files_Read(&*R, R__typ, (void*)&ch);
} while (!(!done || ch == 0x00));
x[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"ReadString", 11, x, x__len);
}
} }
void Files_ReadLine (Files_Rider *R, ADDRESS *R__typ, CHAR *x, ADDRESS x__len) void Files_ReadLine (Files_Rider *R, ADDRESS *R__typ, CHAR *x, ADDRESS x__len)
{ {
INT16 i; INT16 i;
CHAR ch;
i = 0; i = 0;
if (x__len < 2) {
Files_ErrBO((CHAR*)"ReadLine", 9, (CHAR*)"*buffer too short*", 19);
}
do { do {
Files_Read(&*R, R__typ, (void*)&x[i]); Files_Read(&*R, R__typ, (void*)&ch);
x[i] = ch;
i += 1; i += 1;
} while (!(x[i - 1] == 0x00 || x[i - 1] == 0x0a)); } while (!((i >= x__len - 1 || ch == 0x00) || ch == 0x0a));
if (x[i - 1] == 0x0a) { if (x[i - 1] == 0x0d) {
if (i >= x__len - 1) {
Files_Peek(&*R, R__typ, (void*)&ch);
if (ch == 0x0a) {
i -= 1;
Files_Read(&*R, R__typ, (void*)&ch);
}
} else {
i -= 1; i -= 1;
} }
if ((i > 0 && x[i - 1] == 0x0d)) {
i -= 1;
} }
x[i] = 0x00; x[i] = 0x00;
} }

View file

@ -60,6 +60,7 @@ export ADDRESS *Files_FileDesc__typ;
export ADDRESS *Files_BufDesc__typ; export ADDRESS *Files_BufDesc__typ;
export ADDRESS *Files_Rider__typ; export ADDRESS *Files_Rider__typ;
static void Files_AppendStr (CHAR *src, ADDRESS src__len, CHAR *dest, ADDRESS dest__len, INT32 *dx, BOOLEAN *done);
static void Files_Assert (BOOLEAN truth); static void Files_Assert (BOOLEAN truth);
export Files_File Files_Base (Files_Rider *r, ADDRESS *r__typ); export Files_File Files_Base (Files_Rider *r, ADDRESS *r__typ);
static Files_File Files_CacheEntry (Platform_FileIdentity identity); static Files_File Files_CacheEntry (Platform_FileIdentity identity);
@ -70,6 +71,7 @@ static void Files_Create (Files_File f);
export void Files_Delete (CHAR *name, ADDRESS name__len, INT16 *res); export void Files_Delete (CHAR *name, ADDRESS name__len, INT16 *res);
static void Files_Deregister (CHAR *name, ADDRESS name__len); static void Files_Deregister (CHAR *name, ADDRESS name__len);
static void Files_Err (CHAR *s, ADDRESS s__len, Files_File f, INT16 errcode); static void Files_Err (CHAR *s, ADDRESS s__len, Files_File f, INT16 errcode);
static void Files_ErrBO (CHAR *where, ADDRESS where__len, CHAR *culprit, ADDRESS culprit__len);
static void Files_Finalize (SYSTEM_PTR o); static void Files_Finalize (SYSTEM_PTR o);
static void Files_FlipBytes (SYSTEM_BYTE *src, ADDRESS src__len, SYSTEM_BYTE *dest, ADDRESS dest__len); static void Files_FlipBytes (SYSTEM_BYTE *src, ADDRESS src__len, SYSTEM_BYTE *dest, ADDRESS dest__len);
static void Files_Flush (Files_Buffer buf); static void Files_Flush (Files_Buffer buf);
@ -77,10 +79,12 @@ export void Files_GetDate (Files_File f, INT32 *t, INT32 *d);
export void Files_GetName (Files_File f, CHAR *name, ADDRESS name__len); export void Files_GetName (Files_File f, CHAR *name, ADDRESS name__len);
static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len); static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len);
static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len); static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len);
static void Files_IntToStr (INT32 n, CHAR *buffer, ADDRESS buffer__len);
export INT32 Files_Length (Files_File f); export INT32 Files_Length (Files_File f);
static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len); static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len);
export Files_File Files_New (CHAR *name, ADDRESS name__len); export Files_File Files_New (CHAR *name, ADDRESS name__len);
export Files_File Files_Old (CHAR *name, ADDRESS name__len); export Files_File Files_Old (CHAR *name, ADDRESS name__len);
static void Files_Peek (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x);
export INT32 Files_Pos (Files_Rider *r, ADDRESS *r__typ); export INT32 Files_Pos (Files_Rider *r, ADDRESS *r__typ);
export void Files_Purge (Files_File f); export void Files_Purge (Files_File f);
export void Files_Read (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x); export void Files_Read (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x);
@ -147,27 +151,87 @@ static void Files_Err (CHAR *s, ADDRESS s__len, Files_File f, INT16 errcode)
__DEL(s); __DEL(s);
} }
static void Files_ErrBO (CHAR *where, ADDRESS where__len, CHAR *culprit, ADDRESS culprit__len)
{
INT32 ix;
__DUP(where, where__len, CHAR);
__DUP(culprit, culprit__len, CHAR);
Out_Ln();
Out_String((CHAR*)"-- Files.", 10);
Out_String(where, where__len);
Out_String((CHAR*)": Buffer overflow (", 20);
Out_String(culprit, culprit__len);
Out_String((CHAR*)"|<", 3);
Out_String((CHAR*)")", 2);
Out_Ln();
__HALT(99);
__DEL(where);
__DEL(culprit);
}
static void Files_AppendStr (CHAR *src, ADDRESS src__len, CHAR *dest, ADDRESS dest__len, INT32 *dx, BOOLEAN *done)
{
INT32 sx;
__DUP(src, src__len, CHAR);
sx = 0;
while (src[sx] != 0x00) {
if (*dx >= dest__len - 1) {
*done = 0;
__DEL(src);
return;
}
dest[*dx] = src[sx];
*dx += 1;
sx += 1;
}
*done = 1;
__DEL(src);
}
static void Files_IntToStr (INT32 n, CHAR *buffer, ADDRESS buffer__len)
{
INT32 bx;
BOOLEAN sign;
sign = 0;
if (n < 0) {
n = -n;
sign = 1;
}
bx = buffer__len;
bx -= 1;
buffer[bx] = 0x00;
do {
if (bx > 0) {
bx -= 1;
buffer[bx] = (CHAR)((int)__MOD(n, 10) + 48);
n = __DIV(n, 10);
}
} while (!(n == 0));
if ((sign && bx > 0)) {
bx -= 1;
buffer[bx] = '-';
}
__MOVE((ADDRESS)buffer + (INT64)bx, (ADDRESS)buffer, buffer__len - bx);
}
static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len) static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len)
{ {
INT16 i, j; INT32 i;
BOOLEAN done;
__DUP(dir, dir__len, CHAR); __DUP(dir, dir__len, CHAR);
__DUP(name, name__len, CHAR); __DUP(name, name__len, CHAR);
i = 0; i = 0;
j = 0; Files_AppendStr(dir, dir__len, (void*)dest, dest__len, &i, &done);
while (dir[i] != 0x00) { if ((done && dest[i - 1] != '/')) {
dest[i] = dir[i]; Files_AppendStr((CHAR*)"/", 2, (void*)dest, dest__len, &i, &done);
i += 1;
} }
if (dest[i - 1] != '/') { if (done) {
dest[i] = '/'; Files_AppendStr(name, name__len, (void*)dest, dest__len, &i, &done);
i += 1;
}
while (name[j] != 0x00) {
dest[i] = name[j];
i += 1;
j += 1;
} }
dest[i] = 0x00; dest[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"MakeFileName", 13, dest, dest__len);
}
__DEL(dir); __DEL(dir);
__DEL(name); __DEL(name);
} }
@ -175,50 +239,42 @@ static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS
static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len) static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len)
{ {
INT32 n, i, j; INT32 n, i, j;
CHAR numBuffer[40];
BOOLEAN done;
__DUP(finalName, finalName__len, CHAR); __DUP(finalName, finalName__len, CHAR);
Files_tempno += 1; Files_tempno += 1;
n = Files_tempno; n = Files_tempno;
i = 0; i = 0;
done = 1;
if (finalName[0] != '/') { if (finalName[0] != '/') {
while (Platform_CWD[i] != 0x00) { Files_AppendStr(Platform_CWD, 256, (void*)name, name__len, &i, &done);
name[i] = Platform_CWD[i]; if ((done && name[i - 1] != '/')) {
i += 1; Files_AppendStr((CHAR*)"/", 2, (void*)name, name__len, &i, &done);
}
if (Platform_CWD[i - 1] != '/') {
name[i] = '/';
i += 1;
} }
} }
j = 0; if (done) {
while (finalName[j] != 0x00) { Files_AppendStr(finalName, finalName__len, (void*)name, name__len, &i, &done);
name[i] = finalName[j];
i += 1;
j += 1;
} }
if (done) {
i -= 1; i -= 1;
while (name[i] != '/') { while (name[i] != '/') {
i -= 1; i -= 1;
} }
name[i + 1] = '.';
name[i + 2] = 't';
name[i + 3] = 'm';
name[i + 4] = 'p';
name[i + 5] = '.';
i += 6;
while (n > 0) {
name[i] = (CHAR)((int)__MOD(n, 10) + 48);
n = __DIV(n, 10);
i += 1; i += 1;
Files_AppendStr((CHAR*)".tmp.", 6, (void*)name, name__len, &i, &done);
} }
name[i] = '.'; if (done) {
i += 1; Files_IntToStr(Files_tempno, (void*)numBuffer, 40);
n = Platform_PID; Files_AppendStr(numBuffer, 40, (void*)name, name__len, &i, &done);
while (n > 0) { }
name[i] = (CHAR)((int)__MOD(n, 10) + 48); if (done) {
n = __DIV(n, 10); Files_IntToStr(Platform_PID, (void*)numBuffer, 40);
i += 1; Files_AppendStr(numBuffer, 40, (void*)name, name__len, &i, &done);
} }
name[i] = 0x00; name[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"GetTempName", 12, name, name__len);
}
__DEL(finalName); __DEL(finalName);
} }
@ -349,13 +405,15 @@ Files_File Files_New (CHAR *name, ADDRESS name__len)
static void Files_ScanPath (INT16 *pos, CHAR *dir, ADDRESS dir__len) static void Files_ScanPath (INT16 *pos, CHAR *dir, ADDRESS dir__len)
{ {
INT16 i; INT32 i;
INT16 pos1;
CHAR ch; CHAR ch;
BOOLEAN done;
i = 0; i = 0;
done = 1;
if (Files_SearchPath == NIL) { if (Files_SearchPath == NIL) {
if (*pos == 0) { if (*pos == 0) {
dir[0] = '.'; Files_AppendStr((CHAR*)".", 2, (void*)dir, dir__len, &i, &done);
i = 1;
*pos += 1; *pos += 1;
} }
} else { } else {
@ -367,27 +425,35 @@ static void Files_ScanPath (INT16 *pos, CHAR *dir, ADDRESS dir__len)
if (ch == '~') { if (ch == '~') {
*pos += 1; *pos += 1;
ch = (Files_SearchPath->data)[*pos]; ch = (Files_SearchPath->data)[*pos];
while (Files_HOME[i] != 0x00) { Files_AppendStr(Files_HOME, 1024, (void*)dir, dir__len, &i, &done);
dir[i] = Files_HOME[i]; if ((((((((done && ch != '/')) && ch != 0x00)) && ch != ';')) && ch != ' ')) {
i += 1;
}
if ((((((ch != '/' && ch != 0x00)) && ch != ';')) && ch != ' ')) {
while ((i > 0 && dir[i - 1] != '/')) { while ((i > 0 && dir[i - 1] != '/')) {
i -= 1; i -= 1;
} }
} }
} }
while ((ch != 0x00 && ch != ';')) { if (done) {
while ((((done && ch != 0x00)) && ch != ';')) {
if (i >= dir__len - 1) {
done = 0;
} else {
dir[i] = ch; dir[i] = ch;
i += 1; i += 1;
*pos += 1; *pos += 1;
ch = (Files_SearchPath->data)[*pos]; ch = (Files_SearchPath->data)[*pos];
} }
}
if (done) {
while ((i > 0 && dir[i - 1] == ' ')) { while ((i > 0 && dir[i - 1] == ' ')) {
i -= 1; i -= 1;
} }
} }
}
}
dir[i] = 0x00; dir[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"ScanPath", 9, dir, dir__len);
}
} }
static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len) static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len)
@ -634,6 +700,30 @@ void Files_Read (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x)
} }
} }
static void Files_Peek (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x)
{
INT32 offset;
Files_Buffer buf = NIL;
buf = (*r).buf;
offset = (*r).offset;
if ((*r).org != buf->org) {
Files_Set(&*r, r__typ, buf->f, (*r).org + offset);
buf = (*r).buf;
offset = (*r).offset;
}
Files_Assert(offset <= buf->size);
if (offset < buf->size) {
*x = buf->data[offset];
} else if ((*r).org + offset < buf->f->len) {
Files_Set(&*r, r__typ, (*r).buf->f, (*r).org + offset);
*x = (*r).buf->data[0];
(*r).offset = 0;
} else {
*x = 0x00;
(*r).eof = 1;
}
}
void Files_ReadBytes (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x, ADDRESS x__len, INT32 n) void Files_ReadBytes (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x, ADDRESS x__len, INT32 n)
{ {
INT32 xpos, min, restInBuf, offset; INT32 xpos, min, restInBuf, offset;
@ -897,27 +987,47 @@ void Files_ReadString (Files_Rider *R, ADDRESS *R__typ, CHAR *x, ADDRESS x__len)
{ {
INT16 i; INT16 i;
CHAR ch; CHAR ch;
BOOLEAN done;
i = 0; i = 0;
do { done = 1;
Files_Read(&*R, R__typ, (void*)&ch); Files_Read(&*R, R__typ, (void*)&ch);
do {
if (i >= x__len - 1) {
done = 0;
}
x[i] = ch; x[i] = ch;
i += 1; i += 1;
} while (!(ch == 0x00)); Files_Read(&*R, R__typ, (void*)&ch);
} while (!(!done || ch == 0x00));
x[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"ReadString", 11, x, x__len);
}
} }
void Files_ReadLine (Files_Rider *R, ADDRESS *R__typ, CHAR *x, ADDRESS x__len) void Files_ReadLine (Files_Rider *R, ADDRESS *R__typ, CHAR *x, ADDRESS x__len)
{ {
INT16 i; INT16 i;
CHAR ch;
i = 0; i = 0;
if (x__len < 2) {
Files_ErrBO((CHAR*)"ReadLine", 9, (CHAR*)"*buffer too short*", 19);
}
do { do {
Files_Read(&*R, R__typ, (void*)&x[i]); Files_Read(&*R, R__typ, (void*)&ch);
x[i] = ch;
i += 1; i += 1;
} while (!(x[i - 1] == 0x00 || x[i - 1] == 0x0a)); } while (!((i >= x__len - 1 || ch == 0x00) || ch == 0x0a));
if (x[i - 1] == 0x0a) { if (x[i - 1] == 0x0d) {
if (i >= x__len - 1) {
Files_Peek(&*R, R__typ, (void*)&ch);
if (ch == 0x0a) {
i -= 1;
Files_Read(&*R, R__typ, (void*)&ch);
}
} else {
i -= 1; i -= 1;
} }
if ((i > 0 && x[i - 1] == 0x0d)) {
i -= 1;
} }
x[i] = 0x00; x[i] = 0x00;
} }

View file

@ -60,6 +60,7 @@ export ADDRESS *Files_FileDesc__typ;
export ADDRESS *Files_BufDesc__typ; export ADDRESS *Files_BufDesc__typ;
export ADDRESS *Files_Rider__typ; export ADDRESS *Files_Rider__typ;
static void Files_AppendStr (CHAR *src, ADDRESS src__len, CHAR *dest, ADDRESS dest__len, INT32 *dx, BOOLEAN *done);
static void Files_Assert (BOOLEAN truth); static void Files_Assert (BOOLEAN truth);
export Files_File Files_Base (Files_Rider *r, ADDRESS *r__typ); export Files_File Files_Base (Files_Rider *r, ADDRESS *r__typ);
static Files_File Files_CacheEntry (Platform_FileIdentity identity); static Files_File Files_CacheEntry (Platform_FileIdentity identity);
@ -70,6 +71,7 @@ static void Files_Create (Files_File f);
export void Files_Delete (CHAR *name, ADDRESS name__len, INT16 *res); export void Files_Delete (CHAR *name, ADDRESS name__len, INT16 *res);
static void Files_Deregister (CHAR *name, ADDRESS name__len); static void Files_Deregister (CHAR *name, ADDRESS name__len);
static void Files_Err (CHAR *s, ADDRESS s__len, Files_File f, INT16 errcode); static void Files_Err (CHAR *s, ADDRESS s__len, Files_File f, INT16 errcode);
static void Files_ErrBO (CHAR *where, ADDRESS where__len, CHAR *culprit, ADDRESS culprit__len);
static void Files_Finalize (SYSTEM_PTR o); static void Files_Finalize (SYSTEM_PTR o);
static void Files_FlipBytes (SYSTEM_BYTE *src, ADDRESS src__len, SYSTEM_BYTE *dest, ADDRESS dest__len); static void Files_FlipBytes (SYSTEM_BYTE *src, ADDRESS src__len, SYSTEM_BYTE *dest, ADDRESS dest__len);
static void Files_Flush (Files_Buffer buf); static void Files_Flush (Files_Buffer buf);
@ -77,10 +79,12 @@ export void Files_GetDate (Files_File f, INT32 *t, INT32 *d);
export void Files_GetName (Files_File f, CHAR *name, ADDRESS name__len); export void Files_GetName (Files_File f, CHAR *name, ADDRESS name__len);
static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len); static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len);
static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len); static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len);
static void Files_IntToStr (INT32 n, CHAR *buffer, ADDRESS buffer__len);
export INT32 Files_Length (Files_File f); export INT32 Files_Length (Files_File f);
static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len); static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len);
export Files_File Files_New (CHAR *name, ADDRESS name__len); export Files_File Files_New (CHAR *name, ADDRESS name__len);
export Files_File Files_Old (CHAR *name, ADDRESS name__len); export Files_File Files_Old (CHAR *name, ADDRESS name__len);
static void Files_Peek (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x);
export INT32 Files_Pos (Files_Rider *r, ADDRESS *r__typ); export INT32 Files_Pos (Files_Rider *r, ADDRESS *r__typ);
export void Files_Purge (Files_File f); export void Files_Purge (Files_File f);
export void Files_Read (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x); export void Files_Read (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x);
@ -147,27 +151,87 @@ static void Files_Err (CHAR *s, ADDRESS s__len, Files_File f, INT16 errcode)
__DEL(s); __DEL(s);
} }
static void Files_ErrBO (CHAR *where, ADDRESS where__len, CHAR *culprit, ADDRESS culprit__len)
{
INT32 ix;
__DUP(where, where__len, CHAR);
__DUP(culprit, culprit__len, CHAR);
Out_Ln();
Out_String((CHAR*)"-- Files.", 10);
Out_String(where, where__len);
Out_String((CHAR*)": Buffer overflow (", 20);
Out_String(culprit, culprit__len);
Out_String((CHAR*)"|<", 3);
Out_String((CHAR*)")", 2);
Out_Ln();
__HALT(99);
__DEL(where);
__DEL(culprit);
}
static void Files_AppendStr (CHAR *src, ADDRESS src__len, CHAR *dest, ADDRESS dest__len, INT32 *dx, BOOLEAN *done)
{
INT32 sx;
__DUP(src, src__len, CHAR);
sx = 0;
while (src[sx] != 0x00) {
if (*dx >= dest__len - 1) {
*done = 0;
__DEL(src);
return;
}
dest[*dx] = src[sx];
*dx += 1;
sx += 1;
}
*done = 1;
__DEL(src);
}
static void Files_IntToStr (INT32 n, CHAR *buffer, ADDRESS buffer__len)
{
INT32 bx;
BOOLEAN sign;
sign = 0;
if (n < 0) {
n = -n;
sign = 1;
}
bx = buffer__len;
bx -= 1;
buffer[bx] = 0x00;
do {
if (bx > 0) {
bx -= 1;
buffer[bx] = (CHAR)((int)__MOD(n, 10) + 48);
n = __DIV(n, 10);
}
} while (!(n == 0));
if ((sign && bx > 0)) {
bx -= 1;
buffer[bx] = '-';
}
__MOVE(((ADDRESS)buffer) + bx, (ADDRESS)buffer, buffer__len - bx);
}
static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len) static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len)
{ {
INT16 i, j; INT32 i;
BOOLEAN done;
__DUP(dir, dir__len, CHAR); __DUP(dir, dir__len, CHAR);
__DUP(name, name__len, CHAR); __DUP(name, name__len, CHAR);
i = 0; i = 0;
j = 0; Files_AppendStr(dir, dir__len, (void*)dest, dest__len, &i, &done);
while (dir[i] != 0x00) { if ((done && dest[i - 1] != '/')) {
dest[i] = dir[i]; Files_AppendStr((CHAR*)"/", 2, (void*)dest, dest__len, &i, &done);
i += 1;
} }
if (dest[i - 1] != '/') { if (done) {
dest[i] = '/'; Files_AppendStr(name, name__len, (void*)dest, dest__len, &i, &done);
i += 1;
}
while (name[j] != 0x00) {
dest[i] = name[j];
i += 1;
j += 1;
} }
dest[i] = 0x00; dest[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"MakeFileName", 13, dest, dest__len);
}
__DEL(dir); __DEL(dir);
__DEL(name); __DEL(name);
} }
@ -175,50 +239,42 @@ static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS
static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len) static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len)
{ {
INT32 n, i, j; INT32 n, i, j;
CHAR numBuffer[40];
BOOLEAN done;
__DUP(finalName, finalName__len, CHAR); __DUP(finalName, finalName__len, CHAR);
Files_tempno += 1; Files_tempno += 1;
n = Files_tempno; n = Files_tempno;
i = 0; i = 0;
done = 1;
if (finalName[0] != '/') { if (finalName[0] != '/') {
while (Platform_CWD[i] != 0x00) { Files_AppendStr(Platform_CWD, 4096, (void*)name, name__len, &i, &done);
name[i] = Platform_CWD[i]; if ((done && name[i - 1] != '/')) {
i += 1; Files_AppendStr((CHAR*)"/", 2, (void*)name, name__len, &i, &done);
}
if (Platform_CWD[i - 1] != '/') {
name[i] = '/';
i += 1;
} }
} }
j = 0; if (done) {
while (finalName[j] != 0x00) { Files_AppendStr(finalName, finalName__len, (void*)name, name__len, &i, &done);
name[i] = finalName[j];
i += 1;
j += 1;
} }
if (done) {
i -= 1; i -= 1;
while (name[i] != '/') { while (name[i] != '/') {
i -= 1; i -= 1;
} }
name[i + 1] = '.';
name[i + 2] = 't';
name[i + 3] = 'm';
name[i + 4] = 'p';
name[i + 5] = '.';
i += 6;
while (n > 0) {
name[i] = (CHAR)((int)__MOD(n, 10) + 48);
n = __DIV(n, 10);
i += 1; i += 1;
Files_AppendStr((CHAR*)".tmp.", 6, (void*)name, name__len, &i, &done);
} }
name[i] = '.'; if (done) {
i += 1; Files_IntToStr(Files_tempno, (void*)numBuffer, 40);
n = Platform_PID; Files_AppendStr(numBuffer, 40, (void*)name, name__len, &i, &done);
while (n > 0) { }
name[i] = (CHAR)((int)__MOD(n, 10) + 48); if (done) {
n = __DIV(n, 10); Files_IntToStr(Platform_PID, (void*)numBuffer, 40);
i += 1; Files_AppendStr(numBuffer, 40, (void*)name, name__len, &i, &done);
} }
name[i] = 0x00; name[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"GetTempName", 12, name, name__len);
}
__DEL(finalName); __DEL(finalName);
} }
@ -349,13 +405,15 @@ Files_File Files_New (CHAR *name, ADDRESS name__len)
static void Files_ScanPath (INT16 *pos, CHAR *dir, ADDRESS dir__len) static void Files_ScanPath (INT16 *pos, CHAR *dir, ADDRESS dir__len)
{ {
INT16 i; INT32 i;
INT16 pos1;
CHAR ch; CHAR ch;
BOOLEAN done;
i = 0; i = 0;
done = 1;
if (Files_SearchPath == NIL) { if (Files_SearchPath == NIL) {
if (*pos == 0) { if (*pos == 0) {
dir[0] = '.'; Files_AppendStr((CHAR*)".", 2, (void*)dir, dir__len, &i, &done);
i = 1;
*pos += 1; *pos += 1;
} }
} else { } else {
@ -367,27 +425,35 @@ static void Files_ScanPath (INT16 *pos, CHAR *dir, ADDRESS dir__len)
if (ch == '~') { if (ch == '~') {
*pos += 1; *pos += 1;
ch = (Files_SearchPath->data)[*pos]; ch = (Files_SearchPath->data)[*pos];
while (Files_HOME[i] != 0x00) { Files_AppendStr(Files_HOME, 1024, (void*)dir, dir__len, &i, &done);
dir[i] = Files_HOME[i]; if ((((((((done && ch != '/')) && ch != 0x00)) && ch != ';')) && ch != ' ')) {
i += 1;
}
if ((((((ch != '/' && ch != 0x00)) && ch != ';')) && ch != ' ')) {
while ((i > 0 && dir[i - 1] != '/')) { while ((i > 0 && dir[i - 1] != '/')) {
i -= 1; i -= 1;
} }
} }
} }
while ((ch != 0x00 && ch != ';')) { if (done) {
while ((((done && ch != 0x00)) && ch != ';')) {
if (i >= dir__len - 1) {
done = 0;
} else {
dir[i] = ch; dir[i] = ch;
i += 1; i += 1;
*pos += 1; *pos += 1;
ch = (Files_SearchPath->data)[*pos]; ch = (Files_SearchPath->data)[*pos];
} }
}
if (done) {
while ((i > 0 && dir[i - 1] == ' ')) { while ((i > 0 && dir[i - 1] == ' ')) {
i -= 1; i -= 1;
} }
} }
}
}
dir[i] = 0x00; dir[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"ScanPath", 9, dir, dir__len);
}
} }
static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len) static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len)
@ -634,6 +700,30 @@ void Files_Read (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x)
} }
} }
static void Files_Peek (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x)
{
INT32 offset;
Files_Buffer buf = NIL;
buf = (*r).buf;
offset = (*r).offset;
if ((*r).org != buf->org) {
Files_Set(&*r, r__typ, buf->f, (*r).org + offset);
buf = (*r).buf;
offset = (*r).offset;
}
Files_Assert(offset <= buf->size);
if (offset < buf->size) {
*x = buf->data[offset];
} else if ((*r).org + offset < buf->f->len) {
Files_Set(&*r, r__typ, (*r).buf->f, (*r).org + offset);
*x = (*r).buf->data[0];
(*r).offset = 0;
} else {
*x = 0x00;
(*r).eof = 1;
}
}
void Files_ReadBytes (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x, ADDRESS x__len, INT32 n) void Files_ReadBytes (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x, ADDRESS x__len, INT32 n)
{ {
INT32 xpos, min, restInBuf, offset; INT32 xpos, min, restInBuf, offset;
@ -897,27 +987,47 @@ void Files_ReadString (Files_Rider *R, ADDRESS *R__typ, CHAR *x, ADDRESS x__len)
{ {
INT16 i; INT16 i;
CHAR ch; CHAR ch;
BOOLEAN done;
i = 0; i = 0;
do { done = 1;
Files_Read(&*R, R__typ, (void*)&ch); Files_Read(&*R, R__typ, (void*)&ch);
do {
if (i >= x__len - 1) {
done = 0;
}
x[i] = ch; x[i] = ch;
i += 1; i += 1;
} while (!(ch == 0x00)); Files_Read(&*R, R__typ, (void*)&ch);
} while (!(!done || ch == 0x00));
x[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"ReadString", 11, x, x__len);
}
} }
void Files_ReadLine (Files_Rider *R, ADDRESS *R__typ, CHAR *x, ADDRESS x__len) void Files_ReadLine (Files_Rider *R, ADDRESS *R__typ, CHAR *x, ADDRESS x__len)
{ {
INT16 i; INT16 i;
CHAR ch;
i = 0; i = 0;
if (x__len < 2) {
Files_ErrBO((CHAR*)"ReadLine", 9, (CHAR*)"*buffer too short*", 19);
}
do { do {
Files_Read(&*R, R__typ, (void*)&x[i]); Files_Read(&*R, R__typ, (void*)&ch);
x[i] = ch;
i += 1; i += 1;
} while (!(x[i - 1] == 0x00 || x[i - 1] == 0x0a)); } while (!((i >= x__len - 1 || ch == 0x00) || ch == 0x0a));
if (x[i - 1] == 0x0a) { if (x[i - 1] == 0x0d) {
if (i >= x__len - 1) {
Files_Peek(&*R, R__typ, (void*)&ch);
if (ch == 0x0a) {
i -= 1;
Files_Read(&*R, R__typ, (void*)&ch);
}
} else {
i -= 1; i -= 1;
} }
if ((i > 0 && x[i - 1] == 0x0d)) {
i -= 1;
} }
x[i] = 0x00; x[i] = 0x00;
} }

View file

@ -61,6 +61,7 @@ export ADDRESS *Files_FileDesc__typ;
export ADDRESS *Files_BufDesc__typ; export ADDRESS *Files_BufDesc__typ;
export ADDRESS *Files_Rider__typ; export ADDRESS *Files_Rider__typ;
static void Files_AppendStr (CHAR *src, ADDRESS src__len, CHAR *dest, ADDRESS dest__len, INT32 *dx, BOOLEAN *done);
static void Files_Assert (BOOLEAN truth); static void Files_Assert (BOOLEAN truth);
export Files_File Files_Base (Files_Rider *r, ADDRESS *r__typ); export Files_File Files_Base (Files_Rider *r, ADDRESS *r__typ);
static Files_File Files_CacheEntry (Platform_FileIdentity identity); static Files_File Files_CacheEntry (Platform_FileIdentity identity);
@ -71,6 +72,7 @@ static void Files_Create (Files_File f);
export void Files_Delete (CHAR *name, ADDRESS name__len, INT16 *res); export void Files_Delete (CHAR *name, ADDRESS name__len, INT16 *res);
static void Files_Deregister (CHAR *name, ADDRESS name__len); static void Files_Deregister (CHAR *name, ADDRESS name__len);
static void Files_Err (CHAR *s, ADDRESS s__len, Files_File f, INT16 errcode); static void Files_Err (CHAR *s, ADDRESS s__len, Files_File f, INT16 errcode);
static void Files_ErrBO (CHAR *where, ADDRESS where__len, CHAR *culprit, ADDRESS culprit__len);
static void Files_Finalize (SYSTEM_PTR o); static void Files_Finalize (SYSTEM_PTR o);
static void Files_FlipBytes (SYSTEM_BYTE *src, ADDRESS src__len, SYSTEM_BYTE *dest, ADDRESS dest__len); static void Files_FlipBytes (SYSTEM_BYTE *src, ADDRESS src__len, SYSTEM_BYTE *dest, ADDRESS dest__len);
static void Files_Flush (Files_Buffer buf); static void Files_Flush (Files_Buffer buf);
@ -78,10 +80,12 @@ export void Files_GetDate (Files_File f, INT32 *t, INT32 *d);
export void Files_GetName (Files_File f, CHAR *name, ADDRESS name__len); export void Files_GetName (Files_File f, CHAR *name, ADDRESS name__len);
static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len); static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len);
static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len); static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len);
static void Files_IntToStr (INT32 n, CHAR *buffer, ADDRESS buffer__len);
export INT32 Files_Length (Files_File f); export INT32 Files_Length (Files_File f);
static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len); static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len);
export Files_File Files_New (CHAR *name, ADDRESS name__len); export Files_File Files_New (CHAR *name, ADDRESS name__len);
export Files_File Files_Old (CHAR *name, ADDRESS name__len); export Files_File Files_Old (CHAR *name, ADDRESS name__len);
static void Files_Peek (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x);
export INT32 Files_Pos (Files_Rider *r, ADDRESS *r__typ); export INT32 Files_Pos (Files_Rider *r, ADDRESS *r__typ);
export void Files_Purge (Files_File f); export void Files_Purge (Files_File f);
export void Files_Read (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x); export void Files_Read (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x);
@ -148,27 +152,87 @@ static void Files_Err (CHAR *s, ADDRESS s__len, Files_File f, INT16 errcode)
__DEL(s); __DEL(s);
} }
static void Files_ErrBO (CHAR *where, ADDRESS where__len, CHAR *culprit, ADDRESS culprit__len)
{
INT32 ix;
__DUP(where, where__len, CHAR);
__DUP(culprit, culprit__len, CHAR);
Out_Ln();
Out_String((CHAR*)"-- Files.", 10);
Out_String(where, where__len);
Out_String((CHAR*)": Buffer overflow (", 20);
Out_String(culprit, culprit__len);
Out_String((CHAR*)"|<", 3);
Out_String((CHAR*)")", 2);
Out_Ln();
__HALT(99);
__DEL(where);
__DEL(culprit);
}
static void Files_AppendStr (CHAR *src, ADDRESS src__len, CHAR *dest, ADDRESS dest__len, INT32 *dx, BOOLEAN *done)
{
INT32 sx;
__DUP(src, src__len, CHAR);
sx = 0;
while (src[sx] != 0x00) {
if (*dx >= dest__len - 1) {
*done = 0;
__DEL(src);
return;
}
dest[*dx] = src[sx];
*dx += 1;
sx += 1;
}
*done = 1;
__DEL(src);
}
static void Files_IntToStr (INT32 n, CHAR *buffer, ADDRESS buffer__len)
{
INT32 bx;
BOOLEAN sign;
sign = 0;
if (n < 0) {
n = -n;
sign = 1;
}
bx = buffer__len;
bx -= 1;
buffer[bx] = 0x00;
do {
if (bx > 0) {
bx -= 1;
buffer[bx] = (CHAR)((int)__MOD(n, 10) + 48);
n = __DIV(n, 10);
}
} while (!(n == 0));
if ((sign && bx > 0)) {
bx -= 1;
buffer[bx] = '-';
}
__MOVE((ADDRESS)buffer + (INT64)bx, (ADDRESS)buffer, buffer__len - bx);
}
static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len) static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS name__len, CHAR *dest, ADDRESS dest__len)
{ {
INT16 i, j; INT32 i;
BOOLEAN done;
__DUP(dir, dir__len, CHAR); __DUP(dir, dir__len, CHAR);
__DUP(name, name__len, CHAR); __DUP(name, name__len, CHAR);
i = 0; i = 0;
j = 0; Files_AppendStr(dir, dir__len, (void*)dest, dest__len, &i, &done);
while (dir[i] != 0x00) { if ((done && dest[i - 1] != '/')) {
dest[i] = dir[i]; Files_AppendStr((CHAR*)"/", 2, (void*)dest, dest__len, &i, &done);
i += 1;
} }
if (dest[i - 1] != '/') { if (done) {
dest[i] = '/'; Files_AppendStr(name, name__len, (void*)dest, dest__len, &i, &done);
i += 1;
}
while (name[j] != 0x00) {
dest[i] = name[j];
i += 1;
j += 1;
} }
dest[i] = 0x00; dest[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"MakeFileName", 13, dest, dest__len);
}
__DEL(dir); __DEL(dir);
__DEL(name); __DEL(name);
} }
@ -176,50 +240,42 @@ static void Files_MakeFileName (CHAR *dir, ADDRESS dir__len, CHAR *name, ADDRESS
static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len) static void Files_GetTempName (CHAR *finalName, ADDRESS finalName__len, CHAR *name, ADDRESS name__len)
{ {
INT32 n, i, j; INT32 n, i, j;
CHAR numBuffer[40];
BOOLEAN done;
__DUP(finalName, finalName__len, CHAR); __DUP(finalName, finalName__len, CHAR);
Files_tempno += 1; Files_tempno += 1;
n = Files_tempno; n = Files_tempno;
i = 0; i = 0;
done = 1;
if (finalName[0] != '/') { if (finalName[0] != '/') {
while (Platform_CWD[i] != 0x00) { Files_AppendStr(Platform_CWD, 4096, (void*)name, name__len, &i, &done);
name[i] = Platform_CWD[i]; if ((done && name[i - 1] != '/')) {
i += 1; Files_AppendStr((CHAR*)"/", 2, (void*)name, name__len, &i, &done);
}
if (Platform_CWD[i - 1] != '/') {
name[i] = '/';
i += 1;
} }
} }
j = 0; if (done) {
while (finalName[j] != 0x00) { Files_AppendStr(finalName, finalName__len, (void*)name, name__len, &i, &done);
name[i] = finalName[j];
i += 1;
j += 1;
} }
if (done) {
i -= 1; i -= 1;
while (name[i] != '/') { while (name[i] != '/') {
i -= 1; i -= 1;
} }
name[i + 1] = '.';
name[i + 2] = 't';
name[i + 3] = 'm';
name[i + 4] = 'p';
name[i + 5] = '.';
i += 6;
while (n > 0) {
name[i] = (CHAR)((int)__MOD(n, 10) + 48);
n = __DIV(n, 10);
i += 1; i += 1;
Files_AppendStr((CHAR*)".tmp.", 6, (void*)name, name__len, &i, &done);
} }
name[i] = '.'; if (done) {
i += 1; Files_IntToStr(Files_tempno, (void*)numBuffer, 40);
n = Platform_PID; Files_AppendStr(numBuffer, 40, (void*)name, name__len, &i, &done);
while (n > 0) { }
name[i] = (CHAR)((int)__MOD(n, 10) + 48); if (done) {
n = __DIV(n, 10); Files_IntToStr(Platform_PID, (void*)numBuffer, 40);
i += 1; Files_AppendStr(numBuffer, 40, (void*)name, name__len, &i, &done);
} }
name[i] = 0x00; name[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"GetTempName", 12, name, name__len);
}
__DEL(finalName); __DEL(finalName);
} }
@ -350,13 +406,15 @@ Files_File Files_New (CHAR *name, ADDRESS name__len)
static void Files_ScanPath (INT16 *pos, CHAR *dir, ADDRESS dir__len) static void Files_ScanPath (INT16 *pos, CHAR *dir, ADDRESS dir__len)
{ {
INT16 i; INT32 i;
INT16 pos1;
CHAR ch; CHAR ch;
BOOLEAN done;
i = 0; i = 0;
done = 1;
if (Files_SearchPath == NIL) { if (Files_SearchPath == NIL) {
if (*pos == 0) { if (*pos == 0) {
dir[0] = '.'; Files_AppendStr((CHAR*)".", 2, (void*)dir, dir__len, &i, &done);
i = 1;
*pos += 1; *pos += 1;
} }
} else { } else {
@ -368,27 +426,35 @@ static void Files_ScanPath (INT16 *pos, CHAR *dir, ADDRESS dir__len)
if (ch == '~') { if (ch == '~') {
*pos += 1; *pos += 1;
ch = (Files_SearchPath->data)[*pos]; ch = (Files_SearchPath->data)[*pos];
while (Files_HOME[i] != 0x00) { Files_AppendStr(Files_HOME, 1024, (void*)dir, dir__len, &i, &done);
dir[i] = Files_HOME[i]; if ((((((((done && ch != '/')) && ch != 0x00)) && ch != ';')) && ch != ' ')) {
i += 1;
}
if ((((((ch != '/' && ch != 0x00)) && ch != ';')) && ch != ' ')) {
while ((i > 0 && dir[i - 1] != '/')) { while ((i > 0 && dir[i - 1] != '/')) {
i -= 1; i -= 1;
} }
} }
} }
while ((ch != 0x00 && ch != ';')) { if (done) {
while ((((done && ch != 0x00)) && ch != ';')) {
if (i >= dir__len - 1) {
done = 0;
} else {
dir[i] = ch; dir[i] = ch;
i += 1; i += 1;
*pos += 1; *pos += 1;
ch = (Files_SearchPath->data)[*pos]; ch = (Files_SearchPath->data)[*pos];
} }
}
if (done) {
while ((i > 0 && dir[i - 1] == ' ')) { while ((i > 0 && dir[i - 1] == ' ')) {
i -= 1; i -= 1;
} }
} }
}
}
dir[i] = 0x00; dir[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"ScanPath", 9, dir, dir__len);
}
} }
static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len) static BOOLEAN Files_HasDir (CHAR *name, ADDRESS name__len)
@ -635,6 +701,30 @@ void Files_Read (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x)
} }
} }
static void Files_Peek (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x)
{
INT32 offset;
Files_Buffer buf = NIL;
buf = (*r).buf;
offset = (*r).offset;
if ((*r).org != buf->org) {
Files_Set(&*r, r__typ, buf->f, (*r).org + offset);
buf = (*r).buf;
offset = (*r).offset;
}
Files_Assert(offset <= buf->size);
if (offset < buf->size) {
*x = buf->data[offset];
} else if ((*r).org + offset < buf->f->len) {
Files_Set(&*r, r__typ, (*r).buf->f, (*r).org + offset);
*x = (*r).buf->data[0];
(*r).offset = 0;
} else {
*x = 0x00;
(*r).eof = 1;
}
}
void Files_ReadBytes (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x, ADDRESS x__len, INT32 n) void Files_ReadBytes (Files_Rider *r, ADDRESS *r__typ, SYSTEM_BYTE *x, ADDRESS x__len, INT32 n)
{ {
INT32 xpos, min, restInBuf, offset; INT32 xpos, min, restInBuf, offset;
@ -899,27 +989,47 @@ void Files_ReadString (Files_Rider *R, ADDRESS *R__typ, CHAR *x, ADDRESS x__len)
{ {
INT16 i; INT16 i;
CHAR ch; CHAR ch;
BOOLEAN done;
i = 0; i = 0;
do { done = 1;
Files_Read(&*R, R__typ, (void*)&ch); Files_Read(&*R, R__typ, (void*)&ch);
do {
if (i >= x__len - 1) {
done = 0;
}
x[i] = ch; x[i] = ch;
i += 1; i += 1;
} while (!(ch == 0x00)); Files_Read(&*R, R__typ, (void*)&ch);
} while (!(!done || ch == 0x00));
x[i] = 0x00;
if (!done) {
Files_ErrBO((CHAR*)"ReadString", 11, x, x__len);
}
} }
void Files_ReadLine (Files_Rider *R, ADDRESS *R__typ, CHAR *x, ADDRESS x__len) void Files_ReadLine (Files_Rider *R, ADDRESS *R__typ, CHAR *x, ADDRESS x__len)
{ {
INT16 i; INT16 i;
CHAR ch;
i = 0; i = 0;
if (x__len < 2) {
Files_ErrBO((CHAR*)"ReadLine", 9, (CHAR*)"*buffer too short*", 19);
}
do { do {
Files_Read(&*R, R__typ, (void*)&x[i]); Files_Read(&*R, R__typ, (void*)&ch);
x[i] = ch;
i += 1; i += 1;
} while (!(x[i - 1] == 0x00 || x[i - 1] == 0x0a)); } while (!((i >= x__len - 1 || ch == 0x00) || ch == 0x0a));
if (x[i - 1] == 0x0a) { if (x[i - 1] == 0x0d) {
if (i >= x__len - 1) {
Files_Peek(&*R, R__typ, (void*)&ch);
if (ch == 0x0a) {
i -= 1;
Files_Read(&*R, R__typ, (void*)&ch);
}
} else {
i -= 1; i -= 1;
} }
if ((i > 0 && x[i - 1] == 0x0d)) {
i -= 1;
} }
x[i] = 0x00; x[i] = 0x00;
} }

View file

@ -91,32 +91,127 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files
HALT(99) HALT(99)
END Err; END Err;
(* ************************************************************************* **
** Some helper procedures to be used in the modified versions of **
** 'MakeFileName()', 'GetTempName()' and 'ScanPath()', 'ReadString()' and **
** 'ReadLine()'. These should simplify the implementation of the named **
** procedures and help reducing buffer overflow problems ... **
** ************************************************************************* **
*)
(* Write a buffer overflow message to "stdout" and terminate ... *)
PROCEDURE ErrBO(where, culprit: ARRAY OF CHAR);
VAR ix: LONGINT;
BEGIN
Out.Ln; Out.String("-- Files."); Out.String(where);
Out.String(": Buffer overflow ("); Out.String(culprit);
Out.String("|<"); Out.String(")"); Out.Ln;
HALT(99)
END ErrBO;
(* Append a string (from a given position until its end) to the content of
** a file buffer. This procedure returns TRUE through its last argument
** if appending the string was successful (i.e., if the remaining buffer's
** size was long enough for the string - including a 0X), and FALSE otherwise.
** This procedure counts the ending 0X, but doesn't include it into the
** output, meaning the terminating 0X must be appended manually after the
** string was successfully completely.
*)
PROCEDURE AppendStr(src: ARRAY OF CHAR;
VAR dest: ARRAY OF CHAR; VAR dx: LONGINT;
VAR done: BOOLEAN);
VAR sx: LONGINT;
BEGIN
sx := 0;
WHILE src[sx] # 0X DO
IF dx >= LEN(dest) - 1 THEN done := FALSE; RETURN END;
dest[dx] := src[sx]; INC(dx); INC(sx);
END;
done := TRUE
END AppendStr;
(* Small helper procedure for dumping a part of a string buffer ...
PROCEDURE DumpPath(tag, name, path: ARRAY OF CHAR; sx, px: LONGINT);
VAR ix: LONGINT;
BEGIN
Out.String(tag); Out.String(": "); Out.String(name); Out.String(' = "');
IF px = 0 THEN
ix := sx; WHILE path[ix] # 0X DO Out.Char(path[ix]); INC(ix) END;
ELSE
FOR ix := sx TO px - 2 DO Out.Char(path[ix]) END
END;
Out.String('"'); Out.Ln
END DumpPath;
*)
(* Convert an integer (LONGINT) into a string in the supplied 'buffer'.
** 'buffer' must be big enough to hold the complete integer (including the
** string terminator (0X) after the conversion. (A buffer of 40 characters
** should be enough for even 128bit numbers ...)
*)
PROCEDURE IntToStr(n: LONGINT; VAR buffer: ARRAY OF CHAR);
VAR bx: LONGINT; sign: BOOLEAN;
BEGIN
sign := FALSE; IF n < 0 THEN n := -n; sign := TRUE END;
bx := LEN(buffer);
DEC(bx); buffer[bx] := 0X;
REPEAT
IF bx > 0 THEN
DEC(bx); buffer[bx] := CHR(n MOD 10 + ORD("0"));
n := n DIV 10
END
UNTIL (n = 0);
IF sign & (bx > 0) THEN DEC(bx); buffer[bx] := "-" END;
SYSTEM.MOVE(SYSTEM.ADR(buffer) + bx, SYSTEM.ADR(buffer), LEN(buffer) - bx)
END IntToStr;
(* Reimplemented version of 'MakeFileName()', which makes use of
** 'AppendStr()'. The status variable 'done' which is returned by
** 'AppendStr()' is passed through the complete implementation, skipping
** further appends after the first failure ...
*)
PROCEDURE MakeFileName(dir, name: ARRAY OF CHAR; VAR dest: ARRAY OF CHAR); PROCEDURE MakeFileName(dir, name: ARRAY OF CHAR; VAR dest: ARRAY OF CHAR);
VAR i, j: INTEGER; VAR i: LONGINT; done: BOOLEAN;
BEGIN i := 0; j := 0; BEGIN i := 0;
WHILE dir[i] # 0X DO dest[i] := dir[i]; INC(i) END; AppendStr(dir, dest, i, done);
IF dest[i-1] # "/" THEN dest[i] := "/"; INC(i) END; IF done & (dest[i-1] # "/") THEN
WHILE name[j] # 0X DO dest[i] := name[j]; INC(i); INC(j) END; AppendStr("/", dest, i, done)
dest[i] := 0X END;
IF done THEN AppendStr(name, dest, i, done); END;
dest[i] := 0X;
(* Generate an error message and terminate on failure *)
IF ~ done THEN ErrBO("MakeFileName", dest) END
END MakeFileName; END MakeFileName;
(* Reimplemented version of 'GetTempName()'. The errorneous appending of
** sequence number and process id was rewritten (using 'IntToStr()' and
** 'AppendStr()').
*)
PROCEDURE GetTempName(finalName: ARRAY OF CHAR; VAR name: ARRAY OF CHAR); PROCEDURE GetTempName(finalName: ARRAY OF CHAR; VAR name: ARRAY OF CHAR);
VAR n, i, j: LONGINT; VAR n, i, j: LONGINT; numBuffer: ARRAY 40 OF CHAR; done: BOOLEAN;
BEGIN BEGIN
INC(tempno); n := tempno; i := 0; INC(tempno); n := tempno; i := 0; done := TRUE;
IF finalName[0] # "/" THEN (* relative pathname *) IF finalName[0] # "/" THEN (* relative pathname *)
WHILE Platform.CWD[i] # 0X DO name[i] := Platform.CWD[i]; INC(i) END; (* Prepend the current working directory *)
IF Platform.CWD[i-1] # "/" THEN name[i] := "/"; INC(i) END AppendStr(Platform.CWD, name, i, done);
IF done & (name[i - 1] # "/") THEN AppendStr("/", name, i, done) END
END; END;
j := 0; (* Append the "final" pathname, but only for the directory *)
WHILE finalName[j] # 0X DO name[i] := finalName[j]; INC(i); INC(j) END; IF done THEN AppendStr(finalName, name, i, done) END;
DEC(i); IF done THEN
WHILE name[i] # "/" DO DEC(i) END; DEC(i); WHILE name[i] # "/" DO DEC(i) END; INC(i);
name[i+1] := "."; name[i+2] := "t"; name[i+3] := "m"; name[i+4] := "p"; name[i+5] := "."; INC(i, 6); AppendStr(".tmp.", name, i, done)
WHILE n > 0 DO name[i] := CHR(n MOD 10 + ORD("0")); n := n DIV 10; INC(i) END; END;
name[i] := "."; INC(i); n := Platform.PID; IF done THEN
WHILE n > 0 DO name[i] := CHR(n MOD 10 + ORD("0")); n := n DIV 10; INC(i) END; IntToStr(tempno, numBuffer);
name[i] := 0X AppendStr(numBuffer, name, i, done);
END;
IF done THEN
IntToStr(Platform.PID, numBuffer);
AppendStr(numBuffer, name, i, done)
END;
name[i] := 0X;
IF ~ done THEN ErrBO("GetTempName", name) END
END GetTempName; END GetTempName;
(* When registering a file, it may turn out that the name we want to use (* When registering a file, it may turn out that the name we want to use
@ -240,28 +335,40 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files
PROCEDURE ScanPath(VAR pos: INTEGER; VAR dir: ARRAY OF CHAR); PROCEDURE ScanPath(VAR pos: INTEGER; VAR dir: ARRAY OF CHAR);
(* Extract next individual directory from searchpath starting at pos, (* Extract next individual directory from searchpath starting at pos,
updating pos and returning dir. updating pos and returning dir.
Supports ~, ~user and blanks inside path *) Supports ~, ~user (???) and blanks inside path *)
VAR i: INTEGER; ch: CHAR; VAR i: LONGINT; pos1: INTEGER; ch: CHAR; done: BOOLEAN;
BEGIN BEGIN
i := 0; i := 0; done := TRUE;
IF SearchPath = NIL THEN IF SearchPath = NIL THEN
IF pos = 0 THEN IF pos = 0 THEN
dir[0] := "."; i := 1; INC(pos) (* Default search path is just the current directory *) (* Default search path is just the current directory *)
AppendStr(".", dir, i, done); INC(pos)
END END
ELSE ELSE
ch := SearchPath[pos]; ch := SearchPath[pos];
WHILE (ch = " ") OR (ch = ";") DO INC(pos); ch := SearchPath[pos] END; WHILE (ch = " ") OR (ch = ";") DO INC(pos); ch := SearchPath[pos] END;
IF ch = "~" THEN IF ch = "~" THEN
INC(pos); ch := SearchPath[pos]; INC(pos); ch := SearchPath[pos];
WHILE HOME[i] # 0X DO dir[i] := HOME[i]; INC(i) END; AppendStr(HOME, dir, i, done);
IF (ch # "/") & (ch # 0X) & (ch # ";") & (ch # " ") THEN IF done & (ch # "/") & (ch # 0X) & (ch # ";") & (ch # " ") THEN
WHILE (i > 0) & (dir[i-1] # "/") DO DEC(i) END WHILE (i > 0) & (dir[i-1] # "/") DO DEC(i) END
END END
END; END;
WHILE (ch # 0X) & (ch # ";") DO dir[i] := ch; INC(i); INC(pos); ch := SearchPath[pos] END; IF done THEN
WHILE (i > 0) & (dir[i-1] = " ") DO DEC(i) END WHILE done & (ch # 0X) & (ch # ";") DO
IF i >= LEN(dir) - 1 THEN
done := FALSE
ELSE
dir[i] := ch; INC(i); INC(pos); ch := SearchPath[pos]
END
END; END;
dir[i] := 0X IF done THEN
WHILE (i > 0) & (dir[i - 1] = " ") DO DEC(i) END
END
END
END;
dir[i] := 0X;
IF ~ done THEN ErrBO("ScanPath", dir) END
END ScanPath; END ScanPath;
PROCEDURE HasDir(VAR name: ARRAY OF CHAR): BOOLEAN; PROCEDURE HasDir(VAR name: ARRAY OF CHAR): BOOLEAN;
@ -402,6 +509,7 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files
r.buf := buf; r.org := org; r.offset := offset; r.eof := FALSE; r.res := 0 r.buf := buf; r.org := org; r.offset := offset; r.eof := FALSE; r.res := 0
END Set; END Set;
PROCEDURE Read* (VAR r: Rider; VAR x: SYSTEM.BYTE); PROCEDURE Read* (VAR r: Rider; VAR x: SYSTEM.BYTE);
VAR offset: LONGINT; buf: Buffer; VAR offset: LONGINT; buf: Buffer;
BEGIN BEGIN
@ -420,6 +528,30 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files
END END
END Read; END Read;
(* Read the next character from the stream, but don't advance after it.
** This is a primitive 'look ahead' mechanism implemented especially for
** 'ReadLine()'. Maybe it could be exported, too ...
*)
PROCEDURE Peek(VAR r: Rider; VAR x: SYSTEM.BYTE);
VAR offset: LONGINT; buf: Buffer;
BEGIN
buf := r.buf; offset := r.offset;
IF r.org # buf.org THEN
Set(r, buf.f, r.org + offset); buf := r.buf; offset := r.offset
END;
Assert(offset <= buf.size);
IF (offset < buf.size) THEN
x := buf.data[offset] (*Don't advance the offset*)
ELSIF r.org + offset < buf.f.len THEN
Set(r, r.buf.f, r.org + offset);
x := r.buf.data[0]; r.offset := 0 (*Same here - don't advance*)
ELSE
x := 0X; r.eof := TRUE
END
END Peek;
PROCEDURE ReadBytes* (VAR r: Rider; VAR x: ARRAY OF SYSTEM.BYTE; n: LONGINT); PROCEDURE ReadBytes* (VAR r: Rider; VAR x: ARRAY OF SYSTEM.BYTE; n: LONGINT);
VAR xpos, min, restInBuf, offset: LONGINT; buf: Buffer; VAR xpos, min, restInBuf, offset: LONGINT; buf: Buffer;
BEGIN BEGIN
@ -636,19 +768,64 @@ Especially Length would become fairly complex.
BEGIN ReadBytes(R, b, 8); FlipBytes(b, x) BEGIN ReadBytes(R, b, 8); FlipBytes(b, x)
END ReadLReal; END ReadLReal;
(* Reimplemented version of 'ReadString()' which checks for a buffer overflow
** and terminates the program in this case.
*)
PROCEDURE ReadString* (VAR R: Rider; VAR x: ARRAY OF CHAR); PROCEDURE ReadString* (VAR R: Rider; VAR x: ARRAY OF CHAR);
VAR i: INTEGER; ch: CHAR; VAR i: INTEGER; ch: CHAR; done: BOOLEAN;
BEGIN i := 0; BEGIN i := 0; done := TRUE;
REPEAT Read(R, ch); x[i] := ch; INC(i) UNTIL ch = 0X Read(R, ch);
REPEAT
IF i >= LEN(x) - 1 THEN done := FALSE END;
x[i] := ch; INC(i); Read(R, ch)
UNTIL ~ done OR (ch = 0X);
x[i] := 0X;
IF ~ done THEN ErrBO("ReadString", x) END
END ReadString; END ReadString;
(* Buffer-overflow safe variant of 'ReadLine()'.
** This variant read as much characters of a line as fit in the output
** variable 'x' (excluding the terminating 0X). The terminating 0X will be
** inserted manually after the read-loop. If the line has been read
** incompletely (meaning there was no 0AX before the end of the buffer was
** reached), the length of the resulting string is LEN(x) - 1. Otherwise, it
** is always shorter.
** In order to keep this procedure's semantics consistent in the case of a
** CR/LF sequence being read partially into the buffer (due to a buffer
** overflow), the procedure 'Peek()' (see above) was introduced.
*)
PROCEDURE ReadLine* (VAR R: Rider; VAR x: ARRAY OF CHAR); PROCEDURE ReadLine* (VAR R: Rider; VAR x: ARRAY OF CHAR);
VAR i: INTEGER; VAR i: INTEGER; ch: CHAR;
BEGIN BEGIN
i := 0; REPEAT Read(R, x[i]); INC(i) UNTIL (x[i-1] = 0X) OR (x[i-1] = 0AX); i := 0;
IF x[i-1] = 0AX THEN DEC(i) END; (* Omit trailing LF *) IF LEN(x) < 2 THEN ErrBO("ReadLine", "*buffer too short*") END;
IF (i > 0) & (x[i-1] = 0DX) THEN DEC(i) END; (* Also omit preceeding trailing CR if present. *) REPEAT
x[i] := 0X; (* Guarantee zero termination. *) Read(R, ch); x[i] := ch; INC(i)
UNTIL (i >= LEN(x) - 1) OR (ch = 0X) OR (ch = 0AX);
IF x[i-1] = 0DX THEN
(* Handle the two cases which may occur if the last valid character in the
** buffer is 0DX ...
*)
(* Handle the special situation that the buffer overflowed, the last valid
** character in the buffer is a 0DX and the next character in the stream
** is 0AX ...
*)
IF (i >= LEN(x) - 1) THEN
(* The buffer overflowed. IF the next character in the input stream is
** a LF, a CR/LF sequence was found. This means that the 0DX must be
** removed from the buffer and the LF must be consumed. Otherwise, the
** next character must remain in the input stream. Here, 'Peek()' is
** used for getting the next character from the input stream, but *not*
** consuming it. For consuming the character from the input stream,
** 'Read()' is used ...
*)
Peek(R, ch); IF (ch = 0AX) THEN DEC(i); Read(R, ch) END
ELSE
DEC(i)
END
END;
x[i] := 0X
END ReadLine; END ReadLine;
PROCEDURE ReadNum*(VAR R: Rider; VAR x: ARRAY OF SYSTEM.BYTE); PROCEDURE ReadNum*(VAR R: Rider; VAR x: ARRAY OF SYSTEM.BYTE);