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