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