FreeNOS
FileSystemServer.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015 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 <FreeNOS/User.h>
19#include <Assert.h>
20#include <Vector.h>
21#include <HashTable.h>
22#include <HashIterator.h>
23#include <DatastoreClient.h>
24#include <KernelTimer.h>
25#include "FileSystemClient.h"
26#include "FileSystemMount.h"
27#include "FileSystemServer.h"
28
50
52{
53 if (m_requests)
54 {
55 delete m_requests;
56 }
57
59}
60
62{
63 return m_mountPath;
64}
65
67{
68 static u32 next = 2;
69
70 // Ensure that the inode is not already used
71 while (m_inodeMap.get(++next) != ZERO)
72 ;
73
74 return next;
75}
76
78{
79 // The rootfs server manages the mounts table. Retrieve it from the datastore.
80 if (m_pid == ROOTFS_PID)
81 {
82 const DatastoreClient datastore;
83 const Datastore::Result result =
84 datastore.registerBuffer("mounts", &m_mounts, sizeof(FileSystemMount) * MaximumFileSystemMounts);
85
86 if (result != Datastore::Success)
88
90
91 // Fill the mounts table
94 }
95 // Other file systems send a request to root file system to mount.
96 else if (m_mountPath != ZERO)
97 {
98 const FileSystemClient rootfs(ROOTFS_PID);
99 const FileSystem::Result result = rootfs.mountFileSystem(m_mountPath);
100
101 assert(result == FileSystem::Success);
102 return result;
103 }
104 else
105 {
106 return FileSystem::Success;
107 }
108}
109
114
116{
117 // Add to the filesystem cache
118 FileCache *cache = insertFileCache(file, path);
119 if (cache == ZERO)
120 {
121 return FileSystem::IOError;
122 }
123
124 // Also add to the parent directory
125 Directory *parent = getParentDirectory(path);
126 if (parent != ZERO)
127 {
128 const FileSystemPath p(path);
129 parent->insert(file->getType(), *p.base());
130 return FileSystem::Success;
131 }
132 else
133 {
135 }
136}
137
139 const char *path)
140{
141 // Add the directory itself first
142 FileSystem::Result result = registerFile(dir, path);
143 if (result != FileSystem::Success)
144 {
145 ERROR("failed to register directory " << path <<
146 ": result = " << (int) result);
147 return result;
148 }
149
150 String dot;
151 dot << path;
152 dot << "/.";
153
154 // Insert the '.' directory which points to itself
155 result = registerFile(dir, *dot);
156 if (result != FileSystem::Success)
157 {
158 ERROR("failed to register '.' for directory " << path <<
159 ": result = " << (int) result);
160 return result;
161 }
162
163 // Insert the '..' directory which points to its parent
164 Directory *parent = getParentDirectory(path);
165 if (parent == ZERO)
166 {
167 ERROR("failed to retrieve parent directory for " << path);
169 }
170
171 dot << ".";
172 return registerFile(parent, *dot);
173}
174
176{
177 DEBUG("path = " << path);
178
179 FileCache *cache = findFileCache(path);
180 if (!cache)
181 {
183 }
184
185 if (cache->entries.count() != 0)
186 {
188 }
189
190 clearFileCache(cache);
191 return FileSystem::Success;
192}
193
195{
196 // Prepare request
197 FileSystemRequest req(msg);
198
199 // Process the request.
201 {
202 FileSystemRequest *reqCopy = new FileSystemRequest(msg);
203 assert(reqCopy != NULL);
204 m_requests->append(reqCopy);
205 }
206}
207
209{
210 Size savedMountLength = 0;
211 FileSystemMount *mnt = ZERO;
212
213 // Search for the longest matching mount
214 for (Size i = 0; i < MaximumFileSystemMounts; i++)
215 {
216 if (m_mounts[i].path[0] != ZERO)
217 {
218 const String mountStr(m_mounts[i].path, false);
219 const Size mountStrLen = mountStr.length();
220
221 if (mountStrLen > savedMountLength && mountStr.compareTo(path, true, mountStrLen) == 0)
222 {
223 savedMountLength = mountStrLen;
224 mnt = &m_mounts[i];
225 }
226 }
227 }
228
229 // If no match was found, no redirect is needed
230 if (!mnt)
231 return false;
232
234
237 else
239 msg->pid = mnt->procID;
240 msg->pathMountLength = savedMountLength;
241
242 sendResponse(msg);
243 return true;
244}
245
247{
248 FileSystemMessage *msg = req.getMessage();
249 File *file = ZERO;
250
251 DEBUG(m_self << ": inode = " << msg->inode << " action = " << msg->action);
252
253 File *const *f = m_inodeMap.get(msg->inode);
254 if (f == ZERO)
255 {
256
258 sendResponse(msg);
259 return msg->result;
260 }
261 file = (*f);
262
263 if (msg->action == FileSystem::ReadFile)
264 {
265 msg->result = file->read(req.getBuffer(), msg->size, msg->offset);
266
267 if (msg->result == FileSystem::Success)
268 {
269 if (req.getBuffer().getCount())
270 {
271 req.getBuffer().flushWrite();
272 }
273 }
274
275 DEBUG(m_self << ": read = " << (int)msg->result);
276 }
277 else if (msg->action == FileSystem::WriteFile)
278 {
279 if (!req.getBuffer().getCount())
280 {
281 req.getBuffer().bufferedRead();
282 }
283
284 msg->result = file->write(req.getBuffer(), msg->size, msg->offset);
285 DEBUG(m_self << ": write = " << (int)msg->result);
286 }
287 else
288 {
290 }
291
292 // Only send reply if completed (not RetryAgain)
293 if (msg->result != FileSystem::RetryAgain)
294 {
295 sendResponse(msg);
296 }
297
298 return msg->result;
299}
300
302{
303 FileSystemMessage *msg = req.getMessage();
305 const Size count = msg->size / sizeof(FileSystem::WaitSet) < MaximumWaitSetCount ?
307 IOBuffer & ioBuffer = req.getBuffer();
308
309 // Read waitset input struct
310 msg->result = ioBuffer.read(&waitBuf, count * sizeof(FileSystem::WaitSet), 0);
311 if (msg->result != FileSystem::Success)
312 {
313 ERROR("failed to read WaitSet input from PID " << msg->from << ": result = " << (int) msg->result);
314 sendResponse(msg);
315 return msg->result;
316 }
317
318 // By default, retry again
320
321 // fill the struct
322 for (Size i = 0; i < count; i++)
323 {
324 File *const *f = m_inodeMap.get(waitBuf[i].inode);
325 if (f != ZERO)
326 {
327 waitBuf[i].current = 0;
328
329 if ((waitBuf[i].requested & FileSystem::Readable) && (*f)->canRead())
330 {
331 DEBUG("inode " << waitBuf[i].inode << " is readable");
332 waitBuf[i].current |= FileSystem::Readable;
334 }
335
336 if ((waitBuf[i].requested & FileSystem::Writable) && (*f)->canWrite())
337 {
338 DEBUG("inode " << waitBuf[i].inode << " is writable");
339 waitBuf[i].current |= FileSystem::Writable;
341 }
342 }
343 }
344
345 // write back
346 ioBuffer.write(&waitBuf, count * sizeof(FileSystem::WaitSet), 0);
348 {
349 ERROR("failed to write WaitSet output to PID " << msg->from << ": result = " << (int) msg->result);
350 sendResponse(msg);
351 return msg->result;
352 }
353
354 // Check for timeout
355 if (msg->timeout.frequency != 0 && msg->result == FileSystem::RetryAgain)
356 {
357 KernelTimer timer;
358 timer.tick();
359
360 if (timer.isExpired(msg->timeout))
361 {
363 }
364 else
365 {
367 {
369 }
371 }
372 }
373
374 // Only send reply if completed (not RetryAgain)
375 if (msg->result != FileSystem::RetryAgain)
376 {
377 sendResponse(msg);
378 }
379
380 return msg->result;
381}
382
384{
386 FileCache *cache = ZERO;
387 File *file = ZERO;
388 FileSystemMessage *msg = req.getMessage();
390
391 // Retrieve file by inode or by file path?
393 {
394 return inodeHandler(req);
395 }
396 else if (msg->action == FileSystem::WaitFile)
397 {
398 return waitFileHandler(req);
399 }
400
401 // Copy the file path
402 const API::Result result = VMCopy(msg->from, API::Read, (Address) buf,
404 if (result != API::Success)
405 {
406 ERROR("VMCopy failed: result = " << (int)result << " from = " << msg->from <<
407 " addr = " << (void *) msg->buffer << " action = " << (int) msg->action);
409 sendResponse(msg);
410 return msg->result;
411 }
412 DEBUG(m_self << ": path = " << buf << " action = " << msg->action);
413
414 // Handle mounted file system paths (will result in redirect messages)
415 if (m_pid == ROOTFS_PID && redirectRequest(buf, msg))
416 {
417 DEBUG(m_self << ": redirect " << buf << " to " << msg->pid);
418 return msg->result;
419 }
420
421 const FileSystemPath path(buf + String::length(m_mountPath));
422
423 // Do we have this file cached?
424 if ((cache = findFileCache(path)) ||
425 (cache = lookupFile(path)))
426 {
427 file = cache->file;
428 }
429
430 // Check for File not found
431 if (file == ZERO &&
434 {
435 DEBUG(m_self << ": not found");
437 sendResponse(msg);
438 return msg->result;
439 }
440
441 // Perform I/O on the file
442 switch (msg->action)
443 {
445 if (cache)
446 {
448 }
449 else
450 {
451 const API::Result stResult = VMCopy(msg->from, API::Read, (Address) &st,
452 (Address) msg->stat, sizeof(st));
453 if (stResult != API::Success)
454 {
455 ERROR("VMCopy failed for FileStat: result = " << (int) stResult <<
456 " from = " << msg->from << " addr = " << (void *) msg->stat <<
457 " action = " << (int) msg->action);
459 }
460 else
461 {
462 // Attempt to create the new file
463 file = createFile(st.type);
464 if (!file)
465 {
467 }
468 else
469 {
470 msg->result = registerFile(file, *path.full());
471 }
472 }
473 }
474 DEBUG(m_self << ": create = " << (int)msg->result);
475 break;
476
478 msg->result = unregisterFile(*path.full());
479 DEBUG(m_self << ": delete = " << (int)msg->result);
480 break;
481
483 if (file->status(st) == FileSystem::Success)
484 {
485 st.pid = m_self;
486
487 // Copy to the remote process
488 const API::Result stResult = VMCopy(msg->from, API::Write, (Address) &st,
489 (Address) msg->stat, sizeof(st));
490 if (stResult == API::Success)
491 {
493 }
494 else
495 {
496 ERROR("VMCopy failed of FileStat for PID " << msg->from << ": result = " << (int) stResult);
498 }
499 }
500 else
501 {
503 }
504 DEBUG(m_self << ": stat = " << (int)msg->result);
505 break;
506
510 break;
511
513 // Do nothing here. Once the targeted file system is mounted
514 // this function will send a redirect message when called again
515 DEBUG(m_self << ": wait for " << buf);
517 break;
518 }
519
520 default: {
521 ERROR("unhandled file I/O operation: " << (int)msg->action);
523 break;
524 }
525 }
526
527 // Only send reply if completed (not RetryAgain)
528 if (msg->result != FileSystem::RetryAgain)
529 {
530 sendResponse(msg);
531 }
532
533 return msg->result;
534}
535
537{
539
540 DEBUG(m_self << ": sending response to PID " << msg->from <<
541 " for action = " << (int) msg->action <<
542 " with result = " << (int) msg->result);
543
544 Channel *channel = m_registry.getProducer(msg->from);
545 if (channel == ZERO)
546 {
547 ERROR("failed to retrieve channel for PID " << msg->from);
548 return;
549 }
550
551 const Channel::Result result = channel->write(msg);
552 if (result != Channel::Success)
553 {
554 ERROR("failed to write channel for PID " << msg->from);
555 return;
556 }
557
558 ProcessCtl(msg->from, Wakeup, 0);
559}
560
562{
563 char buf[FileSystemPath::MaximumLength + 1];
564
565 // Copy the file path
566 const API::Result result = VMCopy(msg->from, API::Read, (Address) buf,
568 if (result != API::Success)
569 {
570 ERROR("failed to copy mount path: result = " << (int) result);
572 return;
573 }
574
575 // Null-terminate
577 const String path(buf);
578
579 // Check for already existing entry (re-mount)
580 for (Size i = 0; i < MaximumFileSystemMounts; i++)
581 {
582 const String entry(m_mounts[i].path);
583
584 if (path.equals(entry))
585 {
586 m_mounts[i].procID = msg->from;
587 m_mounts[i].options = ZERO;
588 NOTICE("remounted " << m_mounts[i].path);
590 return;
591 }
592 }
593
594 // Append to our filesystem mounts table
595 for (Size i = 0; i < MaximumFileSystemMounts; i++)
596 {
597 if (!m_mounts[i].path[0])
598 {
599 MemoryBlock::copy(m_mounts[i].path, buf, sizeof(m_mounts[i].path));
600 m_mounts[i].procID = msg->from;
601 m_mounts[i].options = ZERO;
602 NOTICE("mounted " << m_mounts[i].path);
604 return;
605 }
606 }
607
608 // Not space left
610}
611
613{
614 // Copy mounts table to the requesting process
615 const Size mountsSize = sizeof(FileSystemMount) * MaximumFileSystemMounts;
616 const Size numBytes = msg->size < mountsSize ? msg->size : mountsSize;
617 const API::Result result = VMCopy(msg->from, API::Write, (Address) m_mounts,
618 (Address) msg->buffer, numBytes);
619 if (result != API::Success)
620 {
621 ERROR("failed to copy mount table: result = " << (int) result);
623 return;
624 }
625
627}
628
630{
631 bool restartNeeded = false;
632
633 DEBUG("");
634
636 {
637 FileSystem::Result result = processRequest(*i.current());
638 if (result != FileSystem::RetryAgain)
639 {
640 delete i.current();
641 i.remove();
642 restartNeeded = true;
643 }
644 }
645
646 return restartNeeded;
647}
648
650{
651 if (newRoot != ZERO)
652 {
653 m_root = new FileCache(newRoot, "/", ZERO);
654 insertFileCache(newRoot, ".");
655 insertFileCache(newRoot, "..");
656 }
657}
658
660{
661 const FileSystemPath p(path);
662 Directory *parent = ZERO;
663
664 if (p.parent().length() > 0)
665 {
666 FileCache *cache = findFileCache(*p.parent());
667 if (cache != ZERO)
668 {
669 parent = static_cast<Directory *>(cache->file);
670 }
671 }
672 else
673 {
674 parent = static_cast<Directory *>(m_root->file);
675 }
676
677 return parent;
678}
679
681{
682 const List<String> &entries = path.split();
683 FileCache *c = m_root;
684 File *file = ZERO;
685 Directory *dir;
686
687 // Loop the entire path
688 for (ListIterator<String> i(entries); i.hasCurrent(); i++)
689 {
690 // Do we have this entry cached already?
691 if (!c->entries.contains(i.current()))
692 {
693 // If this isn't a directory, we cannot perform a lookup
695 {
696 return ZERO;
697 }
698 dir = (Directory *) c->file;
699
700 // Fetch the file, if possible
701 if (!(file = dir->lookup(*i.current())))
702 {
703 return ZERO;
704 }
705 // Insert into the FileCache
706 c = new FileCache(file, *i.current(), c);
707 assert(c != NULL);
708
709 // Add file to the inode map
710 if (!m_inodeMap.insert(file->getInode(), file))
711 {
712 return ZERO;
713 }
714 }
715 // Move to the next entry
716 else if (c != ZERO)
717 {
718 c = (FileCache *) c->entries.value(i.current());
719 }
720 else
721 {
722 break;
723 }
724 }
725
726
727 // All done
728 return c;
729}
730
732{
733 const FileSystemPath path(pathStr);
734 FileCache *parent = ZERO;
735
736 // Lookup our parent
737 if (path.parent().length() == 0)
738 {
739 parent = m_root;
740 }
741 else if (!(parent = findFileCache(path.parent())))
742 {
743 return ZERO;
744 }
745
746 // Add file to the inode map
747 if (!m_inodeMap.insert(file->getInode(), file))
748 {
749 return ZERO;
750 }
751
752 // Create new cache
753 FileCache *c = new FileCache(file, *path.base(), parent);
754 assert(c != NULL);
755 return c;
756}
757
759{
760 const FileSystemPath p(path);
761 return findFileCache(p);
762}
763
765{
766 return findFileCache(*path);
767}
768
770{
771 const List<String> &entries = path.split();
772 FileCache *c = m_root;
773
774 // Root is treated special
775 if (path.parent().length() == 0 && path.length() == 0)
776 {
777 return m_root;
778 }
779
780 // Loop the entire path
781 for (ListIterator<String> i(entries); i.hasCurrent(); i++)
782 {
783 if (!c->entries.contains(i.current()))
784 {
785 return ZERO;
786 }
787 c = (FileCache *) c->entries.value(i.current());
788 }
789
790 // Return what we got
791 return c;
792}
793
795{
796 assert(cache != ZERO);
797 assert(file != ZERO);
798
799 // Walk all our childs
800 for (HashIterator<String, FileCache *> i(cache->entries); i.hasCurrent(); i++)
801 {
802 FileCache *child = i.current();
803
804 if (child->file == cache->file)
805 {
806 static_cast<Directory *>(cache->file)->remove(*child->name);
807 removeFileFromCache(child, file);
808 child->file = ZERO;
809 }
810 }
811}
812
814{
815 // Start from root?
816 if (!cache)
817 {
818 cache = m_root;
819 }
820
821 // Make sure the current file is removed from all childs and below
822 if (cache->file != ZERO)
823 {
824 removeFileFromCache(cache, cache->file);
825 }
826
827 // Walk all our childs
828 for (HashIterator<String, FileCache *> i(cache->entries); i.hasCurrent();)
829 {
830 FileCache *child = i.current();
831
832 static_cast<Directory *>(cache->file)->remove(*child->name);
833 if (cache->parent && cache->parent->file == child->file)
834 {
835 child->file = ZERO;
836 }
837 clearFileCache(child);
838 i.remove();
839 }
840
841 // Cleanup this cache object
842 assert(cache->entries.count() == 0);
843
844 if (cache->file != ZERO)
845 {
846 // Remove entry from parent */
847 if (cache->parent)
848 {
849 if (cache->parent->file)
850 {
851 static_cast<Directory *>(cache->parent->file)->remove(*cache->name);
852 }
853 cache->parent->entries.remove(cache->name);
854 }
855
856 m_inodeMap.remove(cache->file->getInode());
857 delete cache->file;
858 }
859 delete cache;
860}
u8 type
Definition IntelACPI.h:0
u32 entry[]
Definition IntelACPI.h:1
Result
Enumeration of generic kernel API result codes.
Definition API.h:69
@ Success
Definition API.h:70
@ Read
Definition API.h:98
@ Write
Definition API.h:99
virtual bool contains(const K &key) const
Check if the given key exists.
ProcessID from
Source process of the message.
Type type
Message type is either a request or response.
Channel * getProducer(const ProcessID pid)
Get one producer.
Template class which serves incoming messages from Channels using MessageHandlers.
Timer::Info m_expiry
System timer expiration value.
ChannelRegistry & m_registry
Contains registered channels.
void addIPCHandler(const Size slot, IPCHandlerFunction h, const bool sendReply=true)
Register a new IPC message action handler.
Unidirectional point-to-point messaging channel.
Definition Channel.h:35
virtual Result write(const void *buffer)
Write a message.
Definition Channel.cpp:40
Result
Result codes.
Definition Channel.h:42
@ Success
Definition Channel.h:43
Datastore client.
Datastore::Result registerBuffer(const char *key, void *buffer, const Size size) const
Add a new buffer.
Directory File functionality.
Definition Directory.h:60
virtual File * lookup(const char *name)
Retrieve a File from storage.
Definition Directory.cpp:61
void insert(FileSystem::FileType type, const char *name)
Insert a new directory entry.
Definition Directory.cpp:66
FileSystemClient provides a simple interface to a FileSystemServer.
FileSystem::Result mountFileSystem(const char *mountPath) const
Mount the current process as a file system on the rootfs.
Simple filesystem path parser.
const String & full() const
Get the full path as a String.
static const Size MaximumLength
Maximum length of a filesystem path in bytes.
const List< String > & split() const
Returns a List of separate path elements.
const String & parent() const
Retrieve the full path of our parent.
Size length() const
Get Length of our full path.
const String & base() const
The name of the last element in the path.
Encapsulates a pending FileSystemMessage.
IOBuffer & getBuffer()
Get IOBuffer.
FileSystemMessage * getMessage()
Get message.
Abstract filesystem class.
FileCache * m_root
Root entry of the filesystem tree.
FileSystem::Result mount()
Mount the FileSystem.
FileCache * findFileCache(const char *path) const
Search the cache for an entry.
void setRoot(Directory *newRoot)
Change the filesystem root directory.
virtual bool retryRequests()
Retry any pending requests.
void sendResponse(FileSystemMessage *msg) const
Send response for a FileSystemMessage.
static const Size MaximumFileSystemMounts
Maximum number of supported file system mount entries.
FileSystem::Result waitFileHandler(FileSystemRequest &req)
Handle a WaitFile request.
HashTable< u32, File * > m_inodeMap
Contains a mapping of inode number to file of all cached files.
FileSystem::Result processRequest(FileSystemRequest &req)
Process a FileSystemRequest.
virtual ~FileSystemServer()
Destructor function.
static const Size MaximumWaitSetCount
Maximum number of WaitSet entries supported.
u32 getNextInode()
Get next unused inode.
FileSystem::Result inodeHandler(FileSystemRequest &req)
Handle a request for a File specified by its inode.
FileCache * lookupFile(const FileSystemPath &path)
Retrieve a File from storage.
FileSystem::Result unregisterFile(const char *path)
Remove a File from the FileSystemServer.
virtual File * createFile(const FileSystem::FileType type)
Create a new file.
const ProcessID m_pid
Process identifier.
void mountHandler(FileSystemMessage *msg)
Process a filesystem mount request message.
const char * getMountPath() const
Get mount path.
void clearFileCache(FileCache *cache=ZERO)
Cleans up the entire file cache (except opened file caches and root).
FileSystemServer(Directory *root, const char *path)
Constructor function.
FileSystemMount * m_mounts
Table with mounted file systems (only used by the root file system).
FileSystem::Result registerDirectory(Directory *dir, const char *path)
Register a new Directory.
FileSystem::Result registerFile(File *file, const char *path)
Register a new File.
void removeFileFromCache(FileCache *cache, File *file)
Remove a File from the cache.
List< FileSystemRequest * > * m_requests
Contains ongoing requests.
bool redirectRequest(const char *path, FileSystemMessage *msg)
Try to forward the given FileSystemMessage to a mount file system.
void getFileSystemsHandler(FileSystemMessage *msg)
Read the file system mounts table.
void pathHandler(FileSystemMessage *msg)
Process an incoming filesystem request using a path.
const char * m_mountPath
Mount point path.
FileCache * insertFileCache(File *file, const char *pathFormat)
Inserts a file into the in-memory filesystem tree.
Directory * getParentDirectory(const char *path)
Retrieve parent Directory for a file.
Represents a file present on a FileSystem.
Definition File.h:40
FileSystem::FileType getType() const
Retrieve our filetype.
Definition File.cpp:43
u32 getInode() const
Get inode number.
Definition File.cpp:38
virtual FileSystem::Result write(IOBuffer &buffer, Size &size, const Size offset)
Write bytes to the file.
Definition File.cpp:55
virtual FileSystem::Result read(IOBuffer &buffer, Size &size, const Size offset)
Read bytes from the file.
Definition File.cpp:48
virtual FileSystem::Result status(FileSystem::FileStat &st)
Retrieve file statistics.
Definition File.cpp:62
Iterate through a HashTable.
virtual const V value(const K &key, const V defaultValue=V()) const
Return the first value for the given key.
Definition HashTable.h:325
virtual int remove(const K &key)
Remove value(s) for the given key.
Definition HashTable.h:178
virtual const V * get(const K &key) const
Returns the first value for the given key.
Definition HashTable.h:287
virtual Size count() const
Get the number of values stored in the HashTable.
Definition HashTable.h:211
virtual bool insert(const K &key, const V &value)
Inserts the given item to the HashTable.
Definition HashTable.h:133
Abstract Input/Output buffer.
Definition IOBuffer.h:38
FileSystem::Result flushWrite()
Flush write buffers.
Definition IOBuffer.cpp:204
Size getCount() const
Get byte count.
Definition IOBuffer.cpp:109
FileSystem::Result read(void *buffer, const Size size, const Size offset=ZERO)
Read bytes from the I/O buffer.
Definition IOBuffer.cpp:156
FileSystem::Result write(const void *buffer, const Size size, const Size offset=ZERO)
Write bytes to the I/O buffer.
Definition IOBuffer.cpp:180
FileSystem::Result bufferedRead()
Buffered read bytes from the I/O buffer.
Definition IOBuffer.cpp:130
Provides the timer of the kernel.
Definition KernelTimer.h:37
virtual Result tick()
Process timer tick.
Iterate through a List.
virtual bool hasCurrent() const
Check if there is a current item on the List.
Simple linked list template class.
Definition List.h:37
void append(T t)
Insert an item at the end of the list.
Definition List.h:139
static void * set(void *dest, int ch, unsigned count)
Fill memory with a constant byte.
static Size copy(void *dest, const void *src, Size count)
Copy memory from one place to another.
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
bool isExpired(const Info &info) const
Check if a timer value is expired.
Definition Timer.cpp:85
API::Result VMCopy(const ProcessID proc, const API::Operation how, const Address ours, const Address theirs, const Size sz)
Prototype for user applications.
Definition VMCopy.h:42
#define ROOTFS_PID
Definition ProcessID.h:41
#define SELF
Definition ProcessID.h:35
API::Result ProcessCtl(const ProcessID proc, const ProcessOperation op, const Address addr=0, const Address output=0)
Prototype for user applications.
Definition ProcessCtl.h:93
@ GetPID
Definition ProcessCtl.h:41
@ Wakeup
Definition ProcessCtl.h:53
#define assert(exp)
Insert program diagnostics.
Definition assert.h:60
#define NULL
NULL means zero.
Definition Macros.h:39
unsigned int u32
Unsigned 32-bit number.
Definition Types.h:53
unsigned long Address
A memory address.
Definition Types.h:131
#define ERROR(msg)
Output an error message.
Definition Log.h:61
#define NOTICE(msg)
Output a notice message.
Definition Log.h:75
unsigned int Size
Any sane size indicator cannot go negative.
Definition Types.h:128
#define ZERO
Zero value.
Definition Macros.h:43
#define DEBUG(msg)
Output a debug message to standard output.
Definition Log.h:89
Result
Result codes.
Definition Datastore.h:43
FileType
All possible filetypes.
Definition FileSystem.h:71
Result
Result code for filesystem Actions.
Definition FileSystem.h:53
@ PermissionDenied
Definition FileSystem.h:59
@ RedirectRequest
Definition FileSystem.h:62
@ Writable
< File can be read without blocking
Definition FileSystem.h:140
@ MountFileSystem
Definition FileSystem.h:44
Cached in-memory file.
Definition FileCache.h:36
HashTable< String, FileCache * > entries
Contains childs.
Definition FileCache.h:62
File * file
File pointer.
Definition FileCache.h:56
String name
Our name.
Definition FileCache.h:59
FileCache * parent
Parent.
Definition FileCache.h:65
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.
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
Provides information about an inode.
Definition FileSystem.h:128
u16 current
< Requested status flags of the inode
Definition FileSystem.h:131
u32 ticks
Definition Timer.h:44
Size frequency
Definition Timer.h:45