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