1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#pragma once
4
5#include "mos/assert.hpp"
6#include "mos/mm/mm_types.hpp"
7#include "mos/syslog/syslog.hpp"
8
9#include <mos/io/io_types.h>
10#include <mos/mm/mm_types.h>
11#include <mos/string.hpp>
12#include <mos/types.hpp>
13
14struct IO;
15struct vmap_t; // forward declaration
16
17typedef enum
18{
19 IO_NULL, // null io port
20 IO_FILE, // a file
21 IO_DIR, // a directory (i.e. readdir())
22 IO_IPC, // an IPC channel
23 IO_PIPE, // an end of a pipe
24 IO_CONSOLE, // a console
25} io_type_t;
26
27typedef enum
28{
29 IO_NONE = MEM_PERM_NONE, // 0
30 IO_READABLE = MEM_PERM_READ, // 1 << 0
31 IO_WRITABLE = MEM_PERM_WRITE, // 1 << 1
32 IO_EXECUTABLE = MEM_PERM_EXEC, // 1 << 2
33 IO_SEEKABLE = 1 << 3,
34 IO_MMAPABLE = 1 << 4,
35} io_flags_t;
36MOS_ENUM_FLAGS(io_flags_t, IOFlags);
37
38struct IO
39{
40 const IOFlags io_flags = IO_NONE;
41 const io_type_t io_type = IO_NULL;
42
43 explicit IO(IOFlags flags, io_type_t type);
44 virtual ~IO() = 0;
45
46 static bool IsValid(const IO *io)
47 {
48 return io && !io->io_closed && io->io_refcount > 0;
49 }
50
51 friend mos::SyslogStreamWriter operator<<(mos::SyslogStreamWriter stream, const IO *io)
52 {
53 stream << fmt("\\{ '{}', {}}", io->name(), io->io_closed ? "closed" : "active");
54 return stream;
55 }
56
57 inline IO *ref()
58 {
59 if (unlikely(io_closed))
60 {
61 mos_warn("%p is already closed", (void *) this);
62 return 0;
63 }
64
65 io_refcount++;
66 return this;
67 }
68
69 inline IO *unref()
70 {
71 if (unlikely(io_closed))
72 {
73 mos_warn("%p is already closed", (void *) this);
74 return nullptr;
75 }
76
77 if (--io_refcount == 0)
78 {
79 io_closed = true;
80 on_closed();
81 return nullptr;
82 }
83
84 return this;
85 }
86
87 virtual mos::string name() const;
88 virtual off_t seek(off_t, io_seek_whence_t) final;
89 virtual off_t tell() final;
90
91 virtual size_t read(void *buf, size_t count) final;
92 virtual size_t pread(void *buf, size_t count, off_t offset) final;
93 virtual size_t write(const void *buf, size_t count) final;
94
95 virtual bool VerifyMMapPermissions(VMFlags flags, bool is_private) final;
96
97 bool map(vmap_t *vmap, off_t offset);
98 bool unmap(vmap_t *vmap, bool *unmapped);
99
100 private:
101 virtual void on_closed() = 0;
102 virtual size_t on_read(void *, size_t);
103 virtual size_t on_write(const void *, size_t);
104 virtual bool on_mmap(vmap_t *, off_t);
105 virtual bool on_munmap(vmap_t *, bool *);
106 virtual off_t on_seek(off_t, io_seek_whence_t);
107
108 private:
109 bool io_closed = false;
110 atomic_t io_refcount = 0;
111};
112
113extern IO *const io_null;
114