xref: /minix3/external/bsd/libarchive/dist/cpio/cpio_windows.c (revision 543adbed3a3a783ed36434adafbc258b6bde442d)
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