sl@0: /*
sl@0: * Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: * All rights reserved.
sl@0: * This component and the accompanying materials are made available
sl@0: * under the terms of "Eclipse Public License v1.0"
sl@0: * which accompanies this distribution, and is available
sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: *
sl@0: * Initial Contributors:
sl@0: * Nokia Corporation - initial contribution.
sl@0: *
sl@0: * Contributors:
sl@0: *
sl@0: * Description:
sl@0: * Test code for directory and file handling
sl@0: * 
sl@0: *
sl@0: */
sl@0: 
sl@0: 
sl@0: 
sl@0: #include <stdlib.h>
sl@0: #include <stdio.h>
sl@0: #include <string.h>
sl@0: #include <unistd.h>
sl@0: #include <sys/stat.h>
sl@0: #include <sys/fcntl.h>
sl@0: #include <dirent.h>
sl@0: #include <errno.h>
sl@0: 
sl@0: #include "CTEST.H"	/* includes C interface to EPOC32 threads, and SpawnPosixServer */
sl@0: 
sl@0: test_Data;
sl@0: char rootpath[MAXPATHLEN];
sl@0: 
sl@0: /* construct a directory tree in various ways */
sl@0: #define WIDENAME {L'/', L'T', L'o', L'p', L'/', L'e', L'u', L'r', L'o', 0x20ac, 0}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-STDLIB-CT-1047
sl@0: @SYMTestCaseDesc	    Tests for operations on directory 
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Tests by creating directory with invalid name,existing directory name,wide characters
sl@0:                         Tests for the error code returned while creating directories.
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: void make_tree()
sl@0: 	{
sl@0: 	int err;
sl@0: 	char namebuf[MAXPATHLEN], namebuf2[MAXPATHLEN];
sl@0: 	char toobig[MAXPATHLEN+MAXPATHLEN+1];
sl@0: 	char *p;
sl@0: 	wchar_t *wp;
sl@0: 
sl@0: 	
sl@0: 	wchar_t widenamebuf[MAXPATHLEN+1];
sl@0: 	wchar_t widename[] = WIDENAME;
sl@0: 
sl@0: 
sl@0: 
sl@0: 	test_Next("Create Directory Tree - relative paths");
sl@0: 
sl@0: 	err=mkdir("***", 0777);
sl@0: 	test_errno(err==-1,EINVAL);	/* bad directory name */
sl@0: 
sl@0: 
sl@0: 	err=mkdir("top", 0777);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=mkdir("top", 0777);
sl@0: 	test_errno(err==-1,EEXIST);	/* directory already exists */
sl@0: 
sl@0: 	
sl@0: 	//make a dir with a wide character in the name
sl@0: 	err = wcstombs(namebuf, widename, MAXPATHLEN);
sl@0: 	test(err!=-1);
sl@0: 	
sl@0: 	err=mkdir(namebuf, 0777);
sl@0: 	test(err==0);
sl@0: 	
sl@0: 
sl@0: 	err=mkdir("top/middle1/bottom1", 0777);
sl@0: 	test_errno(err==-1,ENOENT);	/* missing middle bit of path */
sl@0: 
sl@0: 	err=mkdir("top/middle1", 0777);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=chdir("./top//\\/.\\.\\../top/.");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	p = getcwd(rootpath,sizeof(rootpath));	/* save name of toplevel directory */
sl@0: 	test(p==rootpath);
sl@0: 
sl@0: 	err=chdir("middle1");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=chdir("bottom2");
sl@0: 	test_errno(err==-1,ENOENT);	/* directory doesn't exist yet */
sl@0: 
sl@0: 	p = getcwd(namebuf,sizeof(namebuf));	/* prepare name for tests later */
sl@0: 	test(p==namebuf);
sl@0: 
sl@0: 	err=mkdir("bottom1",0777);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=mkdir("read-only",0444);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=mkdir("read-only/sub-read-only",0444);
sl@0: 	/* test_errno(err==-1,EACCES); */
sl@0: 	test(err==0);	/* Omission - EPOC32 has Win32 semantics for read-only directories */
sl@0: 
sl@0: 	err=chdir("../../top/middle1/bottom1");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	test_Next("Create Directory Tree - absolute paths");
sl@0: 
sl@0: 	p = strcat(namebuf,"/bottom2");
sl@0: 	test(p==namebuf);	/* .../top/middle1/bottom2 */
sl@0: 
sl@0: 	err=chdir(namebuf);
sl@0: 	test_errno(err==-1,ENOENT);	/* directory doesn't exist yet */
sl@0: 	
sl@0: 	err=mkdir(namebuf, 0777);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=chdir(namebuf);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	p = getcwd(namebuf,sizeof(namebuf));
sl@0: 	test(p==namebuf);
sl@0: 
sl@0: 	err=mkdir("../../middle2", 0777);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	p = getcwd(namebuf2,sizeof(namebuf2));
sl@0: 	test(p==namebuf2);
sl@0: 	test(strcmp(namebuf,namebuf2)==0);	/* mkdir shouldn't change cwd */
sl@0: 
sl@0: 	memset(toobig,'a', sizeof(toobig));
sl@0: 	toobig[sizeof(toobig)-1]='\0';
sl@0: 
sl@0: 	err=mkdir(toobig,0777);
sl@0: 	test_errno(err<0,ENAMETOOLONG);
sl@0: 
sl@0: 
sl@0: 	test_Next("Test getcwd");
sl@0: 	
sl@0: 	//size too small
sl@0: 	p = getcwd(namebuf, 4);
sl@0: 	test_errno(0==p, ERANGE);
sl@0: 
sl@0: 	//make it alloc a buffer
sl@0: 	p = getcwd(NULL, 300);
sl@0: 	test (NULL != p);
sl@0: 	free(p);
sl@0: 
sl@0: 	//alloc a buffer then fail with a too small size
sl@0: 	p = getcwd(NULL, 10);
sl@0: 	test_errno(0==p, ERANGE);
sl@0: 
sl@0: 	wp = wgetcwd(widenamebuf, MAXPATHLEN-1);
sl@0: 	test (NULL != wp);
sl@0: 
sl@0: 	p = getcwd(namebuf2, MAXPATHLEN-1);
sl@0: 	test (NULL != p);
sl@0: 
sl@0: 	wcstombs(namebuf, widenamebuf, MAXPATHLEN-1);
sl@0: 	test(strcmp(namebuf, namebuf2) == 0);
sl@0: 	
sl@0: 	
sl@0: 	//test realpath
sl@0: 	strcpy(namebuf,"bobby.dog");
sl@0: 	test( (0==strcmp("C:\\top\\", realpath("/top/../top/../top/./",namebuf))) || 
sl@0: 		  (0==strcmp("D:\\top\\", realpath("/top/../top/../top/./",namebuf))));
sl@0: 
sl@0: 	
sl@0: 
sl@0: }
sl@0: 
sl@0: /**
sl@0:    Directory tree is now
sl@0:  
sl@0:      top / middle2   
sl@0:            middle1 / bottom1
sl@0:                    / bottom2
sl@0:  		   / read-only / sub-read-only
sl@0:  
sl@0: 
sl@0: @SYMTestCaseID          SYSLIB-STDLIB-CT-1048
sl@0: @SYMTestCaseDesc	    Tests for operations on creating files
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Tests by opening files which does not exists,check for closing a file twice
sl@0:                         Tests for the error code returned while creating files
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: void create_files()
sl@0: 	{
sl@0: 	int err;
sl@0: 	int fd;
sl@0: 	char namebuf[MAXPATHLEN],*p;
sl@0: 
sl@0: 	test_Next("Creating Files - relative paths");
sl@0: 
sl@0: 	err=chdir(rootpath);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	fd = open("topfile",O_RDWR+O_APPEND,0777);
sl@0: 	test_errno(fd<0,ENOENT);	/* doesn't exist */
sl@0: 
sl@0: 	fd = open("topfile",O_RDWR+O_CREAT,0777);
sl@0: 	test(fd>=0);
sl@0: 
sl@0: 	err=close(fd);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=close(fd);
sl@0: 	test_errno(err<0,EBADF);	/* can't close it twice */
sl@0: 
sl@0: 	fd = open("topfile",O_RDWR+O_APPEND,0777);
sl@0: 	test(fd>=0);
sl@0: 
sl@0: 	err=close(fd);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	fd = open("topfile",O_RDWR+O_CREAT+O_EXCL,0777);
sl@0: 	test_errno(fd<0,EEXIST);	/* already exists */
sl@0: 
sl@0: 	fd = open("middle1/bottom2/file",O_RDONLY+O_CREAT,0444);
sl@0: 	test(fd>=0);
sl@0: 
sl@0: 	err=close(fd);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	fd = open("middle1/bottom2/file",O_RDWR+O_APPEND,0777);
sl@0: 	/* test_errno(fd<0,EACCES); */
sl@0: 	test(fd>=0);	/* Omission - the original O_CREAT ignores the 0444 permissions */
sl@0: 	if (fd>=0)
sl@0: 		{
sl@0: 		err=close(fd);
sl@0: 		test(err==0);
sl@0: 		}
sl@0: 
sl@0: 	err=chmod("middle1/bottom2/file",0444);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	fd = open("middle1/bottom2/file",O_RDWR+O_APPEND,0777);
sl@0: 	test_errno(fd<0,EACCES);	/* not writeable */
sl@0: 
sl@0: 	fd = open("middle2",O_RDWR+O_CREAT,0777);
sl@0: 	/* test_errno(fd<0,EISDIR); */
sl@0: 	test_errno(fd<0,EACCES);	/* Omission - we don't do EISDIR */
sl@0: 
sl@0: 	test_Next("Creating Files - absolute paths");
sl@0: 
sl@0: 	err=chdir("middle1/bottom1");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	p = getcwd(namebuf,sizeof(namebuf));	/* prepare name for tests later */
sl@0: 	test(p==namebuf);
sl@0: 
sl@0: 	p = strcat(namebuf,"absfile");
sl@0: 	test(p==namebuf);
sl@0: 
sl@0: 	fd = open(namebuf,O_RDWR+O_CREAT,0777);
sl@0: 	test(fd>=0);
sl@0: 
sl@0: 	err=close(fd);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	fd = open("../read-only/file",O_RDWR+O_CREAT,0444);
sl@0: 	/* test_errno(fd<0,EACCES); */
sl@0: 	test(fd>=0);	/* Omission - EPOC32 has Win32 semantics for read-only directories */
sl@0: 	if (fd>=0)
sl@0: 		{
sl@0: 		err=close(fd);
sl@0: 		test(err==0);
sl@0: 		}
sl@0: 	
sl@0: 	}
sl@0: 
sl@0: /**
sl@0:    Directory tree is now
sl@0:  
sl@0:     top / topfile
sl@0:            middle2 /   
sl@0:            middle1 / bottom1 / absfile
sl@0:                    / bottom2 / file                -- read-only
sl@0:  		   / read-only / sub-read-only /
sl@0:                                  file
sl@0:  
sl@0: 
sl@0: @SYMTestCaseID          SYSLIB-STDLIB-CT-1049
sl@0: @SYMTestCaseDesc	    Tests for renaming operations 
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Tests by renaming files.Tests for the error code returned while renaming files
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: void renaming()
sl@0: 	{
sl@0: 	int err;
sl@0: 
sl@0: 	test_Next("Renaming");
sl@0: 
sl@0: 	err=chdir(rootpath);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rename("middle1","middle2");
sl@0: 	test_errno(err<0,EEXIST);
sl@0: 
sl@0: 	err=rename("middle1/bottom1/absfile","middle2/absfile");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rename("middle2/absfile","middle1/bottom1/absfile");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rename("middle1/bottom1/absfile","middle2/nonsuch/newname");
sl@0: 	test_errno(err<0,ENOENT);
sl@0: 
sl@0: 	err=rename("middle1","middle1/bottom1/subdirectory_of_self");
sl@0: 	test_errno(err<0,EACCES);
sl@0: 
sl@0: 	err=rename("middle1","newname");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rename("newname/bottom2/file","middle2/file");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rename("newname","middle1");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rename("middle2/file","middle1/bottom2/file");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rename("no such file","valid new name");
sl@0: 	test_errno(err<0,ENOENT);
sl@0: 
sl@0: 	err=rename("no such file","topfile");
sl@0: 	test_errno(err<0,ENOENT);
sl@0: 
sl@0: 	err=rename(".","../different top");
sl@0: 	/* test_errno(err<0,EACCES);	-- can't change "." */
sl@0: 	test(err==0);	/* STDLIB resolves "." to full path, so this works */
sl@0: 
sl@0: 	err=rename("../different top",rootpath);
sl@0: 	test(err==0);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0:    Directory tree is now
sl@0:  
sl@0:      top / topfile
sl@0:            middle2 /   
sl@0:            middle1 / bottom1 / absfile
sl@0:                    / bottom2 / file                -- read-only
sl@0:  		   / read-only / sub-read-only /
sl@0:                                  file
sl@0:  
sl@0: 
sl@0: @SYMTestCaseID          SYSLIB-STDLIB-CT-1050
sl@0: @SYMTestCaseDesc	    Tests for enumeration on directories 
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Tests by opening directories
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: void directory()
sl@0: 	{
sl@0: 	int err, count, i, j, fd;
sl@0: 	DIR *dp;
sl@0: 	struct dirent *ep;
sl@0: 	char name[MAXPATHLEN+1];
sl@0: 	off_t pos;
sl@0: 
sl@0: 	test_Next("Enumerating Directories");
sl@0: 
sl@0: 	err=chdir(rootpath);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	dp=opendir("topfile");
sl@0: 	/* test_errno(dp==0,ENOTDIR); -- not convinced about this anyway */
sl@0: 	test_errno(dp==0,ENOENT);
sl@0: 
sl@0: 	dp=opendir("no such file");
sl@0: 	test_errno(dp==0,ENOENT);
sl@0: 
sl@0: 
sl@0: 	//test something sensible happens if someone uses a WDIR inplace of a DIR
sl@0: 	{
sl@0: 		WDIR *wp = wopendir((wchar_t*)L".");
sl@0: 		test(wp!=0);
sl@0: 
sl@0: 		// Test wants a WDIR passed but won't compile under CW.
sl@0: 		// Force the compile by casting. The function will still get a WDIR.
sl@0: 		// DIR inherits from WDIR.
sl@0: 		ep=readdir((DIR*)wp);
sl@0: 		test_errno(ep==0,EINVAL);
sl@0: 
sl@0: 		wclosedir(wp);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: 
sl@0: 
sl@0: 	dp=opendir(".");
sl@0: 	test(dp!=0);
sl@0: 
sl@0: 	count=0;
sl@0: 	do
sl@0: 		{
sl@0: 		ep=readdir(dp);
sl@0: 		if (ep && strcmp(ep->d_name,".")!=0 && strcmp(ep->d_name,"..")!=0)
sl@0: 			count++;
sl@0: 		}
sl@0: 	while (ep!=0);
sl@0: 	test(count==4);
sl@0: 
sl@0: 	for (i=0; i<4; i++)
sl@0: 		{
sl@0: 		rewinddir(dp);
sl@0: 		for (j=0; j<=i; j++)
sl@0: 			{
sl@0: 			ep=readdir(dp);
sl@0: 			test(ep!=0);
sl@0: 			}
sl@0: 		strcpy(name,ep->d_name);
sl@0: 		rewinddir(dp);
sl@0: 		for (j=0; j<=i; j++)
sl@0: 			{
sl@0: 			ep=readdir(dp);
sl@0: 			test(ep!=0);
sl@0: 			}
sl@0: 		test(strcmp(name,ep->d_name)==0);
sl@0: 		}
sl@0: 
sl@0: 	for (i=0; i<4; i++)
sl@0: 		{
sl@0: 		rewinddir(dp);
sl@0: 		pos=telldir(dp);
sl@0: 		for (j=0; j<=i; j++)
sl@0: 			{
sl@0: 			pos=telldir(dp);
sl@0: 			ep=readdir(dp);
sl@0: 			test(ep!=0);
sl@0: 			}
sl@0: 		strcpy(name,ep->d_name);
sl@0: 		rewinddir(dp);
sl@0: 		seekdir(dp, pos);
sl@0: 		ep=readdir(dp);
sl@0: 		test(ep!=0);
sl@0: 		test(strcmp(name,ep->d_name)==0);
sl@0: 		}
sl@0: 
sl@0: 	err=closedir(dp);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	dp=opendir("middle2");
sl@0: 	test(dp!=0);
sl@0: 
sl@0: 	count=0;
sl@0: 	do
sl@0: 		{
sl@0: 		ep=readdir(dp);
sl@0: 		if (ep && strcmp(ep->d_name,".")!=0 && strcmp(ep->d_name,"..")!=0)
sl@0: 			count++;
sl@0: 		}
sl@0: 	while (ep!=0);
sl@0: 	test(count==0);	/* empty directory */
sl@0: 
sl@0: 	rewinddir(dp);
sl@0: 
sl@0: 	fd = open("middle2/extrafile",O_RDWR+O_CREAT,0777);
sl@0: 	test(fd>=0);
sl@0: 
sl@0: 	err=close(fd);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	count=0;
sl@0: 	do
sl@0: 		{
sl@0: 		ep=readdir(dp);
sl@0: 		if (ep && strcmp(ep->d_name,".")!=0 && strcmp(ep->d_name,"..")!=0)
sl@0: 			count++;
sl@0: 		}
sl@0: 	while (ep!=0);
sl@0: 	test(count==0);	/* shouldn't have noticed the change */
sl@0: 
sl@0: 	rewinddir(dp);	/* and spot the new file */
sl@0: 	count=0;
sl@0: 	do
sl@0: 		{
sl@0: 		ep=readdir(dp);
sl@0: 		if (ep && strcmp(ep->d_name,".")!=0 && strcmp(ep->d_name,"..")!=0)
sl@0: 			count++;
sl@0: 		}
sl@0: 	while (ep!=0);
sl@0: 	test(count==1);
sl@0: 
sl@0: 	closedir(dp);
sl@0: 
sl@0: 	dp=opendir("/");
sl@0: 	test(dp!=0);
sl@0: 
sl@0: 	count=0;
sl@0: 	do
sl@0: 		{
sl@0: 		ep=readdir(dp);
sl@0: 		if (ep && strcmp(ep->d_name,".")!=0 && strcmp(ep->d_name,"..")!=0)
sl@0: 			count++;
sl@0: 		}
sl@0: 	while (ep!=0);
sl@0: 	test(count>0);
sl@0: 
sl@0: 	closedir(dp);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0:    Directory tree is now
sl@0:  
sl@0:      top / topfile
sl@0:             middle2 / extrafile  
sl@0:            middle1 / bottom1 / absfile
sl@0:                    / bottom2 / file                -- read-only
sl@0:  		   / read-only / sub-read-only /
sl@0:                                  file
sl@0:  
sl@0: @SYMTestCaseID          SYSLIB-STDLIB-CT-1051
sl@0: @SYMTestCaseDesc	    Tests for file attributes
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Tests the attributes on files and directories
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: void attributes()
sl@0: 	{
sl@0: 	int err;
sl@0: 	struct stat s1,s2;
sl@0: 	int fd;
sl@0: 	double diff;
sl@0: 
sl@0: 	test_Next("File Attributes");
sl@0: 
sl@0: 	err=chdir(rootpath);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=stat("middle earth/bag end/hobbit",&s1);
sl@0: 	test_errno(err<0,ENOENT);
sl@0: 
sl@0: 	err=stat("middle1/bottom2/file",&s1);
sl@0: 	test(err==0);
sl@0: 	test(S_ISREG(s1.st_mode)!=0);
sl@0: 	test(S_ISDIR(s1.st_mode)==0);
sl@0: 	test((s1.st_mode&S_IWUSR)==0);
sl@0: 	test(s1.st_size==0);
sl@0: 
sl@0: 	err=stat("topfile",&s1);
sl@0: 	test(err==0);
sl@0: 	test(S_ISREG(s1.st_mode)!=0);
sl@0: 	test(S_ISDIR(s1.st_mode)==0);
sl@0: 	test((s1.st_mode&S_IWUSR)!=0);
sl@0: 	test(s1.st_size==0);
sl@0: 
sl@0: 	err=stat("topfile",&s2);
sl@0: 	test(err==0);
sl@0: 	test(s1.st_mode==s2.st_mode);
sl@0: 	test(s1.st_size==s2.st_size);
sl@0: 	diff=difftime(s1.st_mtime,s2.st_mtime);
sl@0: 	test(diff==(double)0.0);
sl@0: 
sl@0: 	fd=open("topfile", O_RDONLY, 0);
sl@0: 	test(fd>=0);
sl@0: 
sl@0: 	err=fstat(fd,&s2);
sl@0: 	test(err==0);
sl@0: 	test(s1.st_mode==s2.st_mode);
sl@0: 	test(s1.st_size==s2.st_size);
sl@0: 	diff=difftime(s1.st_mtime,s2.st_mtime);
sl@0: 	test(diff==(double)0.0);
sl@0: 
sl@0: 	err=stat("topfile",&s2);
sl@0: 	test(err==0);
sl@0: 	test(s1.st_mode==s2.st_mode);
sl@0: 	test(s1.st_size==s2.st_size);
sl@0: 	diff=difftime(s1.st_mtime,s2.st_mtime);
sl@0: 	test(diff==(double)0.0);
sl@0: 
sl@0: 	err=close(fd);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	sleep(1);	/* to ensure that the modify time changes */
sl@0: 
sl@0: 	fd=open("topfile", O_RDWR+O_APPEND, 0);
sl@0: 	test(fd>=0);
sl@0: 
sl@0: 	err=stat("topfile",&s2);
sl@0: 	test(err==0);
sl@0: 	test(s1.st_mode==s2.st_mode);
sl@0: 	test(s1.st_size==s2.st_size);
sl@0: 	/* probably not guaranteeed to have changed the modtime at this point */
sl@0: 
sl@0: 	err=write(fd,rootpath,3);
sl@0: 	test(err==3);
sl@0: 
sl@0: 	err=fsync(fd);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=close(fd);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=stat("topfile",&s2);
sl@0: 	test(err==0);
sl@0: 	test(s1.st_mode==s2.st_mode);
sl@0: 	test(s2.st_size==3);
sl@0: 	diff=difftime(s2.st_mtime,s1.st_mtime);
sl@0: 	test(diff>(double)0.0);
sl@0: 
sl@0: 	test_Next("Directory Attributes");
sl@0: 
sl@0: 	err=stat("middle1",&s1);
sl@0: 	test(err==0);
sl@0: 	test(S_ISREG(s1.st_mode)==0);
sl@0: 	test(S_ISDIR(s1.st_mode)==1);
sl@0: 	test((s1.st_mode&S_IWUSR)!=0);
sl@0: 
sl@0: 	err=stat("middle1/read-only",&s1);
sl@0: 	test(err==0);
sl@0: 	test(S_ISREG(s1.st_mode)==0);
sl@0: 	test(S_ISDIR(s1.st_mode)==1);
sl@0: 	test((s1.st_mode&S_IWUSR)==0);
sl@0: 
sl@0: 	err=stat("/",&s1);
sl@0: 	test(err==0);
sl@0: 	test(S_ISREG(s1.st_mode)==0);
sl@0: 	test(S_ISDIR(s1.st_mode)==1);
sl@0: 
sl@0: 	err=access("middle1/bottom1/absfile",W_OK);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=access("middle1/bottom1/absfile",R_OK);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=access("middle1/bottom2/file",W_OK);
sl@0: 	test(err!=0);
sl@0: 
sl@0: 	err=access("middle1/bottom2/file",R_OK);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=access("middle1/read-only",W_OK);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=access("middle1/read-only",R_OK);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=access("middle1/no such directory",R_OK);
sl@0: 	test(err!=0);
sl@0: }
sl@0: 
sl@0: /**
sl@0:    Directory tree is now
sl@0:  
sl@0:      top / topfile
sl@0:            middle2 / extrafile  
sl@0:            middle1 / bottom1 / absfile
sl@0:                    / bottom2 / file                -- read-only
sl@0:  		   / read-only / sub-read-only /
sl@0:                                  file
sl@0:  
sl@0: 
sl@0: @SYMTestCaseID          SYSLIB-STDLIB-CT-1052
sl@0: @SYMTestCaseDesc	    Tests for searching on different drives
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Tests by searching on z drive,test for the error codes 
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0:  void searching()
sl@0: 	{
sl@0: 	int err,fd;
sl@0: 	char name[MAXPATHLEN+1];
sl@0: 
sl@0: 	test_Next("Searching across drives");
sl@0: 
sl@0: 	sprintf(name,"%s/middle2/extrafile",rootpath);
sl@0: 
sl@0: 	err=chdir("z:/");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	fd=open(name+2, O_RDONLY, 0);
sl@0: 	test_errno(fd<0,ENOENT);	// doesn't exist on z:
sl@0: 
sl@0: 	name[0]='?';
sl@0: 	fd=open(name, O_RDWR, 0);
sl@0: 	test(fd>=0);			// found it on the original drive
sl@0: 
sl@0: 	err=close(fd);
sl@0: 	test(err==0);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0:    Directory tree is now
sl@0:  
sl@0:      top / topfile
sl@0:            middle2 / extrafile  
sl@0:            middle1 / bottom1 / absfile
sl@0:                    / bottom2 / file                -- read-only
sl@0:  		   / read-only / sub-read-only /
sl@0:                                  file
sl@0:  
sl@0: 
sl@0: @SYMTestCaseID          SYSLIB-STDLIB-CT-1053
sl@0: @SYMTestCaseDesc	    Tests for deleting files
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Tests by deleting files and directories.Test for error codes
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: void deletion()
sl@0: 	{
sl@0: 	int err;
sl@0: 	char namebuf[MAXPATHLEN];
sl@0: 	wchar_t widename[] = WIDENAME;
sl@0: 
sl@0: 
sl@0: 	test_Next("Deleting - files");
sl@0: 
sl@0: 	err=chdir(rootpath);
sl@0: 	test(err==0);
sl@0: 
sl@0: 
sl@0: 
sl@0: 	err=unlink("middle1/bottom2/file");
sl@0: 	test_errno(err<0,EACCES);	/* file is read-only */
sl@0: 
sl@0: 	err=chmod("middle1/bottom2/file",0777);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=unlink("middle1/bottom2/file");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=unlink("middle2/extrafile");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=unlink("middle1/read-only/file");
sl@0: 	/* test_errno(err<0,EPERM);	parent directory is read-only */
sl@0: 	test(err==0);	/* Omission - EPOC32 uses Win32 semantics for read-only directories */
sl@0: 
sl@0: 	test_Next("Deleting - directories");
sl@0: 
sl@0: 	err=chdir(rootpath);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	//delete the dir with a wide character in the name
sl@0: 	err = wcstombs(namebuf, widename, MAXPATHLEN);
sl@0: 	test(err!=-1);
sl@0: 	
sl@0: 	err=rmdir(namebuf);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rmdir("middle1");
sl@0: 	test_errno(err<0,EEXIST);	/* not empty */
sl@0: 
sl@0: 	err=rmdir("middle1/bottom1");
sl@0: 	test_errno(err<0,EEXIST);	/* not empty */
sl@0: 
sl@0: 	err=unlink("middle1/bottom1/absfile");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rmdir("middle1/bottom1");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rmdir("middle1/bottom1");
sl@0: 	test_errno(err<0,ENOENT);	/* already deleted */
sl@0: 
sl@0: 	err=rmdir("middle1");
sl@0: 	test_errno(err<0,EEXIST);
sl@0: 
sl@0: 	err=rmdir("middle1/bottom2");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	test_Next("Deleting - read-only directories");
sl@0: 
sl@0: 	err=rmdir("middle1/read-only/sub-read-only");
sl@0: 	/* test_errno(err!=0,EACCES);	-- permission denied - read-only parent */
sl@0: 	test_errno(err<0,EACCES);	/* Omission - EPOC32 uses Win32 semantics */
sl@0: 
sl@0: 	err=chmod("middle1/read-only",0777);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rmdir("middle1/read-only/sub-read-only");
sl@0: 	/* test(err==0); */
sl@0: 	/* EPOC32 doesn't use the writeability of the parent directory, but instead looks 
sl@0: 	 * at the attributes of the directory itself.
sl@0: 	 */
sl@0: 	test_errno(err!=0,EACCES);
sl@0: 
sl@0: 	err=chmod("middle1/read-only/sub-read-only",0777);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rmdir("middle1/read-only/sub-read-only");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rmdir("middle1/read-only");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rmdir("middle?");
sl@0: 	test_errno(err<0,EINVAL);	/* no wild cards please */
sl@0: 
sl@0: 	err=rmdir("middle1");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rmdir("../top/middle2");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rmdir(".");
sl@0: 	test_errno(err<0,EEXIST);	/* not empty */
sl@0: 
sl@0: 	err=unlink("topfile");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=rmdir(".");
sl@0: 	test(err==0);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-STDLIB-CT-1054
sl@0: @SYMTestCaseDesc	    Tests for creation of temporary directory and files in it.
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Tests by creating a temporary directory,files and writing to the files.
sl@0:                         Check for error codes.
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: void temporary_files()
sl@0: 	{
sl@0: #define tmpdir        "c:/system/temp"
sl@0: 
sl@0: 	int err, count1, count2;
sl@0: 	DIR *dp;
sl@0: 	struct dirent *ep;
sl@0: 	FILE *fp;
sl@0: 	char name[L_tmpnam];
sl@0: 	char name2[L_tmpnam];
sl@0: 	char *p;
sl@0: 
sl@0: 	test_Next("Temporary files");
sl@0: 
sl@0: 	dp=opendir(tmpdir);
sl@0: 	if (dp==0)
sl@0: 		{
sl@0: 		printf("  Creating the directory %s ...\n", tmpdir);
sl@0: 		err=mkdir("c:/system", 0777);
sl@0: 		test(err==0);
sl@0: 		err=mkdir(tmpdir, 0777);
sl@0: 		test(err==0);
sl@0: 		dp=opendir(tmpdir);
sl@0: 		}
sl@0: 	test(dp!=0);
sl@0: 
sl@0: 	count1=0;
sl@0: 	do
sl@0: 		{
sl@0: 		ep=readdir(dp);
sl@0: 		if (ep && strcmp(ep->d_name,".")!=0 && strcmp(ep->d_name,"..")!=0)
sl@0: 			count1++;
sl@0: 		}
sl@0: 	while (ep!=0);
sl@0: 
sl@0: 	fp=tmpfile();
sl@0: 	test(fp!=0);
sl@0: 
sl@0: 	err=fprintf(fp,"hello");
sl@0: 	test(err==5);
sl@0: 
sl@0: 	rewinddir(dp);
sl@0: 	count2=0;
sl@0: 	do
sl@0: 		{
sl@0: 		ep=readdir(dp);
sl@0: 		if (ep && strcmp(ep->d_name,".")!=0 && strcmp(ep->d_name,"..")!=0)
sl@0: 			count2++;
sl@0: 		}
sl@0: 	while (ep!=0);
sl@0: 	test(count2==count1+1);	/* EPOC32 temporary files are visible in file system */
sl@0: 	err=fclose(fp);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	rewinddir(dp);
sl@0: 	count2=0;
sl@0: 	do
sl@0: 		{
sl@0: 		ep=readdir(dp);
sl@0: 		if (ep && strcmp(ep->d_name,".")!=0 && strcmp(ep->d_name,"..")!=0)
sl@0: 			count2++;
sl@0: 		}
sl@0: 	while (ep!=0);
sl@0: 	test(count2==count1);		/* should be automatically deleted */
sl@0: 
sl@0: 	closedir(dp);
sl@0: 
sl@0: 	p=tmpnam(NULL);
sl@0: 	test(p!=0);
sl@0: 
sl@0: 	count1=strlen(p);
sl@0: 	test(count1<L_tmpnam);
sl@0: 
sl@0: 	p=tmpnam(name);
sl@0: 	test(p==name);
sl@0: 
sl@0: 	fp=fopen(name,"wb+");
sl@0: 	test(fp!=0);
sl@0: 
sl@0: 	p=tmpnam(name2);
sl@0: 	test(p==name2);
sl@0: 
sl@0: 	err=strcmp(name,name2);
sl@0: 	test(err!=0);
sl@0: 
sl@0: 	err=fclose(fp);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	err=unlink(name);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	printf("  Tmpnam suggested %s and %s\n", name, name2);
sl@0: 	}
sl@0: 
sl@0: int close_console=0;
sl@0: void allTests()
sl@0: 	{
sl@0: 	int err=chdir("C:\\");
sl@0: 	test(err==0);
sl@0: 
sl@0: 	make_tree();
sl@0: 	create_files();
sl@0: 	renaming();
sl@0: 	directory();
sl@0: 	attributes();
sl@0: 	searching();
sl@0: 	deletion();
sl@0: 	temporary_files();
sl@0: 
sl@0: 	if (close_console)
sl@0: 		{
sl@0: 		test_Close();
sl@0: 		close(0);
sl@0: 		close(1);
sl@0: 		close(2);
sl@0: 
sl@0: 		CloseSTDLIB();
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: int main()
sl@0: 	{
sl@0: 	void* client;
sl@0: 	int err;
sl@0: 
sl@0: 	test_Title("Directory Handling");
sl@0: 
sl@0: 	allTests();
sl@0: 
sl@0: 	test_Next("Do it again using the CPosixServer (for them, not me)");
sl@0: 	close_console=1;
sl@0: 
sl@0: 	start_posix_server();	/* calls SpawnPosixServer from C++ code */
sl@0: 
sl@0: 	client=create_thread(allTests, "TDIRS tests");
sl@0: 	test(client!=0);
sl@0: 	start_thread(client);
sl@0: 	err=wait_for_thread(client);
sl@0: 	test(err==0);
sl@0: 
sl@0: 	CloseSTDLIB();
sl@0: 	test_Close();
sl@0: 	return 0;
sl@0: 	}