FreeNOS
FileSystemClient.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2020 Niek Linnenbank
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <Log.h>
19#include <ChannelClient.h>
20#include <KernelTimer.h>
21#include "FileSystemMessage.h"
22#include "FileDescriptor.h"
23#include "FileSystemClient.h"
24
25FileSystemMount FileSystemClient::m_mounts[MaximumFileSystemMounts] = {};
26
28
30 : m_pid(pid)
31{
32}
33
35 FileSystemMessage &msg) const
36{
37 const ProcessID mnt = m_pid == ANY ? findMount(path) : m_pid;
38 char fullpath[FileSystemPath::MaximumLength];
39
40 // Use the current directory as prefix for relative paths
41 if (path[0] != '/' && m_currentDirectory != NULL)
42 {
43 const Size copied = MemoryBlock::copy(fullpath, **m_currentDirectory, sizeof(fullpath));
44
45 if (copied < sizeof(fullpath))
46 MemoryBlock::copy(fullpath + copied, path, sizeof(fullpath) - copied);
47 }
48 else
49 {
50 MemoryBlock::copy(fullpath, path, sizeof(fullpath));
51 }
52
53 msg.buffer = fullpath;
54
55 return request(mnt, msg);
56}
57
59 FileSystemMessage &msg) const
60{
63 {
64 ERROR("failed to send request to PID " << pid <<
65 " for path " << msg.buffer << ": result = " << (int) r);
67 }
68 else if (msg.result != FileSystem::RedirectRequest)
69 {
70 return msg.result;
71 }
72
73 // If the path is mounted by a different file system process, the request is re-directed.
74 // Update the cached file system mounts table and re-send the request.
75 assert(msg.pid != ROOTFS_PID);
78
79 // Extend mounts table
80 for (Size i = 0; i < MaximumFileSystemMounts; i++)
81 {
82 if (m_mounts[i].path[0] == ZERO)
83 {
84 assert(msg.pathMountLength + 1 <= sizeof(m_mounts[i].path));
85 MemoryBlock::copy(m_mounts[i].path, msg.buffer, msg.pathMountLength + 1);
86 m_mounts[i].procID = msg.pid;
88 break;
89 }
90 }
91
93 r = ChannelClient::instance()->syncSendReceive(&msg, sizeof(msg), msg.pid);
95 {
96 ERROR("failed to redirect request to PID " << msg.pid <<
97 " for path " << msg.buffer << ": result = " << (int) r);
99 }
100
102 return msg.result;
103}
104
106{
108 Size length = 0;
109 char fullpath[FileSystemPath::MaximumLength];
110
111 // Use the current directory as prefix for relative paths
112 if (path[0] != '/' && m_currentDirectory != NULL)
113 {
114 const Size copied = MemoryBlock::copy(fullpath, **m_currentDirectory, sizeof(fullpath));
115
116 if (copied < sizeof(fullpath))
117 MemoryBlock::copy(fullpath + copied, path, sizeof(fullpath) - copied);
118 }
119 else
120 {
121 MemoryBlock::copy(fullpath, path, sizeof(fullpath));
122 }
123
124 // Find the longest match
125 for (Size i = 0; i < MaximumFileSystemMounts; i++)
126 {
127 if (m_mounts[i].path[0])
128 {
129 String str(m_mounts[i].path, false);
130 Size len = str.length();
131
132 // Only choose this mount, if it matches,
133 // and is longer than the last match.
134 if (str.compareTo(fullpath, true, len) == 0 && len > length)
135 {
136 length = len;
137 m = &m_mounts[i];
138 }
139 }
140 }
141
142 // All done
143 return m ? m->procID : ROOTFS_PID;
144}
145
150
152{
154 *m_currentDirectory = directory;
155}
156
158{
160 {
161 *m_currentDirectory = *directory;
162 }
163 else
164 {
165 m_currentDirectory = directory;
166 }
167}
168
171 const FileSystem::FileModes mode) const
172{
174 st.type = type;
175 st.access = mode;
176
180 msg.buffer = (char *)path;
181 msg.stat = &st;
182
183 return request(path, msg);
184}
185
187 FileSystem::FileStat *st) const
188{
192 msg.buffer = (char *)path;
193 msg.stat = st;
194
195 return request(path, msg);
196}
197
199 Size & descriptor) const
200{
202
203 const FileSystem::Result result = statFile(path, &st);
204 if (result == FileSystem::Success)
205 {
207
208 const FileDescriptor::Result fdResult = fd->openEntry(st.inode, st.pid, descriptor);
209 if (fdResult != FileDescriptor::Success)
210 {
211 return FileSystem::IOError;
212 }
213 }
214
215 return result;
216}
217
219{
220 const FileDescriptor::Result result = FileDescriptor::instance()->closeEntry(descriptor);
221 if (result != FileDescriptor::Success)
222 {
223 return FileSystem::IOError;
224 }
225
226 return FileSystem::Success;
227}
228
230 void *buf,
231 Size *size) const
232{
234 if (!fd || !fd->open)
235 {
237 }
238
242 msg.inode = fd->inode;
243 msg.buffer = (char *)buf;
244 msg.size = *size;
245 msg.offset = fd->position;
246
247 const FileSystem::Result result = request(fd->pid, msg);
248 if (result == FileSystem::Success)
249 {
250 *size = msg.size;
251 fd->position += msg.size;
252 }
253
254 return result;
255}
256
258 const void *buf,
259 Size *size) const
260{
262 if (!fd || !fd->open)
263 {
265 }
266
270 msg.inode = fd->inode;
271 msg.buffer = (char *)buf;
272 msg.size = *size;
273 msg.offset = fd->position;
274
275 const FileSystem::Result result = request(fd->pid, msg);
276 if (result == FileSystem::Success)
277 {
278 *size = msg.size;
279 fd->position += msg.size;
280 }
281
282 return result;
283}
284
285
287{
291 msg.buffer = (char *)path;
292
293 return request(path, msg);
294}
295
297 const FileSystem::WaitSet *waitSet,
298 const Size count,
299 const Size msecTimeout) const
300{
301 const ProcessID pid = findMount(filesystemPath);
302
306 msg.buffer = (char *) waitSet;
307 msg.size = count * sizeof(FileSystem::WaitSet);
308
309 if (msecTimeout != 0)
310 {
311 KernelTimer timer;
312 timer.tick();
313 timer.getCurrent(&msg.timeout, 500);
314 }
315 else
316 {
317 msg.timeout.ticks = 0;
318 msg.timeout.frequency = 0;
319 }
320
321 return request(pid, msg);
322}
323
325{
329 msg.buffer = (char *) mountPath;
330
331 return request(ROOTFS_PID, msg);
332}
333
335{
339 msg.buffer = (char *) path;
340
341 return request(ROOTFS_PID, msg);
342}
343
345{
349 msg.buffer = (char *) m_mounts;
350 msg.size = sizeof(m_mounts);
351
352 const FileSystem::Result result = request(ROOTFS_PID, msg);
353 if (result == FileSystem::Success)
354 {
355 numberOfMounts = MaximumFileSystemMounts;
356 return m_mounts;
357 }
358
359 return (FileSystemMount *) NULL;
360}
u8 type
Definition IntelACPI.h:0
u32 length
Definition IntelACPI.h:1
virtual Result syncSendReceive(void *buffer, const Size msgSize, const ProcessID pid)
Synchronous send and receive to/from one process.
Result
Result codes.
Type type
Message type is either a request or response.
Abstracts files which are opened by a user process.
Entry * getEntry(const Size index)
Retrieve a file descriptor Entry.
Result openEntry(const u32 inode, const ProcessID filesystem, Size &index)
Add new file descriptor entry.
Result
Result code.
Result closeEntry(const Size index)
Remove file descriptor entry.
FileSystem::Result closeFile(const Size descriptor) const
Close a file.
FileSystem::Result writeFile(const Size descriptor, const void *buf, Size *size) const
Write a file.
const ProcessID m_pid
ProcessID of the target file system or ANY to lookup in mounts table.
FileSystem::Result request(const char *path, FileSystemMessage &msg) const
Send an IPC request to the target file system.
static String * m_currentDirectory
Current directory path is prefixed to relative path inputs.
const String * getCurrentDirectory() const
Get current directory String.
FileSystem::Result waitFile(const char *filesystemPath, const FileSystem::WaitSet *waitSet, const Size count, const Size msecTimeout) const
Wait for one or more files to become readable/writable.
FileSystem::Result statFile(const char *path, FileSystem::FileStat *st) const
Retrieve status of a file.
FileSystem::Result waitFileSystem(const char *path) const
Blocking wait for a mounted filesystem.
FileSystem::Result readFile(const Size descriptor, void *buf, Size *size) const
Read a file.
static const Size MaximumFileSystemMounts
Maximum number of mounted filesystems.
FileSystemClient(const ProcessID pid=ANY)
Class constructor function.
void setCurrentDirectory(const String &directory)
Set new current directory.
FileSystem::Result mountFileSystem(const char *mountPath) const
Mount the current process as a file system on the rootfs.
FileSystem::Result deleteFile(const char *path) const
Remove a file from the file system.
FileSystem::Result createFile(const char *path, const FileSystem::FileType type, const FileSystem::FileModes mode) const
Create a new file.
FileSystem::Result openFile(const char *path, Size &descriptor) const
Open a file.
ProcessID findMount(const char *path) const
Retrieve the ProcessID of the FileSystemMount for the given path.
static FileSystemMount m_mounts[MaximumFileSystemMounts]
FileSystem mounts table.
FileSystemMount * getFileSystems(Size &numberOfMounts) const
Get file system mounts table.
static const Size MaximumLength
Maximum length of a filesystem path in bytes.
Provides the timer of the kernel.
Definition KernelTimer.h:37
virtual Result tick()
Process timer tick.
static Size copy(void *dest, const void *src, Size count)
Copy memory from one place to another.
static ChannelClient * instance()
Retrieve the instance.
Definition Singleton.h:53
Abstraction of strings.
Definition String.h:42
Size length() const
Same as count().
Definition String.cpp:105
virtual int compareTo(const String &str) const
Compares this String to the given String.
Definition String.cpp:231
virtual Result getCurrent(Info *info, const Size msecOffset=0)
Get current timer info.
Definition Timer.cpp:44
#define ROOTFS_PID
Definition ProcessID.h:41
#define ANY
Definition ProcessID.h:34
#define assert(exp)
Insert program diagnostics.
Definition assert.h:60
#define NULL
NULL means zero.
Definition Macros.h:39
u32 ProcessID
Process Identification Number.
Definition Types.h:140
#define ERROR(msg)
Output an error message.
Definition Log.h:61
unsigned int Size
Any sane size indicator cannot go negative.
Definition Types.h:128
#define ZERO
Zero value.
Definition Macros.h:43
FileType
All possible filetypes.
Definition FileSystem.h:71
Result
Result code for filesystem Actions.
Definition FileSystem.h:53
@ RedirectRequest
Definition FileSystem.h:62
@ MountFileSystem
Definition FileSystem.h:44
u16 FileModes
Multiple FileMode values combined.
Definition FileSystem.h:108
Describes a single file opened by a user process.
ProcessID pid
< Inode number of the file
bool open
< Current position indicator.
Size position
< Process identifier of the filesystem
FileSystem IPC message.
u32 inode
Inode number of the file.
Timer::Info timeout
Timeout value for the action.
char * buffer
Points to a buffer for I/O.
FileSystem::Result result
Result code.
FileSystem::Action action
Action to perform.
FileSystem::FileStat * stat
File Statistics.
Size pathMountLength
Length of the mounted path (used for redirection)
Size size
Size of the buffer.
ProcessID pid
Process identifier (used for redirection)
Size offset
Offset in the file for I/O.
Represents a mounted filesystem.
char path[FileSystemPath::MaximumLength]
Path of the mount.
ProcessID procID
Server which is responsible for the mount.
ulong options
Mount options.
Contains file information.
Definition FileSystem.h:114
ProcessID pid
< Inode number
Definition FileSystem.h:117
u32 inode
< File type.
Definition FileSystem.h:116
FileModes access
< Process identifier of filesystem
Definition FileSystem.h:118
Provides information about an inode.
Definition FileSystem.h:128
u32 ticks
Definition Timer.h:44
Size frequency
Definition Timer.h:45