[关闭]
@ChristopherWu 2015-06-25T17:18:54.000000Z 字数 9439 阅读 1364

Wine GSOC Note

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

  1. #include "winioctl.h"
  2. #ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE
  3. #define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 )
  4. #endif
  5. #ifndef IO_REPARSE_TAG_SYMLINK
  6. #define IO_REPARSE_TAG_SYMLINK (0xA000000C)
  7. #endif
  8. #ifndef IO_REPARSE_TAG_MOUNT_POINT
  9. #define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003)
  10. #endif
  11. typedef struct {
  12. ULONG ReparseTag;
  13. USHORT ReparseDataLength;
  14. USHORT Reserved;
  15. union {
  16. struct {
  17. USHORT SubstituteNameOffset;
  18. USHORT SubstituteNameLength;
  19. USHORT PrintNameOffset;
  20. USHORT PrintNameLength;
  21. ULONG Flags;
  22. WCHAR PathBuffer[1];
  23. } SymbolicLinkReparseBuffer;
  24. struct {
  25. USHORT SubstituteNameOffset;
  26. USHORT SubstituteNameLength;
  27. USHORT PrintNameOffset;
  28. USHORT PrintNameLength;
  29. WCHAR PathBuffer[1];
  30. } MountPointReparseBuffer;
  31. struct {
  32. UCHAR DataBuffer[1];
  33. } GenericReparseBuffer;
  34. };
  35. } REPARSE_DATA_BUFFER;
  36. BOOL is_reparse_point_a_symlink(char const *path)
  37. {
  38. char buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
  39. DWORD dwRetLen;
  40. HANDLE handle;
  41. BOOL result;
  42. handle = CreateFileA(path, FILE_READ_EA,
  43. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
  44. FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
  45. if (handle == INVALID_HANDLE_VALUE)
  46. return FALSE;
  47. result = DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, buf,
  48. MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &dwRetLen, NULL);
  49. if (!result) return FALSE;
  50. return (((REPARSE_DATA_BUFFER*)buf)->ReparseTag == IO_REPARSE_TAG_SYMLINK
  51. || ((REPARSE_DATA_BUFFER*)buf)->ReparseTag ==IO_REPARSE_TAG_MOUNT_POINT
  52. );
  53. }

stat

  1. if(attr & FILE_ATTRIBUTE_REPARSE_POINT) {
  2. FIXME("reparse point is not supported yet\n");
  3. handle = CreateFileA(path, 0,
  4. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  5. 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
  6. if(handle == INVALID_HANDLE_VALUE) {
  7. ret = process_status_failure(error_code);
  8. return ret;
  9. }
  10. if(!is_reparse_point_a_symlink(path))
  11. ret = fifo_file;//shoule be reparse file?
  12. return ret;
  13. }

Lstat

  1. return is_reparse_point_a_symlink(path)?symlink_file:fifo_file;//shoule be reparse file?
  1. #include <filesystem>
  2. #include <stdio.h>
  3. #include <windows.h>
  4. #include <iostream>
  5. using namespace std;
  6. int main(void)
  7. {
  8. HANDLE file;
  9. int ret;
  10. __int64 last_write_time, newtime;
  11. ret = tr2::sys::_Make_dir("tr2_test_dir");
  12. if( ret != 1 )
  13. printf("test_tr2_sys__Make_dir(): expect %d got %d\n", 1, ret);
  14. file = CreateFileA("tr2_test_dir/f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
  15. if(file == INVALID_HANDLE_VALUE)
  16. printf("create file failed: INVALID_HANDLE_VALUE\n");
  17. CloseHandle(file);
  18. last_write_time = tr2::sys::_Last_write_time("tr2_test_dir/f1");
  19. newtime = last_write_time + 11111111;
  20. tr2::sys::_Last_write_time("tr2_test_dir/f1", newtime);
  21. if(last_write_time == tr2::sys::_Last_write_time("tr2_test_dir/f1"))
  22. printf("last_write_time before modfied should not equal to last_write_time now\n");
  23. printf("last_write_time is\t %lld\n", last_write_time);
  24. printf("newtime is\t\t %lld\n", newtime);
  25. printf("access is\t\t %lld\n", tr2::sys::_Last_write_time("tr2_test_dir/f1"));
  26. if(!DeleteFileA("tr2_test_dir/f1"))
  27. printf("Expected tr2_test_dir/f1 to exist\n");
  28. ret = tr2::sys::_Remove_dir("tr2_test_dir");
  29. if(ret != 1)
  30. printf("test_tr2_sys__Remove_dir(): expect %d got %d\n", 1, ret);
  31. system("pause");
  32. }

end

  1. void * __cdecl std::tr2::sys::_Open_dir(char *,char const *,int &,enum std::tr2::sys::file_type &)
  2. _Open_dir(_Dest, _Pval._Ptr(), _Errno, _Ftype);
  3. char * __cdecl std::tr2::sys::_Read_dir(char *,void *,enum std::tr2::sys::file_type &)
  4. string_type _Str = _Read_dir(_Dest, *_Mypdir, _Ftype);
  1. char a[100], dest[MAX_PATH];
  2. GetCurrentDirectory(MAX_PATH, dest);
  3. HANDLE x;
  4. int err;
  5. enum std::tr2::sys::file_type type;
  6. x = std::tr2::sys::_Open_dir(a, dest, err, type);
  7. char *t = a;
  8. do {
  9. cout<<"return is "<<t<<endl;
  10. t = std::tr2::sys::_Read_dir(dest, x, type);
  11. } while(strlen(t) != 0);
  12. cout<<GetLastError()<<" & err"<<err<<endl;
  13. ````
  14. http://stackoverflow.com/questions/883594/microsoft-visual-studio-opendir-and-readdir-how
  15. file.c:4053: Test failed: OpenFileById: failed to query for FileIdBothDirectoryInfo, got error 234.
  16. file.c:4070: Test failed: OpenFileById: failed to find the temp file in the temp folder.
  17. file.c:4081: Test failed: OpenFileById: failed to open the file, got error 5.
  18. file.c:4085: Test failed: OpenFileById: ReadFile failed, got error 6.
  19. file.c:4086: Test failed: OpenFileById: invalid contents of the temp file.
  20. ```
  21. not_found:
  22. unix_name[pos - 1] = 0;
  23. - return STATUS_OBJECT_PATH_NOT_FOUND;
  24. + return STATUS_OBJECT_NAME_NOT_FOUND;
  25. + //return STATUS_OBJECT_PATH_NOT_FOUND;
  26. success:
  27. if (is_win_dir && !stat( unix_name, &st )) *is_win_dir = is_same_file( &windir, &st );
  28. @@ -3002,18 +3003,19 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
  29. /* if this is the last element, not finding it is not necessarily fatal */
  30. if (!name_len)
  31. {
  32. - if (status == STATUS_OBJECT_PATH_NOT_FOUND)
  33. + if (status == STATUS_OBJECT_PATH_NOT_FOUND || status == STATUS_OBJECT_NAME_NOT_FOUND)
  34. {
  35. - status = STATUS_OBJECT_NAME_NOT_FOUND;
  36. + //status = STATUS_OBJECT_NAME_NOT_FOUND;
  37. if (disposition != FILE_OPEN && disposition != FILE_OVERWRITE)
  38. {
  39. ret = ntdll_wcstoumbs( 0, name, end - name, unix_name + pos + 1,
  40. MAX_DIR_ENTRY_LEN, NULL, &used_default );
  41. if (ret > 0 && !used_default)
  42. {
  43. + if(status != STATUS_OBJECT_PATH_NOT_FOUND)
  44. + status = STATUS_NO_SUCH_FILE;
  45. unix_name[pos] = '/';
  46. unix_name[pos + 1 + ret] = 0;
  47. - status = STATUS_NO_SUCH_FILE;
  48. break;
  49. }
  50. }
  51. ```
  52. 3.关于_GetLastWriteTime的测试,crosstest的结果与在vs上得到的结果不一样,如下图:
  53. _GetLastWriteTime是重载函数,功能按照在vs上的结果,可以确定为2个。原型为:
  54. <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. 1.只有char const*参数的,是返回文件的LastWriteTime
  2. 2.char const*与_int64做参数的,是修改文件的LastWriteTime
  3. 那么为什么crosstest是在testbot里运行还是在win7里运行,都是不行的呢?
  4. 1.
  5. 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.
  6. > 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.
  7. 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类型返回。
  8. 返回值enum的具体信息在[file_typeEnumeration](https://msdn.microsoft.com/zh-cn/library/hh874821.aspx)
  9. 至于参数,待定中。
  10. <div class="md-section-divider"></div>

inline bool is_regular(
file_status Stat
);
template
inline bool is_regular(
const Path& Pval
);

  1. is_regular是重载函数,有两个参数。
  2. 对于第一个参数[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。
  3. > The first function returns Stat.type() == regular_file.
  4. 所以要实现[file_status::type Method](https://msdn.microsoft.com/zh-cn/library/hh874717.aspx`)
  5. ---
  6. <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");
}

  1. <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有问题)
```

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注