Use _dos_allocmem for OW, similar to the Turbo C technique.

Split copy function into readfile and writefile functions.
Preserve time and date of kernel.sys and command.com.


git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@1354 6ac86273-5f31-0410-b378-82cca8765d1b
This commit is contained in:
Bart Oldeman 2007-08-29 14:17:21 +00:00
parent 69d767be50
commit 953e7b2007

355
sys/sys.c
View File

@ -40,7 +40,6 @@
#include <mem.h> #include <mem.h>
#else #else
#include <memory.h> #include <memory.h>
#include <malloc.h> /* fmalloc() in open watcom */
#endif #endif
#include <string.h> #include <string.h>
#ifdef __TURBOC__ #ifdef __TURBOC__
@ -158,12 +157,23 @@ char *getenv(const char *name)
} }
#endif #endif
#ifdef __TURBOC__
typedef struct ftime ftime;
#else
typedef struct
{
unsigned short date, time;
} ftime;
#endif
BYTE pgm[] = "SYS"; BYTE pgm[] = "SYS";
void put_boot(int, char *, char *, int, int); void put_boot(int, char *, char *, int, int);
BOOL check_space(COUNT, ULONG); BOOL check_space(COUNT, ULONG);
BYTE far * copy(COUNT drive, BYTE * srcPath, BYTE * rootPath, BYTE far * readfile(COUNT drive, BYTE * srcPath, BYTE * rootPath,
BYTE * file, BYTE far * buffer, ULONG * filesize); BYTE * file, ULONG * filesize, ftime *filetime);
BOOL writefile(COUNT drive, BYTE * rootPath,
BYTE * file, BYTE far * buffer, ULONG filesize, ftime *filetime);
#define SEC_SIZE 512 #define SEC_SIZE 512
#define COPY_SIZE 0x7e00 #define COPY_SIZE 0x7e00
@ -242,51 +252,6 @@ struct VerifyBootSectorSize {
int FDKrnConfigMain(int argc, char **argv); int FDKrnConfigMain(int argc, char **argv);
#ifndef __TURBOC__
#ifdef __WATCOMC__
/* int 21.48 takes a paragraph (16 byte units) count as input in bx */
/* ... int 21.48 returns the segment after the allocated MCB in ax */
void far * farmalloc( ULONG __size );
#pragma aux farmalloc = \
"shr cx, 1" \
"rcr bx, 1" \
"shr cx, 1" \
"rcr bx, 1" \
"shr cx, 1" \
"rcr bx, 1" \
"shr cx, 1" \
"rcr bx, 1" \
"inc bx" \
"xor dx, dx" \
"or cx, cx" \
"jnz nomalloc" \
"mov ax, 0x4800" \
"int 0x21" \
"jc nomalloc" \
"mov dx, ax" \
"nomalloc:" \
"xor ax, ax" \
parm [cx bx] \
modify [bx] \
value [dx ax];
void initalloc( void );
#pragma aux initalloc = \
"push es" \
"mov ax, cs" \
"mov es, ax" \
"mov bx, 0x1000" \
"mov ax, 0x4a00" \
"int 0x21" \
"pop es" \
modify [ax bx];
#endif
#endif
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
COUNT drive; /* destination drive */ COUNT drive; /* destination drive */
@ -294,8 +259,10 @@ int main(int argc, char **argv)
COUNT srcarg = 0; /* source argument position */ COUNT srcarg = 0; /* source argument position */
BYTE *bsFile = NULL; /* user specified destination boot sector */ BYTE *bsFile = NULL; /* user specified destination boot sector */
ULONG kernelsize = 0; /* size of the kernel to be copied */ ULONG kernelsize = 0; /* size of the kernel to be copied */
ftime kerneltime; /* time of the kernel to be copied */
BYTE far *kernelbuf = NULL; /* kernel to be copied */ BYTE far *kernelbuf = NULL; /* kernel to be copied */
ULONG shellsize = 0; /* size of the shell to be copied */ ULONG shellsize = 0; /* size of the shell to be copied */
ftime shelltime; /* time of the shell to be copied */
BYTE far *shellbuf = NULL; /* shell to be copied */ BYTE far *shellbuf = NULL; /* shell to be copied */
unsigned srcDrive; /* source drive */ unsigned srcDrive; /* source drive */
BYTE srcPath[SYS_MAXPATH]; /* user specified source drive and/or path */ BYTE srcPath[SYS_MAXPATH]; /* user specified source drive and/or path */
@ -307,10 +274,6 @@ int main(int argc, char **argv)
char *kernel_name = "KERNEL.SYS"; char *kernel_name = "KERNEL.SYS";
int load_segment = 0x60; int load_segment = 0x60;
#ifdef __WATCOMC__
initalloc(); /* reduce main MCB of .com file to 64 kB */
#endif
printf("FreeDOS System Installer " SYS_VERSION ", " __DATE__ "\n\n"); printf("FreeDOS System Installer " SYS_VERSION ", " __DATE__ "\n\n");
if (argc > 1 && memicmp(argv[1], "CONFIG", 6) == 0) if (argc > 1 && memicmp(argv[1], "CONFIG", 6) == 0)
@ -426,21 +389,24 @@ int main(int argc, char **argv)
if (!bootonly) if (!bootonly)
{ {
printf("Reading %s...\n", kernel_name); printf("Reading %s...\n", kernel_name);
kernelbuf = copy(drive, srcPath, rootPath, kernel_name, NULL, &kernelsize); kernelbuf = readfile(drive, srcPath, rootPath, kernel_name, &kernelsize,
&kerneltime);
if (kernelbuf == NULL) if (kernelbuf == NULL)
{ {
printf("\n%s: cannot read \"%s\"\n", pgm, kernel_name); printf("\n%s: cannot read \"%s\"\n", pgm, kernel_name);
exit(1); exit(1);
} /* fetch kernel */ } /* fetch kernel */
printf("\nReading COMMAND.COM...\n"); printf("\nReading COMMAND.COM...\n");
shellbuf = copy(drive, srcPath, rootPath, "COMMAND.COM", NULL, &shellsize); shellbuf = readfile(drive, srcPath, rootPath, "COMMAND.COM", &shellsize,
&shelltime);
if (shellbuf == NULL) if (shellbuf == NULL)
{ {
char *comspec = getenv("COMSPEC"); char *comspec = getenv("COMSPEC");
if (comspec != NULL) if (comspec != NULL)
{ {
printf("%s: Trying \"%s\"\n", pgm, comspec); printf("%s: Trying \"%s\"\n", pgm, comspec);
shellbuf = copy(drive, comspec, NULL, "COMMAND.COM", NULL, &shellsize); shellbuf = readfile(drive, comspec, NULL, "COMMAND.COM", &shellsize,
&shelltime);
if (shellbuf == NULL) if (shellbuf == NULL)
comspec = NULL; comspec = NULL;
} }
@ -458,14 +424,16 @@ int main(int argc, char **argv)
if (!bootonly) if (!bootonly)
{ {
printf("\nWriting %s...\n", kernel_name); printf("\nWriting %s...\n", kernel_name);
if (copy(drive, NULL, rootPath, kernel_name, kernelbuf, &kernelsize)==NULL) if (!writefile(drive, rootPath, kernel_name, kernelbuf, kernelsize,
&kerneltime))
{ {
printf("\n%s: cannot write \"%s\"\n", pgm, kernel_name); printf("\n%s: cannot write \"%s\"\n", pgm, kernel_name);
exit(1); exit(1);
} /* write kernel */ } /* write kernel */
printf("\nWriting COMMAND.COM...\n"); printf("\nWriting COMMAND.COM...\n");
if (copy(drive, NULL, rootPath, "COMMAND.COM", shellbuf, &shellsize)==NULL) if (!writefile(drive, rootPath, "COMMAND.COM", shellbuf, shellsize,
&shelltime))
{ {
printf("\n%s: cannot write \"COMMAND.COM\"\n", pgm); printf("\n%s: cannot write \"COMMAND.COM\"\n", pgm);
exit(1); exit(1);
@ -1006,30 +974,24 @@ BOOL check_space(COUNT drive, ULONG bytes)
BYTE copybuffer[COPY_SIZE]; BYTE copybuffer[COPY_SIZE];
/* if buffer is NULL, read the file, set filesize, and return a buffer */ /* read the file, set filesize, and return a buffer */
/* if buffer is not NULL, write, according to filesize, from buffer... */ BYTE far * readfile(COUNT drive, BYTE * srcPath, BYTE * rootPath,
BYTE far * copy(COUNT drive, BYTE * srcPath, BYTE * rootPath, BYTE * file, ULONG * filesize, ftime *filetime)
BYTE * file, BYTE far * buffer, ULONG * filesize)
{ {
static BYTE dest[SYS_MAXPATH], source[SYS_MAXPATH]; static BYTE dest[SYS_MAXPATH], source[SYS_MAXPATH];
UWORD ret; UWORD ret;
int fdin, fdout; int fdin;
ULONG copied = 0; ULONG copied = 0;
struct stat fstatbuf; struct stat fstatbuf;
BOOL reading = (buffer==NULL); BYTE far *bufptr;
BYTE far *buffer;
UWORD theseg;
strcpy(source, srcPath); strcpy(source, srcPath);
if (rootPath != NULL) /* trick for comspec */ if (rootPath != NULL) /* trick for comspec */
strcat(source, file); strcat(source, file);
if (!reading && *filesize==0) /* write mode but no writing needed */ if (stat(source, &fstatbuf)) /* read mode */
{
printf("%s: source and destination were identical: skipping \"%s\"\n",
pgm, source);
return buffer;
}
if (reading && stat(source, &fstatbuf)) /* read mode */
{ {
printf("%s: \"%s\" not found\n", pgm, source); printf("%s: \"%s\" not found\n", pgm, source);
@ -1047,140 +1009,138 @@ BYTE far * copy(COUNT drive, BYTE * srcPath, BYTE * rootPath,
return NULL; return NULL;
} }
if (reading) /* if reading */ truename(dest, source); /* use dest as buffer for truename(source) */
strcpy(source, dest); /* write updated source string */
sprintf(dest, "%c:\\%s", 'A' + drive, file);
if (stricmp(source, dest) == 0)
{ {
truename(dest, source); /* use dest as buffer for truename(source) */ printf("%s: source and destination are identical: skipping \"%s\"\n",
strcpy(source, dest); /* write updated source string */ pgm, source);
sprintf(dest, "%c:\\%s", 'A' + drive, file); *filesize = 0; /* special size */
if (stricmp(source, dest) == 0) return (BYTE far *) 1; /* return something non-null */
{ }
printf("%s: source and destination are identical: skipping \"%s\"\n",
pgm, source);
*filesize = 0; /* special size */
return (BYTE far *) 1; /* return something non-null */
}
if ((fdin = open(source, O_RDONLY | O_BINARY)) < 0) if ((fdin = open(source, O_RDONLY | O_BINARY)) < 0)
{
printf("%s: failed to open \"%s\"\n", pgm, source);
return NULL;
}
*filesize = filelength(fdin); /* return size */
} /* reading */
if (!reading) /* writing */
{ {
if (!check_space(drive, *filesize)) printf("%s: failed to open \"%s\"\n", pgm, source);
{ return NULL;
printf("%s: Not enough space to transfer %s\n", pgm, file); }
/* close(fdin); */ *filesize = filelength(fdin); /* return size */
/* exit(1); too pessimistic? we might overwrite a pre-existing file */
return NULL; /* still pessimistic, did not even try to overwrite... */
}
sprintf(dest, "%c:\\%s", 'A' + drive, file); /* allocate dos memory */
if ((fdout = #ifdef __TURBOC__
if (allocmem((unsigned)((*filesize+15)>>4), &theseg)!=-1)
#else
if (_dos_allocmem((unsigned)((*filesize+15)>>4), &theseg)!=0)
#endif
{
printf("Not enough memory to buffer %lu bytes for %s\n", *filesize, source);
return NULL;
}
bufptr = buffer = MK_FP(theseg, 0);
while ((ret = read(fdin, copybuffer, COPY_SIZE)) > 0)
{
UWORD offs;
if ((copied+ret) > *filesize)
{
ULONG dropped = copied + ret - *filesize;
printf("More bytes received than expected, dropping %lu??", dropped);
ret = ret - (UWORD) dropped;
}
for (offs = 0; offs < ret; offs++)
{
*bufptr = copybuffer[offs];
bufptr++;
if (FP_OFF(bufptr) > 0x7777) /* watcom needs this in tiny model */
{
bufptr = MK_FP(FP_SEG(bufptr)+0x700, FP_OFF(bufptr)-0x7000);
}
}
copied += ret;
}
#if defined __WATCOMC__ || defined _MSC_VER /* || defined __BORLANDC__ */
_dos_getftime(fdin, &filetime->date, &filetime->time);
#elif defined __TURBOC__
getftime(fdin, filetime);
#endif
close(fdin);
printf("%lu Bytes transferred", copied);
return buffer;
} /* readfile */
/* write, according to filesize, from buffer... */
BOOL writefile(COUNT drive, BYTE * rootPath,
BYTE * file, BYTE far * buffer, ULONG filesize, ftime *filetime)
{
static BYTE dest[SYS_MAXPATH], source[SYS_MAXPATH];
UWORD ret;
int fdout;
ULONG copied = 0;
BYTE far * bufptr = buffer;
if (filesize==0) /* write mode but no writing needed */
{
printf("%s: source and destination were identical: skipping \"%s\"\n",
pgm, source);
return TRUE;
}
if (!check_space(drive, filesize))
{
printf("%s: Not enough space to transfer %s\n", pgm, file);
/* exit(1); too pessimistic? we might overwrite a pre-existing file */
return FALSE; /* still pessimistic, did not even try to overwrite... */
}
sprintf(dest, "%c:\\%s", 'A' + drive, file);
if ((fdout =
open(dest, O_RDWR | O_TRUNC | O_CREAT | O_BINARY, open(dest, O_RDWR | O_TRUNC | O_CREAT | O_BINARY,
S_IREAD | S_IWRITE)) < 0) S_IREAD | S_IWRITE)) < 0)
{
printf(" %s: can't create\"%s\"\nDOS errnum %d", pgm, dest, errno);
/* close(fdin); */
return NULL;
}
} /* writing */
if (reading) /* reading */
{ {
BYTE far *bufptr; printf(" %s: can't create\"%s\"\nDOS errnum %d", pgm, dest, errno);
#ifdef __TURBOC__ /* workaround: farmalloc is nearmalloc if tiny model in TC2 ?? */ return FALSE;
UWORD theseg;
if (allocmem((*filesize+15)>>4, &theseg)!=-1) /* allocate dos memory */
#else
buffer = (BYTE far *)farmalloc(*filesize);
if (buffer==NULL)
#endif
{
printf("Not enough memory to buffer %lu bytes for %s\n", *filesize, source);
return NULL;
}
#ifdef __TURBOC__
buffer = MK_FP(theseg, 0);
#endif
bufptr = buffer;
while ((ret = read(fdin, copybuffer, COPY_SIZE)) > 0)
{
UWORD offs;
if ((copied+ret) > *filesize)
{
ULONG dropped = copied + ret - *filesize;
printf("More bytes received than expected, dropping %lu??", dropped);
ret = ret - (UWORD) dropped;
}
for (offs = 0; offs < ret; offs++)
{
*bufptr = copybuffer[offs];
bufptr++;
if (FP_OFF(bufptr) > 0x7777) /* watcom needs this in tiny model */
{
bufptr = MK_FP(FP_SEG(bufptr)+0x700, FP_OFF(bufptr)-0x7000);
}
}
copied += ret;
}
} /* reading */
if (!reading) /* writing */
{
BYTE far * bufptr = buffer;
while (TRUE)
{
UWORD offs;
ULONG tocopy = *filesize - copied;
if (tocopy==0)
break; /* done */
if (tocopy > (ULONG)COPY_SIZE)
tocopy = COPY_SIZE; /* cannot do all in one go */
for (offs=0; offs < tocopy; offs++)
{
copybuffer[offs] = *bufptr;
bufptr++;
if (FP_OFF(bufptr) > 0x7777) /* watcom needs this in tiny model */
{
bufptr = MK_FP(FP_SEG(bufptr)+0x700, FP_OFF(bufptr)-0x7000);
}
}
ret = (UWORD) tocopy;
if (write(fdout, copybuffer, ret) != ret)
{
printf("Can't write %u bytes to %s\n", ret, dest);
close(fdout);
unlink(dest);
break;
}
copied += ret;
}
} /* writing */
#if 0 /* TODO: Clone file timestamps even in 2 pass copy mode... */
{
#if defined __WATCOMC__ || defined _MSC_VER /* || defined __BORLANDC__ */
unsigned short date, time;
_dos_getftime(fdin, &date, &time);
_dos_setftime(fdout, date, time);
#elif defined __TURBOC__
struct ftime ftime;
getftime(fdin, &ftime);
setftime(fdout, &ftime);
#endif
} }
#endif /* timestamps */
if (reading) while (TRUE)
close(fdin); {
if (!reading) UWORD offs;
close(fdout); ULONG tocopy = filesize - copied;
if (tocopy==0)
break; /* done */
if (tocopy > (ULONG)COPY_SIZE)
tocopy = COPY_SIZE; /* cannot do all in one go */
for (offs=0; offs < tocopy; offs++)
{
copybuffer[offs] = *bufptr;
bufptr++;
if (FP_OFF(bufptr) > 0x7777) /* watcom needs this in tiny model */
{
bufptr = MK_FP(FP_SEG(bufptr)+0x700, FP_OFF(bufptr)-0x7000);
}
}
ret = (UWORD) tocopy;
if (write(fdout, copybuffer, ret) != ret)
{
printf("Can't write %u bytes to %s\n", ret, dest);
close(fdout);
unlink(dest);
break;
}
copied += ret;
}
#if defined __WATCOMC__ || defined _MSC_VER /* || defined __BORLANDC__ */
_dos_setftime(fdout, filetime->date, filetime->time);
#elif defined __TURBOC__
setftime(fdout, filetime);
#endif
close(fdout);
#if 0 /* no way :-p */
#ifdef __SOME_OTHER_COMPILER__ #ifdef __SOME_OTHER_COMPILER__
{ {
#include <utime.h> #include <utime.h>
@ -1190,11 +1150,10 @@ BYTE far * copy(COUNT drive, BYTE * srcPath, BYTE * rootPath,
utimb.modtime = fstatbuf.st_mtime; /* modification time */ utimb.modtime = fstatbuf.st_mtime; /* modification time */
utime(dest, &utimb); utime(dest, &utimb);
}; };
#endif
#endif #endif
printf("%lu Bytes transferred", copied); printf("%lu Bytes transferred", copied);
return buffer; return TRUE;
} /* copy */ } /* writefile */