]> asedeno.scripts.mit.edu Git - linux.git/blob - arch/um/os-Linux/file.c
Merge tag 'kconfig-v5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
[linux.git] / arch / um / os-Linux / file.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
4  */
5
6 #include <stdio.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <signal.h>
11 #include <sys/ioctl.h>
12 #include <sys/mount.h>
13 #include <sys/socket.h>
14 #include <sys/stat.h>
15 #include <sys/sysmacros.h>
16 #include <sys/un.h>
17 #include <sys/types.h>
18 #include <sys/eventfd.h>
19 #include <os.h>
20
21 static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
22 {
23         *dst = ((struct uml_stat) {
24                 .ust_dev     = src->st_dev,     /* device */
25                 .ust_ino     = src->st_ino,     /* inode */
26                 .ust_mode    = src->st_mode,    /* protection */
27                 .ust_nlink   = src->st_nlink,   /* number of hard links */
28                 .ust_uid     = src->st_uid,     /* user ID of owner */
29                 .ust_gid     = src->st_gid,     /* group ID of owner */
30                 .ust_size    = src->st_size,    /* total size, in bytes */
31                 .ust_blksize = src->st_blksize, /* blocksize for filesys I/O */
32                 .ust_blocks  = src->st_blocks,  /* number of blocks allocated */
33                 .ust_atime   = src->st_atime,   /* time of last access */
34                 .ust_mtime   = src->st_mtime,   /* time of last modification */
35                 .ust_ctime   = src->st_ctime,   /* time of last change */
36         });
37 }
38
39 int os_stat_fd(const int fd, struct uml_stat *ubuf)
40 {
41         struct stat64 sbuf;
42         int err;
43
44         CATCH_EINTR(err = fstat64(fd, &sbuf));
45         if (err < 0)
46                 return -errno;
47
48         if (ubuf != NULL)
49                 copy_stat(ubuf, &sbuf);
50         return err;
51 }
52
53 int os_stat_file(const char *file_name, struct uml_stat *ubuf)
54 {
55         struct stat64 sbuf;
56         int err;
57
58         CATCH_EINTR(err = stat64(file_name, &sbuf));
59         if (err < 0)
60                 return -errno;
61
62         if (ubuf != NULL)
63                 copy_stat(ubuf, &sbuf);
64         return err;
65 }
66
67 int os_access(const char *file, int mode)
68 {
69         int amode, err;
70
71         amode = (mode & OS_ACC_R_OK ? R_OK : 0) |
72                 (mode & OS_ACC_W_OK ? W_OK : 0) |
73                 (mode & OS_ACC_X_OK ? X_OK : 0) |
74                 (mode & OS_ACC_F_OK ? F_OK : 0);
75
76         err = access(file, amode);
77         if (err < 0)
78                 return -errno;
79
80         return 0;
81 }
82
83 /* FIXME? required only by hostaudio (because it passes ioctls verbatim) */
84 int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
85 {
86         int err;
87
88         err = ioctl(fd, cmd, arg);
89         if (err < 0)
90                 return -errno;
91
92         return err;
93 }
94
95 /* FIXME: ensure namebuf in os_get_if_name is big enough */
96 int os_get_ifname(int fd, char* namebuf)
97 {
98         if (ioctl(fd, SIOCGIFNAME, namebuf) < 0)
99                 return -errno;
100
101         return 0;
102 }
103
104 int os_set_slip(int fd)
105 {
106         int disc, sencap;
107
108         disc = N_SLIP;
109         if (ioctl(fd, TIOCSETD, &disc) < 0)
110                 return -errno;
111
112         sencap = 0;
113         if (ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
114                 return -errno;
115
116         return 0;
117 }
118
119 int os_mode_fd(int fd, int mode)
120 {
121         int err;
122
123         CATCH_EINTR(err = fchmod(fd, mode));
124         if (err < 0)
125                 return -errno;
126
127         return 0;
128 }
129
130 int os_file_type(char *file)
131 {
132         struct uml_stat buf;
133         int err;
134
135         err = os_stat_file(file, &buf);
136         if (err < 0)
137                 return err;
138
139         if (S_ISDIR(buf.ust_mode))
140                 return OS_TYPE_DIR;
141         else if (S_ISLNK(buf.ust_mode))
142                 return OS_TYPE_SYMLINK;
143         else if (S_ISCHR(buf.ust_mode))
144                 return OS_TYPE_CHARDEV;
145         else if (S_ISBLK(buf.ust_mode))
146                 return OS_TYPE_BLOCKDEV;
147         else if (S_ISFIFO(buf.ust_mode))
148                 return OS_TYPE_FIFO;
149         else if (S_ISSOCK(buf.ust_mode))
150                 return OS_TYPE_SOCK;
151         else return OS_TYPE_FILE;
152 }
153
154 int os_file_mode(const char *file, struct openflags *mode_out)
155 {
156         int err;
157
158         *mode_out = OPENFLAGS();
159
160         err = access(file, W_OK);
161         if (err && (errno != EACCES))
162                 return -errno;
163         else if (!err)
164                 *mode_out = of_write(*mode_out);
165
166         err = access(file, R_OK);
167         if (err && (errno != EACCES))
168                 return -errno;
169         else if (!err)
170                 *mode_out = of_read(*mode_out);
171
172         return err;
173 }
174
175 int os_open_file(const char *file, struct openflags flags, int mode)
176 {
177         int fd, err, f = 0;
178
179         if (flags.r && flags.w)
180                 f = O_RDWR;
181         else if (flags.r)
182                 f = O_RDONLY;
183         else if (flags.w)
184                 f = O_WRONLY;
185         else f = 0;
186
187         if (flags.s)
188                 f |= O_SYNC;
189         if (flags.c)
190                 f |= O_CREAT;
191         if (flags.t)
192                 f |= O_TRUNC;
193         if (flags.e)
194                 f |= O_EXCL;
195         if (flags.a)
196                 f |= O_APPEND;
197
198         fd = open64(file, f, mode);
199         if (fd < 0)
200                 return -errno;
201
202         if (flags.cl && fcntl(fd, F_SETFD, 1)) {
203                 err = -errno;
204                 close(fd);
205                 return err;
206         }
207
208         return fd;
209 }
210
211 int os_connect_socket(const char *name)
212 {
213         struct sockaddr_un sock;
214         int fd, err;
215
216         sock.sun_family = AF_UNIX;
217         snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
218
219         fd = socket(AF_UNIX, SOCK_STREAM, 0);
220         if (fd < 0) {
221                 err = -errno;
222                 goto out;
223         }
224
225         err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
226         if (err) {
227                 err = -errno;
228                 goto out_close;
229         }
230
231         return fd;
232
233 out_close:
234         close(fd);
235 out:
236         return err;
237 }
238
239 void os_close_file(int fd)
240 {
241         close(fd);
242 }
243 int os_fsync_file(int fd)
244 {
245         if (fsync(fd) < 0)
246             return -errno;
247         return 0;
248 }
249
250 int os_seek_file(int fd, unsigned long long offset)
251 {
252         unsigned long long actual;
253
254         actual = lseek64(fd, offset, SEEK_SET);
255         if (actual != offset)
256                 return -errno;
257         return 0;
258 }
259
260 int os_read_file(int fd, void *buf, int len)
261 {
262         int n = read(fd, buf, len);
263
264         if (n < 0)
265                 return -errno;
266         return n;
267 }
268
269 int os_pread_file(int fd, void *buf, int len, unsigned long long offset)
270 {
271         int n = pread(fd, buf, len, offset);
272
273         if (n < 0)
274                 return -errno;
275         return n;
276 }
277
278 int os_write_file(int fd, const void *buf, int len)
279 {
280         int n = write(fd, (void *) buf, len);
281
282         if (n < 0)
283                 return -errno;
284         return n;
285 }
286
287 int os_sync_file(int fd)
288 {
289         int n = fsync(fd);
290
291         if (n < 0)
292                 return -errno;
293         return n;
294 }
295
296 int os_pwrite_file(int fd, const void *buf, int len, unsigned long long offset)
297 {
298         int n = pwrite(fd, (void *) buf, len, offset);
299
300         if (n < 0)
301                 return -errno;
302         return n;
303 }
304
305
306 int os_file_size(const char *file, unsigned long long *size_out)
307 {
308         struct uml_stat buf;
309         int err;
310
311         err = os_stat_file(file, &buf);
312         if (err < 0) {
313                 printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
314                        -err);
315                 return err;
316         }
317
318         if (S_ISBLK(buf.ust_mode)) {
319                 int fd;
320                 long blocks;
321
322                 fd = open(file, O_RDONLY, 0);
323                 if (fd < 0) {
324                         err = -errno;
325                         printk(UM_KERN_ERR "Couldn't open \"%s\", "
326                                "errno = %d\n", file, errno);
327                         return err;
328                 }
329                 if (ioctl(fd, BLKGETSIZE, &blocks) < 0) {
330                         err = -errno;
331                         printk(UM_KERN_ERR "Couldn't get the block size of "
332                                "\"%s\", errno = %d\n", file, errno);
333                         close(fd);
334                         return err;
335                 }
336                 *size_out = ((long long) blocks) * 512;
337                 close(fd);
338         }
339         else *size_out = buf.ust_size;
340
341         return 0;
342 }
343
344 int os_file_modtime(const char *file, long long *modtime)
345 {
346         struct uml_stat buf;
347         int err;
348
349         err = os_stat_file(file, &buf);
350         if (err < 0) {
351                 printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
352                        -err);
353                 return err;
354         }
355
356         *modtime = buf.ust_mtime;
357         return 0;
358 }
359
360 int os_set_exec_close(int fd)
361 {
362         int err;
363
364         CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC));
365
366         if (err < 0)
367                 return -errno;
368         return err;
369 }
370
371 int os_pipe(int *fds, int stream, int close_on_exec)
372 {
373         int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
374
375         err = socketpair(AF_UNIX, type, 0, fds);
376         if (err < 0)
377                 return -errno;
378
379         if (!close_on_exec)
380                 return 0;
381
382         err = os_set_exec_close(fds[0]);
383         if (err < 0)
384                 goto error;
385
386         err = os_set_exec_close(fds[1]);
387         if (err < 0)
388                 goto error;
389
390         return 0;
391
392  error:
393         printk(UM_KERN_ERR "os_pipe : Setting FD_CLOEXEC failed, err = %d\n",
394                -err);
395         close(fds[1]);
396         close(fds[0]);
397         return err;
398 }
399
400 int os_set_fd_async(int fd)
401 {
402         int err, flags;
403
404         flags = fcntl(fd, F_GETFL);
405         if (flags < 0)
406                 return -errno;
407
408         flags |= O_ASYNC | O_NONBLOCK;
409         if (fcntl(fd, F_SETFL, flags) < 0) {
410                 err = -errno;
411                 printk(UM_KERN_ERR "os_set_fd_async : failed to set O_ASYNC "
412                        "and O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
413                 return err;
414         }
415
416         if ((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
417             (fcntl(fd, F_SETOWN, os_getpid()) < 0)) {
418                 err = -errno;
419                 printk(UM_KERN_ERR "os_set_fd_async : Failed to fcntl F_SETOWN "
420                        "(or F_SETSIG) fd %d, errno = %d\n", fd, errno);
421                 return err;
422         }
423
424         return 0;
425 }
426
427 int os_clear_fd_async(int fd)
428 {
429         int flags;
430
431         flags = fcntl(fd, F_GETFL);
432         if (flags < 0)
433                 return -errno;
434
435         flags &= ~(O_ASYNC | O_NONBLOCK);
436         if (fcntl(fd, F_SETFL, flags) < 0)
437                 return -errno;
438         return 0;
439 }
440
441 int os_set_fd_block(int fd, int blocking)
442 {
443         int flags;
444
445         flags = fcntl(fd, F_GETFL);
446         if (flags < 0)
447                 return -errno;
448
449         if (blocking)
450                 flags &= ~O_NONBLOCK;
451         else
452                 flags |= O_NONBLOCK;
453
454         if (fcntl(fd, F_SETFL, flags) < 0)
455                 return -errno;
456
457         return 0;
458 }
459
460 int os_accept_connection(int fd)
461 {
462         int new;
463
464         new = accept(fd, NULL, 0);
465         if (new < 0)
466                 return -errno;
467         return new;
468 }
469
470 #ifndef SHUT_RD
471 #define SHUT_RD 0
472 #endif
473
474 #ifndef SHUT_WR
475 #define SHUT_WR 1
476 #endif
477
478 #ifndef SHUT_RDWR
479 #define SHUT_RDWR 2
480 #endif
481
482 int os_shutdown_socket(int fd, int r, int w)
483 {
484         int what, err;
485
486         if (r && w)
487                 what = SHUT_RDWR;
488         else if (r)
489                 what = SHUT_RD;
490         else if (w)
491                 what = SHUT_WR;
492         else
493                 return -EINVAL;
494
495         err = shutdown(fd, what);
496         if (err < 0)
497                 return -errno;
498         return 0;
499 }
500
501 int os_rcv_fd(int fd, int *helper_pid_out)
502 {
503         int new, n;
504         char buf[CMSG_SPACE(sizeof(new))];
505         struct msghdr msg;
506         struct cmsghdr *cmsg;
507         struct iovec iov;
508
509         msg.msg_name = NULL;
510         msg.msg_namelen = 0;
511         iov = ((struct iovec) { .iov_base  = helper_pid_out,
512                                 .iov_len   = sizeof(*helper_pid_out) });
513         msg.msg_iov = &iov;
514         msg.msg_iovlen = 1;
515         msg.msg_control = buf;
516         msg.msg_controllen = sizeof(buf);
517         msg.msg_flags = 0;
518
519         n = recvmsg(fd, &msg, 0);
520         if (n < 0)
521                 return -errno;
522         else if (n != iov.iov_len)
523                 *helper_pid_out = -1;
524
525         cmsg = CMSG_FIRSTHDR(&msg);
526         if (cmsg == NULL) {
527                 printk(UM_KERN_ERR "rcv_fd didn't receive anything, "
528                        "error = %d\n", errno);
529                 return -1;
530         }
531         if ((cmsg->cmsg_level != SOL_SOCKET) ||
532             (cmsg->cmsg_type != SCM_RIGHTS)) {
533                 printk(UM_KERN_ERR "rcv_fd didn't receive a descriptor\n");
534                 return -1;
535         }
536
537         new = ((int *) CMSG_DATA(cmsg))[0];
538         return new;
539 }
540
541 int os_create_unix_socket(const char *file, int len, int close_on_exec)
542 {
543         struct sockaddr_un addr;
544         int sock, err;
545
546         sock = socket(PF_UNIX, SOCK_DGRAM, 0);
547         if (sock < 0)
548                 return -errno;
549
550         if (close_on_exec) {
551                 err = os_set_exec_close(sock);
552                 if (err < 0)
553                         printk(UM_KERN_ERR "create_unix_socket : "
554                                "close_on_exec failed, err = %d", -err);
555         }
556
557         addr.sun_family = AF_UNIX;
558
559         snprintf(addr.sun_path, len, "%s", file);
560
561         err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
562         if (err < 0)
563                 return -errno;
564
565         return sock;
566 }
567
568 void os_flush_stdout(void)
569 {
570         fflush(stdout);
571 }
572
573 int os_lock_file(int fd, int excl)
574 {
575         int type = excl ? F_WRLCK : F_RDLCK;
576         struct flock lock = ((struct flock) { .l_type   = type,
577                                               .l_whence = SEEK_SET,
578                                               .l_start  = 0,
579                                               .l_len    = 0 } );
580         int err, save;
581
582         err = fcntl(fd, F_SETLK, &lock);
583         if (!err)
584                 goto out;
585
586         save = -errno;
587         err = fcntl(fd, F_GETLK, &lock);
588         if (err) {
589                 err = -errno;
590                 goto out;
591         }
592
593         printk(UM_KERN_ERR "F_SETLK failed, file already locked by pid %d\n",
594                lock.l_pid);
595         err = save;
596  out:
597         return err;
598 }
599
600 unsigned os_major(unsigned long long dev)
601 {
602         return major(dev);
603 }
604
605 unsigned os_minor(unsigned long long dev)
606 {
607         return minor(dev);
608 }
609
610 unsigned long long os_makedev(unsigned major, unsigned minor)
611 {
612         return makedev(major, minor);
613 }
614
615 int os_falloc_punch(int fd, unsigned long long offset, int len)
616 {
617         int n = fallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, offset, len);
618
619         if (n < 0)
620                 return -errno;
621         return n;
622 }
623
624 int os_eventfd(unsigned int initval, int flags)
625 {
626         int fd = eventfd(initval, flags);
627
628         if (fd < 0)
629                 return -errno;
630         return fd;
631 }
632
633 int os_sendmsg_fds(int fd, const void *buf, unsigned int len, const int *fds,
634                    unsigned int fds_num)
635 {
636         struct iovec iov = {
637                 .iov_base = (void *) buf,
638                 .iov_len = len,
639         };
640         union {
641                 char control[CMSG_SPACE(sizeof(*fds) * OS_SENDMSG_MAX_FDS)];
642                 struct cmsghdr align;
643         } u;
644         unsigned int fds_size = sizeof(*fds) * fds_num;
645         struct msghdr msg = {
646                 .msg_iov = &iov,
647                 .msg_iovlen = 1,
648                 .msg_control = u.control,
649                 .msg_controllen = CMSG_SPACE(fds_size),
650         };
651         struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
652         int err;
653
654         if (fds_num > OS_SENDMSG_MAX_FDS)
655                 return -EINVAL;
656         memset(u.control, 0, sizeof(u.control));
657         cmsg->cmsg_level = SOL_SOCKET;
658         cmsg->cmsg_type = SCM_RIGHTS;
659         cmsg->cmsg_len = CMSG_LEN(fds_size);
660         memcpy(CMSG_DATA(cmsg), fds, fds_size);
661         err = sendmsg(fd, &msg, 0);
662
663         if (err < 0)
664                 return -errno;
665         return err;
666 }