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 
25 FileSystemMount 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 {
61  ChannelClient::Result r = ChannelClient::instance()->syncSendReceive(&msg, sizeof(msg), pid);
62  if (r != ChannelClient::Success)
63  {
64  ERROR("failed to send request to PID " << pid <<
65  " for path " << msg.buffer << ": result = " << (int) r);
66  return FileSystem::IpcError;
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;
87  m_mounts[i].options = ZERO;
88  break;
89  }
90  }
91 
93  r = ChannelClient::instance()->syncSendReceive(&msg, sizeof(msg), msg.pid);
94  if (r != ChannelClient::Success)
95  {
96  ERROR("failed to redirect request to PID " << msg.pid <<
97  " for path " << msg.buffer << ": result = " << (int) r);
98  return FileSystem::IpcError;
99  }
100 
102  return msg.result;
103 }
104 
105 ProcessID FileSystemClient::findMount(const char *path) const
106 {
107  FileSystemMount *m = ZERO;
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 
147 {
148  return m_currentDirectory;
149 }
150 
152 {
154  *m_currentDirectory = directory;
155 }
156 
158 {
159  if (m_currentDirectory != NULL)
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 
177  FileSystemMessage msg;
180  msg.buffer = (char *)path;
181  msg.stat = &st;
182 
183  return request(path, msg);
184 }
185 
187  FileSystem::FileStat *st) const
188 {
189  FileSystemMessage msg;
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  {
236  return FileSystem::NotFound;
237  }
238 
239  FileSystemMessage msg;
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  {
264  return FileSystem::NotFound;
265  }
266 
267  FileSystemMessage msg;
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 {
288  FileSystemMessage msg;
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 
303  FileSystemMessage msg;
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 {
326  FileSystemMessage msg;
329  msg.buffer = (char *) mountPath;
330 
331  return request(ROOTFS_PID, msg);
332 }
333 
335 {
336  FileSystemMessage msg;
339  msg.buffer = (char *) path;
340 
341  return request(ROOTFS_PID, msg);
342 }
343 
345 {
346  FileSystemMessage msg;
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 }
FileDescriptor::Entry::position
Size position
< Process identifier of the filesystem
Definition: FileDescriptor.h:50
MemoryBlock::copy
static Size copy(void *dest, const void *src, Size count)
Copy memory from one place to another.
Definition: MemoryBlock.cpp:36
FileSystemClient::createFile
FileSystem::Result createFile(const char *path, const FileSystem::FileType type, const FileSystem::FileModes mode) const
Create a new file.
Definition: FileSystemClient.cpp:169
FileSystemClient::MaximumFileSystemMounts
static const Size MaximumFileSystemMounts
Maximum number of mounted filesystems.
Definition: FileSystemClient.h:47
ChannelClient.h
StrictSingleton< ChannelClient >::instance
static ChannelClient * instance()
Retrieve the instance.
Definition: Singleton.h:53
String::length
Size length() const
Same as count().
Definition: String.cpp:105
FileSystem::WaitFileSystem
@ WaitFileSystem
Definition: FileSystem.h:45
FileSystemMessage::buffer
char * buffer
Points to a buffer for I/O.
Definition: FileSystemMessage.h:41
FileSystem::FileType
FileType
All possible filetypes.
Definition: FileSystem.h:70
FileSystemMount
Represents a mounted filesystem.
Definition: FileSystemMount.h:35
FileSystemClient::statFile
FileSystem::Result statFile(const char *path, FileSystem::FileStat *st) const
Retrieve status of a file.
Definition: FileSystemClient.cpp:186
String
Abstraction of strings.
Definition: String.h:41
FileSystem::WriteFile
@ WriteFile
Definition: FileSystem.h:40
FileSystemMessage::stat
FileSystem::FileStat * stat
File Statistics.
Definition: FileSystemMessage.h:45
FileDescriptor::Entry::open
bool open
< Current position indicator.
Definition: FileDescriptor.h:51
FileSystemClient::waitFileSystem
FileSystem::Result waitFileSystem(const char *path) const
Blocking wait for a mounted filesystem.
Definition: FileSystemClient.cpp:334
FileSystem::WaitSet
Provides information about an inode.
Definition: FileSystem.h:127
ChannelMessage::type
Type type
Message type is either a request or response.
Definition: ChannelMessage.h:48
FileSystemClient::mountFileSystem
FileSystem::Result mountFileSystem(const char *mountPath) const
Mount the current process as a file system on the rootfs.
Definition: FileSystemClient.cpp:324
KernelTimer
Provides the timer of the kernel.
Definition: KernelTimer.h:36
ProcessID
u32 ProcessID
Process Identification Number.
Definition: Types.h:140
FileSystemClient::deleteFile
FileSystem::Result deleteFile(const char *path) const
Remove a file from the file system.
Definition: FileSystemClient.cpp:286
Timer::Info::frequency
Size frequency
Definition: Timer.h:45
FileSystem::FileStat::inode
u32 inode
< File type.
Definition: FileSystem.h:116
ChannelClient::Success
@ Success
Definition: ChannelClient.h:83
FileDescriptor
Abstracts files which are opened by a user process.
Definition: FileDescriptor.h:36
FileSystemMessage
FileSystem IPC message.
Definition: FileSystemMessage.h:37
FileSystem::IOError
@ IOError
Definition: FileSystem.h:58
FileSystemClient::FileSystemClient
FileSystemClient(const ProcessID pid=ANY)
Class constructor function.
Definition: FileSystemClient.cpp:29
FileSystem::FileStat::access
FileModes access
< Process identifier of filesystem
Definition: FileSystem.h:118
FileDescriptor.h
FileSystemMessage::offset
Size offset
Offset in the file for I/O.
Definition: FileSystemMessage.h:43
FileSystem::Success
@ Success
Definition: FileSystem.h:54
String::compareTo
virtual int compareTo(const String &str) const
Compares this String to the given String.
Definition: String.cpp:231
FileSystemMessage::result
FileSystem::Result result
Result code.
Definition: FileSystemMessage.h:40
FileSystemClient::request
FileSystem::Result request(const char *path, FileSystemMessage &msg) const
Send an IPC request to the target file system.
Definition: FileSystemClient.cpp:34
Log.h
FileSystemClient::m_pid
const ProcessID m_pid
ProcessID of the target file system or ANY to lookup in mounts table.
Definition: FileSystemClient.h:246
FileSystemClient::m_currentDirectory
static String * m_currentDirectory
Current directory path is prefixed to relative path inputs.
Definition: FileSystemClient.h:243
FileSystemClient::getCurrentDirectory
const String * getCurrentDirectory() const
Get current directory String.
Definition: FileSystemClient.cpp:146
FileSystemMessage::inode
u32 inode
Inode number of the file.
Definition: FileSystemMessage.h:44
FileDescriptor::getEntry
Entry * getEntry(const Size index)
Retrieve a file descriptor Entry.
Definition: FileDescriptor.cpp:58
FileSystem::IpcError
@ IpcError
Definition: FileSystem.h:63
FileSystemClient::writeFile
FileSystem::Result writeFile(const Size descriptor, const void *buf, Size *size) const
Write a file.
Definition: FileSystemClient.cpp:257
FileSystem::FileStat::type
FileType type
Definition: FileSystem.h:115
FileSystemPath::MaximumLength
static const Size MaximumLength
Maximum length of a filesystem path in bytes.
Definition: FileSystemPath.h:47
FileDescriptor::Entry::inode
u32 inode
Definition: FileDescriptor.h:48
FileSystem::GetFileSystems
@ GetFileSystems
Definition: FileSystem.h:46
FileSystemClient::closeFile
FileSystem::Result closeFile(const Size descriptor) const
Close a file.
Definition: FileSystemClient.cpp:218
FileSystemMount::options
ulong options
Mount options.
Definition: FileSystemMount.h:44
FileSystem::RedirectRequest
@ RedirectRequest
Definition: FileSystem.h:62
FileDescriptor::Entry
Describes a single file opened by a user process.
Definition: FileDescriptor.h:46
FileSystemClient::openFile
FileSystem::Result openFile(const char *path, Size &descriptor) const
Open a file.
Definition: FileSystemClient.cpp:198
FileSystemClient::setCurrentDirectory
void setCurrentDirectory(const String &directory)
Set new current directory.
Definition: FileSystemClient.cpp:151
FileSystemClient::m_mounts
static FileSystemMount m_mounts[MaximumFileSystemMounts]
FileSystem mounts table.
Definition: FileSystemClient.h:240
FileDescriptor::Result
Result
Result code.
Definition: FileDescriptor.h:57
FileSystemMount::procID
ProcessID procID
Server which is responsible for the mount.
Definition: FileSystemMount.h:41
FileSystem::MountFileSystem
@ MountFileSystem
Definition: FileSystem.h:44
FileDescriptor::closeEntry
Result closeEntry(const Size index)
Remove file descriptor entry.
Definition: FileDescriptor.cpp:68
NULL
#define NULL
NULL means zero.
Definition: Macros.h:39
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
ChannelClient::syncSendReceive
virtual Result syncSendReceive(void *buffer, const Size msgSize, const ProcessID pid)
Synchronous send and receive to/from one process.
Definition: ChannelClient.cpp:322
FileSystemClient::getFileSystems
FileSystemMount * getFileSystems(Size &numberOfMounts) const
Get file system mounts table.
Definition: FileSystemClient.cpp:344
FileSystem::WaitFile
@ WaitFile
Definition: FileSystem.h:43
ROOTFS_PID
#define ROOTFS_PID
Definition: ProcessID.h:41
Timer::Info::ticks
u32 ticks
Definition: Timer.h:44
FileSystemClient::readFile
FileSystem::Result readFile(const Size descriptor, void *buf, Size *size) const
Read a file.
Definition: FileSystemClient.cpp:229
FileSystemClient::findMount
ProcessID findMount(const char *path) const
Retrieve the ProcessID of the FileSystemMount for the given path.
Definition: FileSystemClient.cpp:105
FileSystem::FileModes
u16 FileModes
Multiple FileMode values combined.
Definition: FileSystem.h:108
FileDescriptor::Success
@ Success
Definition: FileDescriptor.h:59
FileDescriptor::openEntry
Result openEntry(const u32 inode, const ProcessID filesystem, Size &index)
Add new file descriptor entry.
Definition: FileDescriptor.cpp:38
KernelTimer.h
ChannelClient::Result
Result
Result codes.
Definition: ChannelClient.h:81
FileSystemClient.h
assert
#define assert(exp)
Insert program diagnostics.
Definition: assert.h:60
FileSystem::FileStat
Contains file information.
Definition: FileSystem.h:113
ERROR
#define ERROR(msg)
Output an error message.
Definition: Log.h:61
FileSystemMount::path
char path[FileSystemPath::MaximumLength]
Path of the mount.
Definition: FileSystemMount.h:38
KernelTimer::tick
virtual Result tick()
Process timer tick.
Definition: KernelTimer.cpp:23
FileSystem::Result
Result
Result code for filesystem Actions.
Definition: FileSystem.h:52
FileSystem::DeleteFile
@ DeleteFile
Definition: FileSystem.h:42
FileDescriptor::Entry::pid
ProcessID pid
< Inode number of the file
Definition: FileDescriptor.h:49
FileSystem::ReadFile
@ ReadFile
Definition: FileSystem.h:39
FileSystemMessage::pathMountLength
Size pathMountLength
Length of the mounted path (used for redirection)
Definition: FileSystemMessage.h:48
FileSystemMessage::pid
ProcessID pid
Process identifier (used for redirection)
Definition: FileSystemMessage.h:47
FileSystemMessage::action
FileSystem::Action action
Action to perform.
Definition: FileSystemMessage.h:39
ANY
#define ANY
Definition: ProcessID.h:34
FileSystem::NotFound
@ NotFound
Definition: FileSystem.h:56
FileSystem::StatFile
@ StatFile
Definition: FileSystem.h:41
FileSystemClient::waitFile
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.
Definition: FileSystemClient.cpp:296
type
u8 type
Definition: IntelACPI.h:63
FileSystemMessage::timeout
Timer::Info timeout
Timeout value for the action.
Definition: FileSystemMessage.h:46
FileSystem::FileStat::pid
ProcessID pid
< Inode number
Definition: FileSystem.h:117
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
Timer::getCurrent
virtual Result getCurrent(Info *info, const Size msecOffset=0)
Get current timer info.
Definition: Timer.cpp:44
FileSystemMessage.h
FileSystem::CreateFile
@ CreateFile
Definition: FileSystem.h:38
FileSystemMessage::size
Size size
Size of the buffer.
Definition: FileSystemMessage.h:42
length
u32 length
Definition: IntelACPI.h:64
ChannelMessage::Request
@ Request
Definition: ChannelMessage.h:43