rtfsprorelease/rtfscommon/source/apiregrs.c
2016-06-05 16:09:54 -04:00

3615 lines
136 KiB
C

/*
<TEST> Test File: rtfscommon/source/apiregress.c
<TEST>
<TEST> Procedure:BOOLEAN pc_regression_test()
<TEST> Description: Rtfs baseline feature set regression test suite.
<TEST> This subroutine calls all or most of the API routines while stress testing the system for driver bugs, memory leaks and freespace leaks.
<TEST> The routine may be inoked by typing REGRESS D: from the command shell
<TEST>
*/
#include "rtfs.h"
#if (!RTFS_CFG_READONLY) /* Excluded from build if read only */
#define RGE_FLTDRIVE 3
#define RGE_FREEERROR 4
#define RGE_LEAKERROR 5
#define RGE_MKDIR 6
#define RGE_SCWD 7
#define RGE_MKDIRERR 9
#define RGE_PWD 10
#define RGE_RMDIR 11
#define RGE_DSKCLOSE 12
#define RGE_OPEN 13
#define RGE_SEEK 14
#define RGE_WRITE 15
#define RGE_READ 16
#define RGE_TRUNC 17
#define RGE_FLUSH 18
#define RGE_CLOSE 19
#define RGE_UNLINK 20
#define RGE_MV 21
#define RGE_CHSIZE 22
#define RGE_DELTREE 23
#define RGE_ERRNO 24
#define RGE_LONGFILETEST 25
#define RGE_FILETEST 26
#define RGE_GFIRST 27
#define RGE_GREAD 28
#define RGE_LARGEFILETEST 29
#define RGE_CLUSTERCONVERSIONTEST 30
#define RGE_APPENDFILETEST 31
/* Porting issues */
#define VERBOSE 1 /* Set to zero for quiet operation */
byte test_drive[8]; /* The drive where the test will occur */
#define FIVE12 512 /* Not sector size dependant */
#define NLONGS FIVE12 /* Longs to write in file write test */
#define SUBDIRDEPTH 10 /* Depth of subdirectories */
#define NSUBDIRS 8 /* <= 26 Number of subdirs at below RTFSTEST */
dword test_rtfs_buf[NLONGS]; /* Used in the file write test */
#if (INCLUDE_VFAT && INCLUDE_CS_UNICODE) /* Small piece of compile time VFAT vs's NONVFAT code */
/* Make names a little shorter in Unicode, otherwise path's get too long */
KS_CONSTANT byte * _utest_dir = (byte *) L"Directory"; /* Test will occur in this Directory */
KS_CONSTANT byte * _utest_file_name = (byte *) L"Long File Name";
KS_CONSTANT byte * _utest_newfile_name = (byte *) L"New Long File Name";
KS_CONSTANT byte * _utest_subdir_name = (byte *) L"SUBDIR";
#endif
#if (INCLUDE_VFAT) /* Small piece of compile time VFAT vs's NONVFAT code */
KS_CONSTANT byte _test_dir[] = "RTFS_Test_Directory"; /* Test will occur in this Directory */
KS_CONSTANT byte _test_file_name[] = "Long File Name";
KS_CONSTANT byte _test_newfile_name[] = "New Long File Name";
KS_CONSTANT byte _test_subdir_name[] = "SUBDIR";
#else
KS_CONSTANT byte _test_dir[] = "RTFSTEST"; /* Test will occur in this Directory */
KS_CONSTANT byte _test_file_name[] = "FILE";
KS_CONSTANT byte _test_newfile_name[] = "NEWFILE";
KS_CONSTANT byte _test_subdir_name[] = "SUBDIR";
#endif
/* Above strings are copied into the following buffers in native cha set */
byte test_dir[40];
byte test_file_name[40];
byte test_newfile_name[40];
byte test_subdir_name[40];
#define INNERLOOP 2 /* Number of times we run the tes suite
between open and close. */
#define OUTERLOOP 2 /* Number of times we open the drive
run the inner loop and close the drive */
static BOOLEAN do_test(int loop_count, BOOLEAN do_clean, int use_charset);
static BOOLEAN do_file_test(int loop_count, BOOLEAN do_clean);
static BOOLEAN do_append_test(void);
static BOOLEAN do_po_lseek_test(void);
#if (INCLUDE_VFAT)
static BOOLEAN do_long_file_test(BOOLEAN do_clean,int use_charset);
static BOOLEAN do_more_long_file_tests(BOOLEAN do_clean,int use_charset);
#endif
#if (INCLUDE_MATH64)
static BOOLEAN do_comprehensive_filio_test(void);
#endif
static BOOLEAN do_rm(byte *buffer, int level, int use_charset);
static BOOLEAN check_errno(int expected_error);
static BOOLEAN do_gread_file_test(void);
static BOOLEAN do_buffered_file_test(BOOLEAN do_clean);
static BOOLEAN do_chkdsk_test(void);
#if (INCLUDE_RTFS_PROPLUS)
static BOOLEAN do_cluster_conversion_test(BOOLEAN raw);
#endif
static BOOLEAN check_if_exfat(void);
#define regress_error(E) _regress_error(E, __LINE__)
static void _regress_error(int error, long linenumber)
{
RTFS_PRINT_STRING_1((byte *)"", PRFLG_NL);
RTFS_PRINT_STRING_1((byte *)" regress_error was called line number: (", 0); /* "regress_error was called with error" */
RTFS_PRINT_LONG_1((dword) linenumber, 0);
RTFS_PRINT_STRING_1((byte *)") error: ", 0); /* "regress_error was called with error" */
RTFS_PRINT_LONG_1((dword) error, PRFLG_NL);
ERTFS_ASSERT_TEST(rtfs_debug_zero())
return;
}
/* Copy strings to native character sets */
static void setup_regress_strings(int use_charset)
{
#if (INCLUDE_VFAT && INCLUDE_CS_UNICODE) /* Small piece of compile time VFAT vs's NONVFAT code */
if (use_charset == CS_CHARSET_UNICODE)
{
rtfs_cs_strcpy(test_dir, (byte *) _utest_dir, use_charset);
rtfs_cs_strcpy(test_file_name, (byte *) _utest_file_name, use_charset);
rtfs_cs_strcpy(test_newfile_name, (byte *) _utest_newfile_name, use_charset);
rtfs_cs_strcpy(test_subdir_name, (byte *) _utest_subdir_name, use_charset);
return;
}
#endif
/* Set up strings in native character set */
rtfs_cs_strcpy(test_dir, (byte *) _test_dir, use_charset);
rtfs_cs_strcpy(test_file_name, (byte *) _test_file_name, use_charset);
rtfs_cs_strcpy(test_newfile_name, (byte *) _test_newfile_name, use_charset);
rtfs_cs_strcpy(test_subdir_name, (byte *) _test_subdir_name, use_charset);
}
#define PATHSIZE 256
static BOOLEAN do_comprehensive_filio_seek(void);
//===
static DDRIVE *path_to_drive_struct(byte *path);
extern byte cmdshell_check_disk_scratch_memory[];
extern dword cmdshell_size_check_disk_scratch_memory;
void _debug_chkdsk(void)
{
CHKDISK_STATS chkstat;
CHKDSK_CONTEXT chkcontext;
/*dword current_lost_cluster,current_crossed_points,current_bad_lfns; */
DDRIVE *test_drive_structure;
test_drive_structure = path_to_drive_struct(test_drive);
if (!test_drive_structure)
return;
/* Scan the disk first */
if (!pc_check_disk_ex(test_drive, &chkstat, TRUE, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], cmdshell_size_check_disk_scratch_memory)
|| chkstat.has_errors)
{
rtfs_print_one_string((byte *)"Checkdisk failed", PRFLG_NL);
}
}
//===
BOOLEAN pc_regression_test(byte *driveid, BOOLEAN do_clean) /* __api__ */
{
int inner_loop;
int outer_loop;
//int use_charset = CS_CHARSET_UNICODE;
int use_charset = CS_CHARSET_NOT_UNICODE; /* not tested with CS_CHARSET_UNICODE */
dword blocks_total, blocks_free, blocks_free_too;
rtfs_cs_strcpy(test_drive, driveid, CS_CHARSET_NOT_UNICODE);
setup_regress_strings(use_charset);
for (outer_loop = 0; outer_loop < OUTERLOOP; outer_loop++)
{
#if (VERBOSE)
RTFS_PRINT_LONG_1((dword) outer_loop, PRFLG_NL);
#endif
if (!pc_set_default_drive(test_drive))
{ regress_error(RGE_FLTDRIVE); return(FALSE);}
#if (INCLUDE_RTFS_PROPLUS)
/* September 2007.. Add call */
if (!do_cluster_conversion_test(TRUE)) /* Raw */
return(FALSE);
if (!do_cluster_conversion_test(FALSE))
return(FALSE);
#endif
/* If test_dir is not there, deltree will just fail */
pc_deltree(test_dir);
/* Test buffered IO support. Loop a few times to check for leaks */
for (inner_loop = 0; inner_loop < INNERLOOP; inner_loop++)
{
RTFS_PRINT_STRING_1((byte *)"Performing buffered file io test", PRFLG_NL); /* "Performing buffered file io test" */
if (!do_buffered_file_test(do_clean))
return(FALSE);
RTFS_PRINT_STRING_1((byte *)" Performing pc_gread test", PRFLG_NL);
if (!do_gread_file_test())
return(FALSE);
}
for (inner_loop = 0; inner_loop < INNERLOOP; inner_loop++)
{
/* Check freespace */
if (!pc_blocks_free(test_drive, &blocks_total, &blocks_free))
{
regress_error(RGE_FREEERROR);
return(FALSE);
}
if (!do_test(inner_loop, do_clean,use_charset)) /* Call the main test routine */
return(FALSE);
/* Check freespace again. They should match */
if (!do_clean) /* If not cleaning up don't recheck freespace */
return(TRUE);/* And return */
if (!pc_blocks_free(test_drive, &blocks_total, &blocks_free_too))
{
regress_error(RGE_FREEERROR);
return(FALSE);
}
if (blocks_free_too != blocks_free)
{
RTFS_PRINT_STRING_1((byte *)"Leak detected: blocks free : ", PRFLG_NL);
RTFS_PRINT_LONG_1((dword) blocks_free_too, 0);
RTFS_PRINT_STRING_1((byte *)") Should be: ", 0); /* "regress_error was called with error" */
RTFS_PRINT_LONG_1((dword) blocks_free, PRFLG_NL);
RTFS_PRINT_STRING_1((byte *)"Inner Loop : ", PRFLG_NL);
RTFS_PRINT_LONG_1((dword) inner_loop, 0);
RTFS_PRINT_STRING_1((byte *)") Outer loop: ", 0); /* "regress_error was called with error" */
RTFS_PRINT_LONG_1((dword) outer_loop, PRFLG_NL);
/* regress_error(RGE_LEAKERROR); */
return(FALSE);
}
}
if (check_if_exfat())
{
RTFS_PRINT_STRING_1((byte *)"!!!!!!! NOT Performing check disk test", PRFLG_NL);
}
else
{
if (!do_chkdsk_test())
return(FALSE);
}
}
RTFS_PRINT_STRING_1((byte *)"!!!!!!! Regression test complete", PRFLG_NL);
return(TRUE);
}
/*
<TEST> Procedure: Basic File Regression Test
<TEST> Check Disk Freespace
<TEST> Make the test directory
<TEST> loop
<TEST> Step into the test directory
<TEST> Make another subdiretory
<TEST> loop
<TEST> Make N deep subdirectories
<TEST> Change into each
<TEST> compare what we know is the directory with
<TEST> what pc_get_cwd returns.
<TEST> End loop
<TEST> In the lowest level directory perform file tests (explained below)
<TEST> test long file names
<TEST> test large files (4 Gig)
<TEST> loop
<TEST> create a file
<TEST> open it with multiple file descriptors
<TEST> loop
<TEST> write to it on multiple FDs
<TEST> loop
<TEST> seek and read on multiple FDs. Testing values
<TEST> flush
<TEST> truncate
<TEST> close
<TEST> end loop
<TEST> loop
<TEST> rename file
<TEST> delete file
<TEST> end loop
<TEST> either
<TEST> loop N times
<TEST> change to parent directory
<TEST> delete subdirectory
<TEST> end loop
<TEST> or
<TEST> deltree the test directory
<TEST> Check Disk Freespace again and compare with original
*/
static void build_subdir_name(byte *p, int index, int use_charset)
{
byte c;
/* Create SubDirA, or SubDirB.. SubDir('A'+index) */
rtfs_cs_strcpy(p,test_subdir_name, use_charset);
p = CS_OP_GOTO_EOS(p,use_charset);
/* Put A, or B, C, D.. at the end of the string */
c = 'A';
c = (byte) (c + index);
CS_OP_ASSIGN_ASCII(p,c,use_charset);
CS_OP_INC_PTR(p,use_charset);
CS_OP_TERM_STRING(p,use_charset);
}
static BOOLEAN do_test(int loop_count, BOOLEAN do_clean, int use_charset)
{
int i;
int j;
byte *buffer;
byte *buffer3;
byte *buffer4;
byte *home;
byte *p;
BLKBUFF *scratch_buffer;
BLKBUFF *scratch_buffer3;
BLKBUFF *scratch_buffer4;
BLKBUFF *scratch_home;
scratch_buffer = pc_scratch_blk();
scratch_buffer3 = pc_scratch_blk();
scratch_buffer4 = pc_scratch_blk();
scratch_home = pc_scratch_blk();
if (!(scratch_buffer && scratch_buffer3 && scratch_buffer4 && scratch_home))
{
if (scratch_buffer)
pc_free_scratch_blk(scratch_buffer);
if (scratch_buffer3)
pc_free_scratch_blk(scratch_buffer3);
if (scratch_buffer4)
pc_free_scratch_blk(scratch_buffer4);
if (scratch_home)
pc_free_scratch_blk(scratch_home);
return(FALSE);
}
buffer = (byte *)scratch_buffer->data;
buffer3 = (byte *)scratch_buffer3->data;
buffer4 = (byte *)scratch_buffer4->data;
home = (byte *)scratch_home->data;
#if (VERBOSE)
RTFS_PRINT_STRING_2((byte *)"Creating Subdirectory:", test_dir,PRFLG_NL); /* "Creating Subdirectory:" */
#endif
/* Delete the test dir if it exists */
if (pc_isdir(test_dir))
{
if (!pc_deltree(test_dir))
{ regress_error(RGE_DELTREE); goto return_false;}
}
else
{ if (!check_errno(PENOENT)) goto return_false;}
/* Create the test dir if it exists */
if (!pc_mkdir(test_dir))
{ regress_error(RGE_MKDIR); goto return_false;}
if (!check_errno(0)) goto return_false;
if (!pc_set_cwd(test_dir))
{regress_error(RGE_SCWD); goto return_false;}
if (!check_errno(0)) goto return_false;
/* Save the location of the test directory for later */
if (!pc_get_cwd(test_drive, home))
goto return_false;
if (!check_errno(0)) goto return_false;
for (i = 0; i < NSUBDIRS; i++)
{
if (!pc_set_cwd(home))
{ regress_error(RGE_SCWD); goto return_false;}
if (!check_errno(0)) goto return_false;
/* Make the top level subdirs */
build_subdir_name(buffer, i, use_charset);
#if (VERBOSE)
RTFS_PRINT_STRING_2((byte *)"Creating Subdirectory ", buffer,PRFLG_NL); /* "Creating Subdirectory " */
#endif
if (!pc_mkdir(buffer))
{ regress_error(RGE_MKDIR); goto return_false;}
if (!check_errno(0)) goto return_false;
for (j = 0; j < SUBDIRDEPTH; j++)
{
if (!pc_set_cwd(home))
{ regress_error(RGE_SCWD); goto return_false;}
if (!check_errno(0)) goto return_false;
/* Now make SubdirA\\Subdir in native char set */
p = buffer;
p = CS_OP_GOTO_EOS(p, use_charset);
CS_OP_ASSIGN_ASCII(p,'\\', use_charset);
CS_OP_INC_PTR(p, use_charset);
CS_OP_TERM_STRING(p, use_charset);
rtfs_cs_strcat(buffer,test_subdir_name,use_charset);
#if (VERBOSE)
RTFS_PRINT_STRING_2((byte *)"Creating Subdirectory ", buffer,PRFLG_NL); /* "Creating Subdirectory " */
#endif
/* Save D:\RTFS_Test_Directory\SubdirA\Subdir in native char set */
/* For later comparison with get_pwd results */
rtfs_cs_strcpy(buffer4, home, use_charset);
p = buffer4;
p = CS_OP_GOTO_EOS(p, use_charset);
CS_OP_ASSIGN_ASCII(p,'\\', use_charset);
CS_OP_INC_PTR(p, use_charset);
CS_OP_TERM_STRING(p, use_charset);
rtfs_cs_strcat(buffer4, buffer,use_charset);
/* Create SubdirA\\Subdir under the test directory */
if (!pc_mkdir(buffer))
{ regress_error(RGE_MKDIR); goto return_false;}
if (!check_errno(0)) goto return_false;
/* Create a dir. We know this will fail. Force error recovery */
if (pc_mkdir(buffer))
{ regress_error(RGE_MKDIRERR); goto return_false;}
if (!check_errno(PEEXIST)) goto return_false;
/* Go into the new directory */
if (!pc_set_cwd(buffer))
{ regress_error(RGE_SCWD); goto return_false;}
if (!check_errno(0)) goto return_false;
/* Get the dir string */
/* Should be:D:\RTFS_Test_Directory\SubdirA\\Subdir */
if (!pc_get_cwd(test_drive, buffer3))
{ regress_error(RGE_PWD); goto return_false;}
if (!check_errno(0)) goto return_false;
/* Compare with saved vesrion */
if (rtfs_cs_strcmp(buffer4, buffer3,use_charset) != 0)
{ regress_error(RGE_PWD); goto return_false;}
}
}
#if (INCLUDE_VFAT)
/* Do the long file test */
RTFS_PRINT_STRING_1((byte *)"Performing long file name test", PRFLG_NL); /* "Performing long file name test" */
if (!do_long_file_test(do_clean, use_charset))
{
regress_error(RGE_LONGFILETEST);
goto return_false;
}
// RTFS_PRINT_STRING_1((byte *)"!!!!!!! Skipping everal tests", PRFLG_NL);
// goto skip_to_file_test;
RTFS_PRINT_STRING_1((byte *)"Performing more long file name tests", PRFLG_NL); /* "Performing long file name test" */
if (!do_more_long_file_tests(do_clean, use_charset))
{
regress_error(RGE_LONGFILETEST);
goto return_false;
}
#endif
/* Do the test of append mode */
if (!do_append_test())
goto return_false;
/* Do the test of po_lseek (signed seek) */
if (!do_po_lseek_test())
goto return_false;
/* Do the file test */
if (!do_file_test(loop_count, do_clean))
{
regress_error(RGE_FILETEST);
goto return_false;
}
/* DELETE the subdirs */
if (!pc_set_cwd(home))
{ regress_error(RGE_SCWD); goto return_false;}
if (!check_errno(0)) goto return_false;
if (do_clean && (loop_count & 1))
{
/* Manually remove subdirs on odd loops */
for (i = 0; i < NSUBDIRS; i++)
{
/* Delete sub directories SubdirectoryA\SUBDIR\SUBDIR ... */
for (j = SUBDIRDEPTH; j > 0; j--)
{
build_subdir_name(buffer, i, use_charset);
if (!do_rm(buffer, j, use_charset))
goto return_false;
}
/* Delete sub directories SUB_? */
build_subdir_name(buffer, i, use_charset);
if (!pc_rmdir(buffer))
{ regress_error(RGE_RMDIR); goto return_false;}
if (!check_errno(0)) goto return_false;
}
}
/* Delete the test dir */
if (!pc_set_cwd(home))
{ regress_error(RGE_SCWD); goto return_false;}
/* Now make .. in native char set */
p = buffer;
CS_OP_ASSIGN_ASCII(p,'.', use_charset);
CS_OP_INC_PTR(p, use_charset);
CS_OP_ASSIGN_ASCII(p,'.', use_charset);
CS_OP_INC_PTR(p, use_charset);
CS_OP_TERM_STRING(p, use_charset);
if (!pc_set_cwd(buffer))
{ regress_error(RGE_SCWD); goto return_false;}
if (!check_errno(0)) goto return_false;
if (do_clean && (loop_count & 1))
{
if (!pc_rmdir(test_dir))
{ regress_error(RGE_RMDIR); goto return_false;}
if (!check_errno(0)) goto return_false;
}
else if (do_clean)
{
if (!pc_deltree(test_dir))
{ regress_error(RGE_DELTREE); goto return_false;}
if (!check_errno(0)) goto return_false;
}
pc_free_scratch_blk(scratch_buffer);
pc_free_scratch_blk(scratch_buffer3);
pc_free_scratch_blk(scratch_buffer4);
pc_free_scratch_blk(scratch_home);
return(TRUE);
return_false:
pc_free_scratch_blk(scratch_buffer);
pc_free_scratch_blk(scratch_buffer3);
pc_free_scratch_blk(scratch_buffer4);
pc_free_scratch_blk(scratch_home);
return(FALSE);
}
/* Delete a subdir at level */
static BOOLEAN do_rm(byte *buffer, int level, int use_charset) /*__fn__*/
{
int i;
byte *p;
for (i = 0; i < level; i++)
{
p = buffer;
p = CS_OP_GOTO_EOS(p, use_charset);
CS_OP_ASSIGN_ASCII(p,'\\', use_charset);
CS_OP_INC_PTR(p, use_charset);
CS_OP_TERM_STRING(p, use_charset);
rtfs_cs_strcat(buffer,test_subdir_name,use_charset);
}
#if (VERBOSE)
RTFS_PRINT_STRING_2((byte *)"Removing Directory ", buffer,PRFLG_NL); /* "Removing Directory " */
#endif
if (!pc_rmdir(buffer))
{
{ regress_error(RGE_RMDIR); return(FALSE);}
}
if (!check_errno(0)) return(FALSE);
return(TRUE);
}
#if (INCLUDE_VFAT)
byte *plong_name;
static void create_long_name(int len, byte c, int use_charset);
static int write_long_name(int len, byte c, int use_charset);
static int reopen_long_name(int len, byte c, int use_charset);
static int remove_long_name(int len, byte c, int use_charset);
/*
<TEST> Procedure: Long file name test
<TEST> Verify proper operation of file create, reopen and delete on files with
<TEST> name lengths that vary between 32 and 255 characters.
<TEST> Verify the attempting to create filename with a length greater that 255 characters fails
*/
static BOOLEAN do_long_file_test(BOOLEAN do_clean,int use_charset)
{
/* Use this buffer since under unicode we need more than FIVE12 bytes to test */
plong_name = (byte *) &test_rtfs_buf[0];
if (write_long_name(32, (byte) 'X', use_charset)) goto big_error;
if (write_long_name(64, (byte) 'X', use_charset)) goto big_error;
if (write_long_name(63, (byte) 'X', use_charset)) goto big_error;
if (write_long_name(127,(byte) 'X', use_charset)) goto big_error;
if (write_long_name(34, (byte) 'X', use_charset)) goto big_error;
if (write_long_name(66, (byte) 'X', use_charset)) goto big_error;
if (write_long_name(68, (byte) 'X', use_charset)) goto big_error;
if (write_long_name(124,(byte) 'X', use_charset)) goto big_error;
if (write_long_name(221,(byte) 'X', use_charset)) goto big_error;
if (write_long_name(255,(byte) 'X', use_charset)) goto big_error;
/* This one should fail */
if (!write_long_name(256,(byte) 'X', use_charset)) goto big_error;
if (write_long_name(66, (byte) 'Y', use_charset)) goto big_error;
if (write_long_name(68, (byte) 'Y', use_charset)) goto big_error;
if (write_long_name(124,(byte) 'Y', use_charset)) goto big_error;
if (write_long_name(221,(byte) 'Y', use_charset)) goto big_error;
if (write_long_name(255,(byte) 'Y', use_charset)) goto big_error;
if (write_long_name(32, (byte) 'Y', use_charset)) goto big_error;
if (write_long_name(64, (byte) 'Y', use_charset)) goto big_error;
if (write_long_name(63, (byte) 'Y', use_charset)) goto big_error;
if (write_long_name(127,(byte) 'Y', use_charset)) goto big_error;
if (write_long_name(34, (byte) 'Y', use_charset)) goto big_error;
if (reopen_long_name(32, (byte) 'X', use_charset)) goto big_error;
if (reopen_long_name(64, (byte) 'X', use_charset)) goto big_error;
if (reopen_long_name(63, (byte) 'X', use_charset)) goto big_error;
if (reopen_long_name(127,(byte) 'X', use_charset)) goto big_error;
if (reopen_long_name(34, (byte) 'X', use_charset)) goto big_error;
if (reopen_long_name(66, (byte) 'X', use_charset)) goto big_error;
if (reopen_long_name(68, (byte) 'X', use_charset)) goto big_error;
if (reopen_long_name(124,(byte) 'X', use_charset)) goto big_error;
if (reopen_long_name(221,(byte) 'X', use_charset)) goto big_error;
if (reopen_long_name(255,(byte) 'X', use_charset)) goto big_error;
if (reopen_long_name(66, (byte) 'Y', use_charset)) goto big_error;
if (reopen_long_name(68, (byte) 'Y', use_charset)) goto big_error;
if (reopen_long_name(124,(byte) 'Y', use_charset)) goto big_error;
if (reopen_long_name(221,(byte) 'Y', use_charset)) goto big_error;
if (reopen_long_name(255,(byte) 'Y', use_charset)) goto big_error;
if (reopen_long_name(32, (byte) 'Y', use_charset)) goto big_error;
if (reopen_long_name(64, (byte) 'Y', use_charset)) goto big_error;
if (reopen_long_name(63, (byte) 'Y', use_charset)) goto big_error;
if (reopen_long_name(127,(byte) 'Y', use_charset)) goto big_error;
if (reopen_long_name(34, (byte) 'Y', use_charset)) goto big_error;
/* Return here if you want to see the results */
/* pc_free_scratch_blk(scratch); */
/* return(1); */
if (do_clean)
{
if (remove_long_name(32, (byte) 'X', use_charset)) goto big_error;
if (remove_long_name(64, (byte) 'X', use_charset)) goto big_error;
if (remove_long_name(63, (byte) 'X', use_charset)) goto big_error;
if (remove_long_name(127,(byte) 'X', use_charset)) goto big_error;
if (remove_long_name(34, (byte) 'X', use_charset)) goto big_error;
if (remove_long_name(66, (byte) 'X', use_charset)) goto big_error;
if (remove_long_name(68, (byte) 'X', use_charset)) goto big_error;
if (remove_long_name(124,(byte) 'X', use_charset)) goto big_error;
if (remove_long_name(221,(byte) 'X', use_charset)) goto big_error;
if (remove_long_name(255,(byte) 'X', use_charset)) goto big_error;
if (remove_long_name(66, (byte) 'Y', use_charset)) goto big_error;
if (remove_long_name(68, (byte) 'Y', use_charset)) goto big_error;
if (remove_long_name(124,(byte) 'Y', use_charset)) goto big_error;
if (remove_long_name(221,(byte) 'Y', use_charset)) goto big_error;
if (remove_long_name(255,(byte) 'Y', use_charset)) goto big_error;
if (remove_long_name(32, (byte) 'Y', use_charset)) goto big_error;
if (remove_long_name(64, (byte) 'Y', use_charset)) goto big_error;
if (remove_long_name(63, (byte) 'Y', use_charset)) goto big_error;
if (remove_long_name(127,(byte) 'Y', use_charset)) goto big_error;
if (remove_long_name(34, (byte) 'Y', use_charset)) goto big_error;
}
return(TRUE);
big_error:
return(FALSE);
}
static void create_long_name(int len, byte c, int use_charset)
{
int i;
byte *p;
p = plong_name;
for (i = 0; i < len; i++)
{
CS_OP_ASSIGN_ASCII(p,c, use_charset);
CS_OP_INC_PTR(p, use_charset);
};
CS_OP_TERM_STRING(p, use_charset);
}
static int write_long_name(int len, byte c, int use_charset)
{
int fd, ret_val;
create_long_name(len, c, use_charset);
if ((fd = po_open(plong_name,(word)(PO_BINARY|PO_WRONLY|PO_CREAT|PO_TRUNC),(word)(PS_IWRITE | PS_IREAD))) >= 0)
{
po_close(fd);
ret_val = 0;
}
else
{
ret_val = -1;
}
return(ret_val);
}
static int reopen_long_name(int len, byte c, int use_charset)
{
int fd;
create_long_name(len, c, use_charset);
if ((fd = po_open(plong_name,(word)(PO_BINARY|PO_WRONLY),(word)(PS_IWRITE | PS_IREAD))) >= 0)
{
po_close(fd);
return(0);
}
else
{
return(-1);
}
}
static int remove_long_name(int len, byte c, int use_charset)
{
create_long_name(len, c, use_charset);
if (!pc_unlink(plong_name))
{
return(-1);
}
else
return(0);
}
/*
<TEST> Procedure: More long file name tests
<TEST> The test repeats once creating the file once using unicode and once using long file name
<TEST> The test repeats to test pc_unlink() once using alias, once using unicode and once using long file name.
<TEST> Verify proper alias name creation.
<TEST> Verify proper handling of file names with illegal characters.
<TEST> The test contains a table of long file names and the alias name that should result when the file is created.
<TEST> The alias name in the table is set zero when the long name contains illegal characters.
<TEST> The file is created
<TEST> If it succeeds and the alias is NULL then illegal character handling is incorrect.
<TEST> Test all illegal characters and reserved names.
<TEST> If it fails and the alias is not null then some other error has occured.
<TEST> The alias name and the long name are written to the file.
<TEST> The the file is re-opened by it's alias name and unicode and long file name and alias names are read in and compared to the table.
<TEST> The the file is found with pc_gfirst() using unicode and long file name and alias names are read in and compared to the table.
*/
struct lfnaliaspairs {
char *lfn;
char *alias;
byte *unicode_lfn;
};
struct lfnaliaspairs namepairs[] = {
#if (0)
/* Test bad alias characters that are okay in the long file name " ,;=+[]"; */
{",", "_~1", (byte *)L","},
{";", "_~2", (byte *)L";"},
{"=", "_~3", (byte *)L"="},
{"+", "_~4", (byte *)L"+"},
{"[", "_~5", (byte *)L"["},
{"]", "_~6", (byte *)L"]"}, // remove
#endif
#if (INCLUDE_CS_JIS)
/* Test JIS support */
{"\345TEST.XXX", "\345TEST.XXX", 0}, /* File starting with e5 */
{"T\345EST.XXX", "T\345EST.XXX", 0}, /* File with e5 in the middle */
{"\345TESTlongfile.XXX", "\345TESTL~1.XXX", 0}, /* Long file starting with e5 */
{"TE\345STlongfile.XXX", "TE\345STL~1.XXX", 0}, /* Long file with e5 in the middle */
{"TEST567\201\100.XXX", "TEST56~1.XXX", 0}, /* File with JIS 2 byte character (\201\100) as 8th character in file name */
{"TEST56\201\100.XXX", "TEST56\201\100.XXX", 0}, /* File with JIS 2 byte character (\201\100) as 7th character in file name */
{"\201\100TEST.XXX", "\201\100TEST.XXX", 0}, /* File with JIS 2 byte character (\201\100) as 1st character in file name */
{"TEST567.YY\201\100", "TEST56~1.YY", 0}, /* File with JIS 2 byte character (\201\100) as 3d character in file ext */
{"TEST.Y\201\100", "TEST.Y\201\100", 0}, /* File with JIS 2 byte character (\201\100) as 2nd character in file ext */
{"TEST.\201\100Y", "TEST.\201\100Y", 0}, /* File with JIS 2 byte character (\201\100) as 1st character in file ext */
{"TEST567\242.XXX", "TEST567\242.XXX", 0}, /* File with JIS 1 byte character (\242) as 8th character in file name */
{"TEST56\242.XXX", "TEST56\242.XXX", 0}, /* File with JIS 1 byte character (\242) as 7th character in file name */
{"\242TEST.XXX", "\242TEST.XXX", 0}, /* File with JIS 1 byte character (\242) as 1st character in file name */
{"TEST567.YY\242", "TEST567.YY\242", 0}, /* File with JIS 1 byte character (\242) as 3d character in file ext */
{"TEST.Y\242", "TEST.Y\242", 0}, /* File with JIS 1 byte character (\242) as 2nd character in file ext */
{"TEST.\242Y", "TEST.\242Y", 0}, /* File with JIS 1 byte character (\242) as 1st character in file ext */
{"\201\076EST.XXX", 0, 0}, /* File illegal JIS character in start file name */
{"TES\201\076T.ABC", 0, 0}, /* File illegal JIS character in mid file name */
{"TEST567\201\076.ABC", 0, 0}, /* File illegal JIS character in end file name */
{"TTEST.\201\076XX", 0, 0}, /* File illegal JIS character in start file ext */
{"TTEST.X\201\076X", 0, 0}, /* File illegal JIS character in mid file ext */
{"TTEST.XX\201\076", 0, 0}, /* File illegal JIS character in end file ext */
{"Thisisalongfile\201\076name.xx", 0, 0}, /* File illegal JIS character in lfn */
#endif
/* Test all bad characters */
// {"\\TEST.XXX", 0, 0}, /* Bad characters in file name or extension */
{"T\\ST.XXX" , 0, (byte *)L"T\\ST.XXX" },
{"TEST\\.XXX", 0, (byte *)L"TEST\\.XXX"},
{"TESTLONGNAME\\XXX.XX", 0, (byte *)L"TESTLONGNAME\\XXX.XX"},
{"TEST.\\XX" , 0, (byte *)L"TEST.\\XX"},
{"TEST.X\\" , 0, (byte *)L"TEST.X\\" },
{"TEST.XX\\" , 0, (byte *)L"TEST.XX\\"},
{"/TEST.XXX" , 0, (byte *)L"/TEST.XXX"},
{"T/ST.XXX" , 0, (byte *)L"T/ST.XXX" },
{"TEST/.XXX" , 0, (byte *)L"TEST/.XXX"},
{"TESTLONGNAME/XXX.XX", 0, (byte *)L"TESTLONGNAME/XXX.XX"},
{"TEST./XX" , 0, (byte *)L"TEST./XX" },
{"TEST.X/" , 0, (byte *)L"TEST.X/" },
{"TEST.XX/" , 0, (byte *)L"TEST.XX/" },
{":TEST.XXX" , 0, (byte *)L":TEST.XXX"},
{"T:ST.XXX" , 0, (byte *)L"T:ST.XXX" },
{"TEST:.XXX" , 0, (byte *)L"TEST:.XXX"},
{"TESTLONGNAME:XXX.XX", 0, (byte *)L"TESTLONGNAME:XXX.XX"},
{"TEST.:XX" , 0, (byte *)L"TEST.:XX" },
{"TEST.X:" , 0, (byte *)L"TEST.X:" },
{"TEST.XX:" , 0, (byte *)L"TEST.XX:" },
{"*TEST.XXX" , 0, (byte *)L"*TEST.XXX"},
{"T*ST.XXX" , 0, (byte *)L"T*ST.XXX" },
{"TEST*.XXX" , 0, (byte *)L"TEST*.XXX"},
{"TESTLONGNAME*XXX.XX", 0, (byte *)L"TESTLONGNAME*XXX.XX"},
{"TEST.*XX" , 0, (byte *)L"TEST.*XX" },
{"TEST.X*" , 0, (byte *)L"TEST.X*" },
{"TEST.XX*" , 0, (byte *)L"TEST.XX*" },
{"?TEST.XXX" , 0, (byte *)L"?TEST.XXX" },
{"T?ST.XXX" , 0, (byte *)L"T?ST.XXX" },
{"TEST?.XXX" , 0, (byte *)L"TEST?.XXX" },
{"TESTLONGNAME?XXX.XX", 0, (byte *)L"TESTLONGNAME?XXX.XX"},
{"TEST.?XX" , 0, (byte *)L"TEST.?XX" },
{"TEST.X?" , 0, (byte *)L"TEST.X?" },
{"TEST.XX?" , 0, (byte *)L"TEST.XX?" },
{"\"TEST.XXX", 0, (byte *)L"\"TEST.XXX"},
{"T\"ST.XXX" , 0, (byte *)L"T\"ST.XXX" },
{"TEST\".XXX", 0, (byte *)L"TEST\".XXX"},
{"TESTLONGNAME\"XXX.XX", 0, (byte *)L"TESTLONGNAME\"XXX.XX"},
{"TEST.\"XX" , 0, (byte *)L"TEST.\"XX" },
{"TEST.X\"" , 0, (byte *)L"TEST.X\"" },
{"TEST.XX\"" , 0, (byte *)L"TEST.XX\"" },
{"<TEST.XXX" , 0, (byte *)L"<TEST.XXX" },
{"T<ST.XXX" , 0, (byte *)L"T<ST.XXX" },
{"TEST<.XXX" , 0, (byte *)L"TEST<.XXX" },
{"TESTLONGNAME<XXX.XX", 0, (byte *)L"TESTLONGNAME<XXX.XX"},
{"TEST.<XX" , 0, (byte *)L"TEST.<XX" },
{"TEST.X<" , 0, (byte *)L"TEST.X<" },
{"TEST.XX<" , 0, (byte *)L"TEST.XX<" },
{">TEST.XXX" , 0, (byte *)L">TEST.XXX"},
{"T>ST.XXX" , 0, (byte *)L"T>ST.XXX" },
{"TEST>.XXX" , 0, (byte *)L"TEST>.XXX"},
{"TESTLONGNAME>XXX.XX", 0, (byte *)L"TESTLONGNAME>XXX.XX"},
{"TEST.>XX" , 0, (byte *)L"TEST.>XX" },
{"TEST.X>" , 0, (byte *)L"TEST.X>" },
{"TEST.XX>" , 0, (byte *)L"TEST.XX>" },
{"|TEST.XXX" , 0, (byte *)L"|TEST.XXX"},
{"T|ST.XXX" , 0, (byte *)L"T|ST.XXX" },
{"TEST|.XXX" , 0, (byte *)L"TEST|.XXX"},
{"TESTLONGNAME|XXX.XX", 0, (byte *)L"TESTLONGNAME|XXX.XX"},
{"TEST.|XX" , 0, (byte *)L"TEST.|XX"},
{"TEST.X|" , 0, (byte *)L"TEST.X|" },
{"TEST.XX|" , 0, (byte *)L"TEST.XX|"},
/* Test bad alias characters that are okay in the long file name " ,;=+[]"; */
{",", "_~1", (byte *)L","},
{";", "_~2", (byte *)L";"},
{"=", "_~3", (byte *)L"="},
{"+", "_~4", (byte *)L"+"},
{"[", "_~5", (byte *)L"["},
{"]", "_~6", (byte *)L"]"},
{",.,", "_~1._", (byte *)L",.,"},
{";.;", "_~2._", (byte *)L";.;"},
{"=.=", "_~3._", (byte *)L"=.="},
{"+.+", "_~4._", (byte *)L"+.+"},
{"[.[", "_~5._", (byte *)L"[.["},
{"].]", "_~6._", (byte *)L"].]"},
/* {" TEST.XXX", "_TEST~1.XXX", 0}, == should be */
/* April 2012 changed test to verify that leading spaces are accepted
{" TEST.XXX", "TEST.XXX" , (byte *)L" TEST.XXX"},
*/
{" TEST.XXX", "TEST~1.XXX" , (byte *)L" TEST.XXX"},
/* April 2012 added test to verify that trailing spaces are not accepted*/
{"TSET.XXX ", "TSET.XXX" , (byte *)L"TSET.XXX"},
/* July 2012 changed fro ~1 to ~2 because ~1 already used */
{"T EST.XXX", "TEST~2.XXX" , (byte *)L"T EST.XXX"},
{"TES .XXX" , "TES~1.XXX" , (byte *)L"TES .XXX" },
{"TEST. XX" , "TEST~1.XX" , (byte *)L"TEST. XX" },
{"TEST.X X" , "TEST~2.XX" , (byte *)L"TEST.X X" },
{"TEST.XX " , "TEST.XX" , (byte *)L"TEST.XX " },
{",TEST.ZZZ", "_TEST~1.ZZZ", (byte *)L",TEST.ZZZ"},
{"T,EST.ZZZ", "T_EST~1.ZZZ", (byte *)L"T,EST.ZZZ"},
{"TES,.ZZZ" , "TES_~1.ZZZ" , (byte *)L"TES,.ZZZ" },
{"TEST.,ZZ" , "TEST~1._ZZ" , (byte *)L"TEST.,ZZ" },
{"TEST.Z,Z" , "TEST~1.Z_Z" , (byte *)L"TEST.Z,Z" },
{"TEST.ZZ," , "TEST~1.ZZ_" , (byte *)L"TEST.ZZ," },
{";TEST.AAA", "_TEST~1.AAA", (byte *)L";TEST.AAA"},
{"T;EST.AAA", "T_EST~1.AAA", (byte *)L"T;EST.AAA"},
{"TES;.AAA" , "TES_~1.AAA" , (byte *)L"TES;.AAA" },
{"TEST.;AA" , "TEST~1._AA" , (byte *)L"TEST.;AA" },
{"TEST.A;A" , "TEST~1.A_A" , (byte *)L"TEST.A;A" },
{"TEST.AA;" , "TEST~1.AA_" , (byte *)L"TEST.AA;" },
{"=TEST.BBB", "_TEST~1.BBB", (byte *)L"=TEST.BBB"},
{"T=EST.BBB", "T_EST~1.BBB", (byte *)L"T=EST.BBB"},
{"TES=.BBB" , "TES_~1.BBB" , (byte *)L"TES=.BBB" },
{"TEST.=BB" , "TEST~1._BB" , (byte *)L"TEST.=BB" },
{"TEST.B=B" , "TEST~1.B_B" , (byte *)L"TEST.B=B" },
{"TEST.BB=" , "TEST~1.BB_" , (byte *)L"TEST.BB=" },
{"+TEST.CCC", "_TEST~1.CCC", (byte *)L"+TEST.CCC"},
{"T+EST.CCC", "T_EST~1.CCC", (byte *)L"T+EST.CCC"},
{"TES+.CCC" , "TES_~1.CCC" , (byte *)L"TES+.CCC" },
{"TEST.+CC" , "TEST~1._CC" , (byte *)L"TEST.+CC" },
{"TEST.C+C" , "TEST~1.C_C" , (byte *)L"TEST.C+C" },
{"TEST.CC+" , "TEST~1.CC_" , (byte *)L"TEST.CC+" },
{"[TEST.DDD", "_TEST~1.DDD", (byte *)L"[TEST.DDD"},
{"T[EST.DDD", "T_EST~1.DDD", (byte *)L"T[EST.DDD"},
{"TES[.DDD" , "TES_~1.DDD" , (byte *)L"TES[.DDD" },
{"TEST.[DD" , "TEST~1._DD" , (byte *)L"TEST.[DD" },
{"TEST.D[D" , "TEST~1.D_D" , (byte *)L"TEST.D[D" },
{"TEST.DD[" , "TEST~1.DD_" , (byte *)L"TEST.DD[" },
{"]TEST.EEE", "_TEST~1.EEE", (byte *)L"]TEST.EEE"},
{"T]EST.EEE", "T_EST~1.EEE", (byte *)L"T]EST.EEE"},
{"TES].EEE" , "TES_~1.EEE" , (byte *)L"TES].EEE" },
{"TEST.]EE" , "TEST~1._EE" , (byte *)L"TEST.]EE" },
{"TEST.E]E" , "TEST~1.E_E" , (byte *)L"TEST.E]E" },
{"TEST.EE]" , "TEST~1.EE_" , (byte *)L"TEST.EE]" },
/* Test Reserved names */
{"CON" , 0, (byte *)L"CON" },
{"PRN" , 0, (byte *)L"PRN" },
{"NUL" , 0, (byte *)L"NUL" },
{"AUX" , 0, (byte *)L"AUX" },
{"LPT1", 0, (byte *)L"LPT1"},
{"LPT2", 0, (byte *)L"LPT2"},
{"LPT3", 0, (byte *)L"LPT3"},
{"LPT4", 0, (byte *)L"LPT4"},
{"COM1", 0, (byte *)L"COM1"},
{"COM2", 0, (byte *)L"COM2"},
{"COM3", 0, (byte *)L"COM3"},
{"COM4", 0, (byte *)L"COM4"},
{"con" , 0, (byte *)L"con" },
{"prn" , 0, (byte *)L"prn" },
{"nul" , 0, (byte *)L"nul" },
{"aux" , 0, (byte *)L"aux" },
{"lpt1", 0, (byte *)L"lpt1"},
{"lpt2", 0, (byte *)L"lpt2"},
{"lpt3", 0, (byte *)L"lpt3"},
{"lpt4", 0, (byte *)L"lpt4"},
{"com1", 0, (byte *)L"com1"},
{"com2", 0, (byte *)L"com2"},
{"com3", 0, (byte *)L"com3"},
{"com4", 0, (byte *)L"com4"},
/* Test Reserved names with extensions */
{"CON.XXX" , 0, (byte *)L"CON.XXX" },
{"PRN.XXX" , 0, (byte *)L"PRN.XXX" },
{"NUL.XXX" , 0, (byte *)L"NUL.XXX" },
{"AUX.XXX" , 0, (byte *)L"AUX.XXX" },
{"LPT1.XXX", 0, (byte *)L"LPT1.XXX"},
{"LPT2.XXX", 0, (byte *)L"LPT2.XXX"},
{"LPT3.XXX", 0, (byte *)L"LPT3.XXX"},
{"LPT4.XXX", 0, (byte *)L"LPT4.XXX"},
{"COM1.XXX", 0, (byte *)L"COM1.XXX"},
{"COM2.XXX", 0, (byte *)L"COM2.XXX"},
{"COM3.XXX", 0, (byte *)L"COM3.XXX"},
{"COM4.XXX", 0, (byte *)L"COM4.XXX"},
{"con.XXX" , 0, (byte *)L"con.XXX" },
{"prn.XXX" , 0, (byte *)L"prn.XXX" },
{"nul.XXX" , 0, (byte *)L"nul.XXX" },
{"aux.XXX" , 0, (byte *)L"aux.XXX" },
{"lpt1.XXX", 0, (byte *)L"lpt1.XXX"},
{"lpt2.XXX", 0, (byte *)L"lpt2.XXX"},
{"lpt3.XXX", 0, (byte *)L"lpt3.XXX"},
{"lpt4.XXX", 0, (byte *)L"lpt4.XXX"},
{"com1.XXX", 0, (byte *)L"com1.XXX"},
{"com2.XXX", 0, (byte *)L"com2.XXX"},
{"com3.XXX", 0, (byte *)L"com3.XXX"},
{"com4.XXX", 0, (byte *)L"com4.XXX"},
/* More tests */
{"TEST_LFN1.TXT" , "TEST_L~1.TXT", (byte *)L"TEST_LFN1.TXT" }, /* File name > 8 ext == 3*/
{"TEST_LFN2.TxT" , "TEST_L~2.TXT", (byte *)L"TEST_LFN2.TxT" },
{"TeST_LFN3.TXT" , "TEST_L~3.TXT", (byte *)L"TeST_LFN3.TXT" },
{"TEST_LFN1.TXTA", "TEST_L~4.TXT", (byte *)L"TEST_LFN1.TXTA"}, /* File name > 8 ext == 4*/
{"TEST_LFN2.TxTB", "TEST_L~5.TXT", (byte *)L"TEST_LFN2.TxTB"},
{"TeST_LFN3.TXTC", "TEST_L~6.TXT", (byte *)L"TeST_LFN3.TXTC"},
{"TEST_lFN1.Tx" , "TEST_L~1.TX", (byte *)L"TEST_lFN1.Tx" }, /* File name > 8 ext == 2 */
{"TEST_LfN2.tX" , "TEST_L~2.TX", (byte *)L"TEST_LfN2.tX" },
{"TEST_LFn3.TX" , "TEST_L~3.TX", (byte *)L"TEST_LFn3.TX" },
{"TEST_lFN1.T" , "TEST_L~1.T", (byte *)L"TEST_lFN1.T" }, /* File name > 8 ext == 1 */
{"TEST_LfN2.t" , "TEST_L~2.T", (byte *)L"TEST_LfN2.t" },
{"TEST_LFn3.T" , "TEST_L~3.T", (byte *)L"TEST_LFn3.T" },
{"T2ST_LFN1.TXT" , "T2ST_L~1.TXT", (byte *)L"T2ST_LFN1.TXT" }, /* File name >8 ext == 3*/
{"T2ST_LFN2.TxT" , "T2ST_L~2.TXT", (byte *)L"T2ST_LFN2.TxT" },
{"T2ST_LFN3.TXT" , "T2ST_L~3.TXT", (byte *)L"T2ST_LFN3.TXT" },
{"T2ST_lFN1.Tx" , "T2ST_L~1.TX", (byte *)L"T2ST_lFN1.Tx" }, /* File name == 8 ext == 2 */
{"T2ST_LfN2.tX" , "T2ST_L~2.TX", (byte *)L"T2ST_LfN2.tX" },
{"T2ST_LFn3.TX" , "T2ST_L~3.TX", (byte *)L"T2ST_LFn3.TX" },
{"T2ST_lFN1.TxTA", "T2ST_L~4.TXT", (byte *)L"T2ST_lFN1.TxTA"}, /* File name == 8 ext == 4 */
{"T2ST_LfN2.tXTB", "T2ST_L~5.TXT", (byte *)L"T2ST_LfN2.tXTB"},
{"T2ST_LFn3.TXTC", "T2ST_L~6.TXT", (byte *)L"T2ST_LFn3.TXTC"},
{"T2ST_lFN.T" , "T2ST_LFN.T", (byte *)L"T2ST_lFN.T" }, /* File name == 8 ext == 1 */
{"T2ST_LfN.t", 0, 0}, /* Should fail */
{"TEST.T", "TEST.T", (byte *)L"TEST.T"}, /* File name < 8 ext == 1,2,3,4 */
{"TeST.T", 0, 0}, /* Should fail */
{"SfN.T", "SFN.T", (byte *)L"SfN.T"}, /* Legal SFN except case */
{"sfN.T", 0, 0}, /* Same Legal SFN except case Should fail */
{"TEST.TX" , "TEST.TX" ,(byte *)L"TEST.TX"},
{"TEST.TXT" , "TEST.TXT" ,(byte *)L"TEST.TXT" },
{"TEST.TXTA", "TEST~1.TXT",(byte *)L"TEST.TXTA" },
{"TEST.TXTB", "TEST~2.TXT",(byte *)L"TEST.TXTB" },
{"TEST" , "TEST" , (byte *)L"TEST"}, /* File name < 8 No extension */
{"TeST1" , "TEST1", (byte *)L"TEST1"}, /* No extension */
{"TEsT1" , 0, 0}, /* Same Legal SFN except Should fail */
{"TESt56789" ,"TEST56~1" ,(byte *)L"TESt56789" }, /* File name > 8 No extension */
{"TeST5678A" ,"TEST56~2" ,(byte *)L"TeST5678A" },
{"TESt5678.123" ,"TEST5678.123" ,(byte *)L"TESt5678.123" }, /* File name == 8 extension == 3 */
{"TESt5678.1234" ,"TEST56~1.123" ,(byte *)L"TESt5678.1234" }, /* File name == 8 extension > 3 */
{"TESt5678.12345","TEST56~2.123" ,(byte *)L"TESt5678.12345" }, /* File name == 8 extension > 3 */
{"a", "A" , (byte *)L"a"}, /* File name == 1 extension == 0 */
{"A", 0, 0}, /* Should fail */
{"A.B" , "A.B" , (byte *)L"A.B" }, /* File name == 1 extension == 1 */
{"A.ABC" , "A.ABC" , (byte *)L"A.ABC" }, /* File name == 1 extension == 3 */
{"a.ABCd" , "A~1.ABC", (byte *)L"a.ABCd" }, /* File name == 1 extension == 4 */
{"a.ABCde" , "A~2.ABC", (byte *)L"a.ABCde" }, /* File name == 1 extension == 5 */
{".yyy" , "YYY~1" , (byte *)L".yyy" }, /* File name with leading '.' no extension */
{".y.yy" , "Y~1.YY" , (byte *)L".y.yy" }, /* File name with leading '.' and extension */
{".y.yy.xx", "YYY~1.XX",(byte *)L".y.yy.xx"}, /* File name with leading '.' and extension */
{0,0, 0}
};
static BOOLEAN do_one_long_file_test(int i, int use_unicode);
static BOOLEAN do_more_long_file_tests(BOOLEAN do_clean,int use_charset)
{
int i;
byte *p;
BOOLEAN isExFat;
isExFat = check_if_exfat();
/* Create an empty subdirectory named RTFS_Test_Directory\\RTFS_Test_Directory */
if (pc_isdir(test_dir))
{
if (!pc_deltree(test_dir))
{ regress_error(RGE_DELTREE); goto return_false;}
}
else
{ if (!check_errno(PENOENT)) goto return_false;}
if (!pc_mkdir(test_dir))
{ regress_error(RGE_MKDIR); goto return_false;}
if (!check_errno(0)) goto return_false;
if (!pc_set_cwd(test_dir))
{regress_error(RGE_SCWD); goto return_false;}
if (!check_errno(0)) goto return_false;
/* Create using lfn */
RTFS_PRINT_STRING_1((byte *)"Performing long file name tests", PRFLG_NL); /* "Performing buffered file io test" */
for (i = 0; namepairs[i].lfn; i++)
{
if (!namepairs[i].lfn)
break;
if (!do_one_long_file_test(i, FALSE))
goto return_false;
if (namepairs[i].alias)
{
if (isExFat)
{
/* delete using lfn since there is no alias */
if (!pc_unlink((byte *)namepairs[i].lfn))
{ regress_error(RGE_UNLINK); goto return_false; }
}
else
{
/* Test delete using alias */
if (!pc_unlink((byte *)namepairs[i].alias))
{ regress_error(RGE_UNLINK); goto return_false; }
}
/* Now do it again */
if (!do_one_long_file_test(i, FALSE))
goto return_false;
/* Test delete using lfn */
if (!pc_unlink((byte *)namepairs[i].lfn))
{ regress_error(RGE_UNLINK); goto return_false; }
/* Now do it again */
if (!do_one_long_file_test(i, FALSE))
goto return_false;
}
#if (INCLUDE_CS_UNICODE)
if (namepairs[i].unicode_lfn)
{
if (namepairs[i].alias)
{
/* Test delete using unicode */
if (!pc_unlink_uc((byte *)namepairs[i].unicode_lfn))
{ regress_error(RGE_UNLINK); goto return_false; }
}
/* Test File create using unicode */
if (!do_one_long_file_test(i, TRUE))
goto return_false;
}
#endif
}
/* Now make .. in native char set */
p = (byte *) &test_rtfs_buf[0];
CS_OP_ASSIGN_ASCII(p,'.', use_charset);
CS_OP_INC_PTR(p, use_charset);
CS_OP_ASSIGN_ASCII(p,'.', use_charset);
CS_OP_INC_PTR(p, use_charset);
CS_OP_TERM_STRING(p, use_charset);
if (!pc_set_cwd((byte *) &test_rtfs_buf[0]))
{ regress_error(RGE_SCWD); goto return_false;}
if (!check_errno(0)) goto return_false;
if (do_clean)
{
if (!pc_deltree(test_dir))
{ regress_error(RGE_DELTREE); goto return_false;}
if (!check_errno(0)) goto return_false;
}
RTFS_PRINT_STRING_1((byte *)" ", PRFLG_NL); /* "Performing buffered file io test" */
return(TRUE);
return_false:
RTFS_PRINT_STRING_1((byte *)" ", PRFLG_NL); /* "Performing buffered file io test" */
return(FALSE);
}
static BOOLEAN do_one_long_file_test(int i, int use_unicode)
{
int j;
int fd;
byte *plfn;
DRIVE_INFO drive_info_struture;
BOOLEAN isExFat;
#if (INCLUDE_CS_UNICODE)
if (use_unicode)
{
RTFS_PRINT_STRING_1((byte *)"== Unicode: ", 0);
}
#else
RTFS_ARGSUSED_INT((int) use_unicode);
#endif
if (namepairs[i].alias)
RTFS_PRINT_STRING_1((byte *)"Testing legal file name :\"", 0);
else
RTFS_PRINT_STRING_1((byte *)"Testing illegal file name:\"", 0);
RTFS_PRINT_STRING_1((byte *)namepairs[i].lfn, 0);
RTFS_PRINT_STRING_1((byte *)"\"", PRFLG_NL);
if (!pc_diskio_info(test_drive, &drive_info_struture, TRUE) || drive_info_struture.sector_size > sizeof(test_rtfs_buf))
{
RTFS_PRINT_STRING_1((byte *)"Buffer too small for long file test ", PRFLG_NL);
return(FALSE);
}
isExFat = (BOOLEAN) drive_info_struture.is_exfat;
#if (INCLUDE_CS_UNICODE)
if (use_unicode)
fd = po_open_uc((byte *)namepairs[i].unicode_lfn,(word)(PO_BINARY|PO_WRONLY|PO_CREAT|PO_EXCL),(word)(PS_IWRITE | PS_IREAD));
else
#endif
fd = po_open((byte *)namepairs[i].lfn, (word)(PO_BINARY|PO_WRONLY|PO_CREAT|PO_EXCL),(word)(PS_IWRITE | PS_IREAD));
if (fd < 0)
{
if (namepairs[i].alias) /* If there is an alias, it should have worked */
{
regress_error(RGE_OPEN);
return(FALSE);
}
}
else
{
byte *b;
if (!namepairs[i].alias) /* If there is no alias, it should have failed */
{
regress_error(RGE_OPEN);
return(FALSE);
}
b = (byte *) &test_rtfs_buf[0];
rtfs_memset(b, 0, 256);
rtfs_cs_strcpy(b, (byte *)namepairs[i].lfn, CS_CHARSET_NOT_UNICODE);
po_write(fd, b, 256);
b = (byte *) &test_rtfs_buf[0];
rtfs_memset(b, 0, 256);
rtfs_cs_strcpy(b, (byte *)namepairs[i].alias, CS_CHARSET_NOT_UNICODE);
po_write(fd, b, 256);
po_close(fd);
/* reopen the file using the lfn (unicode and non-unicode) and check contents */
for (j = 0; j < 6; j++)
{
byte *b2;
b = (byte *) &test_rtfs_buf[0];
b2 = b + 256;
rtfs_memset(b, 0, FIVE12);
/*
j == 0 -> po_open lfn
j == 1 -> pc_gfirst lfn
j == 2 -> po_open sfn
j == 3 -> pc_gfirst sfn
j == 4 -> Use po_open_uc
j == 5 -> pc_gfirst_uc
*/
if (j < 2) /* Use lfn and non-unicode interface */
plfn = (byte *) namepairs[i].lfn;
else if (j < 4) /* Use alias and non-unicode interface */
{
if (isExFat) /* No aliases under exFat, skip to the next */
continue;
plfn = (byte *) namepairs[i].alias;
}
else /* Use unicode interface, break if unicode disabled or no unicode in the table */
{
#if (INCLUDE_CS_UNICODE)
plfn = (byte *) namepairs[i].unicode_lfn;
#else
plfn = 0;
#endif
}
if (!plfn)
break;
if (j == 0 || j == 2 || j == 4) /* 0, 2 and 4 use open */
{
#if (INCLUDE_CS_UNICODE)
if (j == 4)
{
fd = po_open_uc((byte *)plfn,(word)(PO_BINARY|PO_RDONLY),(word)(PS_IWRITE | PS_IREAD));
}
else
#endif
{
fd = po_open((byte *)plfn,(word)(PO_BINARY|PO_RDONLY),(word)(PS_IWRITE | PS_IREAD));
}
if (fd < 0)
{
regress_error(RGE_OPEN);
return(FALSE);
}
/* read lfn */
po_read(fd, b, 256);
/* read alias */
po_read(fd, b2, 256);
po_close(fd);
}
else /* 1, 3 and 5 use gfirst */
{
DSTAT statobj;
BOOLEAN gfirst_res;
int blocks_read;
#if (INCLUDE_CS_UNICODE)
if (j == 5)
gfirst_res = pc_gfirst_uc(&statobj, (byte *)plfn);
else
#endif
gfirst_res = pc_gfirst(&statobj, (byte *)plfn);
if (!gfirst_res)
{ regress_error(RGE_GFIRST); return(FALSE);}
if (!pc_gread(&statobj, 1, (byte *)b, &blocks_read) || blocks_read != 1)
{ regress_error(RGE_GREAD); return(FALSE);}
pc_gdone(&statobj);
}
if (rtfs_cs_strcmp(b, (byte *)namepairs[i].lfn, CS_CHARSET_NOT_UNICODE) != 0)
{
regress_error(RGE_READ);
return(FALSE);
}
if (rtfs_cs_strcmp(b2, (byte *)namepairs[i].alias, CS_CHARSET_NOT_UNICODE) != 0)
{
regress_error(RGE_READ);
return(FALSE);
}
}
}
return(TRUE);
}
#endif
/*
<TEST> Verify proper operation of files opened with buffering
<TEST>
<TEST> Open the same file twice simultaneously in buffered mode.
<TEST> verify that the file buffer remains coherent when reads, writes and seeks are are performed on the two file descriptors
<TEST> po_lseek
*/
static BOOLEAN do_buffered_file_test(BOOLEAN do_clean)
{
int fd1, fd2;
word i,j, *wbuff;
wbuff = (word *) &test_rtfs_buf[0];
/* Write 1024 bytes, close to flush, re-open and read */
fd1 = po_open(test_file_name, PO_RDWR|PO_CREAT|PO_TRUNC|PO_BUFFERED, PS_IWRITE|PS_IREAD);
if (fd1 < 0)
{ regress_error(RGE_OPEN); return(FALSE);}
for (i = 0; i < FIVE12; i++)
{
if (po_write(fd1, (byte *)&i, 2) != 2)
{ regress_error(RGE_WRITE); return(FALSE);}
}
po_close(fd1);
fd1 = po_open(test_file_name, PO_RDWR|PO_BUFFERED, 0);
if (fd1 < 0)
{ regress_error(RGE_OPEN); return(FALSE);}
for (i = 0; i < FIVE12; i++)
{
if ( (po_read(fd1, (byte *)&j, 2) != 2) || j != i)
{
{ po_close(fd1); regress_error(RGE_READ); return(FALSE);}
}
}
po_close(fd1);
/* Read two buffered viewports of the same file.
Note: Buffer thrashing occurs here */
fd1 = po_open(test_file_name, PO_RDWR|PO_BUFFERED, PS_IWRITE|PS_IREAD);
if (fd1 < 0)
{ regress_error(RGE_OPEN); return(FALSE);}
fd2 = po_open(test_file_name, PO_RDWR|PO_BUFFERED, PS_IWRITE|PS_IREAD);
if (fd2 < 0)
{ regress_error(RGE_OPEN); po_close(fd1); return(FALSE);}
if (po_lseek(fd2, FIVE12, PSEEK_SET) != FIVE12)
{ regress_error(RGE_SEEK); po_close(fd1); po_close(fd2); return(FALSE);}
for (i = 0; i < 256; i++)
{
int r1, r2;
word v1, v2;
r1 = r2 = 0;
v1 = v2 = 0xfff;
r1 = po_read(fd1, (byte *)&v1, 2);
r2 = po_read(fd2, (byte *)&v2, 2);
if (r1 != 2 || r2 != 2 || v1 != i || v2 != i+256)
{ regress_error(RGE_READ); po_close(fd1); po_close(fd2);return(FALSE);}
}
/* Write buffered, read unbuffered */
if ( (po_lseek(fd1, 0, PSEEK_SET) != 0) || (po_lseek(fd2, 0, PSEEK_SET) != 0))
{ regress_error(RGE_SEEK); po_close(fd1); po_close(fd2);return(FALSE);}
/* Do this in two steps for testing */
for (j = 99, i = 0; i < FIVE12/2; i++)
if (po_write(fd1, (byte *)&j, 2) != 2)
{ regress_error(RGE_WRITE); po_close(fd1); po_close(fd2);return(FALSE);}
for (j = 99, i = 0; i < FIVE12/2; i++)
if (po_write(fd1, (byte *)&j, 2) != 2)
{ regress_error(RGE_WRITE); po_close(fd1); po_close(fd2);return(FALSE);}
if (po_read(fd2, (byte *)wbuff, 1024) != 1024)
{ regress_error(RGE_READ); po_close(fd1); po_close(fd2);return(FALSE);}
for (j = 99, i = 0; i < FIVE12; i++)
{
if (wbuff[i] != j)
{
regress_error(RGE_READ);
po_close(fd1);
po_close(fd2);
return(FALSE);
}
}
/* Seek test */
if ( (po_lseek(fd1, 520, PSEEK_SET) != 520) )
{ regress_error(RGE_SEEK); po_close(fd1); po_close(fd2);return(FALSE);}
j = 520; po_write(fd1, (byte *)&j, 2);
if ( (po_lseek(fd1, 20, PSEEK_SET) != 20) )
{ regress_error(RGE_SEEK); po_close(fd1); po_close(fd2);return(FALSE);}
j = 20; po_write(fd1, (byte *)&j, 2);
if ( (po_lseek(fd1, 520, PSEEK_SET) != 520) )
{ regress_error(RGE_SEEK); po_close(fd1); po_close(fd2);return(FALSE);}
j = 0; po_read(fd1, (byte *)&j, 2);
if (j != 520)
{ regress_error(RGE_READ); po_close(fd1); po_close(fd2);return(FALSE);}
if ( (po_lseek(fd1, 20, PSEEK_SET) != 20) )
{ regress_error(RGE_SEEK); po_close(fd1); po_close(fd2);return(FALSE);}
j = 0; po_read(fd1,(byte *) &j, 2);
if (j != 20)
{ regress_error(RGE_READ); po_close(fd1); po_close(fd2);return(FALSE);}
/* Write buffered and write unbuffered */
if ( (po_lseek(fd1, 0, PSEEK_SET) != 0) || (po_lseek(fd2, 0, PSEEK_SET) != 0))
{ regress_error(RGE_SEEK); po_close(fd1); po_close(fd2);return(FALSE);}
for (i = 0; i < FIVE12; i++)
wbuff[i] = (word) (FIVE12-i);
for (i = 0; i < FIVE12; i++)
if (po_write(fd1, (byte *)&i, 2) != 2)
{ regress_error(RGE_WRITE); po_close(fd1); po_close(fd2);return(FALSE);}
if (po_write(fd2, (byte *)wbuff, 1024) != 1024)
{ regress_error(RGE_WRITE); po_close(fd1); po_close(fd2);return(FALSE);}
po_close(fd1);
if ( po_lseek(fd2, 0, PSEEK_SET) != 0 )
{ regress_error(RGE_SEEK); po_close(fd2);return(FALSE);}
for (i = 0; i < FIVE12; i++)
if ( (po_read(fd2, (byte *)&j, 2) != 2) || j != FIVE12-i)
{ regress_error(RGE_READ); po_close(fd2); return(FALSE);}
po_close(fd2);
if (do_clean)
pc_unlink(test_file_name);
return(TRUE);
}
/*
<TEST> Procedure:Verify proper operation of the pc_gread() API function.
<TEST> Write data to a file and verify that the data can be accessed during a directory
<TEST> enumeration using the pc_gread API call.
*/
static BOOLEAN do_gread_file_test(void)
{
int fd,i, blocks_read,blocks_to_read,sector_size_dwords;
dword value;
DSTAT statobj;
/* Write 1024 bytes, close to flush, re-open and read */
fd = po_open(test_file_name, PO_RDWR|PO_CREAT|PO_TRUNC|PO_BUFFERED, PS_IWRITE|PS_IREAD);
if (fd< 0)
{ regress_error(RGE_OPEN); return(FALSE);}
value = 0;
for (i = 0; i < NLONGS; i++)
test_rtfs_buf[i] = value++;
if (po_write(fd, (byte *)&test_rtfs_buf[0], (NLONGS * 4)) != (NLONGS * 4))
{
regress_error(RGE_WRITE);
return(FALSE);}
po_close(fd);
for (i = 0; i < NLONGS; i++)
test_rtfs_buf[i] = 0;
if (!pc_gfirst(&statobj, test_file_name))
{ regress_error(RGE_GFIRST); return(FALSE);}
sector_size_dwords = pc_sector_size(test_drive)/4;
if (sector_size_dwords > NLONGS)
blocks_to_read = 1;
else
blocks_to_read = ((NLONGS+(sector_size_dwords-1))/sector_size_dwords);
if (!pc_gread(&statobj, blocks_to_read, (byte *)&test_rtfs_buf[0], &blocks_read) || blocks_read != blocks_to_read)
{
regress_error(RGE_GREAD); return(FALSE);}
pc_gdone(&statobj);
value = 0;
for (i = 0; i < (NLONGS/128)*128; i++)
{
if (test_rtfs_buf[i] != value++)
{ regress_error(RGE_GFIRST); return(FALSE);}
}
pc_unlink(test_file_name);
return(TRUE);
}
#define FOUR_GIG_BLOCKS 0x80000
#define ONE_MEG (dword) 0x100000
#define ONE_MEG_SHY (0x100000-FIVE12)
#define FILL_TEST_HIT_WRAP 0
#define DO_LARGE_FILE_TEST 1
#ifndef RTFS_MAX_FILE_SIZE /* BUGFIX */
/* Must be ProPlus because it doesn't use these compile time constants. So set them to
correct values for this test under ProPlus */
#define RTFS_MAX_FILE_SIZE 0xffffffff
#define RTFS_TRUNCATE_WRITE_TO_MAX 1
#endif
/*
<TEST> Procedure:Test correct behavior with large (4 Gig) files
<TEST> Verify proper operation of a 32 bit file when it is almost full (4 Gigabytes)
<TEST> Verify that file write and file extends behave appropriately when the maximum file size is reached.
<TEST> Verify that file read behaves appropriately when the maximum file size is reached.
<TEST> Verify that file seek behaves appropriately over the range including The maximum file size is reached.
*/
#if (DO_LARGE_FILE_TEST)
static BOOLEAN do_large_file_test(void)
{
int residual,fd;
dword i, max_filesize_megs,ltemp,ltemp2,target_value,blocks_total,blocks_free;
ERTFS_STAT stat_buff;
max_filesize_megs = RTFS_MAX_FILE_SIZE/ONE_MEG;
ltemp = max_filesize_megs * ONE_MEG;
ltemp2 = (RTFS_MAX_FILE_SIZE-ltemp);
residual = (int)ltemp2;
/* Won't work on a 16 bit machine */
if ((dword) residual != ltemp2)
return(FALSE);
if (residual == 0)
{
max_filesize_megs -= 1;
residual = ONE_MEG;
}
pc_blocks_free(test_drive, &blocks_total, &blocks_free);
if (blocks_free/2048 <= max_filesize_megs) /* Not enough space to do long test */
return(TRUE);
#if (VERBOSE)
RTFS_PRINT_STRING_1((byte *)"Performing Large 4GIG File io test",PRFLG_NL); /* "Performing Large 4GIG File io test" */
#endif
/* Test read, write, ulseek, chsize, extend file */
fd = po_open(test_file_name, PO_RDWR|PO_CREAT|PO_EXCL, PS_IWRITE|PS_IREAD);
if (fd < 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (!check_errno(0)) return(FALSE);
test_rtfs_buf[0] = 0;
/* Write the file - 1 meg at a time */
for (i = 0 ; i < max_filesize_megs; i++)
{
if (po_write(fd, (byte *) test_rtfs_buf, FIVE12) != FIVE12)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (po_write(fd, (byte *) 0, ONE_MEG_SHY) != ONE_MEG_SHY)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
test_rtfs_buf[0] += ONE_MEG;
}
if (check_if_exfat())
{
if ((dword) residual != 0)
if (po_write(fd, (byte *) 0, residual) != residual)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
}
else
{
/* The last meg will be truncated */
#if(FILL_TEST_HIT_WRAP)
#if (RTFS_TRUNCATE_WRITE_TO_MAX)
if (po_write(fd, (byte *) 0, residual+1) != residual)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (po_write(fd, (byte *) 0, 1) != 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
#else
if (po_write(fd, (byte *) 0, residual+1) != -1)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (po_write(fd, (byte *) 0, residual) != residual)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
#endif
#else
/* The last meg will be truncated */
if (po_write(fd, (byte *) test_rtfs_buf, FIVE12) != FIVE12)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
#if (RTFS_TRUNCATE_WRITE_TO_MAX)
{
if (po_write(fd, (byte *) 0, ONE_MEG) != (residual-FIVE12))
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
}
#else
if (po_write(fd, (byte *) 0, ONE_MEG) != -1)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (po_write(fd, (byte *) 0, (residual-FIVE12)) != (residual-FIVE12))
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
#endif
#endif
}
/* Read it back - 1 gig at a time */
if (!po_ulseek(fd, 0, &ltemp, PSEEK_SET))
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
/* Read the file - 1 gig at a time */
target_value = 0;
for (i = 0 ; i < max_filesize_megs; i++)
{
if ( (po_read(fd, (byte *) test_rtfs_buf, FIVE12) != FIVE12) ||
(test_rtfs_buf[0] != target_value) )
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
target_value += ONE_MEG;
if (po_read(fd, (byte *) 0, ONE_MEG_SHY) != ONE_MEG_SHY)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
}
if (check_if_exfat())
{
if (po_read(fd, (byte *) 0, residual) != residual)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
}
else
{
/* The last meg will be truncated */
#if (FILL_TEST_HIT_WRAP)
if (po_read(fd, (byte *) 0, ONE_MEG) != residual)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (po_read(fd, (byte *) 0, ONE_MEG) != 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
#else
if ( (po_read(fd, (byte *) test_rtfs_buf, FIVE12) != FIVE12) ||
(test_rtfs_buf[0] != target_value))
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (po_read(fd, (byte *) 0, ONE_MEG) != residual-FIVE12)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
#endif
#if (FILL_TEST_HIT_WRAP)
po_close(fd);
goto unlink_it;
#endif
}
if (check_if_exfat()) /* Thorough seek test already performed and these test assume a maximum size */
goto around_seek_test;
/* Test seek set */
/* Test po_ulseek */
/* Test seek end */
if (!po_ulseek(fd, 0, &ltemp, PSEEK_END) || ltemp != RTFS_MAX_FILE_SIZE)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
/* Test seek curr neg */
target_value = (dword) (max_filesize_megs * ONE_MEG);
if (!po_ulseek(fd, residual, &ltemp, PSEEK_CUR_NEG) || ltemp != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (!po_ulseek(fd, 0, &ltemp, PSEEK_CUR_NEG) ||
ltemp != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if ( (po_read(fd, (byte *) test_rtfs_buf, FIVE12) != FIVE12) ||
(test_rtfs_buf[0] != target_value))
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (!po_ulseek(fd, FIVE12, &ltemp, PSEEK_CUR_NEG) ||
ltemp != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
target_value -= (10 * ONE_MEG);
if (!po_ulseek(fd, 10 * ONE_MEG, &ltemp, PSEEK_CUR_NEG) || ltemp != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if ( (po_read(fd, (byte *) test_rtfs_buf, FIVE12) != FIVE12) ||
(test_rtfs_buf[0] != target_value))
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (!po_ulseek(fd, FIVE12, &ltemp, PSEEK_CUR_NEG) ||
ltemp != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
/* Test seek curr positive */
target_value += (4 * ONE_MEG);
if (!po_ulseek(fd, 4 * ONE_MEG, &ltemp, PSEEK_CUR) || ltemp != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if ( (po_read(fd, (byte *) test_rtfs_buf, FIVE12) != FIVE12) ||
(test_rtfs_buf[0] != target_value))
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (!po_ulseek(fd, FIVE12, &ltemp, PSEEK_CUR_NEG) ||
ltemp != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (!po_ulseek(fd, 0, &ltemp, PSEEK_CUR) ||
ltemp != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
/* Test seek set */
target_value = (4 * ONE_MEG);
if (!po_ulseek(fd, target_value, &ltemp, PSEEK_SET) || ltemp != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if ( (po_read(fd, (byte *) test_rtfs_buf, FIVE12) != FIVE12) ||
(test_rtfs_buf[0] != target_value))
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
target_value = ((max_filesize_megs - 1000) * ONE_MEG);
if (!po_ulseek(fd, target_value, &ltemp, PSEEK_SET) || ltemp != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if ( (po_read(fd, (byte *) test_rtfs_buf, FIVE12) != FIVE12) ||
(test_rtfs_buf[0] != target_value))
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
/* Test fstat set */
if (pc_fstat(fd, &stat_buff) != 0 || stat_buff.st_size != RTFS_MAX_FILE_SIZE)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (po_close(fd) != 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
/* Test stat set */
if (pc_stat(test_file_name, &stat_buff) != 0 || stat_buff.st_size != RTFS_MAX_FILE_SIZE)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
/* Test reopen */
fd = po_open(test_file_name, PO_RDWR, PS_IWRITE|PS_IREAD);
if (fd < 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (!po_ulseek(fd, 0, &ltemp, PSEEK_END) || ltemp != RTFS_MAX_FILE_SIZE)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
target_value = ((max_filesize_megs - 1000) * ONE_MEG);
if (!po_ulseek(fd, target_value, &ltemp, PSEEK_SET) || ltemp != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if ( (po_read(fd, (byte *) test_rtfs_buf, FIVE12) != FIVE12) ||
(test_rtfs_buf[0] != target_value))
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
/* Test fstat */
if (pc_fstat(fd, &stat_buff) != 0 || stat_buff.st_size != RTFS_MAX_FILE_SIZE)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
around_seek_test:
/* Test chsize (truncate) to zero */
target_value = 0;
if (po_chsize(fd, target_value) != 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (pc_fstat(fd, &stat_buff) != 0 || stat_buff.st_size != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (po_close(fd) != 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (pc_stat(test_file_name, &stat_buff) != 0 || stat_buff.st_size != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
/* Test chsize (expand) to RTFS_MAX_FILE_SIZE */
fd = po_open(test_file_name, PO_RDWR, PS_IWRITE|PS_IREAD);
if (fd < 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
target_value = RTFS_MAX_FILE_SIZE;
if (po_chsize(fd, target_value) != 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (pc_fstat(fd, &stat_buff) != 0 || stat_buff.st_size != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (po_close(fd) != 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (pc_stat(test_file_name, &stat_buff) != 0 || stat_buff.st_size != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
/* Test chsize (expand) to RTFS_MAX_FILE_SIZE */
fd = po_open(test_file_name, PO_RDWR, PS_IWRITE|PS_IREAD);
if (fd < 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
target_value = RTFS_MAX_FILE_SIZE;
if (po_chsize(fd, target_value) != 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (pc_fstat(fd, &stat_buff) != 0 || stat_buff.st_size != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (po_close(fd) != 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (pc_stat(test_file_name, &stat_buff) != 0 || stat_buff.st_size != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
/* Test chsize (truncate) to 4000 meg */
fd = po_open(test_file_name, PO_RDWR, PS_IWRITE|PS_IREAD);
if (fd < 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
target_value = ((max_filesize_megs - 1000) * ONE_MEG);
if (po_chsize(fd, target_value) != 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (pc_fstat(fd, &stat_buff) != 0 || stat_buff.st_size != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (po_close(fd) != 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (pc_stat(test_file_name, &stat_buff) != 0 || stat_buff.st_size != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
/* Test chsize (truncate) to 1000 meg */
fd = po_open(test_file_name, PO_RDWR, PS_IWRITE|PS_IREAD);
if (fd < 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
target_value = (1000 * ONE_MEG);
if (po_chsize(fd, target_value) != 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (pc_fstat(fd, &stat_buff) != 0 || stat_buff.st_size != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (po_close(fd) != 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (pc_stat(test_file_name, &stat_buff) != 0 || stat_buff.st_size != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
/* Test chsize (expand) to ffffffff0 */
fd = po_open(test_file_name, PO_RDWR, PS_IWRITE|PS_IREAD);
if (fd < 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
target_value = RTFS_MAX_FILE_SIZE-16;
if (po_chsize(fd, target_value) != 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (pc_fstat(fd, &stat_buff) != 0 || stat_buff.st_size != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (po_close(fd) != 0)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
if (pc_stat(test_file_name, &stat_buff) != 0 || stat_buff.st_size != target_value)
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
#if (FILL_TEST_HIT_WRAP)
unlink_it:
#endif
if (!pc_unlink(test_file_name))
{ regress_error(RGE_LARGEFILETEST); return(FALSE);}
return(TRUE);
}
//=====
#endif /* (DO_LARGE_FILE_TEST) */
/*
<TEST> Procedure: Test file behavior when handles are opened multiple times
<TEST> Test file create, reopen, close, flush and delete operations files
<TEST> Verify proper operation of exclusive and shared open modes
<TEST> Verify proper operation when a file is opened multiple times simulteously
<TEST> Verify proper operation of functions (delete, chsize) that require exclusive access to a file
*/
static int fdarray[250];
/* Test file manipulation routines */
static BOOLEAN do_file_test(int loop_count, BOOLEAN do_clean)
{
int i;
int j;
dword index;
dword di;
int ntestfiles = prtfs_cfg->cfg_NUSERFILES;
if (ntestfiles >= 250)
ntestfiles = 250;
#if (DO_LARGE_FILE_TEST)
if (!loop_count)
{
if (!do_large_file_test())
return(FALSE);
#if (INCLUDE_MATH64)
if (!do_comprehensive_filio_test())
return(FALSE);
#endif
}
#endif
#if (VERBOSE)
RTFS_PRINT_STRING_1((byte *)"Performing File io test",PRFLG_NL); /* "Performing File io test" */
#endif
fdarray[0] = po_open(test_file_name, PO_RDWR|PO_CREAT|PO_EXCL, PS_IWRITE|PS_IREAD);
if (fdarray[0] < 0)
{ regress_error(RGE_OPEN); return(FALSE);}
if (!check_errno(0)) return(FALSE);
for (i = 1; i < ntestfiles;i++)
{
/* This should fail */
fdarray[i] = po_open(test_file_name, PO_RDWR|PO_CREAT|PO_EXCL, PS_IWRITE|PS_IREAD);
if (fdarray[i] >= 0)
{ regress_error(RGE_OPEN); return(FALSE);}
if (!check_errno(PEEXIST)) return(FALSE);
/* This should work */
fdarray[i] = po_open(test_file_name, PO_RDWR, PS_IWRITE|PS_IREAD);
if (fdarray[i] < 0)
{ regress_error(RGE_OPEN); return(FALSE);}
if (!check_errno(0)) return(FALSE);
}
/* Write into the file using all file descriptors */
index = 0;
for (i = 0; i < ntestfiles;i++)
{
if (po_lseek(fdarray[i], 0L, PSEEK_END) == -1L)
{ regress_error(RGE_SEEK); return(FALSE);}
if (!check_errno(0)) return(FALSE);
for (j = 0; j < NLONGS; j++)
test_rtfs_buf[j] = index++;
if (po_write(fdarray[i], (byte *) test_rtfs_buf, (NLONGS*4)) != (NLONGS*4))
{ regress_error(RGE_WRITE); return(FALSE);}
if (!check_errno(0)) return(FALSE);
}
/* Read file using all fds */
index = 0;
for (i = 0; i < ntestfiles;i++)
{
if (po_lseek(fdarray[i], (dword) (index*4), PSEEK_SET) != (long) (index*4))
{ regress_error(RGE_SEEK); return(FALSE);}
if (!check_errno(0)) return(FALSE);
if (po_read(fdarray[i], (byte *) test_rtfs_buf, (NLONGS*4)) != (NLONGS*4))
{ regress_error(RGE_READ); return(FALSE);}
if (!check_errno(0)) return(FALSE);
for (j = 0; j < NLONGS; j++)
{
if (test_rtfs_buf[j] != index++)
{ regress_error(RGE_READ); return(FALSE);}
}
}
/* This should fail if more than one file is open */
if (ntestfiles > 1)
{
if (po_truncate(fdarray[0], 256))
{ regress_error(RGE_TRUNC); return(FALSE);}
if (!check_errno(PEACCES)) return(FALSE);
}
if (!po_flush(fdarray[0]))
{ regress_error(RGE_FLUSH); return(FALSE);}
if (!check_errno(0)) return(FALSE);
/* Close all secondary files */
for (i = 1; i < ntestfiles;i++)
{
if (po_close(fdarray[i]) != 0)
{ regress_error(RGE_CLOSE); return(FALSE);}
if (!check_errno(0)) return(FALSE);
}
/* This should work */
if (!po_truncate(fdarray[0], 256))
{ regress_error(RGE_TRUNC); return(FALSE);}
if (!check_errno(0)) return(FALSE);
/* This should work */
for (di = 0; di < 64 * 1024; di += 1024)
{
if (po_chsize(fdarray[0], di) != 0)
{ regress_error(RGE_CHSIZE); return(FALSE);}
if (!check_errno(0)) return(FALSE);
}
/* This should work */
for (di = 63 * 1024; di; di -= 1024)
{
if (po_chsize(fdarray[0], di) != 0)
{ regress_error(RGE_CHSIZE); return(FALSE);}
if (!check_errno(0)) return(FALSE);
}
/* This should fail */
if (pc_unlink(test_file_name))
{ regress_error(RGE_UNLINK); return(FALSE);}
if (!check_errno(PEACCES)) return(FALSE);
if (po_close(fdarray[0]) != 0)
{ regress_error(RGE_CLOSE); return(FALSE);}
if (!check_errno(0)) return(FALSE);
if (!pc_mv(test_file_name, test_newfile_name))
{ regress_error(RGE_MV); return(FALSE);}
if (!check_errno(0)) return(FALSE);
/* This should work */
/* Manually delete on odd loops, even loops use deltree */
if (do_clean && (loop_count & 1))
{
if (!pc_unlink(test_newfile_name))
{ regress_error(RGE_UNLINK); return(FALSE);}
if (!check_errno(0)) return(FALSE);
}
return(TRUE);
}
/*
<TEST> Procedure:Test correct operation of append
<TEST>
<TEST> Verify that po_open with append mode correctly appends to the end of the file
<TEST> after a file is reopened or after the file pointer has been moved.
*/
/* Test file manipulation routines */
static BOOLEAN do_append_test(void)
{
int i,j,fd, residual;
dword index = 0;
dword expected_file_size = 0;
byte *pb;
ERTFS_STAT stat_buff;
#if (VERBOSE)
RTFS_PRINT_STRING_1((byte *)"Performing File append test",PRFLG_NL);
#endif
/* Delete the test file if it exists */
pc_unlink(test_file_name);
residual = (NLONGS*4) - 1;
index = 0;
/* write to the file in append mode and be sure everything works correctly */
for (i = 0; i < 128;i++) /* Make 256K file using append (NLONGS == FIVE12) */
{
for (j = 0; j < NLONGS; j++)
test_rtfs_buf[j] = index++;
fd = po_open(test_file_name, PO_RDWR|PO_CREAT|PO_APPEND, PS_IWRITE|PS_IREAD);
if (fd < 0)
{ regress_error(RGE_OPEN); return(FALSE);}
if (!check_errno(0)) return(FALSE);
if (pc_fstat(fd, &stat_buff) != 0 || stat_buff.st_size != expected_file_size)
{ regress_error(RGE_APPENDFILETEST); return(FALSE);}
pb = (byte *) test_rtfs_buf;
/* Write one byte, then seek to beginning and write the rest */
if (po_write(fd, (byte *) pb, 1) != 1)
{ regress_error(RGE_WRITE); return(FALSE);}
pb += 1;
if (po_lseek(fd, 0L, PSEEK_SET) != 0)
{ regress_error(RGE_SEEK); return(FALSE);}
if (po_write(fd, (byte *) pb, residual) != residual) /* Should append */
{ regress_error(RGE_WRITE); return(FALSE);}
expected_file_size += (NLONGS*4);
if (pc_fstat(fd, &stat_buff) != 0 || stat_buff.st_size != expected_file_size)
{ regress_error(RGE_APPENDFILETEST); return(FALSE);}
po_close(fd);
}
/* Read the file and verify contents */
index = 0;
fd = po_open(test_file_name, PO_RDONLY, PS_IWRITE|PS_IREAD);
if (fd < 0)
{ regress_error(RGE_OPEN); return(FALSE);}
for (i = 0; i < 128;i++)
{
if (po_read(fd, (byte *) test_rtfs_buf, (NLONGS*4)) != (NLONGS*4))
{ regress_error(RGE_READ); return(FALSE);}
if (!check_errno(0)) return(FALSE);
for (j = 0; j < NLONGS; j++)
{
if (test_rtfs_buf[j] != index++)
{ regress_error(RGE_READ); return(FALSE);}
}
}
po_close(fd);
pc_unlink(test_file_name);
return(TRUE);
}
/*
<TEST> Procedure:Test correct operation of po_lseek()
<TEST>
<TEST> verify that po_lseek() works correctly
<TEST> po_lseek() with negative offsets is performed by changing the sign if
<TEST> and using an unsigned file pointer move.
<TEST> This test creates a 16 byte file and verifies that the following arguments result in the the following results.
<TEST> origin offset returns errno
<TEST> PSEEK_SET 0 0 0
<TEST> -1 -1 PEINVALIDPARMS
<TEST> 8 8 0
<TEST> 16 16 0
<TEST> 17 16 0 ??
<TEST> PSEK_CUR 0 8 0 (from current postion=8)
<TEST> -9 0 0
<TEST> -8 0 0
<TEST> 8 16 0 ?
<TEST> 9 16 0
<TEST> PSEEK_END 0 16 0
<TEST> 1 -1 PEINVALIDPARMS
<TEST> -9 9 0
<TEST> -16 0 0
<TEST> -17 0 0 ??
*/
/* Test po_lseek() (signed seek) */
static BOOLEAN do_one_po_lseek_test(int fd, int origin, int offset, int expected_return, int expected_errno)
{
if (origin == PSEEK_CUR)
{ /* Seek curr test starts from origin 8 */
if (po_lseek(fd, 8, PSEEK_SET) != 8)
{
regress_error(RGE_SEEK);
return(FALSE);
}
}
if (po_lseek(fd, offset, origin) == expected_return)
{
return(check_errno(expected_errno));
}
regress_error(RGE_SEEK);
return(FALSE);
}
static BOOLEAN do_po_lseek_test(void)
{
int fd;
#if (VERBOSE)
RTFS_PRINT_STRING_1((byte *)"Performing po_lseek (signed seek) test",PRFLG_NL);
#endif
/* Delete the test file if it exists */
pc_unlink(test_file_name);
fd = po_open(test_file_name, PO_RDWR|PO_CREAT, PS_IWRITE|PS_IREAD);
if (fd < 0)
{ regress_error(RGE_OPEN); return(FALSE);}
if (po_write(fd, (byte *) &test_rtfs_buf[0], 16) != 16)
{ regress_error(RGE_WRITE); return(FALSE);}
po_close(fd);
fd = po_open(test_file_name, PO_RDWR, PS_IWRITE|PS_IREAD);
if (fd < 0)
{ regress_error(RGE_OPEN); return(FALSE);}
/* PSEEK_SET 0 0 0
-1 16 0
16 16 0
17 16 0 ?? */
if (!do_one_po_lseek_test(fd, PSEEK_SET, 0, 0, 0)) return(FALSE);
if (!do_one_po_lseek_test(fd, PSEEK_SET, -1, -1, PEINVALIDPARMS)) return(FALSE);
if (!do_one_po_lseek_test(fd, PSEEK_SET, 8, 8, 0)) return(FALSE);
if (!do_one_po_lseek_test(fd, PSEEK_SET, 16, 16, 0)) return(FALSE);
if (!do_one_po_lseek_test(fd, PSEEK_SET, 17, 16, 0)) return(FALSE);
/* PSEK_CUR 0 8 0 (from current postion=8)
-9 0 0
-8 0 0
8 16 0 ?
9 16 0 */
if (!do_one_po_lseek_test(fd, PSEEK_CUR, 0, 8, 0)) return(FALSE);
if (!do_one_po_lseek_test(fd, PSEEK_CUR, -9, 0, 0)) return(FALSE);
if (!do_one_po_lseek_test(fd, PSEEK_CUR, -8, 0, 0)) return(FALSE);
if (!do_one_po_lseek_test(fd, PSEEK_CUR, 8, 16, 0)) return(FALSE);
if (!do_one_po_lseek_test(fd, PSEEK_CUR, 9, 16, 0)) return(FALSE);
/* PSEEK_END 0 16 0
1 15 0
-16 0 0
-17 0 0 ?? */
if (!do_one_po_lseek_test(fd, PSEEK_END, 0, 16, 0)) return(FALSE);
if (!do_one_po_lseek_test(fd, PSEEK_END, 1, -1, PEINVALIDPARMS)) return(FALSE);
if (!do_one_po_lseek_test(fd, PSEEK_END, -9, 7, 0)) return(FALSE);
if (!do_one_po_lseek_test(fd, PSEEK_END, -16, 0, 0)) return(FALSE);
if (!do_one_po_lseek_test(fd, PSEEK_END, -17, 0, 0)) return(FALSE);
po_close(fd);
pc_unlink(test_file_name);
return(TRUE);
}
/*
<TEST> Procedure:Test correct errno setting
<TEST>
<TEST> Every API call that is made by the basic regression test is followed by a check
<TEST> of the errno setting.
<TEST> Verify that errno is cleaerd when there is no error
<TEST> Verify that errno contains the correct value when API calls return an error status
*/
static BOOLEAN check_errno(int expected_error)
{
int current_errno;
current_errno = get_errno();
if (current_errno != expected_error)
{
regress_error(RGE_ERRNO);
RTFS_PRINT_LONG_1((dword) get_errno(), PRFLG_NL);
return(FALSE);
}
else
{
rtfs_set_errno(PEILLEGALERRNO, __FILE__, __LINE__); /* Set it to illegal, it should be cleared */
return(TRUE);
}
}
static BOOLEAN check_if_exfat(void)
{
DRIVE_INFO drive_info_struture;
if (!pc_diskio_info(test_drive, &drive_info_struture, TRUE))
{
RTFS_PRINT_STRING_1((byte *)"Drive info failed ", PRFLG_NL);
return(FALSE);
}
return(drive_info_struture.is_exfat);
}
/*
<TEST> Procedure:Test correct operation of the check disk utility.
<TEST>
<TEST> Create lost cluster chains and verify that checkdisk can find and remove
<TEST> the lost chains.
*/
/*
<TEST> Procedure:Test correct operation of the check disk utility.
<TEST>
<TEST> Create lost cluster chains and verify that checkdisk can find and remove
<TEST> the lost chains.
*/
/* See appcmdsh.c */
extern byte cmdshell_check_disk_scratch_memory[];
extern dword cmdshell_size_check_disk_scratch_memory;
/* Test operation of checkdisk */
static BOOLEAN create_lost_chains(int n_chains,dword clusters_per_chain);
void rtfs_print_one_string(byte *pstr,int flags);
#define REGRESS_CHKDSK_VERBOSE 0 /* or CHKDSK_VERBOSE */
#ifdef RTFS_MAJOR_VERSION
/* Version 6 drive info access */
#define DRIVE_INFO(D,F) D->drive_info.F
#define heapfragfilename (byte *) "BIGFRAG"
#define fragfilename (byte *) "FRAG"
#define brokenfile1 (byte *) "BROKEN1"
#define brokenfile2 (byte *) "BROKEN2"
#define root_dir (byte *) "\\"
#else
#define INCLUDE_VFAT VFAT
#define DRIVE_INFO(D,F) D->F
#define fatop_pfaxx(D, CLUSTER, VALUE) FATOP(D)->fatop_pfaxx(D, CLUSTER, VALUE)
#define fatop_flushfat(D) FATOP(D)->fatop_flushfat(D->driveno)
/* Rtfs 4 emulations of Rtfs 6 functions and structures */
typedef struct region_fragment {
dword start_location;
dword end_location;
struct region_fragment *pnext;
} REGION_FRAGMENT;
#if (INCLUDE_CS_UNICODE)
#define heapfragfilename (byte *) L"BIGFRAG"
#define fragfilename (byte *) L"FRAG"
#define brokenfile1 (byte *) L"BROKEN1"
#define brokenfile2 (byte *) L"BROKEN2"
#define root_dir (byte *) L"\\"
#else
#define heapfragfilename (byte *)"BIGFRAG"
#define fragfilename (byte *) "FRAG"
#define brokenfile1 (byte *) "BROKEN1"
#define brokenfile2 (byte *) "BROKEN2"
#define root_dir (byte *) "\\"
#endif
#endif
/* See apichkdsk.c */
#define CHKDSK_FAT_EOF_VAL 0xffffffff
#define CHKDSK_FAT_ERROR_VAL 0xfffffffe
dword chkdsk_next_cluster(DDRIVE *pdr, dword cluster);
void chkdsk_build_chk_name(byte *pretname, dword file_no);
static DDRIVE *path_to_drive_struct(byte *path);
static dword test_drive_cluster_size_bytes(byte *path);
static BOOLEAN chktest_create_one_file(byte *file_name, int n_clusters, int cl_per_write, int interleaf);
static BOOLEAN chktest_getset_fcluster(byte *file_name, BOOLEAN isset, dword sval, dword *rval);
static BOOLEAN chktest_getset_fsize(byte *file_name, BOOLEAN isset, dword sval, dword *rval);
static int chktest_load_cluster_list(byte *file_name, int list_size, REGION_FRAGMENT *pcluster_list);
static BOOLEAN chkdsk_test_lost_clusters(CHKDSK_CONTEXT *pchkcontext, int scratch_memory_size, dword n_test_chains, dword clusters_per_chain,BOOLEAN do_check_files);
static BOOLEAN _do_chkdsk_test(int scratch_memory_size);
static dword chkdisk_cluster_by_offset(dword offset, REGION_FRAGMENT *pregion_array);
static BOOLEAN chktest_remove_check_files(dword n_test_chains);
static BOOLEAN chktest_check_check_files(dword n_test_chains, dword clusters_per_chain,int scratch_memory_size);
static BOOLEAN do_chkdsk_test(void)
{
if (!pc_set_default_drive(test_drive))
return(FALSE);
if (!pc_set_cwd(root_dir))
return(FALSE);
rtfs_print_one_string((byte *)"Fragmenting freespace to force multiple fat scans", PRFLG_NL);
/* Create a file with 400 interleaved clusters this will fragment freespace and force check disk to perform multiple scans */
if (!chktest_create_one_file(heapfragfilename, 400,1,1))
{
rtfs_print_one_string((byte *)"Failed fragmenting the disk", PRFLG_NL);
return (FALSE);
}
pc_diskflush(test_drive);
if (!_do_chkdsk_test(200 * sizeof(REGION_FRAGMENT)))
{
pc_unlink(heapfragfilename);
return(FALSE);
}
pc_unlink(heapfragfilename);
return(TRUE);
}
static BOOLEAN _do_chkdsk_test(int scratch_memory_size)
{
CHKDISK_STATS chkstat;
CHKDSK_CONTEXT chkcontext;
/*dword current_lost_cluster,current_crossed_points,current_bad_lfns; */
DDRIVE *test_drive_structure;
int test_iteration;
dword file_delete_option = 0;
rtfs_print_one_string((byte *)"Testing check disk", PRFLG_NL);
test_drive_structure = path_to_drive_struct(test_drive);
if (!test_drive_structure)
return(FALSE);
/* Scan the disk first */
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
{
rtfs_print_one_string((byte *)"Checkdisk failed", PRFLG_NL);
return(FALSE);
}
while (chkstat.n_lost_chains)
{
rtfs_print_one_string((byte *)"Cleaning lost chains to start n_lost == ", 0);
rtfs_print_long_1(chkstat.n_lost_chains, PRFLG_NL);
if (!pc_check_disk_ex(test_drive, &chkstat, (REGRESS_CHKDSK_VERBOSE|CHKDSK_FIXPROBLEMS|CHKDSK_FREELOSTCLUSTERS), &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
{
rtfs_print_one_string((byte *)"Checkdisk failed", PRFLG_NL);
return(FALSE);
}
}
if (!chkdsk_test_lost_clusters(&chkcontext, scratch_memory_size, 300, 1, TRUE)) /* Check 300 lost cluster chains one cluster per file, create check files */
return (FALSE);
if (!chkdsk_test_lost_clusters(&chkcontext, scratch_memory_size, 20, 1, FALSE)) /* Check 20 lost cluster chains one cluster per file, free lost clusters */
return (FALSE);
if (!chkdsk_test_lost_clusters(&chkcontext, scratch_memory_size, 20, 1, TRUE)) /* Check 20 lost cluster chains one cluster per file, create check files */
return (FALSE);
if (!chkdsk_test_lost_clusters(&chkcontext, scratch_memory_size, 100, 1, FALSE)) /* Check 100 lost cluster chains one cluster per file, free lost clusters */
return (FALSE);
if (!chkdsk_test_lost_clusters(&chkcontext, scratch_memory_size, 100, 1, TRUE)) /* Check 100 lost cluster chains one cluster per file, create check files */
return (FALSE);
if (!chkdsk_test_lost_clusters(&chkcontext, scratch_memory_size, 300, 1, FALSE)) /* Check 300 lost cluster chains one cluster per file, free lost clusters */
return (FALSE);
if (!chkdsk_test_lost_clusters(&chkcontext, scratch_memory_size, 300, 1, TRUE)) /* Check 300 lost cluster chains one cluster per file, create check files */
return (FALSE);
/* Test check file creation */
/* ======================== */
/* Test file looping on itself */
rtfs_print_one_string((byte *)"Testing an endless loop in a file\'s cluster chain", PRFLG_NL);
{
REGION_FRAGMENT file_fragments[20];
int n_fragments;
/* Create a file with 10 clusters in 5 fragments 2 clusters each */
if (!chktest_create_one_file(brokenfile1, 10,2,1))
{
endless_file_test_failed:
rtfs_print_one_string((byte *)"File endless loop test failed ", PRFLG_NL);
return (FALSE);
}
/* Get the list */
n_fragments=chktest_load_cluster_list(brokenfile1, 10, &file_fragments[0]);
if (n_fragments < 5)
goto endless_file_test_failed;
/* Loop it, point the 4th fragment at the 3rd */
if (!fatop_pfaxx(test_drive_structure, file_fragments[3].start_location, file_fragments[2].start_location))
goto endless_file_test_failed;
if (!fatop_flushfat(test_drive_structure))
goto endless_file_test_failed;
/* Now check again, should be endless loop status */
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto endless_file_test_failed;
if (!chkstat.has_endless_loop)
goto endless_file_test_failed;
/* Now clear it */
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE|CHKDSK_FIXPROBLEMS|CHKDSK_FREELOSTCLUSTERS, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto endless_file_test_failed;
if (!chkstat.has_endless_loop) /* Should still report it */
goto endless_file_test_failed;
/* Note: the number of freed clusters is wrong */
/* Now check again, endless loop status should be cleared */
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto endless_file_test_failed;
if (chkstat.has_endless_loop)
goto endless_file_test_failed;
}
/* ======================== */
/* Test directory looping on itself */
/* ======================== */
/* Test crossed files */
rtfs_print_one_string((byte *)"Testing files with crossed cluster chains", PRFLG_NL);
for (test_iteration = 0; test_iteration < 2; test_iteration++)
{
REGION_FRAGMENT file1_fragments[20];
REGION_FRAGMENT file2_fragments[20];
int n_fragments;
/* Create one file with 10 clusters in 5 fragments 2 clusters each */
if (!chktest_create_one_file(brokenfile1, 10,2,1))
{
crossed_file_test_failed:
rtfs_print_one_string((byte *)"File crossed chain test failed ", PRFLG_NL);
return (FALSE);
}
/* Get the list */
n_fragments=chktest_load_cluster_list(brokenfile1, 10, &file1_fragments[0]);
if (n_fragments < 5)
goto crossed_file_test_failed;
/* Create one file with 10 clusters in 5 fragments 2 clusters each */
if (!chktest_create_one_file(brokenfile2, 10,2,1))
goto crossed_file_test_failed;
/* Get the list */
n_fragments=chktest_load_cluster_list(brokenfile2, 10, &file2_fragments[0]);
if (n_fragments < 5)
goto crossed_file_test_failed;
/* Cross the 5th cluster of the second file with the sixth cluster fragment first file */
/* This leaves the calculated file size the same for both files, otherwise wrong sized files are freed by CHKDSK_FREEFILESWITHERRORS mode */
if (!(fatop_pfaxx(test_drive_structure, chkdisk_cluster_by_offset(4, &file2_fragments[0]), chkdisk_cluster_by_offset(5, &file1_fragments[0]))))
goto crossed_file_test_failed;
if (!fatop_flushfat(test_drive_structure))
goto crossed_file_test_failed;
/* Now check again, should be crossed chains status */
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto crossed_file_test_failed;
if (chkstat.n_crossed_chains != 2)
goto crossed_file_test_failed;
/* Now clear it */
if (test_iteration == 0)
{
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE|CHKDSK_FIXPROBLEMS|CHKDSK_FREELOSTCLUSTERS, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto crossed_file_test_failed;
/* 5 clusters should have been freed */
if (chkstat.n_clusters_freed != 5)
goto crossed_file_test_failed;
}
else
{
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE|CHKDSK_FIXPROBLEMS|CHKDSK_FREELOSTCLUSTERS|CHKDSK_FREEFILESWITHERRORS, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto crossed_file_test_failed;
/* 20 clusters should have been freed */
if (chkstat.n_clusters_freed != 20)
goto crossed_file_test_failed;
}
if (chkstat.n_crossed_chains != 2)
goto crossed_file_test_failed;
/* Now check again, should be no crossed chains */
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto crossed_file_test_failed;
if (chkstat.n_crossed_chains != 0)
goto crossed_file_test_failed;
if (test_iteration == 0)
{ /* The size of the two files combined should be exactly 15 clusters */
dword fsize1, fsize2;
fsize1 = fsize2 = 0;
if (!chktest_getset_fsize(brokenfile1, FALSE, 0, &fsize1))
goto crossed_file_test_failed;
if (!chktest_getset_fsize(brokenfile2, FALSE, 0, &fsize2))
goto crossed_file_test_failed;
if ((fsize1 + fsize2) != (15 * test_drive_cluster_size_bytes(test_drive)))
goto crossed_file_test_failed;
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto crossed_file_test_failed;
}
else
{ /* The files should be gone now */
dword fsize = 0;
if (chktest_getset_fsize(brokenfile1, FALSE, 0, &fsize) || chktest_getset_fsize(brokenfile2, FALSE, 0, &fsize))
goto crossed_file_test_failed;
}
}
/* ======================== */
/* Test crossed subdirectories */
/* ======================== */
/* Test crossed file and subdirectories */
/* ======================== */
/* Test bad file size */
rtfs_print_one_string((byte *)"Testing bad file sizes", PRFLG_NL);
for (test_iteration = 0; test_iteration < 4; test_iteration++)
{
file_delete_option = 0;
if (test_iteration < 2)
file_delete_option = CHKDSK_FREEFILESWITHERRORS;
/* Create one file with 10 clusters in 5 fragments 2 clusters each */
if (!chktest_create_one_file(brokenfile1, 10,2,1))
{
bad_file_size_test_failed:
rtfs_print_one_string((byte *)"Bad file size test failed. ", PRFLG_NL);
return (FALSE);
}
{
dword fsize, rval;
/* Try setting the size larger and smaller than the chain */
if (test_iteration == 0 || test_iteration == 2)
fsize = 18 * test_drive_cluster_size_bytes(test_drive);
else
fsize = 2 * test_drive_cluster_size_bytes(test_drive);
if (!chktest_getset_fsize(brokenfile1, TRUE, fsize, &rval))
goto bad_file_size_test_failed;
if (!chktest_getset_fsize(brokenfile1, FALSE, 0, &rval))
goto bad_file_size_test_failed;
if (rval != fsize)
goto bad_file_size_test_failed;
/* Now fix it */
if (!pc_check_disk_ex(test_drive, &chkstat, file_delete_option|REGRESS_CHKDSK_VERBOSE|CHKDSK_FIXPROBLEMS|CHKDSK_FREELOSTCLUSTERS, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto bad_file_size_test_failed;
if (file_delete_option)
{ /* File should be gone */
if (chktest_getset_fsize(brokenfile1, FALSE, 0, &rval))
goto bad_file_size_test_failed;
}
else
{
if (!chktest_getset_fsize(brokenfile1, FALSE, 0, &rval))
goto bad_file_size_test_failed;
if (rval != (10 * test_drive_cluster_size_bytes(test_drive)))
goto bad_file_size_test_failed;
if (!pc_unlink(brokenfile1))
goto bad_file_size_test_failed;
}
}
}
/* ======================== */
/* Test unterminated file chain */
rtfs_print_one_string((byte *)"Testing an unterminated file chain", PRFLG_NL);
for (test_iteration = 0; test_iteration < 2; test_iteration++)
{
REGION_FRAGMENT file_fragments[20];
int n_fragments;
dword rval;
file_delete_option = 0;
if (test_iteration == 1)
file_delete_option = CHKDSK_FREEFILESWITHERRORS;
/* Create a file with 10 clusters in 5 fragments 2 clusters each */
if (!chktest_create_one_file(brokenfile1, 10,2,1))
{
unterminated_file_test_failed:
rtfs_print_one_string((byte *)"File endless loop test failed ", PRFLG_NL);
return (FALSE);
}
/* Get the list */
n_fragments=chktest_load_cluster_list(brokenfile1, 10, &file_fragments[0]);
if (n_fragments < 5)
goto unterminated_file_test_failed;
/* Replce the terminater with zero */
if (!(fatop_pfaxx(test_drive_structure, chkdisk_cluster_by_offset(9, &file_fragments[0]),0)))
goto unterminated_file_test_failed;
if (!fatop_flushfat(test_drive_structure))
goto unterminated_file_test_failed;
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto unterminated_file_test_failed;
if (chkstat.n_unterminated_chains != 1)
goto unterminated_file_test_failed;
/* Now clear it */
if (!pc_check_disk_ex(test_drive, &chkstat, file_delete_option|REGRESS_CHKDSK_VERBOSE|CHKDSK_FIXPROBLEMS|CHKDSK_FREELOSTCLUSTERS, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto unterminated_file_test_failed;
/* Check again */
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto unterminated_file_test_failed;
if (chkstat.n_unterminated_chains != 0)
goto unterminated_file_test_failed;
if (file_delete_option)
{ /* File should be gone */
if (chktest_getset_fsize(brokenfile1, FALSE, 0, &rval))
goto unterminated_file_test_failed;
}
else
{
if (!pc_unlink(brokenfile1))
goto unterminated_file_test_failed;
}
}
/* ======================== */
/* Test unterminated directory chain */
/* ======================== */
/* Test first cluster unallocated */
/* Add test first cluster unallocated from a directory */
rtfs_print_one_string((byte *)"Testing first cluster unallocated from file ", PRFLG_NL);
for (test_iteration = 0; test_iteration < 2; test_iteration++)
{
REGION_FRAGMENT file_fragments[20];
int n_fragments;
dword rval;
/* Create a file with 10 clusters in 5 fragments 2 clusters each */
if (!chktest_create_one_file(brokenfile1, 10,2,1))
{
unallocated_cluster_test_failed:
rtfs_print_one_string((byte *)"First cluster unallocated test failed ", PRFLG_NL);
return (FALSE);
}
/* Get the list */
n_fragments=chktest_load_cluster_list(brokenfile1, 10, &file_fragments[0]);
if (n_fragments < 5)
goto unallocated_cluster_test_failed;
/* Replace the first cluster with zero */
if (!fatop_pfaxx(test_drive_structure, chkdisk_cluster_by_offset(0, &file_fragments[0]),0))
goto unallocated_cluster_test_failed;
if (!fatop_flushfat(test_drive_structure))
goto unterminated_file_test_failed;
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto unallocated_cluster_test_failed;
if (chkstat.n_bad_dirents != 1)
goto unallocated_cluster_test_failed;
/* Now clear it */
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE|CHKDSK_FIXPROBLEMS|CHKDSK_FREELOSTCLUSTERS, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto unallocated_cluster_test_failed;
/* Check again */
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto unallocated_cluster_test_failed;
if (chkstat.n_bad_dirents != 0)
goto unallocated_cluster_test_failed;
/* File should be gone */
if (chktest_getset_fsize(brokenfile1, FALSE, 0, &rval))
goto unallocated_cluster_test_failed;
}
/* ======================== */
/* Test invalid value in cluster chain */
/* Test unterminated file chain */
rtfs_print_one_string((byte *)"Testing invalid value in a file cluster chain", PRFLG_NL);
for (test_iteration = 0; test_iteration < 2; test_iteration++)
{
REGION_FRAGMENT file_fragments[20];
int n_fragments;
dword rval;
file_delete_option = 0;
if (test_iteration == 1)
file_delete_option = CHKDSK_FREEFILESWITHERRORS;
/* Create a file with 10 clusters in 5 fragments 2 clusters each */
if (!chktest_create_one_file(brokenfile1, 10,2,1))
{
invalid_cluster__file_test_failed:
rtfs_print_one_string((byte *)"Invalid value in a file cluster chain test failed ", PRFLG_NL);
return (FALSE);
}
/* Get the list */
n_fragments=chktest_load_cluster_list(brokenfile1, 10, &file_fragments[0]);
if (n_fragments < 5)
goto invalid_cluster__file_test_failed;
/* Replace a cluster with 1 an invalid value */
if (!(fatop_pfaxx(test_drive_structure, chkdisk_cluster_by_offset(6, &file_fragments[0]), 1)))
goto invalid_cluster__file_test_failed;
if (!fatop_flushfat(test_drive_structure))
goto invalid_cluster__file_test_failed;
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto invalid_cluster__file_test_failed;
if (chkstat.n_badcluster_values != 1)
goto invalid_cluster__file_test_failed;
/* Now clear it */
if (!pc_check_disk_ex(test_drive, &chkstat, file_delete_option|REGRESS_CHKDSK_VERBOSE|CHKDSK_FIXPROBLEMS|CHKDSK_FREELOSTCLUSTERS, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto invalid_cluster__file_test_failed;
if (file_delete_option)
{
/* The whole chain was lost and freed */
if (chkstat.n_clusters_freed != 10)
goto invalid_cluster__file_test_failed;
}
else
{
/* The tail end of the chain was lost and freed */
if (chkstat.n_clusters_freed != 3)
goto invalid_cluster__file_test_failed;
}
/* Check again */
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE, &chkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto invalid_cluster__file_test_failed;
if (chkstat.n_badcluster_values != 0)
goto invalid_cluster__file_test_failed;
if (file_delete_option)
{ /* File should be gone */
if (chktest_getset_fsize(brokenfile1, FALSE, 0, &rval))
goto invalid_cluster__file_test_failed;
}
else
{
if (!chktest_getset_fsize(brokenfile1, FALSE, 0, &rval))
goto invalid_cluster__file_test_failed;
if (rval != (7 * test_drive_cluster_size_bytes(test_drive)))
goto invalid_cluster__file_test_failed;
if (!pc_unlink(brokenfile1))
goto invalid_cluster__file_test_failed;
}
}
/* Test rescan because of too many fragments */
/* Test rescan because of too many lost files and check creation */
return (TRUE);
}
static BOOLEAN chkdsk_test_lost_clusters(CHKDSK_CONTEXT *pchkcontext, int scratch_memory_size, dword n_test_chains, dword clusters_per_chain,BOOLEAN do_check_files)
{
CHKDISK_STATS chkstat;
dword opmode;
if (do_check_files)
{
chktest_remove_check_files(n_test_chains);
opmode = REGRESS_CHKDSK_VERBOSE|CHKDSK_FIXPROBLEMS;
}
else
opmode = REGRESS_CHKDSK_VERBOSE|CHKDSK_FIXPROBLEMS|CHKDSK_FREELOSTCLUSTERS;
rtfs_print_one_string((byte *)"Testing check disk lost chain support (", 0);
rtfs_print_long_1(n_test_chains, 0);
rtfs_print_one_string((byte *)" chains)", 0);
if (do_check_files)
rtfs_print_one_string((byte *)" with check files", PRFLG_NL);
else
rtfs_print_one_string((byte *)" not creating check files", PRFLG_NL);
if (!create_lost_chains(n_test_chains,clusters_per_chain))
{
check_disk_failed:
rtfs_print_one_string((byte *)"Check disk failed", PRFLG_NL);
return (FALSE);
}
if (!pc_check_disk_ex(test_drive, &chkstat, opmode, pchkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
{
rtfs_print_one_string((byte *)"Checkdisk failed", PRFLG_NL);
return(FALSE);
}
if (chkstat.n_lost_chains != n_test_chains || (!do_check_files && chkstat.n_clusters_freed != (n_test_chains*clusters_per_chain)))
{
rtfs_print_one_string((byte *)"Lost chain test failed, returned - ", 0);
rtfs_print_long_1(chkstat.n_lost_chains, 0);
rtfs_print_one_string((byte *)" - Should have been - ", 0);
rtfs_print_long_1((dword)n_test_chains,PRFLG_NL);
return (FALSE);
}
if (do_check_files)
{
if (!chktest_check_check_files(n_test_chains,clusters_per_chain,scratch_memory_size))
{
rtfs_print_one_string((byte *)"Failed verifying check files", PRFLG_NL);
return(FALSE);
}
// chktest_remove_check_files(n_test_chains);
}
/* Now check again, should be no lost chains */
if (!pc_check_disk_ex(test_drive, &chkstat, REGRESS_CHKDSK_VERBOSE, pchkcontext, (void *)&cmdshell_check_disk_scratch_memory[0], scratch_memory_size))
goto check_disk_failed;
if (chkstat.n_lost_chains)
{
rtfs_print_one_string((byte *)"Lost chain test failed, returned - ", 0);
rtfs_print_long_1(chkstat.n_lost_chains, 0);
rtfs_print_one_string((byte *)" - Should have been - zero", PRFLG_NL);
return (FALSE);
}
return(TRUE);
}
static BOOLEAN chktest_remove_check_files(dword n_test_chains)
{
dword file_no;
byte file_name[60];
for (file_no = 0; file_no < n_test_chains; file_no++)
{
chkdsk_build_chk_name(&file_name[0], file_no);
if (!pc_unlink(&file_name[0]))
if (get_errno() != PENOENT)
return(FALSE);
}
return(TRUE);
}
static BOOLEAN chktest_check_check_files(dword n_test_chains, dword clusters_per_chain,int scratch_memory_size)
{
dword file_no, file_size, expected_file_size;
byte file_name[60];
expected_file_size = test_drive_cluster_size_bytes(test_drive)*clusters_per_chain;
for (file_no = 0; file_no < n_test_chains; file_no++)
{
chkdsk_build_chk_name(&file_name[0], file_no);
/* Test if the check file exist and test the file size */
if (!chktest_getset_fsize(file_name, FALSE, 0, &file_size))
return(FALSE);
if (file_size != expected_file_size)
return(FALSE);
if (chktest_load_cluster_list(file_name, scratch_memory_size/sizeof(REGION_FRAGMENT), (REGION_FRAGMENT *)&cmdshell_check_disk_scratch_memory[0]) < 1)
return(FALSE);
/* Test if the cluster chain is exactly clusters_per_chain */
if (!chkdisk_cluster_by_offset(clusters_per_chain-1, (REGION_FRAGMENT *)&cmdshell_check_disk_scratch_memory[0]))
return(FALSE);
if (chkdisk_cluster_by_offset(clusters_per_chain, (REGION_FRAGMENT *)&cmdshell_check_disk_scratch_memory[0]))
return(FALSE);
}
return(TRUE);
}
static DDRIVE *path_to_drive_struct(byte *path)
{
return(pc_drno_to_drive_struct(pc_path_to_driveno(path, CS_CHARSET_NOT_UNICODE)));
}
static dword test_drive_cluster_size_bytes(byte *path)
{
return ((dword) (dword)DRIVE_INFO(path_to_drive_struct(path),bytespcluster));
}
static int chktest_load_cluster_list(byte *file_name, int list_size, REGION_FRAGMENT *pcluster_list)
{
dword cluster,next_cluster;
int n_fragments = 0;
DDRIVE *pdr;
pdr = path_to_drive_struct(test_drive);
if (!chktest_getset_fcluster(file_name, FALSE, 0, &cluster))
return(0);
pcluster_list->start_location = cluster;
pcluster_list->end_location = cluster;
(pcluster_list+1)->start_location =
(pcluster_list+1)->end_location = 0;
n_fragments = 1;
do {
next_cluster = chkdsk_next_cluster(pdr, cluster);
if (next_cluster == CHKDSK_FAT_ERROR_VAL)
return(0);
else if (next_cluster == CHKDSK_FAT_EOF_VAL)
{
return(n_fragments);
}
else
{
if (next_cluster == (cluster+1))
pcluster_list->end_location = next_cluster;
else
{
if (list_size-- == 0)
return(0);
n_fragments += 1;
pcluster_list += 1;
pcluster_list->start_location = next_cluster;
pcluster_list->end_location = next_cluster;
(pcluster_list+1)->start_location =
(pcluster_list+1)->end_location = 0;
}
cluster = next_cluster;
}
} while (next_cluster);
return(n_fragments);
}
#ifndef RTFS_MAJOR_VERSION
static BOOLEAN chktest_readwrite_finode(DDRIVE *pdrive , dword my_block, int my_index, BOOLEAN iswrite, FINODE *pfinode)
{
BLKBUFF *pbuff;
DOSINODE *pi;
pbuff = pc_read_blk(pdrive, my_block);
if (pbuff)
{
pi = (DOSINODE *) &pbuff->data[0];
/* Copy it off and write it */
if (iswrite)
{
pc_ino2dos( (pi+my_index), pfinode );
if (!pc_write_blk(pbuff))
{
pc_discard_buf(pbuff);
return (FALSE);
}
}
else
pc_dos2inode(pfinode , (pi+my_index) );
pc_release_buf(pbuff);
return (TRUE);
}
return (FALSE);
}
#endif
static BOOLEAN chktest_create_one_file(byte *file_name, int n_clusters, int cl_per_write, int interleaf)
{
int i,fd1,fd2;
int cluster_size;
cluster_size = (int) test_drive_cluster_size_bytes(test_drive);
/* Open a file and do a fake write to allocate a cluster */
fd1 = po_open(file_name, PO_RDWR|PO_CREAT|PO_TRUNC, PS_IWRITE|PS_IREAD);
if (fd1 < 0)
return(FALSE);
fd2 = 0;
if (interleaf)
{
fd2 = po_open(fragfilename, PO_RDWR|PO_CREAT|PO_TRUNC, PS_IWRITE|PS_IREAD);
if (fd2 < 0)
return(FALSE);
}
for (i = 0; i < n_clusters; i += cl_per_write)
{
int j;
for (j = 0; j < cl_per_write; j++)
if (po_write(fd1, 0, cluster_size) != cluster_size)
return(FALSE);
if (interleaf)
{
if (po_write(fd2, 0, cluster_size) != cluster_size)
return(FALSE);
}
}
if (interleaf)
{
po_close(fd2);
pc_unlink(fragfilename);
}
po_close(fd1);
return(TRUE);
}
static BOOLEAN chktest_getset_fcluster(byte *file_name, BOOLEAN isset, dword sval, dword *rval)
{
#ifdef RTFS_MAJOR_VERSION
{
DIRENT_INFO dinfo;
/* Now get/set the file start cluster filed */
if (pc_get_dirent_info(file_name, &dinfo))
{
*rval = dinfo.fcluster;
if (isset)
{
dinfo.fcluster = sval;
if (!pc_set_dirent_info(file_name, &dinfo))
return(FALSE);
}
return(TRUE);
}
else
return(FALSE);
}
#else
{
DSTAT statobj;
DROBJ *pobj;
FINODE myfinode;
/* Get the first match */
if (!pc_gfirst(&statobj, file_name))
return(FALSE);
/* The statobj.pobj points to a bogus finode, look up the match in the finode pool */
pobj = (DROBJ *) statobj.pobj;
/* Read the finode */
if (!chktest_readwrite_finode(pobj->pdrive , pobj->blkinfo.my_block, pobj->blkinfo.my_index, FALSE, &myfinode))
{
pc_gdone(&statobj);
return(FALSE);
}
*rval = pc_finode_cluster(pobj->pdrive, &myfinode);
if (isset)
{
/* Change the fcluster value */
pc_pfinode_cluster(pobj->pdrive, &myfinode, sval);
/* Write it */
if (!chktest_readwrite_finode(pobj->pdrive , pobj->blkinfo.my_block, pobj->blkinfo.my_index, TRUE, &myfinode))
{
pc_gdone(&statobj);
return(FALSE);
}
}
pc_gdone(&statobj);
return(TRUE);
}
#endif
}
static BOOLEAN chktest_getset_fsize(byte *file_name, BOOLEAN isset, dword sval, dword *rval)
{
#ifdef RTFS_MAJOR_VERSION
{
DIRENT_INFO dinfo;
/* Now get/set the file start cluster filed */
if (pc_get_dirent_info(file_name, &dinfo))
{
*rval = dinfo.fsize;
if (isset)
{
dinfo.fsize = sval;
if (!pc_set_dirent_info(file_name, &dinfo))
return(FALSE);
}
return(TRUE);
}
else
return(FALSE);
}
#else
{
int fd1;
PC_FILE *pfile;
/* Open a file and do a fake write to allocate a cluster */
fd1 = po_open(file_name, PO_RDWR, PS_IWRITE|PS_IREAD);
if (fd1 < 0)
return(FALSE);
pfile = prtfs_cfg->mem_file_pool+fd1;
/* set fcluster to zero */
*rval = pfile->pobj->finode->fsizeu.fsize;
if (isset)
{
pfile->pobj->finode->fsizeu.fsize = sval;
/* Write it */
if (!pc_update_inode(pfile->pobj, FALSE, 0))
{
po_close(fd1);
return(FALSE);
}
}
po_close(fd1);
return(TRUE);
}
#endif
}
static BOOLEAN chktest_create_one_lost_chain(dword clusters_per_chain)
{
dword rval;
if (!chktest_create_one_file(test_file_name, (int)clusters_per_chain, 1, 0))
return(FALSE);
if (!chktest_getset_fcluster(test_file_name, TRUE, 0, &rval))
return(FALSE);
pc_unlink(test_file_name);
return(TRUE);
}
static BOOLEAN create_lost_chains(int n_chains,dword clusters_per_chain)
{
int i;
for (i = 0; i < n_chains; i++)
{
if (!chktest_create_one_lost_chain(clusters_per_chain))
return(FALSE);
}
return(TRUE);
}
static dword chkdisk_cluster_by_offset(dword offset, REGION_FRAGMENT *pregion_array)
{
dword start_offset, end_offset;
start_offset = end_offset = 0;
while (pregion_array->start_location)
{
end_offset += (pregion_array->end_location-pregion_array->start_location+1);
if (offset >= start_offset && offset < end_offset)
return(pregion_array->start_location + offset-start_offset);
start_offset = end_offset;
pregion_array++;
}
return(0);
}
#if (INCLUDE_RTFS_PROPLUS)
/*
<TEST> Procedure:Cluster conversion test
<TEST>
<TEST> Verify proper operation of cluster to sector and sector to cluster conversion routines.
<TEST> pc_diskio_info
<TEST> pc_cluster_to_sector
<TEST> pc_sector_to_cluster
*/
static BOOLEAN do_cluster_conversion_test(BOOLEAN raw)
{
int driveno;
dword sector;
DRIVE_INFO drive_info_struture;
if (raw)
{ RTFS_PRINT_STRING_1((byte *)"Performing cluster to raw sector conversion test", PRFLG_NL); }
else
{ RTFS_PRINT_STRING_1((byte *)"Performing cluster to sector conversion test", PRFLG_NL); }
if (!pc_diskio_info(test_drive, &drive_info_struture, TRUE))
goto return_false;
driveno = pc_drname_to_drno(test_drive, CS_CHARSET_NOT_UNICODE);
sector = pc_cluster_to_sector(driveno, 2, raw);
if (!sector)
goto return_false;
if (pc_sector_to_cluster(driveno, sector, raw) != 2)
goto return_false;
if (pc_sector_to_cluster(driveno, sector+drive_info_struture.cluster_size-1, raw) != 2)
goto return_false;
if (pc_sector_to_cluster(driveno, sector-1, raw)) /* Out of bounds */
goto return_false;
sector = pc_cluster_to_sector(driveno, drive_info_struture.total_clusters+1, raw);
if (!sector)
goto return_false;
/* Note: using drive_info_struture.total_clusters+XX because allocatable clusters start at 2 */
if (pc_sector_to_cluster(driveno, sector, raw) != drive_info_struture.total_clusters+1)
goto return_false;
if (pc_sector_to_cluster(driveno, sector+drive_info_struture.cluster_size-1, raw) != drive_info_struture.total_clusters+1)
goto return_false;
if (pc_sector_to_cluster(driveno, sector+drive_info_struture.cluster_size, raw)) /* Out of bounds */
goto return_false;
if (pc_sector_to_cluster(driveno, sector-1, raw) != drive_info_struture.total_clusters)
goto return_false;
return(TRUE);
return_false:
regress_error(RGE_CLUSTERCONVERSIONTEST);
return(FALSE);
}
#endif
// ======
#if (INCLUDE_MATH64)
static BOOLEAN do_comprehensive_filio_fill(void);
static BOOLEAN do_comprehensive_filio_read(void);
static BOOLEAN do_comprehensive_filio_seek(void);
#define EXFATLARGFILEBUFFERSIZE 32768
#define EXFATLARGFILESIZEGIGSEXFAT 8
#define EXFATLARGFILESIZEGIGSFAT 1
#define EXFATLARGFILESIZEBYTES (32768*10)
static BOOLEAN check_comprehensive_filio_space(void);
static BOOLEAN do_comprehensive_filio_test(void)
{
if (!check_comprehensive_filio_space())
{
RTFS_PRINT_STRING_1((byte *)"No space to run comprehensive file io",PRFLG_NL);
return (TRUE);
}
RTFS_PRINT_STRING_1((byte *)"Filling large file",PRFLG_NL);
if (!do_comprehensive_filio_fill())
return FALSE;
RTFS_PRINT_STRING_1((byte *)"Reading large file",PRFLG_NL);
if (!do_comprehensive_filio_read())
return FALSE;
RTFS_PRINT_STRING_1((byte *)"Seeking large file",PRFLG_NL);
if (!do_comprehensive_filio_seek())
return FALSE;
pc_unlink(test_file_name);
return (TRUE);
}
static BOOLEAN check_comprehensive_filio_space(void)
{
dword gigabytes,bytes,blocks_total,blocks_free,blocks32;
ddword bytes64;
if (check_if_exfat())
gigabytes = EXFATLARGFILESIZEGIGSEXFAT;
else
gigabytes = EXFATLARGFILESIZEGIGSFAT;
bytes = EXFATLARGFILESIZEBYTES;
bytes64 = M64SET32(0,gigabytes);
bytes64 = M64LSHIFT(bytes64,30);
bytes64 = M64PLUS32(bytes64,bytes);
bytes64 = M64RSHIFT(bytes64,9);
blocks32 = M64LOWDW(bytes64);
pc_blocks_free(test_drive, &blocks_total, &blocks_free);
if (blocks_free > blocks32) /* enough space to do long test ?? */
return(TRUE);
else
return(FALSE);
}
static BOOLEAN do_comprehensive_filio_fill(void)
{
int out_fd = -1;
{
/* RTFS_PRINT_STRING_1((byte *)"Usage: FILLHUGEFILE Filename DOMETADATAONLY buffersizekbytes GIGABYTES BYTES", PRFLG_NL); */
int buffersizebytes,allocedsizebytes,currentwritepointer;
dword gigabytes,bytes;
byte *allocedbuffer,*writebuffer;
ddword bytes64,byteswritten64,fillvalue,nextfillvalue,buffersizebytesddw,bytesleftddw;
BOOLEAN refreshbuffer;
buffersizebytes = EXFATLARGFILEBUFFERSIZE;
if (check_if_exfat())
gigabytes = EXFATLARGFILESIZEGIGSEXFAT;
else
gigabytes = EXFATLARGFILESIZEGIGSFAT;
bytes = EXFATLARGFILESIZEBYTES;
buffersizebytesddw = M64SET32(0,buffersizebytes);
bytes64 = M64SET32(0,gigabytes);
bytes64 = M64LSHIFT(bytes64,30);
bytes64 = M64PLUS32(bytes64,bytes);
if (buffersizebytes >= 1024)
allocedsizebytes = buffersizebytes;
else
allocedsizebytes = 1024;
allocedbuffer = (byte *)rtfs_port_malloc(allocedsizebytes);
if (!allocedbuffer)
return FALSE;
writebuffer = allocedbuffer;
out_fd = po_open(test_file_name,(word) (PO_TRUNC|PO_BINARY|PO_WRONLY|PO_CREAT),(word) (PS_IWRITE | PS_IREAD) );
if (out_fd < 0)
{
RTFS_PRINT_STRING_1((byte *)"exFat large file test file open failed",PRFLG_NL);
regress_error(RGE_LARGEFILETEST);
return(FALSE);
}
byteswritten64 = M64SET32(0,0);
fillvalue = M64SET32(0,0);
nextfillvalue = M64PLUS32(fillvalue,(allocedsizebytes/8));
refreshbuffer = TRUE;
currentwritepointer = 0;
bytesleftddw = bytes64;
while (M64GT(bytes64,byteswritten64))
{
if (writebuffer)
{ /* Fill here */
if (refreshbuffer)
{
ddword *pdw = (ddword *)writebuffer;
while(M64GT(nextfillvalue,fillvalue))
{
*pdw++ = fillvalue;
fillvalue = M64PLUS32(fillvalue, 1);
}
nextfillvalue = M64PLUS32(nextfillvalue,(allocedsizebytes/8));
refreshbuffer = FALSE;
currentwritepointer = 0;
}
if (M64GT(buffersizebytesddw, bytesleftddw))
{
buffersizebytesddw = bytesleftddw;
buffersizebytes = M64LOWDW(buffersizebytesddw);
}
if (buffersizebytes >= allocedsizebytes)
{
if (po_write(out_fd,(byte*)writebuffer,buffersizebytes) != (int)buffersizebytes)
{
RTFS_PRINT_STRING_1((byte *)"Write failure", PRFLG_NL); /* "Write failure" */
goto return_error;
}
refreshbuffer = TRUE;
}
else
{
if (po_write(out_fd,(byte*)writebuffer+currentwritepointer,buffersizebytes) != (int)buffersizebytes)
{
RTFS_PRINT_STRING_1((byte *)"Write failure", PRFLG_NL); /* "Write failure" */
goto return_error;
}
currentwritepointer += buffersizebytes;
if (currentwritepointer >= allocedsizebytes)
refreshbuffer = TRUE;
}
}
else
{
if (po_write(out_fd,0,buffersizebytes) != (int)buffersizebytes)
{
RTFS_PRINT_STRING_1((byte *)"Write failure", PRFLG_NL); /* "Write failure" */
goto return_error;
}
}
byteswritten64 = M64PLUS32(byteswritten64,buffersizebytes);
bytesleftddw = M64MINUS32(bytesleftddw,buffersizebytes);
}
if (allocedbuffer)
rtfs_port_free(allocedbuffer);
RTFS_PRINT_STRING_1((byte *)"File fill succeeded", PRFLG_NL); /* "Write failure" */
po_close(out_fd);
return(TRUE);
return_error:
RTFS_PRINT_STRING_1((byte *)"File fill failed", PRFLG_NL); /* "Write failure" */
regress_error(RGE_LARGEFILETEST);
po_close(out_fd);
if (allocedbuffer)
rtfs_port_free(allocedbuffer);
return(FALSE);
}
}
static BOOLEAN do_comprehensive_filio_read(void)
{
int in_fd = -1;
int docompare,buffersizebytes,allocedsizebytes,currentreadpointer;
byte *allocedbuffer,*readbuffer;
ddword bytes64,bytesread64,testvalue,nexttestvalue,bytesleftddw,buffersizebytesddw;
BOOLEAN comparebuffer;
docompare = 1;
buffersizebytes = EXFATLARGFILEBUFFERSIZE;
buffersizebytesddw = M64SET32(0,buffersizebytes);
if (buffersizebytes >= 1024)
allocedsizebytes = buffersizebytes;
else
allocedsizebytes = 1024;
allocedbuffer = (byte *)rtfs_port_malloc(allocedsizebytes);
if (!allocedbuffer)
return FALSE;
readbuffer = allocedbuffer;
in_fd = po_open(test_file_name, (word) (PO_BINARY|PO_RDONLY),0);
if (in_fd < 0)
{
RTFS_PRINT_STRING_2((byte *)"Cant open file", test_file_name, PRFLG_NL); /* "Cant open file" */
return(FALSE);
}
bytes64 = M64SET32(0,0);
{
ERTFS_STAT st;
if (pc_fstat(in_fd, &st) != 0)
{
RTFS_PRINT_STRING_2((byte *)"Cant fstat file", test_file_name, PRFLG_NL); /* "Cant open file" */
return(FALSE);
}
bytes64 = M64SET32(st.st_size_hi, st.st_size);
}
bytesread64 = M64SET32(0,0);
testvalue = M64SET32(0,0);
nexttestvalue = M64PLUS32(testvalue,(allocedsizebytes/8));
comparebuffer = FALSE;
currentreadpointer = 0;
bytesleftddw = bytes64;
while (M64GT(bytes64,bytesread64))
{
if (readbuffer)
{ /* test here */
if (comparebuffer)
{
ddword *pdw = (ddword *)readbuffer;
while(docompare && M64GT(nexttestvalue,testvalue))
{
if(!M64EQ(*pdw, testvalue))
{
RTFS_PRINT_STRING_1((byte *)"Compare failure", PRFLG_NL); /* "Write failure" */
goto return_error;
}
pdw++;
testvalue = M64PLUS32(testvalue, 1);
}
nexttestvalue = M64PLUS32(nexttestvalue,(allocedsizebytes/8));
comparebuffer = FALSE;
currentreadpointer = 0;
}
if (M64GT(buffersizebytesddw, bytesleftddw))
{
buffersizebytesddw = bytesleftddw;
buffersizebytes = M64LOWDW(buffersizebytesddw);
}
if (buffersizebytes >= allocedsizebytes)
{
if (po_read(in_fd,(byte*)readbuffer,buffersizebytes) != (int)buffersizebytes)
{
RTFS_PRINT_STRING_1((byte *)"Read failure", PRFLG_NL); /* "Write failure" */
goto return_error;
}
comparebuffer = TRUE;
}
else
{
if (po_read(in_fd,(byte*)readbuffer+currentreadpointer,buffersizebytes) != (int)buffersizebytes)
{
RTFS_PRINT_STRING_1((byte *)"Read failure", PRFLG_NL); /* "Write failure" */
goto return_error;
}
currentreadpointer += buffersizebytes;
if (currentreadpointer >= allocedsizebytes)
{
comparebuffer = TRUE;
}
}
}
else
{
if (po_read(in_fd,0,buffersizebytes) != (int)buffersizebytes)
{
RTFS_PRINT_STRING_1((byte *)"Read failure", PRFLG_NL); /* "Write failure" */
goto return_error;
}
}
bytesread64 = M64PLUS32(bytesread64,buffersizebytes);
bytesleftddw = M64MINUS32(bytesleftddw,buffersizebytes);
}
if (allocedbuffer)
rtfs_port_free(allocedbuffer);
RTFS_PRINT_STRING_1((byte *)"File read succeeded", PRFLG_NL); /* "Write failure" */
po_close(in_fd);
return(TRUE);
return_error:
RTFS_PRINT_STRING_1((byte *)"File read failed", PRFLG_NL); /* "Write failure" */
po_close(in_fd);
if (allocedbuffer)
rtfs_port_free(allocedbuffer);
return(FALSE);
}
#include <stdlib.h>
static dword dwrand(void)
{
dword x,y,a;
x = (dword) rand();
y = (dword) rand();
x <<= 16;
a = ((x+y)+3) & ~3L; /* round up to four byte boundary */
return(a);
}
static BOOLEAN do_exfat_one_large_file_seek(int seektype,ddword targetfileoffet,ddword bytes64,dword bytestoend)
{
byte readbyseekset[8];
byte readbyseektest[8];
dword bytestoread = 8;
int in_fd;
if (bytestoend < 8)
bytestoread = 1;
in_fd = -1;
{
/* RTFS_PRINT_STRING_1((byte *)"Usage: FILLHUGEFILE Filename DOMETADATAONLY buffersizekbytes GIGABYTES BYTES", PRFLG_NL); */
ddword bytes64minus1;
ddword testorigin,testoffset,ddw;
bytes64minus1 = M64MINUS32(bytes64,1);
/* Divide file size by eight to get size in octets. largest file size is 4 gig octets == 32 gig */
// RTFS_PRINT_STRING_1((byte *)"Seek to: ",0);
// rtfs_print_long_1(M64HIGHDW(targetfileoffet), 0);
// RTFS_PRINT_STRING_1((byte *)",",0);
// rtfs_print_long_1(M64LOWDW(targetfileoffet), PRFLG_CR);
testoffset = testorigin = M64SET32(0,0);
/* Calculate start point and seek offset */
switch (seektype) {
case PSEEK_SET:
testorigin = M64SET32(0,0); /* Seek to the offset from zero */
testoffset = targetfileoffet;
break;
case PSEEK_END: /* Seek (filelen)-offset from end */
testorigin = M64SET32(0,0);
testoffset = M64MINUS(bytes64,targetfileoffet);
break;
case PSEEK_CUR_NEG: /* Seek start at target + ((filelen-1)-offset)/2 and seek backward ((filelen-1)-offset)/2*/
testoffset = M64MINUS(bytes64minus1,targetfileoffet);
testoffset = M64RSHIFT(testoffset,1);
testorigin = M64PLUS(targetfileoffet,testoffset);
break;
case PSEEK_CUR: /* Seek start at offset - offset/2 and seek foreward offset/2 */
testoffset = targetfileoffet;
testoffset = M64RSHIFT(testoffset,1);
testorigin = M64MINUS(targetfileoffet,testoffset);
break;
}
/* Use seek set to read 1 or 8 bytes at the actual origin */
in_fd = po_open(test_file_name, (word) (PO_BINARY|PO_RDWR),0);
if (in_fd < 0)
{
RTFS_PRINT_STRING_1((byte *)" ", PRFLG_NL);
RTFS_PRINT_STRING_1((byte *)"exFat large file seek test file open failed",PRFLG_NL);
return_error:
RTFS_PRINT_STRING_1((byte *)"error ",PRFLG_NL);
regress_error(RGE_LARGEFILETEST);
po_close(in_fd);
return(FALSE);
}
ddw = po_lseek64(in_fd, targetfileoffet, PSEEK_SET);
if (!(M64EQ(ddw,targetfileoffet)))
{
RTFS_PRINT_STRING_1((byte *)" ", PRFLG_NL);
RTFS_PRINT_STRING_1((byte *)"exFat large file seek PSEEK_SET failed hi: ",0);
rtfs_print_long_1(M64HIGHDW(testorigin), 0);
RTFS_PRINT_STRING_1((byte *)" , lo: ",0);
rtfs_print_long_1(M64LOWDW(testorigin), PRFLG_NL);
goto return_error;
}
if (po_read(in_fd, readbyseekset, bytestoread) != (int)bytestoread)
{
RTFS_PRINT_STRING_1((byte *)" ", PRFLG_NL);
RTFS_PRINT_STRING_1((byte *)"exFat large file seek test file read failed",PRFLG_NL);
goto return_error;
}
po_close(in_fd);
/* Now seek using the method under test and read into another buffer */
in_fd = po_open(test_file_name, (word) (PO_BINARY|PO_RDWR),0);
if (in_fd < 0)
{
RTFS_PRINT_STRING_1((byte *)" ", PRFLG_NL);
RTFS_PRINT_STRING_1((byte *)"exFat large file seek test file open failed",PRFLG_NL);
goto return_error;
}
if (M64NOTZERO(testorigin))
{
ddw = po_lseek64(in_fd, testorigin, PSEEK_SET);
if (!(M64EQ(ddw,testorigin)))
{
RTFS_PRINT_STRING_1((byte *)" ", PRFLG_NL);
RTFS_PRINT_STRING_1((byte *)"exFat large file seek PSEEK_SET failed hi: ",0);
rtfs_print_long_1(M64HIGHDW(testorigin), 0);
RTFS_PRINT_STRING_1((byte *)" , lo: ",0);
rtfs_print_long_1(M64LOWDW(testorigin), PRFLG_NL);
goto return_error;
}
}
/* Now test the seektype method for this offset and compare to seek set */
ddw = po_lseek64(in_fd, testoffset, seektype);
if (!M64EQ(ddw,targetfileoffet))
{
RTFS_PRINT_STRING_1((byte *)" ", PRFLG_NL);
RTFS_PRINT_STRING_1((byte *)"Seek Test == ",0);
rtfs_print_long_1(seektype, PRFLG_NL);
RTFS_PRINT_STRING_1((byte *)"exFat large file seek test failed failed hi: ",0);
rtfs_print_long_1(M64HIGHDW(testorigin), 0);
RTFS_PRINT_STRING_1((byte *)" , lo: ",0);
rtfs_print_long_1(M64LOWDW(testorigin), PRFLG_NL);
goto return_error;
}
if (po_read(in_fd, readbyseektest, bytestoread) != (int)bytestoread)
{
RTFS_PRINT_STRING_1((byte *)" ", PRFLG_NL);
RTFS_PRINT_STRING_1((byte *)"exFat large file seek test file read failed",PRFLG_NL);
goto return_error;
}
/* Be sure that the first byte of the two file read values are the same */
if (readbyseektest[0] != readbyseekset[0])
{
RTFS_PRINT_STRING_1((byte *)" ", PRFLG_NL);
RTFS_PRINT_STRING_1((byte *)"exFat large file seek test file read compare failed",PRFLG_NL);
goto return_error;
}
/* If on an octect boundary the value of the octet should be the offset divided by 3 */
if (bytestoread == 8 && M64LOWDW(targetfileoffet) % 8 == 0)
{
ddword ldw,targval;
targval = targetfileoffet;
targval = M64RSHIFT(targval, 3);
copybuff(&ldw, readbyseektest, 8);
if (!M64EQ(ldw,targval))
{
RTFS_PRINT_STRING_1((byte *)" ", PRFLG_NL);
RTFS_PRINT_STRING_1((byte *)"exFat large file content val check failed",PRFLG_NL);
goto return_error;
}
}
po_close(in_fd);
}
return (TRUE);
}
#define SEEKTESTITERATIONS 100 // 00
static BOOLEAN do_comprehensive_filio_seek(void)
{
ddword bytes64;
dword octets;
int in_fd, test_count;
in_fd = po_open(test_file_name, (word) (PO_BINARY|PO_RDONLY),0);
if (in_fd < 0)
{
RTFS_PRINT_STRING_2((byte *)"Cant open file", test_file_name, PRFLG_NL); /* "Cant open file" */
return(FALSE);
}
bytes64 = M64SET32(0,0);
{
ERTFS_STAT st;
if (pc_fstat(in_fd, &st) != 0)
{
RTFS_PRINT_STRING_2((byte *)"Cant fstat file", test_file_name, PRFLG_NL); /* "Cant open file" */
return(FALSE);
}
bytes64 = M64SET32(st.st_size_hi, st.st_size);
}
po_close(in_fd);
/* Divide file size by eight to get size in octets. largest file size is 4 gig octets == 32 gig */
octets = M64LOWDW(M64RSHIFT(bytes64,3));
for (test_count=0;test_count < SEEKTESTITERATIONS;test_count++)
{
dword targetoctet,byteoffset;
ddword targetfileoffet;
/* Seek target in octets */
targetoctet = dwrand()%octets;
targetfileoffet = M64SET32(0,targetoctet);
targetfileoffet = M64LSHIFT(targetfileoffet,3);
for (byteoffset = 0; byteoffset < 8; byteoffset++)
{
ddword ltargetfileoffet, bytestoend64;
dword bytestoend;
ltargetfileoffet = M64PLUS32(targetfileoffet,byteoffset);
if (M64GTEQ(ltargetfileoffet,bytes64)) /* Check if we walked past the end */
break;
#define VERBOSE_SEEK_TEST 1
#if (VERBOSE_SEEK_TEST)
RTFS_PRINT_STRING_1((byte *)" ", PRFLG_CR);
RTFS_PRINT_STRING_1((byte *)" ", PRFLG_CR);
RTFS_PRINT_STRING_1((byte *)" Seek test: ", 0);
RTFS_PRINT_LONG_1((dword) test_count, 0);
RTFS_PRINT_STRING_1((byte *)" - of - ", 0);
RTFS_PRINT_LONG_1((dword) SEEKTESTITERATIONS, 0);
RTFS_PRINT_STRING_1((byte *)" target: ",0);
rtfs_print_long_1(M64HIGHDW(targetfileoffet), 0);
RTFS_PRINT_STRING_1((byte *)",",0);
rtfs_print_long_1(M64LOWDW(targetfileoffet), 0);
#endif
bytestoend64 = M64MINUS(bytes64,ltargetfileoffet);
if (M64HIGHDW(bytestoend64))
bytestoend = 0xffffffff;
else
bytestoend = M64LOWDW(bytestoend64);
if (!do_exfat_one_large_file_seek(PSEEK_SET, ltargetfileoffet, bytes64,bytestoend))
{
RTFS_PRINT_STRING_1((byte *)"exFat seek PSEEK_SET test failed",PRFLG_NL);
return(FALSE);
}
if (!do_exfat_one_large_file_seek(PSEEK_END, ltargetfileoffet, bytes64,bytestoend))
{
RTFS_PRINT_STRING_1((byte *)"exFat seek PSEEK_END test failed",PRFLG_NL);
return(FALSE);
}
if (!do_exfat_one_large_file_seek(PSEEK_CUR, ltargetfileoffet, bytes64,bytestoend))
{
RTFS_PRINT_STRING_1((byte *)"exFat seek PSEEK_CUR test failed",PRFLG_NL);
return(FALSE);
}
if (!do_exfat_one_large_file_seek(PSEEK_CUR_NEG, ltargetfileoffet, bytes64,bytestoend))
{
RTFS_PRINT_STRING_1((byte *)"exFat seek PSEEK_CUR_NEG test failed",PRFLG_NL);
return(FALSE);
}
}
}
RTFS_PRINT_STRING_1((byte *)"exFat seek test succeeded",PRFLG_NL);
return(TRUE);
}
#endif /*if (INCLUDE_MATH64) else.. */
#endif /* Exclude from build if read only */