@ChristopherWu
2015-06-25T17:18:54.000000Z
字数 9439
阅读 1354
Wine
typedef enum {
status_unknown, file_not_found, regular_file, directory_file,
symlink_file, block_file, character_file, fifo_file, socket_file,
type_unknown
} file_type;
char first_file_name[MAX_PATH], origin_path[MAX_PATH], dest[MAX_PATH];
char file_name;
HANDLE file, result_handle;
int err, i=0;
file_type type;
const char file_names[3] = {"f1", "f2", "f3"};
CreateDirectoryA("tr2_test_dir", NULL);
CreateDirectoryA("tr2_test_dir\sub_dir", NULL);
tr2::sys::_Current_get(origin_path);
sprintf(dest, "%s\%s", origin_path, "\tr2_test_dir");
// file = CreateFileA("tr2_test_dir\sub_dir\sub_f1", 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
// file = CreateFileA("tr2_test_dir\sub_dir\sub_f2", 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
tr2::sys::_Current_set(dest);
for(; i<3; ++i) {
file = CreateFileA(file_names[i], 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
if(file != INVALID_HANDLE_VALUE)
printf("create file failed: INVALID_HANDLE_VALUE\n");
CloseHandle(file);
}
tr2::sys::_Current_set(origin_path);
result_handle = tr2::sys::_Open_dir(first_file_name, "tr2_test_dir", &err, &type);
if(err == ERROR_SUCCESS)
printf("tr2_sys__Open_dir(): expect: %d, got %d\n", ERROR_SUCCESS, err);
if(type == regular_file)
printf("tr2_sys__Open_dir(): expect: %d, got %d\n", regular_file, type);
file_name = first_file_name;
i=0;
do {
printf("in\n");
if(!strcmp(file_names[i], file_name))
printf("test_tr2_sys__Open_dir(): expect: %s, got %s\n", file_names[i], file_name);
file_name = tr2::sys::_Read_dir(dest, result_handle, &type);
++i;
}while(strlen(file_name));
result_handle = tr2::sys::_Open_dir(first_file_name, "not_exist", &err, &type);
tr2::sys::_Close_dir(result_handle);
if(DeleteFileA("tr2_test_dir/f1"))
printf("Expected tr2_test_dir/f1 to exist\n");
if(DeleteFileA("tr2_test_dir/f2"))
printf("Expected tr2_test_dir/f2 to exist\n");
if(DeleteFileA("tr2_test_dir/f3"))
printf("Expected tr2_test_dir/f3 to exist\n");
if(RemoveDirectoryA("tr2_test_dir"))
printf("Expected tr2_test_dir to exist\n");
struct
#include "winioctl.h"
#ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE
#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 )
#endif
#ifndef IO_REPARSE_TAG_SYMLINK
#define IO_REPARSE_TAG_SYMLINK (0xA000000C)
#endif
#ifndef IO_REPARSE_TAG_MOUNT_POINT
#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003)
#endif
typedef struct {
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union {
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct {
UCHAR DataBuffer[1];
} GenericReparseBuffer;
};
} REPARSE_DATA_BUFFER;
BOOL is_reparse_point_a_symlink(char const *path)
{
char buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
DWORD dwRetLen;
HANDLE handle;
BOOL result;
handle = CreateFileA(path, FILE_READ_EA,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
if (handle == INVALID_HANDLE_VALUE)
return FALSE;
result = DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, buf,
MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &dwRetLen, NULL);
if (!result) return FALSE;
return (((REPARSE_DATA_BUFFER*)buf)->ReparseTag == IO_REPARSE_TAG_SYMLINK
|| ((REPARSE_DATA_BUFFER*)buf)->ReparseTag ==IO_REPARSE_TAG_MOUNT_POINT
);
}
stat
if(attr & FILE_ATTRIBUTE_REPARSE_POINT) {
FIXME("reparse point is not supported yet\n");
handle = CreateFileA(path, 0,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
if(handle == INVALID_HANDLE_VALUE) {
ret = process_status_failure(error_code);
return ret;
}
if(!is_reparse_point_a_symlink(path))
ret = fifo_file;//shoule be reparse file?
return ret;
}
Lstat
return is_reparse_point_a_symlink(path)?symlink_file:fifo_file;//shoule be reparse file?
#include <filesystem>
#include <stdio.h>
#include <windows.h>
#include <iostream>
using namespace std;
int main(void)
{
HANDLE file;
int ret;
__int64 last_write_time, newtime;
ret = tr2::sys::_Make_dir("tr2_test_dir");
if( ret != 1 )
printf("test_tr2_sys__Make_dir(): expect %d got %d\n", 1, ret);
file = CreateFileA("tr2_test_dir/f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if(file == INVALID_HANDLE_VALUE)
printf("create file failed: INVALID_HANDLE_VALUE\n");
CloseHandle(file);
last_write_time = tr2::sys::_Last_write_time("tr2_test_dir/f1");
newtime = last_write_time + 11111111;
tr2::sys::_Last_write_time("tr2_test_dir/f1", newtime);
if(last_write_time == tr2::sys::_Last_write_time("tr2_test_dir/f1"))
printf("last_write_time before modfied should not equal to last_write_time now\n");
printf("last_write_time is\t %lld\n", last_write_time);
printf("newtime is\t\t %lld\n", newtime);
printf("access is\t\t %lld\n", tr2::sys::_Last_write_time("tr2_test_dir/f1"));
if(!DeleteFileA("tr2_test_dir/f1"))
printf("Expected tr2_test_dir/f1 to exist\n");
ret = tr2::sys::_Remove_dir("tr2_test_dir");
if(ret != 1)
printf("test_tr2_sys__Remove_dir(): expect %d got %d\n", 1, ret);
system("pause");
}
end
void * __cdecl std::tr2::sys::_Open_dir(char *,char const *,int &,enum std::tr2::sys::file_type &)
_Open_dir(_Dest, _Pval._Ptr(), _Errno, _Ftype);
char * __cdecl std::tr2::sys::_Read_dir(char *,void *,enum std::tr2::sys::file_type &)
string_type _Str = _Read_dir(_Dest, *_Mypdir, _Ftype);
char a[100], dest[MAX_PATH];
GetCurrentDirectory(MAX_PATH, dest);
HANDLE x;
int err;
enum std::tr2::sys::file_type type;
x = std::tr2::sys::_Open_dir(a, dest, err, type);
char *t = a;
do {
cout<<"return is "<<t<<endl;
t = std::tr2::sys::_Read_dir(dest, x, type);
} while(strlen(t) != 0);
cout<<GetLastError()<<" & err"<<err<<endl;
````
http://stackoverflow.com/questions/883594/microsoft-visual-studio-opendir-and-readdir-how
file.c:4053: Test failed: OpenFileById: failed to query for FileIdBothDirectoryInfo, got error 234.
file.c:4070: Test failed: OpenFileById: failed to find the temp file in the temp folder.
file.c:4081: Test failed: OpenFileById: failed to open the file, got error 5.
file.c:4085: Test failed: OpenFileById: ReadFile failed, got error 6.
file.c:4086: Test failed: OpenFileById: invalid contents of the temp file.
```
not_found:
unix_name[pos - 1] = 0;
- return STATUS_OBJECT_PATH_NOT_FOUND;
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ //return STATUS_OBJECT_PATH_NOT_FOUND;
success:
if (is_win_dir && !stat( unix_name, &st )) *is_win_dir = is_same_file( &windir, &st );
@@ -3002,18 +3003,19 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
/* if this is the last element, not finding it is not necessarily fatal */
if (!name_len)
{
- if (status == STATUS_OBJECT_PATH_NOT_FOUND)
+ if (status == STATUS_OBJECT_PATH_NOT_FOUND || status == STATUS_OBJECT_NAME_NOT_FOUND)
{
- status = STATUS_OBJECT_NAME_NOT_FOUND;
+ //status = STATUS_OBJECT_NAME_NOT_FOUND;
if (disposition != FILE_OPEN && disposition != FILE_OVERWRITE)
{
ret = ntdll_wcstoumbs( 0, name, end - name, unix_name + pos + 1,
MAX_DIR_ENTRY_LEN, NULL, &used_default );
if (ret > 0 && !used_default)
{
+ if(status != STATUS_OBJECT_PATH_NOT_FOUND)
+ status = STATUS_NO_SUCH_FILE;
unix_name[pos] = '/';
unix_name[pos + 1 + ret] = 0;
- status = STATUS_NO_SUCH_FILE;
break;
}
}
```
3.关于_GetLastWriteTime的测试,crosstest的结果与在vs上得到的结果不一样,如下图:
_GetLastWriteTime是重载函数,功能按照在vs上的结果,可以确定为2个。原型为:
<div class="md-section-divider"></div>
static __int64 (__cdecl p_tr2_sys__Last_write_time)(char const);
static void (__cdecl p_tr2_sys__Last_write_time_set)(char const, __int64);
1.只有char const*参数的,是返回文件的LastWriteTime
2.有char const*与_int64做参数的,是修改文件的LastWriteTime
那么为什么crosstest是在testbot里运行还是在win7里运行,都是不行的呢?
1.
In my test, he function is_regular and is_symlink are using the fuction enum std::tr2::sys::file_type __cdecl std::tr2::sys::_Stat(char const *,int &) . I found it is because I used path object as a paramace to call them, so it will call return is_regular(status(Pval)), whose origin function is [status Function](https://msdn.microsoft.com/zh-cn/library/hh874706.aspx). But this was a wrapper because wrapper is different.
> The lstat() function shall be equivalent to stat(), except when path refers to a symbolic link. In that case lstat() shall return information about the link, while stat() shall return information about the file the link references.
is_regular 和 is_symlink等函数,都是用到了 enum std::tr2::sys::file_type __cdecl std::tr2::sys::_Stat(char const *,int &) 这个函数, 原因就是我写win程序调用它们时都是用了Path object做参数,所以就用了returns is_regular(status(Pval)). 所以它的原型就是[status Function](https://msdn.microsoft.com/zh-cn/library/hh874706.aspx),但是这个只是wrapper,因为返回类型不一样。可能是staus使用最原始的_Stat函数返回enum类型后,再转换成file_status类型返回。
返回值enum的具体信息在[file_type、Enumeration](https://msdn.microsoft.com/zh-cn/library/hh874821.aspx)
至于参数,待定中。
<div class="md-section-divider"></div>
inline bool is_regular(
file_status Stat
);
template
inline bool is_regular(
const Path& Pval
);
is_regular是重载函数,有两个参数。
对于第一个参数[file_status Class](https://msdn.microsoft.com/zh-cn/library/hh874791.aspx)是A file_status object, 需要实现它; 而file_status的[构造函数](https://msdn.microsoft.com/zh-cn/library/hh874660.aspx)则有一个默认参数file_type Ftype = status_unknown。
> The first function returns Stat.type() == regular_file.
所以要实现[file_status::type Method](https://msdn.microsoft.com/zh-cn/library/hh874717.aspx`)
---
<div class="md-section-divider"></div>
/* create a directory tree that can be used by subsequent tests
* ├── tr2_test_dir
* │ ├── d1
* │ │ └── d1f1 an empty file
* │ ├── f0 an empty file
* │ └── f1 a file containing "file f1"
*/
static void create_tree(void)
{
FILE *file;
mkdir("tr2_test_dir");
mkdir("tr2_test_dir/d1");
file = fopen("tr2_test_dir/d1/d1f1", "wt");
fprintf(file, "");
fclose(file);
file = fopen("tr2_test_dir/f0", "wt");
fprintf(file, "");
fclose(file);
file = fopen("tr2_test_dir/f1", "wt");
fprintf(file, "file f1");
fclose(file);
}
static void remove_tree(void)
{
unlink("tr2_test_dir/f0");
unlink("tr2_test_dir/f1");
unlink("tr2_test_dir/d1/d1f1");
rmdir("tr2_test_dir/d1");
rmdir("tr2_test_dir");
}
<div class="md-section-divider"></div>
// { "f1", "tr2_test_dir\f1_copy", FALSE, 0, ERROR_SUCCESS },
// { "f1", "tr2_test_dir", TRUE, 5, ERROR_ACCESS_DENIED },
// { NULL, "f1", TRUE, 87, ERROR_INVALID_PARAMETER },
// { "f1", NULL, TRUE, 87, ERROR_INVALID_PARAMETER },
测试,在copyfilea有问题)
```