]>
Commit | Line | Data |
---|---|---|
a4b75251 TL |
1 | // SPDX-License-Identifier: BSD-3-Clause |
2 | /* Copyright 2015-2020, Intel Corporation */ | |
3 | ||
4 | /* | |
5 | * file_windows.c -- Windows emulation of Linux-specific system calls | |
6 | */ | |
7 | ||
8 | /* | |
9 | * XXX - The initial approach to PMDK for Windows port was to minimize the | |
10 | * amount of changes required in the core part of the library, and to avoid | |
11 | * preprocessor conditionals, if possible. For that reason, some of the | |
12 | * Linux system calls that have no equivalents on Windows have been emulated | |
13 | * using Windows API. | |
14 | * Note that it was not a goal to fully emulate POSIX-compliant behavior | |
15 | * of mentioned functions. They are used only internally, so current | |
16 | * implementation is just good enough to satisfy PMDK needs and to make it | |
17 | * work on Windows. | |
18 | */ | |
19 | ||
20 | #include <windows.h> | |
21 | #include <sys/stat.h> | |
22 | #include <sys/file.h> | |
23 | ||
24 | #include "alloc.h" | |
25 | #include "file.h" | |
26 | #include "out.h" | |
27 | #include "os.h" | |
28 | ||
29 | /* | |
30 | * util_tmpfile -- create a temporary file | |
31 | */ | |
32 | int | |
33 | util_tmpfile(const char *dir, const char *templ, int flags) | |
34 | { | |
35 | LOG(3, "dir \"%s\" template \"%s\" flags %x", dir, templ, flags); | |
36 | ||
37 | /* only O_EXCL is allowed here */ | |
38 | ASSERT(flags == 0 || flags == O_EXCL); | |
39 | ||
40 | int oerrno; | |
41 | int fd = -1; | |
42 | ||
43 | size_t len = strlen(dir) + strlen(templ) + 1; | |
44 | char *fullname = Malloc(sizeof(*fullname) * len); | |
45 | if (fullname == NULL) { | |
46 | ERR("!Malloc"); | |
47 | return -1; | |
48 | } | |
49 | ||
50 | int ret = _snprintf(fullname, len, "%s%s", dir, templ); | |
51 | if (ret < 0 || ret >= len) { | |
52 | ERR("snprintf: %d", ret); | |
53 | goto err; | |
54 | } | |
55 | ||
56 | LOG(4, "fullname \"%s\"", fullname); | |
57 | ||
58 | /* | |
59 | * XXX - block signals and modify file creation mask for the time | |
60 | * of mkstmep() execution. Restore previous settings once the file | |
61 | * is created. | |
62 | */ | |
63 | ||
64 | fd = os_mkstemp(fullname); | |
65 | if (fd < 0) { | |
66 | ERR("!os_mkstemp"); | |
67 | goto err; | |
68 | } | |
69 | ||
70 | /* | |
71 | * There is no point to use unlink() here. First, because it does not | |
72 | * work on open files. Second, because the file is created with | |
73 | * O_TEMPORARY flag, and it looks like such temp files cannot be open | |
74 | * from another process, even though they are visible on | |
75 | * the filesystem. | |
76 | */ | |
77 | ||
78 | Free(fullname); | |
79 | return fd; | |
80 | ||
81 | err: | |
82 | Free(fullname); | |
83 | oerrno = errno; | |
84 | if (fd != -1) | |
85 | (void) os_close(fd); | |
86 | errno = oerrno; | |
87 | return -1; | |
88 | } | |
89 | ||
90 | /* | |
91 | * util_is_absolute_path -- check if the path is absolute | |
92 | */ | |
93 | int | |
94 | util_is_absolute_path(const char *path) | |
95 | { | |
96 | LOG(3, "path \"%s\"", path); | |
97 | ||
98 | if (path == NULL || path[0] == '\0') | |
99 | return 0; | |
100 | ||
101 | if (path[0] == '\\' || path[1] == ':') | |
102 | return 1; | |
103 | ||
104 | return 0; | |
105 | } | |
106 | ||
107 | /* | |
108 | * util_file_mkdir -- creates new dir | |
109 | */ | |
110 | int | |
111 | util_file_mkdir(const char *path, mode_t mode) | |
112 | { | |
113 | /* | |
114 | * On windows we cannot create read only dir so mode | |
115 | * parameter is useless. | |
116 | */ | |
117 | UNREFERENCED_PARAMETER(mode); | |
118 | LOG(3, "path: %s mode: %d", path, mode); | |
119 | return _mkdir(path); | |
120 | } | |
121 | ||
122 | /* | |
123 | * util_file_dir_open -- open a directory | |
124 | */ | |
125 | int | |
126 | util_file_dir_open(struct dir_handle *handle, const char *path) | |
127 | { | |
128 | /* init handle */ | |
129 | handle->handle = NULL; | |
130 | handle->path = path; | |
131 | return 0; | |
132 | } | |
133 | ||
134 | /* | |
135 | * util_file_dir_next - read next file in directory | |
136 | */ | |
137 | int | |
138 | util_file_dir_next(struct dir_handle *handle, struct file_info *info) | |
139 | { | |
140 | WIN32_FIND_DATAA data; | |
141 | if (handle->handle == NULL) { | |
142 | handle->handle = FindFirstFileA(handle->path, &data); | |
143 | if (handle->handle == NULL) | |
144 | return 1; | |
145 | } else { | |
146 | if (FindNextFileA(handle->handle, &data) == 0) | |
147 | return 1; | |
148 | } | |
149 | info->filename[NAME_MAX] = '\0'; | |
150 | strncpy(info->filename, data.cFileName, NAME_MAX + 1); | |
151 | if (info->filename[NAME_MAX] != '\0') | |
152 | return -1; /* filename truncated */ | |
153 | info->is_dir = data.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY; | |
154 | ||
155 | return 0; | |
156 | } | |
157 | ||
158 | /* | |
159 | * util_file_dir_close -- close a directory | |
160 | */ | |
161 | int | |
162 | util_file_dir_close(struct dir_handle *handle) | |
163 | { | |
164 | return FindClose(handle->handle); | |
165 | } | |
166 | ||
167 | /* | |
168 | * util_file_dir_remove -- remove directory | |
169 | */ | |
170 | int | |
171 | util_file_dir_remove(const char *path) | |
172 | { | |
173 | return RemoveDirectoryA(path) == 0 ? -1 : 0; | |
174 | } | |
175 | ||
176 | /* | |
177 | * util_file_device_dax_alignment -- returns internal Device DAX alignment | |
178 | */ | |
179 | size_t | |
180 | util_file_device_dax_alignment(const char *path) | |
181 | { | |
182 | LOG(3, "path \"%s\"", path); | |
183 | ||
184 | return 0; | |
185 | } | |
186 | ||
187 | /* | |
188 | * util_ddax_region_find -- returns DEV dax region id that contains file | |
189 | */ | |
190 | int | |
191 | util_ddax_region_find(const char *path, unsigned *region_id) | |
192 | { | |
193 | LOG(3, "path \"%s\"", path); | |
194 | ||
195 | return -1; | |
196 | } |