initial commit
[freebsd-arm:freebsd-arm.git] / compat / svr4 / svr4_stat.c
1 /*-
2  * Copyright (c) 1998 Mark Newton
3  * Copyright (c) 1994 Christos Zoulas
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/proc.h>
35 #include <sys/stat.h>
36 #include <sys/filedesc.h>
37 #include <sys/jail.h>
38 #include <sys/kernel.h>
39 #include <sys/malloc.h>
40 #include <sys/namei.h>
41 #include <sys/unistd.h>
42 #include <sys/time.h>
43 #include <sys/syscallsubr.h>
44 #include <sys/sysctl.h>
45 #include <sys/sysproto.h>
46 #include <sys/un.h>
47
48 #include <vm/vm.h>
49
50 #include <netinet/in.h>
51
52 #include <compat/svr4/svr4.h>
53 #include <compat/svr4/svr4_types.h>
54 #include <compat/svr4/svr4_signal.h>
55 #include <compat/svr4/svr4_proto.h>
56 #include <compat/svr4/svr4_util.h>
57 #include <compat/svr4/svr4_stat.h>
58 #include <compat/svr4/svr4_ustat.h>
59 #include <compat/svr4/svr4_utsname.h>
60 #include <compat/svr4/svr4_systeminfo.h>
61 #include <compat/svr4/svr4_socket.h>
62 #include <compat/svr4/svr4_time.h>
63 #if defined(NOTYET)
64 #include "svr4_fuser.h"
65 #endif
66
67 #ifdef sparc
68 /* 
69  * Solaris-2.4 on the sparc has the old stat call using the new
70  * stat data structure...
71  */
72 # define SVR4_NO_OSTAT
73 #endif
74
75 struct svr4_ustat_args {
76         svr4_dev_t              dev;
77         struct svr4_ustat * name;
78 };
79
80 static void bsd_to_svr4_xstat(struct stat *, struct svr4_xstat *);
81 static void bsd_to_svr4_stat64(struct stat *, struct svr4_stat64 *);
82 int svr4_ustat(struct thread *, struct svr4_ustat_args *);
83 static int svr4_to_bsd_pathconf(int);
84
85 /*
86  * SVR4 uses named pipes as named sockets, so we tell programs
87  * that sockets are named pipes with mode 0
88  */
89 #define BSD_TO_SVR4_MODE(mode) (S_ISSOCK(mode) ? S_IFIFO : (mode))
90
91
92 #ifndef SVR4_NO_OSTAT
93 static void bsd_to_svr4_stat(struct stat *, struct svr4_stat *);
94
95 static void
96 bsd_to_svr4_stat(st, st4)
97         struct stat             *st;
98         struct svr4_stat        *st4;
99 {
100         memset(st4, 0, sizeof(*st4));
101         st4->st_dev = bsd_to_svr4_odev_t(st->st_dev);
102         st4->st_ino = st->st_ino;
103         st4->st_mode = BSD_TO_SVR4_MODE(st->st_mode);
104         st4->st_nlink = st->st_nlink;
105         st4->st_uid = st->st_uid;
106         st4->st_gid = st->st_gid;
107         st4->st_rdev = bsd_to_svr4_odev_t(st->st_rdev);
108         st4->st_size = st->st_size;
109         st4->st_atim = st->st_atimespec.tv_sec;
110         st4->st_mtim = st->st_mtimespec.tv_sec;
111         st4->st_ctim = st->st_ctimespec.tv_sec;
112 }
113 #endif
114
115
116 static void
117 bsd_to_svr4_xstat(st, st4)
118         struct stat             *st;
119         struct svr4_xstat       *st4;
120 {
121         memset(st4, 0, sizeof(*st4));
122         st4->st_dev = bsd_to_svr4_dev_t(st->st_dev);
123         st4->st_ino = st->st_ino;
124         st4->st_mode = BSD_TO_SVR4_MODE(st->st_mode);
125         st4->st_nlink = st->st_nlink;
126         st4->st_uid = st->st_uid;
127         st4->st_gid = st->st_gid;
128         st4->st_rdev = bsd_to_svr4_dev_t(st->st_rdev);
129         st4->st_size = st->st_size;
130         st4->st_atim = st->st_atimespec;
131         st4->st_mtim = st->st_mtimespec;
132         st4->st_ctim = st->st_ctimespec;
133         st4->st_blksize = st->st_blksize;
134         st4->st_blocks = st->st_blocks;
135         strcpy(st4->st_fstype, "unknown");
136 }
137
138
139 static void
140 bsd_to_svr4_stat64(st, st4)
141         struct stat             *st;
142         struct svr4_stat64      *st4;
143 {
144         memset(st4, 0, sizeof(*st4));
145         st4->st_dev = bsd_to_svr4_dev_t(st->st_dev);
146         st4->st_ino = st->st_ino;
147         st4->st_mode = BSD_TO_SVR4_MODE(st->st_mode);
148         st4->st_nlink = st->st_nlink;
149         st4->st_uid = st->st_uid;
150         st4->st_gid = st->st_gid;
151         st4->st_rdev = bsd_to_svr4_dev_t(st->st_rdev);
152         st4->st_size = st->st_size;
153         st4->st_atim = st->st_atimespec;
154         st4->st_mtim = st->st_mtimespec;
155         st4->st_ctim = st->st_ctimespec;
156         st4->st_blksize = st->st_blksize;
157         st4->st_blocks = st->st_blocks;
158         strcpy(st4->st_fstype, "unknown");
159 }
160
161 int
162 svr4_sys_stat(td, uap)
163         struct thread *td;
164         struct svr4_sys_stat_args *uap;
165 {
166         struct svr4_stat svr4_st;
167         struct stat st;
168         char *path;
169         int error;
170
171         CHECKALTEXIST(td, uap->path, &path);
172
173         error = kern_stat(td, path, UIO_SYSSPACE, &st);
174         free(path, M_TEMP);
175         if (error)
176                 return (error);
177         bsd_to_svr4_stat(&st, &svr4_st);
178
179         if (S_ISSOCK(st.st_mode))
180                 (void) svr4_add_socket(td, uap->path, &st);
181
182         return (copyout(&svr4_st, uap->ub, sizeof svr4_st));
183 }
184
185
186 int
187 svr4_sys_lstat(td, uap)
188         struct thread *td;
189         struct svr4_sys_lstat_args *uap;
190 {
191         struct svr4_stat svr4_st;
192         struct stat st;
193         char *path;
194         int error;
195
196         CHECKALTEXIST(td, uap->path, &path);
197
198         error = kern_lstat(td, path, UIO_SYSSPACE, &st);
199         free(path, M_TEMP);
200         if (error)
201                 return (error);
202         bsd_to_svr4_stat(&st, &svr4_st);
203
204         if (S_ISSOCK(st.st_mode))
205                 (void) svr4_add_socket(td, uap->path, &st);
206
207         return (copyout(&svr4_st, uap->ub, sizeof svr4_st));
208 }
209
210
211 int
212 svr4_sys_fstat(td, uap)
213         struct thread *td;
214         struct svr4_sys_fstat_args *uap;
215 {
216         struct svr4_stat svr4_st;
217         struct stat st;
218         int error;
219
220
221         error = kern_fstat(td, uap->fd, &st);
222         if (error)
223                 return (error);
224         bsd_to_svr4_stat(&st, &svr4_st);
225         return (copyout(&svr4_st, uap->sb, sizeof svr4_st));
226 }
227
228
229 int
230 svr4_sys_xstat(td, uap)
231         struct thread *td;
232         struct svr4_sys_xstat_args *uap;
233 {
234         struct svr4_xstat svr4_st;
235         struct stat st;
236         char *path;
237         int error;
238
239         CHECKALTEXIST(td, uap->path, &path);
240
241         error = kern_stat(td, path, UIO_SYSSPACE, &st);
242         free(path, M_TEMP);
243         if (error)
244                 return (error);
245
246         bsd_to_svr4_xstat(&st, &svr4_st);
247
248 #if defined(SOCKET_NOTYET)
249         if (S_ISSOCK(st.st_mode))
250                 (void) svr4_add_socket(td, uap->path, &st);
251 #endif
252
253         return (copyout(&svr4_st, uap->ub, sizeof svr4_st));
254 }
255
256 int
257 svr4_sys_lxstat(td, uap)
258         struct thread *td;
259         struct svr4_sys_lxstat_args *uap;
260 {
261         struct svr4_xstat svr4_st;
262         struct stat st;
263         char *path;
264         int error;
265
266         CHECKALTEXIST(td, uap->path, &path);
267
268         error = kern_lstat(td, path, UIO_SYSSPACE, &st);
269         free(path, M_TEMP);
270         if (error)
271                 return (error);
272
273         bsd_to_svr4_xstat(&st, &svr4_st);
274
275 #if defined(SOCKET_NOTYET)
276         if (S_ISSOCK(st.st_mode))
277                 (void) svr4_add_socket(td, uap->path, &st);
278 #endif
279         return (copyout(&svr4_st, uap->ub, sizeof svr4_st));
280 }
281
282
283 int
284 svr4_sys_fxstat(td, uap)
285         struct thread *td;
286         struct svr4_sys_fxstat_args *uap;
287 {
288         struct svr4_xstat svr4_st;
289         struct stat st;
290         int error;
291
292
293         error = kern_fstat(td, uap->fd, &st);
294         if (error)
295                 return (error);
296         bsd_to_svr4_xstat(&st, &svr4_st);
297         return (copyout(&svr4_st, uap->sb, sizeof svr4_st));
298 }
299
300 int
301 svr4_sys_stat64(td, uap)
302         struct thread *td;
303         struct svr4_sys_stat64_args *uap;
304 {
305         struct svr4_stat64 svr4_st;
306         struct stat st;
307         char *path;
308         int error;
309
310         CHECKALTEXIST(td, uap->path, &path);
311
312         error = kern_stat(td, path, UIO_SYSSPACE, &st);
313         free(path, M_TEMP);
314         if (error)
315                 return (error);
316
317         bsd_to_svr4_stat64(&st, &svr4_st);
318
319         if (S_ISSOCK(st.st_mode))
320                 (void) svr4_add_socket(td, uap->path, &st);
321
322         return (copyout(&svr4_st, uap->sb, sizeof svr4_st));
323 }
324
325
326 int
327 svr4_sys_lstat64(td, uap)
328         struct thread *td;
329         struct svr4_sys_lstat64_args *uap;
330 {
331         struct svr4_stat64 svr4_st;
332         struct stat st;
333         char *path;
334         int error;
335
336         CHECKALTEXIST(td, uap->path, &path);
337
338         error = kern_lstat(td, path, UIO_SYSSPACE, &st);
339         free(path, M_TEMP);
340         if (error)
341                 return (error);
342
343         bsd_to_svr4_stat64(&st, &svr4_st);
344
345         if (S_ISSOCK(st.st_mode))
346                 (void) svr4_add_socket(td, uap->path, &st);
347
348         return (copyout(&svr4_st, uap->sb, sizeof svr4_st));
349 }
350
351
352 int
353 svr4_sys_fstat64(td, uap)
354         struct thread *td;
355         struct svr4_sys_fstat64_args *uap;
356 {
357         struct svr4_stat64 svr4_st;
358         struct stat st;
359         int error;
360
361         error = kern_fstat(td, uap->fd, &st);
362         if (error)
363                 return (error);
364         bsd_to_svr4_stat64(&st, &svr4_st);
365         return (copyout(&svr4_st, uap->sb, sizeof svr4_st));
366 }
367
368
369 int
370 svr4_ustat(td, uap)
371         struct thread *td;
372         struct svr4_ustat_args *uap;
373 {
374         struct svr4_ustat       us;
375         int                     error;
376
377         memset(&us, 0, sizeof us);
378
379         /*
380          * XXX: should set f_tfree and f_tinode at least
381          * How do we translate dev -> fstat? (and then to svr4_ustat)
382          */
383         if ((error = copyout(&us, uap->name, sizeof us)) != 0)
384                 return (error);
385
386         return 0;
387 }
388
389 /*extern char ostype[], osrelease[], version[], machine[];*/
390
391 int
392 svr4_sys_uname(td, uap)
393         struct thread *td;
394         struct svr4_sys_uname_args *uap;
395 {
396         struct svr4_utsname     sut;
397         
398         memset(&sut, 0, sizeof(sut));
399
400         strlcpy(sut.sysname, ostype, sizeof(sut.sysname));
401         getcredhostname(td->td_ucred, sut.nodename, sizeof(sut.nodename));
402         strlcpy(sut.release, osrelease, sizeof(sut.release));
403         strlcpy(sut.version, version, sizeof(sut.version));
404         strlcpy(sut.machine, machine, sizeof(sut.machine));
405
406         return copyout((caddr_t) &sut, (caddr_t) uap->name,
407                        sizeof(struct svr4_utsname));
408 }
409
410 int
411 svr4_sys_systeminfo(td, uap)
412         struct thread *td;
413         struct svr4_sys_systeminfo_args *uap;
414 {
415         char            *str = NULL;
416         int             error = 0;
417         register_t      *retval = td->td_retval;
418         u_long          hostid;
419         size_t          len = 0;
420         char            buf[MAXHOSTNAMELEN];
421         u_int           rlen = uap->len;
422
423         switch (uap->what) {
424         case SVR4_SI_SYSNAME:
425                 str = ostype;
426                 break;
427
428         case SVR4_SI_HOSTNAME:
429                 getcredhostname(td->td_ucred, buf, sizeof(buf));
430                 str = buf;
431                 break;
432
433         case SVR4_SI_RELEASE:
434                 str = osrelease;
435                 break;
436
437         case SVR4_SI_VERSION:
438                 str = version;
439                 break;
440
441         case SVR4_SI_MACHINE:
442                 str = machine;
443                 break;
444
445         case SVR4_SI_ARCHITECTURE:
446                 str = machine;
447                 break;
448
449         case SVR4_SI_ISALIST:
450 #if defined(__sparc__)
451                 str = "sparcv9 sparcv9-fsmuld sparcv8 sparcv8-fsmuld sparcv7 sparc";
452 #elif defined(__i386__)
453                 str = "i386";
454 #elif defined(__amd64__)
455                 str = "amd64";
456 #else
457                 str = "unknown";
458 #endif
459                 break;
460
461         case SVR4_SI_HW_SERIAL:
462                 getcredhostid(td->td_ucred, &hostid);
463                 snprintf(buf, sizeof(buf), "%lu", hostid);
464                 str = buf;
465                 break;
466
467         case SVR4_SI_HW_PROVIDER:
468                 str = ostype;
469                 break;
470
471         case SVR4_SI_SRPC_DOMAIN:
472                 getcreddomainname(td->td_ucred, buf, sizeof(buf));
473                 str = buf;
474                 break;
475
476         case SVR4_SI_PLATFORM:
477 #if defined(__i386__)
478                 str = "i86pc";
479 #else
480                 str = "unknown";
481 #endif
482                 break;
483
484         case SVR4_SI_KERB_REALM:
485                 str = "unsupported";
486                 break;
487 #if defined(WHY_DOES_AN_EMULATOR_WANT_TO_SET_HOSTNAMES)
488         case SVR4_SI_SET_HOSTNAME:
489                 name = KERN_HOSTNAME;
490                 return kern_sysctl(&name, 1, 0, 0, uap->buf, rlen, td);
491
492         case SVR4_SI_SET_SRPC_DOMAIN:
493                 name = KERN_NISDOMAINNAME;
494                 return kern_sysctl(&name, 1, 0, 0, uap->buf, rlen, td);
495 #else
496         case SVR4_SI_SET_HOSTNAME:
497         case SVR4_SI_SET_SRPC_DOMAIN:
498                 /* FALLTHROUGH */
499 #endif
500         case SVR4_SI_SET_KERB_REALM:
501                 return 0;
502
503         default:
504                 DPRINTF(("Bad systeminfo command %d\n", uap->what));
505                 return ENOSYS;
506         }
507
508         if (str) {
509                 len = strlen(str) + 1;
510                 if (len > rlen)
511                         len = rlen;
512
513                 if (uap->buf) {
514                         error = copyout(str, uap->buf, len);
515                         if (error)
516                                 return error;
517                         /* make sure we are NULL terminated */
518                         buf[0] = '\0';
519                         error = copyout(buf, &(uap->buf[len - 1]), 1);
520                 }
521                 else
522                         error = 0;
523         }
524         /* XXX NetBSD has hostname setting stuff here.  Why would an emulator
525            want to do that? */
526
527         *retval = len;
528         return error;
529 }
530
531 int
532 svr4_sys_utssys(td, uap)
533         struct thread *td;
534         struct svr4_sys_utssys_args *uap;
535 {
536         switch (uap->sel) {
537         case 0:         /* uname(2)  */
538                 {
539                         struct svr4_sys_uname_args ua;
540                         ua.name = uap->a1;
541                         return svr4_sys_uname(td, &ua);
542                 }
543
544         case 2:         /* ustat(2)  */
545                 {
546                         struct svr4_ustat_args ua;
547                         ua.dev = (svr4_dev_t) uap->a2;
548                         ua.name = uap->a1;
549                         return svr4_ustat(td, &ua);
550                 }
551
552         case 3:         /* fusers(2) */
553                 return ENOSYS;
554
555         default:
556                 return ENOSYS;
557         }
558         return ENOSYS;
559 }
560
561
562 int
563 svr4_sys_utime(td, uap)
564         struct thread *td;
565         struct svr4_sys_utime_args *uap;
566 {
567         struct svr4_utimbuf ub;
568         struct timeval tbuf[2], *tp;
569         char *path;
570         int error;
571      
572         if (uap->ubuf != NULL) {
573                 error = copyin(uap->ubuf, &ub, sizeof(ub));
574                 if (error)
575                         return (error);
576                 tbuf[0].tv_sec = ub.actime;
577                 tbuf[0].tv_usec = 0;
578                 tbuf[1].tv_sec = ub.modtime;
579                 tbuf[1].tv_usec = 0;
580                 tp = tbuf;
581         } else
582                 tp = NULL;
583
584         CHECKALTEXIST(td, uap->path, &path);
585         error = kern_utimes(td, path, UIO_SYSSPACE, tp, UIO_SYSSPACE);
586         free(path, M_TEMP);
587         return (error);
588 }
589
590
591 int
592 svr4_sys_utimes(td, uap)
593         struct thread *td;
594         struct svr4_sys_utimes_args *uap;
595 {
596         char *path;
597         int error;
598
599         CHECKALTEXIST(td, uap->path, &path);
600         error = kern_utimes(td, path, UIO_SYSSPACE, uap->tptr, UIO_USERSPACE);
601         free(path, M_TEMP);
602         return (error);
603 }
604
605 static int
606 svr4_to_bsd_pathconf(name)
607         int name;
608 {
609         switch (name) {
610         case SVR4_PC_LINK_MAX:
611                 return _PC_LINK_MAX;
612
613         case SVR4_PC_MAX_CANON:
614                 return _PC_MAX_CANON;
615
616         case SVR4_PC_MAX_INPUT:
617                 return _PC_MAX_INPUT;
618
619         case SVR4_PC_NAME_MAX:
620                 return _PC_NAME_MAX;
621
622         case SVR4_PC_PATH_MAX:
623                 return _PC_PATH_MAX;
624
625         case SVR4_PC_PIPE_BUF:
626                 return _PC_PIPE_BUF;
627
628         case SVR4_PC_NO_TRUNC:
629                 return _PC_NO_TRUNC;
630
631         case SVR4_PC_VDISABLE:
632                 return _PC_VDISABLE;
633
634         case SVR4_PC_CHOWN_RESTRICTED:
635                 return _PC_CHOWN_RESTRICTED;
636         case SVR4_PC_SYNC_IO:
637 #if defined(_PC_SYNC_IO)
638                 return _PC_SYNC_IO;
639 #else
640                 return 0;
641 #endif
642         case SVR4_PC_ASYNC_IO:
643         case SVR4_PC_PRIO_IO:
644                 /* Not supported */
645                 return 0;
646
647         default:
648                 /* Invalid */
649                 return -1;
650         }
651 }
652
653
654 int
655 svr4_sys_pathconf(td, uap)
656         struct thread *td;
657         struct svr4_sys_pathconf_args *uap;
658 {
659         char *path;
660         int error, name;
661
662         name = svr4_to_bsd_pathconf(uap->name);
663
664         switch (name) {
665         case -1:
666                 td->td_retval[0] = -1;
667                 return (EINVAL);
668         case 0:
669                 td->td_retval[0] = 0;
670                 return (0);
671         default:
672                 CHECKALTEXIST(td, uap->path, &path);
673                 error = kern_pathconf(td, path, UIO_SYSSPACE, name, FOLLOW);
674                 free(path, M_TEMP);
675                 return (error);
676         }
677 }
678
679
680 int
681 svr4_sys_fpathconf(td, uap)
682         struct thread *td;
683         struct svr4_sys_fpathconf_args *uap;
684 {
685         register_t      *retval = td->td_retval;
686
687         uap->name = svr4_to_bsd_pathconf(uap->name);
688
689         switch (uap->name) {
690         case -1:
691                 *retval = -1;
692                 return EINVAL;
693         case 0:
694                 *retval = 0;
695                 return 0;
696         default:
697                 return fpathconf(td, (struct fpathconf_args *)uap);
698         }
699 }