1
0
Fork 0
mirror of https://gitlab.com/sortix/sortix.git synced 2023-02-13 20:55:38 -05:00

Added chdir(2), getcwd(2), which mxsh and ls now uses.

This commit is contained in:
Jonas 'Sortie' Termansen 2011-11-21 12:19:57 +01:00
parent 819c152292
commit d4590cefa1
11 changed files with 182 additions and 22 deletions

View file

@ -78,7 +78,6 @@ __BEGIN_DECLS
#ifndef SORTIX_UNIMPLEMENTED
int access(const char*, int);
unsigned alarm(unsigned);
int chdir(const char*);
int chown(const char*, uid_t, gid_t);
size_t confstr(int, char*, size_t);
char* crypt(const char*, const char*);
@ -100,7 +99,6 @@ int fexecve(int, char* const [], char* const []);
long fpathconf(int, int);
int fsync(int);
int ftruncate(int, off_t);
char* getcwd(char*, size_t);
gid_t getegid(void);
uid_t geteuid(void);
gid_t getgid(void);
@ -157,10 +155,12 @@ extern char* optarg;
extern int opterr, optind, optopt;
#endif
int chdir(const char*);
int close(int);
int dup(int);
void _exit(int);
pid_t fork(void);
char* getcwd(char*, size_t);
pid_t getpid(void);
pid_t getppid(void);
int pipe(int [2]);

View file

@ -55,6 +55,8 @@ namespace Maxsi
const int EROFS = 20;
const int EINVAL = 21;
const int ENOTDIR = 22;
const int ENOMEM = 23;
const int ERANGE = 24;
extern int _errornumber;

View file

@ -38,6 +38,8 @@ namespace Maxsi
DEFN_SYSCALL1(int, SysDup, 22, int);
DEFN_SYSCALL3(int, SysOpen, 23, const char*, int, mode_t);
DEFN_SYSCALL3(int, SysReadDirEnts, 24, int, struct sortix_dirent*, size_t);
DEFN_SYSCALL1(int, SysChDir, 25, const char*);
DEFN_SYSCALL2(char*, SysGetCWD, 26, char*, size_t);
size_t Print(const char* Message)
{
@ -102,6 +104,16 @@ namespace Maxsi
{
return SysReadDirEnts(fd, dirent, size);
}
extern "C" int chdir(const char* path)
{
return SysChDir(path);
}
extern "C" char* getcwd(char* buf, size_t size)
{
return SysGetCWD(buf, size);
}
#endif
}

View file

@ -30,6 +30,8 @@
#include "process.h"
#include "device.h"
#include "directory.h"
#include "filesystem.h"
#include "mount.h"
using namespace Maxsi;
@ -84,9 +86,127 @@ namespace Sortix
}
}
int SysChDir(const char* path)
{
// Calculate the absolute new path.
Process* process = CurrentProcess();
const char* wd = process->workingdir;
char* abs = MakeAbsolute(wd, path);
if ( !abs ) { Error::Set(Error::ENOMEM); return -1; }
size_t abslen = String::Length(abs);
if ( 1 < abslen && abs[abslen-1] == '/' )
{
abs[abslen-1] = '\0';
}
// Lookup the path and see if it is a directory.
size_t pathoffset = 0;
DevFileSystem* fs = Mount::WhichFileSystem(abs, &pathoffset);
if ( !fs ) { delete[] abs; Error::Set(Error::EINVAL); return -1; }
Device* dev = fs->Open(abs + pathoffset, O_SEARCH | O_DIRECTORY, 0);
if ( !dev ) { Error::Set(Error::ENOTDIR); return -1; }
dev->Unref();
// Alright, the path passed.
delete[] process->workingdir; // Works if it was NULL.
process->workingdir = abs;
return 0;
}
char* SysGetCWD(char* buf, size_t size)
{
// Calculate the absolute new path.
Process* process = CurrentProcess();
const char* wd = process->workingdir;
if ( !wd ) { wd = "/"; }
size_t wdsize = String::Length(wd) + 1;
if ( size < wdsize ) { Error::Set(Error::ERANGE); return NULL; }
String::Copy(buf, wd);
return buf;
}
void Init()
{
Syscall::Register(SYSCALL_READDIRENTS, (void*) SysReadDirEnts);
Syscall::Register(SYSCALL_CHDIR, (void*) SysChDir);
Syscall::Register(SYSCALL_GETCWD, (void*) SysGetCWD);
}
// Allocate a byte too much, in case you want to add a trailing slash.
char* MakeAbsolute(const char* wd, const char* rel)
{
// If given no wd, then interpret from the root.
if ( !wd ) { wd = "/"; }
// The resulting size won't ever be larger than this.
size_t wdlen = String::Length(wd);
size_t resultsize = wdlen + String::Length(rel) + 2;
char* result = new char[resultsize + 1];
if ( !result ) { return NULL; }
// Detect if rel is relative to / or to wd, and then continue the
// interpretation from that point.
size_t offset;
if ( *rel == '/' ) { result[0] = '/'; offset = 1; rel++; }
else { String::Copy(result, wd); offset = wdlen; }
// Make sure the working directory ends with a slash.
if ( result[offset-1] != '/' ) { result[offset++] = '/'; }
bool leadingdots = true;
size_t dots = 0;
int c = 1;
while ( c ) // Exit after handling \0
{
c = *rel++;
// Don't insert double //'s into the final path.
if ( c == '/' && result[offset-1] == '/' ) { continue; }
// / or \0 means that we should interpret . and ..
if ( c == '/' || c == '\0' )
{
// If ., just remove the dot and ignore the slash.
if ( leadingdots && dots == 1 )
{
result[--offset] = '\0';
dots = 0;
continue;
}
// If .., remove .. and one element of the path.
if ( leadingdots && dots == 2 )
{
offset -= 2; // Remove ..
offset -= 1; // Remove the trailing slash
while ( offset )
{
if ( result[--offset] == '/' ) { break; }
}
result[offset++] = '/'; // Need to re-insert a slash.
result[offset] = '\0';
dots = 0;
continue;
}
// Reset the dot count after a slash.
dots = 0;
}
// The newest path element consisted solely of dots.
leadingdots = ( c == '/' || c == '.' );
// Count the number of leading dots in the path element.
if ( c == '.' && leadingdots ) { dots++; }
// Insert the character into the result.
result[offset++] = c;
}
// TODO: To avoid wasting space, should we String::Clone(result)?
return result;
}
}
}

View file

@ -57,6 +57,7 @@ namespace Sortix
namespace Directory
{
void Init();
char* MakeAbsolute(const char* wd, const char* rel);
}
}

View file

@ -23,11 +23,13 @@
******************************************************************************/
#include "platform.h"
#include <libmaxsi/error.h>
#include <libmaxsi/memory.h>
#include <libmaxsi/string.h>
#include "syscall.h"
#include "process.h"
#include "filesystem.h"
#include "directory.h"
#include "mount.h"
using namespace Maxsi;
@ -38,22 +40,16 @@ namespace Sortix
{
Device* Open(const char* path, int flags, mode_t mode)
{
const char* workingdir = "/";
char* fullpath = NULL;
if ( *path != '/' )
{
size_t len = String::Length(workingdir) + String::Length(path);
fullpath = new char[len+1];
if ( !fullpath ) { return NULL; }
String::Copy(fullpath, workingdir);
String::Cat(fullpath, path);
path = fullpath;
}
Process* process = CurrentProcess();
const char* wd = process->workingdir;
char* abs = Directory::MakeAbsolute(wd, path);
if ( !abs ) { Error::Set(Error::ENOMEM); return NULL; }
size_t pathoffset = 0;
DevFileSystem* fs = Mount::WhichFileSystem(path, &pathoffset);
if ( !fs ) { delete[] fullpath; return NULL; }
Device* result = fs->Open(path + pathoffset, flags, mode);
delete[] fullpath;
DevFileSystem* fs = Mount::WhichFileSystem(abs, &pathoffset);
if ( !fs ) { delete[] abs; return NULL; }
Device* result = fs->Open(abs + pathoffset, flags, mode);
delete[] abs;
return result;
}

View file

@ -96,6 +96,7 @@ namespace Sortix
firstchild = NULL;
zombiechild = NULL;
firstthread = NULL;
workingdir = NULL;
mmapfrom = 0x80000000UL;
exitstatus = -1;
pid = AllocatePID();
@ -110,6 +111,8 @@ namespace Sortix
// Avoid memory leaks.
ASSERT(segments == NULL);
delete[] workingdir;
// TODO: Delete address space!
}
@ -193,6 +196,8 @@ namespace Sortix
// Copy variables.
clone->mmapfrom = mmapfrom;
if ( workingdir ) { clone->workingdir = String::Clone(workingdir); }
else { clone->workingdir = NULL; }
// Now that the cloned process is fully created, we need to signal to
// its threads that they should insert themselves into the scheduler.

View file

@ -67,8 +67,7 @@ namespace Sortix
public:
addr_t addrspace;
int exitstatus;
public:
char* workingdir;
pid_t pid;
public:

View file

@ -50,7 +50,9 @@
#define SYSCALL_DUP 22
#define SYSCALL_OPEN 23
#define SYSCALL_READDIRENTS 24
#define SYSCALL_MAX_NUM 25 /* index of highest constant + 1 */
#define SYSCALL_CHDIR 25
#define SYSCALL_GETCWD 26
#define SYSCALL_MAX_NUM 27 /* index of highest constant + 1 */
#endif

View file

@ -1,6 +1,7 @@
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/readdirents.h>
#include <libmaxsi/platform.h>
#include <libmaxsi/process.h>
@ -37,7 +38,11 @@ int ls(const char* path)
int main(int argc, char* argv[])
{
const char* path = "/";
const size_t CWD_SIZE = 512;
char cwd[CWD_SIZE];
const char* path = getcwd(cwd, CWD_SIZE);
if ( !path ) { path = "."; }
if ( 1 < argc ) { path = argv[1]; }
return ls(path);

View file

@ -14,7 +14,12 @@ int status = 0;
void command()
{
printf("root@sortix / # ");
const size_t CWD_SIZE = 512;
char cwd[CWD_SIZE];
const char* wd = getcwd(cwd, CWD_SIZE);
if ( !wd ) { wd = "?"; }
printf("root@sortix %s # ", wd);
const size_t commandsize = 128;
char command[commandsize + 1];
@ -81,6 +86,19 @@ void command()
exit(atoi(status));
}
if ( strcmp(argv[0], "cd") == 0 )
{
status = 0;
const char* newdir = "/";
if ( 1 < argc ) { newdir = argv[1]; }
if ( chdir(newdir) )
{
printf("cd: %s: cannot change directory\n", newdir);
status = 1;
}
return;
}
pid_t child = fork();
if ( child < 0 ) { printf("fork failed\n"); return; }
if ( child != 0 )