Skip to content

Commit ad782c2

Browse files
committed
stat/fstat/lstat/realpath
1 parent 791da60 commit ad782c2

File tree

21 files changed

+495
-86
lines changed

21 files changed

+495
-86
lines changed

kernel/src/kernel/calls/syscall.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ void syscallRegisterAll()
146146
_syscallRegister(G_SYSCALL_FS_READ_DIRECTORY, (g_syscall_handler) syscallFsReadDirectory, true);
147147
_syscallRegister(G_SYSCALL_FS_CLOSE_DIRECTORY, (g_syscall_handler) syscallFsCloseDirectory, true);
148148
_syscallRegister(G_SYSCALL_OPEN_IRQ_DEVICE, (g_syscall_handler) syscallOpenIrqDevice, true);
149+
_syscallRegister(G_SYSCALL_FS_REAL_PATH, (g_syscall_handler) syscallFsRealPath, true);
149150

150151
// System
151152
_syscallRegister(G_SYSCALL_LOG, (g_syscall_handler) syscallLog);

kernel/src/kernel/calls/syscall_filesystem.cpp

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -95,16 +95,6 @@ void syscallFsTell(g_task* task, g_syscall_fs_tell* data)
9595
data->status = G_FS_TELL_SUCCESSFUL;
9696
}
9797

98-
void syscallFsStat(g_task* task, g_syscall_fs_stat* data)
99-
{
100-
logInfo("%! stat not implemented", "syscall");
101-
}
102-
103-
void syscallFsFstat(g_task* task, g_syscall_fs_fstat* data)
104-
{
105-
logInfo("%! fstat not implemented", "syscall");
106-
}
107-
10898
void syscallFsPipe(g_task* task, g_syscall_fs_pipe* data)
10999
{
110100
g_fs_node* pipeNode;
@@ -186,11 +176,11 @@ void syscallFsOpenDirectory(g_task* task, g_syscall_fs_open_directory* data)
186176
auto findRes = filesystemFind(nullptr, data->path);
187177
if(findRes.status == G_FS_OPEN_SUCCESSFUL)
188178
{
189-
data->status = filesystemOpenDirectory(findRes.file);
179+
data->status = filesystemOpenDirectory(findRes.node);
190180

191181
if(data->status == G_FS_OPEN_DIRECTORY_SUCCESSFUL)
192182
{
193-
data->iterator->node_id = findRes.file->id;
183+
data->iterator->node_id = findRes.node->id;
194184
data->iterator->position = 0;
195185
}
196186
}
@@ -228,5 +218,20 @@ void syscallFsReadDirectory(g_task* task, g_syscall_fs_read_directory* data)
228218

229219
void syscallFsCloseDirectory(g_task* task, g_syscall_fs_close_directory* data)
230220
{
231-
// TODO: Is this needed?
221+
// TODO
222+
}
223+
224+
void syscallFsRealPath(g_task* task, g_syscall_fs_real_path* data)
225+
{
226+
data->status = filesystemRealPath(task, data->in, data->out);
227+
}
228+
229+
void syscallFsStat(g_task* task, g_syscall_fs_stat* data)
230+
{
231+
data->status = filesystemStat(task, data->path, data->out);
232+
}
233+
234+
void syscallFsFstat(g_task* task, g_syscall_fs_fstat* data)
235+
{
236+
data->status = filesystemFstat(task, data->fd, data->out);
232237
}

kernel/src/kernel/calls/syscall_filesystem.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,6 @@ void syscallFsReadDirectory(g_task* task, g_syscall_fs_read_directory* data);
5454

5555
void syscallFsCloseDirectory(g_task* task, g_syscall_fs_close_directory* data);
5656

57+
void syscallFsRealPath(g_task* task, g_syscall_fs_real_path* data);
58+
5759
#endif

kernel/src/kernel/calls/syscall_tasking.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,17 +235,18 @@ void syscallSetWorkingDirectory(g_task* task, g_syscall_set_working_directory* d
235235
auto findRes = filesystemFind(nullptr, data->path);
236236
if(findRes.status == G_FS_OPEN_SUCCESSFUL)
237237
{
238-
if(findRes.file->type == G_FS_NODE_TYPE_FOLDER || findRes.file->type == G_FS_NODE_TYPE_MOUNTPOINT || findRes.
239-
file->type == G_FS_NODE_TYPE_ROOT)
238+
if(findRes.node->type == G_FS_NODE_TYPE_FOLDER ||
239+
findRes.node->type == G_FS_NODE_TYPE_MOUNTPOINT ||
240+
findRes.node->type == G_FS_NODE_TYPE_ROOT)
240241
{
241242
if(task->process->environment.workingDirectory)
242243
{
243244
heapFree(task->process->environment.workingDirectory);
244245
}
245246

246-
int length = filesystemGetAbsolutePathLength(findRes.file);
247+
int length = filesystemGetAbsolutePathLength(findRes.node);
247248
task->process->environment.workingDirectory = (char*) heapAllocate(length + 1);
248-
filesystemGetAbsolutePath(findRes.file, task->process->environment.workingDirectory);
249+
filesystemGetAbsolutePath(findRes.node, task->process->environment.workingDirectory);
249250
data->result = G_SET_WORKING_DIRECTORY_SUCCESSFUL;
250251
}
251252
else

kernel/src/kernel/filesystem/filesystem.cpp

Lines changed: 105 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ static g_mutex filesystemNextNodeIdLock;
4141

4242
static g_hashmap<g_fs_virt_id, g_fs_node*>* filesystemNodes;
4343

44+
g_fs_open_status _filesystemChooseOrigin(const char* path, g_task* task, g_fs_node*& origin);
45+
4446
void filesystemInitialize()
4547
{
4648
mutexInitializeTask(&filesystemNextNodeIdLock, __func__);
@@ -269,50 +271,37 @@ g_filesystem_find_result filesystemFind(g_fs_node* parent, const char* path)
269271

270272
return {
271273
status: status,
272-
file: node,
274+
node: node,
273275
foundAllButLast: ((nameEnd - nameStart) > 0),
274-
lastFoundNode: lastFoundParent,
276+
lastFoundParent: lastFoundParent,
275277
fileNameStart: nameStart
276278
};
277279
}
278280

279281
g_fs_open_status filesystemOpen(const char* path, g_file_flag_mode flags, g_task* task, g_fd* outFd)
280282
{
281-
// Decide for relative path origin
282-
g_fs_node* origin = nullptr;
283-
if(path[0] != '/')
284-
{
285-
const char* cwd = task->process->environment.workingDirectory;
286-
if(cwd == nullptr)
287-
cwd = "/";
288-
289-
auto findCwdRes = filesystemFind(0, cwd);
290-
if(findCwdRes.status == G_FS_OPEN_SUCCESSFUL)
291-
origin = findCwdRes.file;
292-
else
293-
return findCwdRes.status;
294-
}
295-
296-
if(!origin)
297-
origin = filesystemGetRoot();
283+
g_fs_node* origin;
284+
g_fs_open_status findOriginStatus = _filesystemChooseOrigin(path, task, origin);
285+
if(findOriginStatus != G_FS_OPEN_SUCCESSFUL)
286+
return findOriginStatus;
298287

299288
// Try to find existing node
300289
auto findRes = filesystemFind(origin, path);
301290

302291
// Handle different open cases
303292
if(findRes.status == G_FS_OPEN_SUCCESSFUL)
304293
{
305-
if(findRes.file->type == G_FS_NODE_TYPE_FOLDER)
294+
if(findRes.node->type == G_FS_NODE_TYPE_FOLDER)
306295
{
307296
logInfo("%! tried to open folder", "fs");
308297
return G_FS_OPEN_ERROR;
309298
}
310299

311300
if(flags & G_FILE_FLAG_MODE_TRUNCATE)
312301
{
313-
if(filesystemTruncate(findRes.file) != G_FS_OPEN_SUCCESSFUL)
302+
if(filesystemTruncate(findRes.node) != G_FS_OPEN_SUCCESSFUL)
314303
{
315-
logInfo("%! failed to truncate file %i", "fs", findRes.file->id);
304+
logInfo("%! failed to truncate file %i", "fs", findRes.node->id);
316305
return G_FS_OPEN_ERROR;
317306
}
318307
}
@@ -327,7 +316,7 @@ g_fs_open_status filesystemOpen(const char* path, g_file_flag_mode flags, g_task
327316
origin->id);
328317
return G_FS_OPEN_ERROR;
329318
}
330-
else if(filesystemCreateFile(findRes.lastFoundNode, findRes.fileNameStart, &findRes.file) !=
319+
else if(filesystemCreateFile(findRes.lastFoundParent, findRes.fileNameStart, &findRes.node) !=
331320
G_FS_OPEN_SUCCESSFUL)
332321
{
333322
logInfo("%! failed to create file '%s' in parent %i", "fs", path, origin->id);
@@ -345,7 +334,7 @@ g_fs_open_status filesystemOpen(const char* path, g_file_flag_mode flags, g_task
345334
}
346335

347336
// Actually open the file
348-
return filesystemOpenNodeFd(findRes.file, flags, task->process->id, outFd);
337+
return filesystemOpenNodeFd(findRes.node, flags, task->process->id, outFd);
349338
}
350339

351340
g_fs_open_status filesystemOpenNode(g_fs_node* file, g_file_flag_mode flags, g_pid process,
@@ -809,3 +798,95 @@ bool filesystemGetFileName(g_fd fd, const char** outName)
809798
*outName = node->name;
810799
return true;
811800
}
801+
802+
g_fs_real_path_status filesystemRealPath(g_task* task, const char* in, char* out)
803+
{
804+
g_fs_node* origin;
805+
auto findOriginStatus = _filesystemChooseOrigin(in, task, origin);
806+
if(findOriginStatus != G_FS_OPEN_SUCCESSFUL)
807+
return findOriginStatus;
808+
809+
auto findResult = filesystemFind(origin, in);
810+
if(findResult.status == G_FS_OPEN_NOT_FOUND)
811+
return G_FS_REAL_PATH_NOT_FOUND;
812+
if(findResult.status != G_FS_OPEN_SUCCESSFUL)
813+
return G_FS_REAL_PATH_ERROR;
814+
815+
filesystemGetAbsolutePath(findResult.node, out);
816+
return G_FS_REAL_PATH_SUCCESS;
817+
}
818+
819+
820+
g_fs_open_status _filesystemChooseOrigin(const char* path, g_task* task, g_fs_node*& origin)
821+
{
822+
if(path[0] == '/')
823+
{
824+
origin = filesystemGetRoot();
825+
}
826+
else
827+
{
828+
const char* cwd = task->process->environment.workingDirectory;
829+
if(cwd == nullptr)
830+
cwd = "/";
831+
832+
origin = nullptr;
833+
auto findCwdRes = filesystemFind(nullptr, cwd);
834+
if(findCwdRes.status == G_FS_OPEN_SUCCESSFUL)
835+
origin = findCwdRes.node;
836+
else
837+
return findCwdRes.status;
838+
}
839+
840+
return G_FS_OPEN_SUCCESSFUL;
841+
}
842+
843+
g_fs_stat_status filesystemStat(g_task* task, const char* path, g_fs_stat_data* out)
844+
{
845+
846+
g_fs_node* origin;
847+
g_fs_open_status findOriginStatus = _filesystemChooseOrigin(path, task, origin);
848+
if(findOriginStatus != G_FS_OPEN_SUCCESSFUL)
849+
return findOriginStatus;
850+
851+
auto findRes = filesystemFind(origin, path);
852+
if(findRes.status == G_FS_OPEN_NOT_FOUND)
853+
return G_FS_STAT_NOT_FOUND;
854+
if(findRes.status != G_FS_OPEN_SUCCESSFUL)
855+
return G_FS_STAT_ERROR;
856+
857+
return filesystemStatNode(findRes.node, out);
858+
}
859+
860+
g_fs_stat_status filesystemFstat(g_task* task, g_fd fd, g_fs_stat_data* out)
861+
{
862+
g_file_descriptor* descriptor = filesystemProcessGetDescriptor(task->process->id, fd);
863+
if(!descriptor)
864+
return G_FS_STAT_INVALID_FD;
865+
866+
g_fs_node* node = filesystemGetNode(descriptor->nodeId);
867+
if(!node)
868+
return G_FS_STAT_INVALID_FD;
869+
870+
return filesystemStatNode(node, out);
871+
}
872+
873+
g_fs_stat_status filesystemStatNode(g_fs_node* node, g_fs_stat_data* out)
874+
{
875+
out->virtual_id = node->id;
876+
out->type = node->type;
877+
878+
auto lengthStatus = filesystemGetLength(node, &out->size);
879+
if(lengthStatus != G_FS_LENGTH_SUCCESSFUL)
880+
{
881+
logInfo("%! failed to stat file %i with get-length error %i", "filesystem", node->id, lengthStatus);
882+
out->size = -1;
883+
}
884+
885+
// TODO
886+
out->device = -1;
887+
out->time_last_access = 0;
888+
out->time_last_modification = 0;
889+
out->time_creation = 0;
890+
891+
return G_FS_STAT_SUCCESS;
892+
}

kernel/src/kernel/filesystem/filesystem.hpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ struct g_fs_delegate
9090
struct g_filesystem_find_result
9191
{
9292
g_fs_open_status status;
93-
g_fs_node* file;
93+
g_fs_node* node;
9494

9595
bool foundAllButLast;
96-
g_fs_node* lastFoundNode;
96+
g_fs_node* lastFoundParent;
9797
const char* fileNameStart;
9898
};
9999

@@ -248,4 +248,16 @@ g_fs_read_directory_status filesystemReadDirectory(g_fs_node* parent, uint32_t i
248248
*/
249249
bool filesystemReadToMemory(g_fd fd, size_t offset, uint8_t* buffer, uint64_t len);
250250

251+
/**
252+
* Attempts to retrieve the real path of a path in the filesystem.
253+
*/
254+
g_fs_real_path_status filesystemRealPath(g_task* task, const char* in, char* out);
255+
256+
/**
257+
* Retrieves stats of a path, file descriptor or node.
258+
*/
259+
g_fs_stat_status filesystemStat(g_task* task, const char* path, g_fs_stat_data* out);
260+
g_fs_stat_status filesystemFstat(g_task* task, g_fd fd, g_fs_stat_data* out);
261+
g_fs_stat_status filesystemStatNode(g_fs_node* node, g_fs_stat_data* out);
262+
251263
#endif

kernel/src/kernel/tasking/elf/elf_object.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ g_fd elfObjectOpenDependency(const char* name)
509509
}
510510

511511
g_fd fd;
512-
g_fs_open_status openStatus = filesystemOpenNodeFd(findRes.file, G_FILE_FLAG_MODE_BINARY | G_FILE_FLAG_MODE_READ, taskingGetCurrentTask()->process->id, &fd);
512+
g_fs_open_status openStatus = filesystemOpenNodeFd(findRes.node, G_FILE_FLAG_MODE_BINARY | G_FILE_FLAG_MODE_READ, taskingGetCurrentTask()->process->id, &fd);
513513
if(openStatus != G_FS_OPEN_SUCCESSFUL)
514514
{
515515
logInfo("%! unable to open dependency %s", "elf", absolutePath);

libapi/inc/ghost/filesystem.h

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
#include "common.h"
2525
#include "filesystem/types.h"
26-
#include "tasks.h"
2726
#include "memory.h"
2827

2928
__BEGIN_C
@@ -312,6 +311,41 @@ g_fd g_clone_fd_ts(g_fd source_fd, g_pid source_process, g_fd target_fd, g_pid t
312311
*/
313312
g_open_irq_device_status g_open_irq_device(uint8_t irq, g_fd* outFd);
314313

314+
/**
315+
* Resolves the path and returns the real path.
316+
*
317+
* @param in the input path
318+
* @param out pointer to a buffer where the real path is written
319+
* @return operation status
320+
*
321+
* @security-level APPLICATION
322+
*/
323+
g_fs_real_path_status g_real_path(const char* in, char* out);
324+
325+
/**
326+
* Retrieve stats of a node.
327+
*
328+
* @param path input path
329+
* @param out structure for the stat data
330+
* @param-opt follow_symlinks whether to follow symbolic links
331+
* @return whether the operation was successful
332+
*
333+
* @security-level APPLICATION
334+
*/
335+
g_fs_stat_status g_fs_stat(const char* path, g_fs_stat_data* out);
336+
g_fs_stat_status g_fs_stat_l(const char* path, g_fs_stat_data* out, g_bool follow_symlinks);
337+
338+
/**
339+
* Retrieve stats of a node behind a file descriptor.
340+
*
341+
* @param fd file descriptor
342+
* @param out structure for the stat data
343+
* @return whether the operation was successful
344+
*
345+
* @security-level APPLICATION
346+
*/
347+
g_fs_stat_status g_fs_fstat(g_fd fd, g_fs_stat_data* out);
348+
315349
__END_C
316350

317351
#endif

0 commit comments

Comments
 (0)