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:
parent
819c152292
commit
d4590cefa1
11 changed files with 182 additions and 22 deletions
|
@ -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]);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ namespace Sortix
|
|||
namespace Directory
|
||||
{
|
||||
void Init();
|
||||
char* MakeAbsolute(const char* wd, const char* rel);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -67,8 +67,7 @@ namespace Sortix
|
|||
public:
|
||||
addr_t addrspace;
|
||||
int exitstatus;
|
||||
|
||||
public:
|
||||
char* workingdir;
|
||||
pid_t pid;
|
||||
|
||||
public:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 )
|
||||
|
|
Loading…
Reference in a new issue