xref: /netbsd-src/sys/rump/kern/lib/libsys_cygwin/rump_cygwin_compat.c (revision d91f98a8715141154279122ae81737cb65179572)
1*d91f98a8Spgoyette /*	$NetBSD: rump_cygwin_compat.c,v 1.3 2019/01/27 02:08:49 pgoyette Exp $	*/
2c5ab2014Spooka 
3c5ab2014Spooka /*
4c5ab2014Spooka  * Copyright (c) 2013 Antti Kantee.  All Rights Reserved.
5c5ab2014Spooka  *
6c5ab2014Spooka  * Redistribution and use in source and binary forms, with or without
7c5ab2014Spooka  * modification, are permitted provided that the following conditions
8c5ab2014Spooka  * are met:
9c5ab2014Spooka  * 1. Redistributions of source code must retain the above copyright
10c5ab2014Spooka  *    notice, this list of conditions and the following disclaimer.
11c5ab2014Spooka  * 2. Redistributions in binary form must reproduce the above copyright
12c5ab2014Spooka  *    notice, this list of conditions and the following disclaimer in the
13c5ab2014Spooka  *    documentation and/or other materials provided with the distribution.
14c5ab2014Spooka  *
15c5ab2014Spooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16c5ab2014Spooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17c5ab2014Spooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18c5ab2014Spooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19c5ab2014Spooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20c5ab2014Spooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21c5ab2014Spooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22c5ab2014Spooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23c5ab2014Spooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24c5ab2014Spooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25c5ab2014Spooka  * SUCH DAMAGE.
26c5ab2014Spooka  */
27c5ab2014Spooka 
28a57097d0Salnsn #include <sys/cdefs.h>
29*d91f98a8Spgoyette __KERNEL_RCSID(0, "$NetBSD: rump_cygwin_compat.c,v 1.3 2019/01/27 02:08:49 pgoyette Exp $");
30a57097d0Salnsn 
31c5ab2014Spooka #include <sys/param.h>
32c5ab2014Spooka #include <sys/dirent.h>
33c5ab2014Spooka #include <sys/fcntl.h>
34c5ab2014Spooka #include <sys/file.h>
35c5ab2014Spooka #include <sys/filedesc.h>
36c5ab2014Spooka #include <sys/malloc.h>
37c5ab2014Spooka #include <sys/namei.h>
38c5ab2014Spooka #include <sys/stat.h>
39c5ab2014Spooka #include <sys/syscallargs.h>
40c5ab2014Spooka #include <sys/vnode.h>
41c5ab2014Spooka #include <sys/vfs_syscalls.h>
42c5ab2014Spooka 
43c5ab2014Spooka #include <compat/sys/time_types.h>
44c5ab2014Spooka 
45c5ab2014Spooka #include "rump_cygwin_syscallargs.h"
46c5ab2014Spooka 
47c5ab2014Spooka struct cygwin_stat {
48c5ab2014Spooka         int		st_dev;
49c5ab2014Spooka         int64_t		st_ino;
50c5ab2014Spooka         int		st_mode;
51c5ab2014Spooka         unsigned short	st_nlink;
52c5ab2014Spooka         int		st_uid;
53c5ab2014Spooka         int		st_gid;
54c5ab2014Spooka         int		st_rdev;
55c5ab2014Spooka         off_t		st_size;
56c5ab2014Spooka 
57c5ab2014Spooka         struct timespec50 st_atim;
58c5ab2014Spooka         struct timespec50 st_mtim;
59c5ab2014Spooka         struct timespec50 st_ctim;
60c5ab2014Spooka 
61c5ab2014Spooka         long		st_blksize;
62c5ab2014Spooka         uint64_t	st_blocks;
63c5ab2014Spooka 
64c5ab2014Spooka         struct timespec50 st_btim;
65c5ab2014Spooka };
66c5ab2014Spooka 
67c5ab2014Spooka #define PARCOPY(a) ssb->a = sb->a
68c5ab2014Spooka static void
bsd_to_cygwin_stat(const struct stat * sb,struct cygwin_stat * ssb)69c5ab2014Spooka bsd_to_cygwin_stat(const struct stat *sb, struct cygwin_stat *ssb)
70c5ab2014Spooka {
71c5ab2014Spooka 
72c5ab2014Spooka 	memset(ssb, 0, sizeof(*ssb));
73c5ab2014Spooka 	PARCOPY(st_dev);
74c5ab2014Spooka 	PARCOPY(st_ino);
75c5ab2014Spooka 	PARCOPY(st_mode);
76c5ab2014Spooka 	PARCOPY(st_nlink);
77c5ab2014Spooka 	PARCOPY(st_uid);
78c5ab2014Spooka 	PARCOPY(st_gid);
79c5ab2014Spooka 	PARCOPY(st_rdev);
80c5ab2014Spooka 	PARCOPY(st_size);
81c5ab2014Spooka 	PARCOPY(st_blksize);
82c5ab2014Spooka 	PARCOPY(st_blocks);
83c5ab2014Spooka 
84c5ab2014Spooka 	timespec_to_timespec50(&sb->st_atimespec, &ssb->st_atim);
85c5ab2014Spooka 	timespec_to_timespec50(&sb->st_mtimespec, &ssb->st_mtim);
86c5ab2014Spooka 	timespec_to_timespec50(&sb->st_ctimespec, &ssb->st_ctim);
87c5ab2014Spooka 	timespec_to_timespec50(&sb->st_birthtimespec, &ssb->st_btim);
88c5ab2014Spooka }
89c5ab2014Spooka 
90c5ab2014Spooka int
rump_cygwin_sys_stat(struct lwp * l,const struct rump_cygwin_sys_stat_args * uap,register_t * retval)91c5ab2014Spooka rump_cygwin_sys_stat(struct lwp *l, const struct rump_cygwin_sys_stat_args *uap,
92c5ab2014Spooka 	register_t *retval)
93c5ab2014Spooka {
94c5ab2014Spooka 	struct cygwin_stat ssb;
95c5ab2014Spooka 	struct stat sb;
96c5ab2014Spooka 	int error;
97c5ab2014Spooka 
98c5ab2014Spooka 	error = do_sys_stat(SCARG(uap, path), FOLLOW, &sb);
99c5ab2014Spooka 	if (error)
100c5ab2014Spooka 		return error;
101c5ab2014Spooka 
102c5ab2014Spooka 	bsd_to_cygwin_stat(&sb, &ssb);
103c5ab2014Spooka 
104c5ab2014Spooka 	return copyout(&ssb, SCARG(uap, sp), sizeof(ssb));
105c5ab2014Spooka }
106c5ab2014Spooka 
107c5ab2014Spooka int
rump_cygwin_sys_fstat(struct lwp * l,const struct rump_cygwin_sys_fstat_args * uap,register_t * retval)108c5ab2014Spooka rump_cygwin_sys_fstat(struct lwp *l, const struct rump_cygwin_sys_fstat_args *uap,
109c5ab2014Spooka 	register_t *retval)
110c5ab2014Spooka {
111c5ab2014Spooka 	struct cygwin_stat ssb;
112c5ab2014Spooka 	struct stat sb;
113c5ab2014Spooka 	int error;
114c5ab2014Spooka 
115c5ab2014Spooka 	error = do_sys_fstat(SCARG(uap, fd), &sb);
116c5ab2014Spooka 	if (error)
117c5ab2014Spooka 		return error;
118c5ab2014Spooka 
119c5ab2014Spooka 	bsd_to_cygwin_stat(&sb, &ssb);
120c5ab2014Spooka 
121c5ab2014Spooka 	return copyout(&ssb, SCARG(uap, sp), sizeof(ssb));
122c5ab2014Spooka }
123c5ab2014Spooka 
124c5ab2014Spooka int
rump_cygwin_sys_lstat(struct lwp * l,const struct rump_cygwin_sys_lstat_args * uap,register_t * retval)125c5ab2014Spooka rump_cygwin_sys_lstat(struct lwp *l, const struct rump_cygwin_sys_lstat_args *uap,
126c5ab2014Spooka 	register_t *retval)
127c5ab2014Spooka {
128c5ab2014Spooka 	struct cygwin_stat ssb;
129c5ab2014Spooka 	struct stat sb;
130c5ab2014Spooka 	int error;
131c5ab2014Spooka 
132c5ab2014Spooka 	error = do_sys_stat(SCARG(uap, path), NOFOLLOW, &sb);
133c5ab2014Spooka 	if (error)
134c5ab2014Spooka 		return error;
135c5ab2014Spooka 
136c5ab2014Spooka 	bsd_to_cygwin_stat(&sb, &ssb);
137c5ab2014Spooka 
138c5ab2014Spooka 	return copyout(&ssb, SCARG(uap, sp), sizeof(ssb));
139c5ab2014Spooka }
140c5ab2014Spooka 
141c5ab2014Spooka int
rump_cygwin_sys_open(struct lwp * l,const struct rump_cygwin_sys_open_args * uap,register_t * retval)142c5ab2014Spooka rump_cygwin_sys_open(struct lwp *l, const struct rump_cygwin_sys_open_args *uap,
143c5ab2014Spooka 	register_t *retval)
144c5ab2014Spooka {
145c5ab2014Spooka 	/* {
146c5ab2014Spooka 		syscallarg(const char *) path;
147c5ab2014Spooka 		syscallarg(int) flags;
148c5ab2014Spooka 		syscallarg(int) mode;
149c5ab2014Spooka 	} */
150c5ab2014Spooka 	struct sys_open_args ua;
151c5ab2014Spooka 	int sflags, flags;
152c5ab2014Spooka 
153c5ab2014Spooka 	sflags = SCARG(uap, flags);
154c5ab2014Spooka 	flags = sflags & (3 | O_APPEND | O_ASYNC | O_CREAT | O_TRUNC | O_EXCL);
155c5ab2014Spooka 
156c5ab2014Spooka 	SCARG(&ua, path) = SCARG(uap, path);
157c5ab2014Spooka 	SCARG(&ua, flags) = flags;
158c5ab2014Spooka 	SCARG(&ua, mode) = SCARG(uap, mode);
159c5ab2014Spooka 
160c5ab2014Spooka 	return sys_open(l, &ua, retval);
161c5ab2014Spooka }
162c5ab2014Spooka 
163c5ab2014Spooka #define CYGWIN_NAME_MAX 255
164c5ab2014Spooka struct cygwin_dirent {
165c5ab2014Spooka 	long		d_version;
166c5ab2014Spooka 	int64_t		d_ino;
167c5ab2014Spooka 	unsigned char	d_type;
168c5ab2014Spooka 	unsigned char	d_unused[3];
169c5ab2014Spooka 	uint32_t	d_internal;
170c5ab2014Spooka 	char		d_name[CYGWIN_NAME_MAX + 1];
171c5ab2014Spooka } __packed;
172c5ab2014Spooka 
173c5ab2014Spooka #define CYGWIN_NAMEOFF(dp) 	   offsetof(struct cygwin_dirent,d_name)
174c5ab2014Spooka #define CYGWIN_RECLEN(dp, namlen)  ((CYGWIN_NAMEOFF(dp) + (namlen) + 1))
175c5ab2014Spooka 
176c5ab2014Spooka int
rump_cygwin_sys_getdents(struct lwp * l,const struct rump_cygwin_sys_getdents_args * uap,register_t * retval)177c5ab2014Spooka rump_cygwin_sys_getdents(struct lwp *l,
178c5ab2014Spooka 	const struct rump_cygwin_sys_getdents_args *uap, register_t *retval)
179c5ab2014Spooka {
180c5ab2014Spooka 	struct file *fp;
181c5ab2014Spooka 	struct dirent *bdp;
182c5ab2014Spooka 	struct cygwin_dirent idb;
183c5ab2014Spooka 	char *buf, *inp, *outp;
184c5ab2014Spooka 	size_t resid, buflen, nbytes;
185c5ab2014Spooka 	size_t reclen, cygwin_reclen;
186c5ab2014Spooka 	int error, done;
187c5ab2014Spooka 
188c5ab2014Spooka 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
189c5ab2014Spooka 		return (error);
190c5ab2014Spooka 
191c5ab2014Spooka 	/*
192c5ab2014Spooka 	 * Sneaky, but avoids having "rewind" f_offset due to the
193c5ab2014Spooka 	 * conversions not fitting from our intermediate kernel buffer
194c5ab2014Spooka 	 * into the user buffer
195c5ab2014Spooka 	 */
196c5ab2014Spooka 	nbytes = SCARG(uap, nbytes);
197c5ab2014Spooka 	buflen = min(MAXBSIZE, (nbytes*8)/10);
198c5ab2014Spooka 	buf = kmem_alloc(buflen, KM_SLEEP);
199c5ab2014Spooka 
200c5ab2014Spooka 	if ((fp->f_flag & FREAD) == 0) {
201c5ab2014Spooka 		error = EBADF;
202c5ab2014Spooka 		goto out;
203c5ab2014Spooka 	}
204c5ab2014Spooka 
205c5ab2014Spooka 	resid = nbytes;
206c5ab2014Spooka 	outp = SCARG(uap, buf);
207c5ab2014Spooka 
208c5ab2014Spooka  again:
209c5ab2014Spooka 	if ((error = vn_readdir(fp, buf, UIO_SYSSPACE, buflen, &done,
210c5ab2014Spooka 	    l, NULL, NULL)) != 0)
211c5ab2014Spooka 		goto out;
212c5ab2014Spooka 	if (done == 0)
213c5ab2014Spooka 		goto eof;
214c5ab2014Spooka 
215c5ab2014Spooka 	for (inp = buf; done > 0; done -= reclen) {
216c5ab2014Spooka 		bdp = (struct dirent *)inp;
217c5ab2014Spooka 		reclen = bdp->d_reclen;
218c5ab2014Spooka 
219c5ab2014Spooka 		/* skip empty entries */
220c5ab2014Spooka 		if (bdp->d_fileno == 0) {
221c5ab2014Spooka 			inp += reclen;
222c5ab2014Spooka 			continue;
223c5ab2014Spooka 		}
224c5ab2014Spooka 
225c5ab2014Spooka 		cygwin_reclen = CYGWIN_RECLEN(&idb, bdp->d_namlen);
226c5ab2014Spooka 		if (resid < cygwin_reclen) {
227c5ab2014Spooka 			panic("impossible shortage of resid");
228c5ab2014Spooka 		}
229c5ab2014Spooka 
230c5ab2014Spooka 		memset(&idb, 0, sizeof(idb));
231c5ab2014Spooka 		idb.d_ino = bdp->d_fileno;
232c5ab2014Spooka 		idb.d_type = bdp->d_type;
233c5ab2014Spooka 		strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
234c5ab2014Spooka 		if ((error = copyout(&idb, outp, cygwin_reclen)) != 0)
235c5ab2014Spooka 			goto out;
236c5ab2014Spooka 
237c5ab2014Spooka 		inp += reclen;
238c5ab2014Spooka 		outp += cygwin_reclen;
239c5ab2014Spooka 		resid -= cygwin_reclen;
240c5ab2014Spooka 	}
241c5ab2014Spooka 
242c5ab2014Spooka 	/* if we squished out the whole block, try again */
243c5ab2014Spooka 	if (outp == SCARG(uap, buf)) {
244c5ab2014Spooka 		goto again;
245c5ab2014Spooka 	}
246c5ab2014Spooka 
247c5ab2014Spooka  eof:
248c5ab2014Spooka 	*retval = nbytes - resid;
249c5ab2014Spooka  out:
250c5ab2014Spooka 	kmem_free(buf, buflen);
251c5ab2014Spooka  	fd_putfile(SCARG(uap, fd));
252c5ab2014Spooka 
253c5ab2014Spooka 	return (error);
254c5ab2014Spooka }
255