cpio_windows.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. /*-
  2. * Copyright (c) 2009 Michihiro NAKAJIMA
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  17. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
  18. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. *
  25. * $FreeBSD$
  26. */
  27. #if defined(_WIN32) && !defined(__CYGWIN__)
  28. #include "cpio_platform.h"
  29. #include <ctype.h>
  30. #include <errno.h>
  31. #include <fcntl.h>
  32. #include <io.h>
  33. #include <stddef.h>
  34. #ifdef HAVE_SYS_UTIME_H
  35. #include <sys/utime.h>
  36. #endif
  37. #include <sys/stat.h>
  38. #include <process.h>
  39. #include <stdlib.h>
  40. #include <wchar.h>
  41. #include <windows.h>
  42. #include <sddl.h>
  43. #include "cpio.h"
  44. #include "err.h"
  45. #define EPOC_TIME (116444736000000000ULL)
  46. static void cpio_dosmaperr(unsigned long);
  47. /*
  48. * Prepend "\\?\" to the path name and convert it to unicode to permit
  49. * an extended-length path for a maximum total path length of 32767
  50. * characters.
  51. * see also http://msdn.microsoft.com/en-us/library/aa365247.aspx
  52. */
  53. static wchar_t *
  54. permissive_name(const char *name)
  55. {
  56. wchar_t *wn, *wnp;
  57. wchar_t *ws, *wsp;
  58. DWORD l, len, slen, alloclen;
  59. int unc;
  60. len = (DWORD)strlen(name);
  61. wn = malloc((len + 1) * sizeof(wchar_t));
  62. if (wn == NULL)
  63. return (NULL);
  64. l = MultiByteToWideChar(CP_ACP, 0, name, len, wn, len);
  65. if (l == 0) {
  66. free(wn);
  67. return (NULL);
  68. }
  69. wn[l] = L'\0';
  70. /* Get a full path names */
  71. l = GetFullPathNameW(wn, 0, NULL, NULL);
  72. if (l == 0) {
  73. free(wn);
  74. return (NULL);
  75. }
  76. wnp = malloc(l * sizeof(wchar_t));
  77. if (wnp == NULL) {
  78. free(wn);
  79. return (NULL);
  80. }
  81. len = GetFullPathNameW(wn, l, wnp, NULL);
  82. free(wn);
  83. wn = wnp;
  84. if (wnp[0] == L'\\' && wnp[1] == L'\\' &&
  85. wnp[2] == L'?' && wnp[3] == L'\\')
  86. /* We have already permissive names. */
  87. return (wn);
  88. if (wnp[0] == L'\\' && wnp[1] == L'\\' &&
  89. wnp[2] == L'.' && wnp[3] == L'\\') {
  90. /* Device names */
  91. if (((wnp[4] >= L'a' && wnp[4] <= L'z') ||
  92. (wnp[4] >= L'A' && wnp[4] <= L'Z')) &&
  93. wnp[5] == L':' && wnp[6] == L'\\')
  94. wnp[2] = L'?';/* Not device names. */
  95. return (wn);
  96. }
  97. unc = 0;
  98. if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') {
  99. wchar_t *p = &wnp[2];
  100. /* Skip server-name letters. */
  101. while (*p != L'\\' && *p != L'\0')
  102. ++p;
  103. if (*p == L'\\') {
  104. wchar_t *rp = ++p;
  105. /* Skip share-name letters. */
  106. while (*p != L'\\' && *p != L'\0')
  107. ++p;
  108. if (*p == L'\\' && p != rp) {
  109. /* Now, match patterns such as
  110. * "\\server-name\share-name\" */
  111. wnp += 2;
  112. len -= 2;
  113. unc = 1;
  114. }
  115. }
  116. }
  117. alloclen = slen = 4 + (unc * 4) + len + 1;
  118. ws = wsp = malloc(slen * sizeof(wchar_t));
  119. if (ws == NULL) {
  120. free(wn);
  121. return (NULL);
  122. }
  123. /* prepend "\\?\" */
  124. wcsncpy(wsp, L"\\\\?\\", 4);
  125. wsp += 4;
  126. slen -= 4;
  127. if (unc) {
  128. /* append "UNC\" ---> "\\?\UNC\" */
  129. wcsncpy(wsp, L"UNC\\", 4);
  130. wsp += 4;
  131. slen -= 4;
  132. }
  133. wcsncpy(wsp, wnp, slen);
  134. free(wn);
  135. ws[alloclen - 1] = L'\0';
  136. return (ws);
  137. }
  138. static HANDLE
  139. cpio_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode,
  140. LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
  141. DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
  142. {
  143. wchar_t *wpath;
  144. HANDLE handle;
  145. # if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
  146. CREATEFILE2_EXTENDED_PARAMETERS createExParams;
  147. #endif
  148. #if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP)
  149. handle = CreateFileA(path, dwDesiredAccess, dwShareMode,
  150. lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes,
  151. hTemplateFile);
  152. if (handle != INVALID_HANDLE_VALUE)
  153. return (handle);
  154. if (GetLastError() != ERROR_PATH_NOT_FOUND)
  155. return (handle);
  156. #endif
  157. wpath = permissive_name(path);
  158. if (wpath == NULL)
  159. return INVALID_HANDLE_VALUE;
  160. # if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
  161. ZeroMemory(&createExParams, sizeof(createExParams));
  162. createExParams.dwSize = sizeof(createExParams);
  163. createExParams.dwFileAttributes = dwFlagsAndAttributes & 0xFFFF;
  164. createExParams.dwFileFlags = dwFlagsAndAttributes & 0xFFF00000;
  165. createExParams.dwSecurityQosFlags = dwFlagsAndAttributes & 0x000F0000;
  166. createExParams.lpSecurityAttributes = lpSecurityAttributes;
  167. createExParams.hTemplateFile = hTemplateFile;
  168. handle = CreateFile2(wpath, dwDesiredAccess, dwShareMode,
  169. dwCreationDisposition, &createExParams);
  170. #else
  171. handle = CreateFileW(wpath, dwDesiredAccess, dwShareMode,
  172. lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes,
  173. hTemplateFile);
  174. #endif
  175. free(wpath);
  176. return (handle);
  177. }
  178. #define WINTIME(sec, usec) ((Int32x32To64(sec, 10000000) + EPOC_TIME) + (usec * 10))
  179. static int
  180. __hutimes(HANDLE handle, const struct __timeval *times)
  181. {
  182. ULARGE_INTEGER wintm;
  183. FILETIME fatime, fmtime;
  184. wintm.QuadPart = WINTIME(times[0].tv_sec, times[0].tv_usec);
  185. fatime.dwLowDateTime = wintm.LowPart;
  186. fatime.dwHighDateTime = wintm.HighPart;
  187. wintm.QuadPart = WINTIME(times[1].tv_sec, times[1].tv_usec);
  188. fmtime.dwLowDateTime = wintm.LowPart;
  189. fmtime.dwHighDateTime = wintm.HighPart;
  190. if (SetFileTime(handle, NULL, &fatime, &fmtime) == 0) {
  191. errno = EINVAL;
  192. return (-1);
  193. }
  194. return (0);
  195. }
  196. int
  197. futimes(int fd, const struct __timeval *times)
  198. {
  199. return (__hutimes((HANDLE)_get_osfhandle(fd), times));
  200. }
  201. int
  202. utimes(const char *name, const struct __timeval *times)
  203. {
  204. int ret;
  205. HANDLE handle;
  206. handle = cpio_CreateFile(name, GENERIC_READ | GENERIC_WRITE,
  207. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
  208. FILE_FLAG_BACKUP_SEMANTICS, NULL);
  209. if (handle == INVALID_HANDLE_VALUE) {
  210. cpio_dosmaperr(GetLastError());
  211. return (-1);
  212. }
  213. ret = __hutimes(handle, times);
  214. CloseHandle(handle);
  215. return (ret);
  216. }
  217. /*
  218. * The following function was modified from PostgreSQL sources and is
  219. * subject to the copyright below.
  220. */
  221. /*-------------------------------------------------------------------------
  222. *
  223. * win32error.c
  224. * Map win32 error codes to errno values
  225. *
  226. * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  227. *
  228. * IDENTIFICATION
  229. * $PostgreSQL: pgsql/src/port/win32error.c,v 1.4 2008/01/01 19:46:00 momjian Exp $
  230. *
  231. *-------------------------------------------------------------------------
  232. */
  233. /*
  234. PostgreSQL Database Management System
  235. (formerly known as Postgres, then as Postgres95)
  236. Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  237. Portions Copyright (c) 1994, The Regents of the University of California
  238. Permission to use, copy, modify, and distribute this software and its
  239. documentation for any purpose, without fee, and without a written agreement
  240. is hereby granted, provided that the above copyright notice and this
  241. paragraph and the following two paragraphs appear in all copies.
  242. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  243. DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
  244. LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
  245. DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
  246. POSSIBILITY OF SUCH DAMAGE.
  247. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  248. INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  249. AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
  250. ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
  251. PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  252. */
  253. static const struct {
  254. DWORD winerr;
  255. int doserr;
  256. } doserrors[] =
  257. {
  258. { ERROR_INVALID_FUNCTION, EINVAL },
  259. { ERROR_FILE_NOT_FOUND, ENOENT },
  260. { ERROR_PATH_NOT_FOUND, ENOENT },
  261. { ERROR_TOO_MANY_OPEN_FILES, EMFILE },
  262. { ERROR_ACCESS_DENIED, EACCES },
  263. { ERROR_INVALID_HANDLE, EBADF },
  264. { ERROR_ARENA_TRASHED, ENOMEM },
  265. { ERROR_NOT_ENOUGH_MEMORY, ENOMEM },
  266. { ERROR_INVALID_BLOCK, ENOMEM },
  267. { ERROR_BAD_ENVIRONMENT, E2BIG },
  268. { ERROR_BAD_FORMAT, ENOEXEC },
  269. { ERROR_INVALID_ACCESS, EINVAL },
  270. { ERROR_INVALID_DATA, EINVAL },
  271. { ERROR_INVALID_DRIVE, ENOENT },
  272. { ERROR_CURRENT_DIRECTORY, EACCES },
  273. { ERROR_NOT_SAME_DEVICE, EXDEV },
  274. { ERROR_NO_MORE_FILES, ENOENT },
  275. { ERROR_LOCK_VIOLATION, EACCES },
  276. { ERROR_SHARING_VIOLATION, EACCES },
  277. { ERROR_BAD_NETPATH, ENOENT },
  278. { ERROR_NETWORK_ACCESS_DENIED, EACCES },
  279. { ERROR_BAD_NET_NAME, ENOENT },
  280. { ERROR_FILE_EXISTS, EEXIST },
  281. { ERROR_CANNOT_MAKE, EACCES },
  282. { ERROR_FAIL_I24, EACCES },
  283. { ERROR_INVALID_PARAMETER, EINVAL },
  284. { ERROR_NO_PROC_SLOTS, EAGAIN },
  285. { ERROR_DRIVE_LOCKED, EACCES },
  286. { ERROR_BROKEN_PIPE, EPIPE },
  287. { ERROR_DISK_FULL, ENOSPC },
  288. { ERROR_INVALID_TARGET_HANDLE, EBADF },
  289. { ERROR_INVALID_HANDLE, EINVAL },
  290. { ERROR_WAIT_NO_CHILDREN, ECHILD },
  291. { ERROR_CHILD_NOT_COMPLETE, ECHILD },
  292. { ERROR_DIRECT_ACCESS_HANDLE, EBADF },
  293. { ERROR_NEGATIVE_SEEK, EINVAL },
  294. { ERROR_SEEK_ON_DEVICE, EACCES },
  295. { ERROR_DIR_NOT_EMPTY, ENOTEMPTY },
  296. { ERROR_NOT_LOCKED, EACCES },
  297. { ERROR_BAD_PATHNAME, ENOENT },
  298. { ERROR_MAX_THRDS_REACHED, EAGAIN },
  299. { ERROR_LOCK_FAILED, EACCES },
  300. { ERROR_ALREADY_EXISTS, EEXIST },
  301. { ERROR_FILENAME_EXCED_RANGE, ENOENT },
  302. { ERROR_NESTING_NOT_ALLOWED, EAGAIN },
  303. { ERROR_NOT_ENOUGH_QUOTA, ENOMEM }
  304. };
  305. static void
  306. cpio_dosmaperr(unsigned long e)
  307. {
  308. int i;
  309. if (e == 0) {
  310. errno = 0;
  311. return;
  312. }
  313. for (i = 0; i < (int)sizeof(doserrors); i++) {
  314. if (doserrors[i].winerr == e) {
  315. errno = doserrors[i].doserr;
  316. return;
  317. }
  318. }
  319. /* fprintf(stderr, "unrecognized win32 error code: %lu", e); */
  320. errno = EINVAL;
  321. return;
  322. }
  323. #endif