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