summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-10-24 13:19:36 +0200
committerAndreas Kling <awesomekling@gmail.com>2018-10-24 13:19:36 +0200
commit5f36a5f22e8bf0e9de9a8059722352d2f8cf9b5f (patch)
treedcb425849c408c6d2adf9f195ee34d23acd8901d
parentbca4b71bfa1e3db74aaa706a9849e36768282a95 (diff)
downloadserenity-5f36a5f22e8bf0e9de9a8059722352d2f8cf9b5f.zip
Add an lstat() syscall and use it to make "ls" nicer.
-rw-r--r--Kernel/Syscall.cpp2
-rw-r--r--Kernel/Syscall.h1
-rw-r--r--Kernel/Task.cpp11
-rw-r--r--Kernel/Task.h1
-rw-r--r--Kernel/VGA.cpp1
-rw-r--r--Kernel/_fs_contentsbin1024000 -> 1024000 bytes
-rw-r--r--LibC/types.h23
-rw-r--r--LibC/unistd.cpp5
-rw-r--r--LibC/unistd.h32
-rw-r--r--Userland/ls.cpp44
10 files changed, 118 insertions, 2 deletions
diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp
index 4be04cbfac..846c1b99ea 100644
--- a/Kernel/Syscall.cpp
+++ b/Kernel/Syscall.cpp
@@ -68,6 +68,8 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3)
return current->sys$spawn((const char*)arg1);
case Syscall::GetDirEntries:
return current->sys$get_dir_entries((int)arg1, (void*)arg2, (size_t)arg3);
+ case Syscall::PosixLstat:
+ return current->sys$lstat((const char*)arg1, (void*)arg2);
case Syscall::PosixOpen:
//kprintf("syscall: open('%s', %u)\n", arg1, arg2);
return current->sys$open((const char*)arg1, (size_t)arg2);
diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h
index 70b3f12983..ff0b8af69e 100644
--- a/Kernel/Syscall.h
+++ b/Kernel/Syscall.h
@@ -27,6 +27,7 @@ enum Function {
PosixMmap = 0x1995,
PosixMunmap = 0x1996,
GetDirEntries = 0x1997,
+ PosixLstat = 0x1998,
};
void initialize();
diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp
index fe185cc154..7005394ee5 100644
--- a/Kernel/Task.cpp
+++ b/Kernel/Task.cpp
@@ -700,13 +700,22 @@ int Task::sys$close(int fd)
return 0;
}
+int Task::sys$lstat(const char* path, void* statbuf)
+{
+ auto handle = VirtualFileSystem::the().open(move(path));
+ if (!handle)
+ return -1;
+ handle->stat((Unix::stat*)statbuf);
+ return 0;
+}
+
int Task::sys$open(const char* path, size_t pathLength)
{
Task::checkSanity("sys$open");
#ifdef DEBUG_IO
kprintf("Task::sys$open(): PID=%u, path=%s {%u}\n", m_pid, path, pathLength);
#endif
- auto* handle = current->openFile(String(path, pathLength));
+ auto* handle = openFile(String(path, pathLength));
if (handle)
return handle->fd();
return -1;
diff --git a/Kernel/Task.h b/Kernel/Task.h
index 8ff28a00ed..c7ca13eeb4 100644
--- a/Kernel/Task.h
+++ b/Kernel/Task.h
@@ -92,6 +92,7 @@ public:
int sys$open(const char* path, size_t pathLength);
int sys$close(int fd);
int sys$read(int fd, void* outbuf, size_t nread);
+ int sys$lstat(const char*, void* statbuf);
int sys$seek(int fd, int offset);
int sys$kill(pid_t pid, int sig);
int sys$geterror() { return m_error; }
diff --git a/Kernel/VGA.cpp b/Kernel/VGA.cpp
index 458a3c967c..59e3c73267 100644
--- a/Kernel/VGA.cpp
+++ b/Kernel/VGA.cpp
@@ -10,6 +10,7 @@ PRIVATE BYTE current_attr = 0x07;
void vga_scroll_up()
{
+ InterruptDisabler disabler;
memcpy(vga_mem, vga_mem + 160, 160 * 24);
memset(vga_mem + (160 * 24), 0, 160);
}
diff --git a/Kernel/_fs_contents b/Kernel/_fs_contents
index 25f45186bf..7aacb359bb 100644
--- a/Kernel/_fs_contents
+++ b/Kernel/_fs_contents
Binary files differ
diff --git a/LibC/types.h b/LibC/types.h
index cedc52280c..d28920f7f2 100644
--- a/LibC/types.h
+++ b/LibC/types.h
@@ -20,5 +20,28 @@ typedef signed_dword ssize_t;
typedef dword ino_t;
typedef signed_dword off_t;
+typedef dword dev_t;
+typedef dword mode_t;
+typedef dword nlink_t;
+typedef dword blksize_t;
+typedef dword blkcnt_t;
+typedef dword time_t;
+
+struct stat {
+ dev_t st_dev; /* ID of device containing file */
+ ino_t st_ino; /* inode number */
+ mode_t st_mode; /* protection */
+ nlink_t st_nlink; /* number of hard links */
+ uid_t st_uid; /* user ID of owner */
+ gid_t st_gid; /* group ID of owner */
+ dev_t st_rdev; /* device ID (if special file) */
+ off_t st_size; /* total size, in bytes */
+ blksize_t st_blksize; /* blocksize for file system I/O */
+ blkcnt_t st_blocks; /* number of 512B blocks allocated */
+ time_t st_atime; /* time of last access */
+ time_t st_mtime; /* time of last modification */
+ time_t st_ctime; /* time of last status change */
+};
+
}
diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp
index 81570ece70..42e3f49c32 100644
--- a/LibC/unistd.cpp
+++ b/LibC/unistd.cpp
@@ -40,5 +40,10 @@ pid_t waitpid(pid_t waitee)
return Syscall::invoke(Syscall::PosixWaitpid, waitee);
}
+int lstat(const char* path, stat* statbuf)
+{
+ return Syscall::invoke(Syscall::PosixLstat, (dword)path, (dword)statbuf);
+}
+
}
diff --git a/LibC/unistd.h b/LibC/unistd.h
index 078a90fe0e..7dcbe0b51f 100644
--- a/LibC/unistd.h
+++ b/LibC/unistd.h
@@ -12,5 +12,37 @@ ssize_t read(int fd, void* buf, size_t count);
int close(int fd);
pid_t waitpid(pid_t);
+int lstat(const char* path, stat* statbuf);
+
+#define S_IFMT 0170000
+#define S_IFDIR 0040000
+#define S_IFCHR 0020000
+#define S_IFBLK 0060000
+#define S_IFREG 0100000
+#define S_IFIFO 0010000
+#define S_IFLNK 0120000
+#define S_IFSOCK 0140000
+
+#define S_ISUID 04000
+#define S_ISGID 02000
+#define S_ISVTX 01000
+#define S_IRUSR 0400
+#define S_IWUSR 0200
+#define S_IXUSR 0100
+#define S_IRGRP 0040
+#define S_IWGRP 0020
+#define S_IXGRP 0010
+#define S_IROTH 0004
+#define S_IWOTH 0002
+#define S_IXOTH 0001
+
+
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+
}
diff --git a/Userland/ls.cpp b/Userland/ls.cpp
index dfaa0d4eb2..eab5de08c6 100644
--- a/Userland/ls.cpp
+++ b/Userland/ls.cpp
@@ -9,9 +9,51 @@ int main(int c, char** v)
printf("opendir failed :(\n");
return 1;
}
+ char pathbuf[256];
while (auto* de = readdir(dirp)) {
- printf("%s\n", de->d_name);
+ sprintf(pathbuf, "/%s", de->d_name);
+ stat st;
+ int rc = lstat(pathbuf, &st);
+ if (rc == -1) {
+ printf("Failed to stat '%s'\n", pathbuf);
+ return 2;
+ }
+ if (S_ISDIR(st.st_mode))
+ printf("d");
+ else if (S_ISLNK(st.st_mode))
+ printf("l");
+ else if (S_ISBLK(st.st_mode))
+ printf("b");
+ else if (S_ISCHR(st.st_mode))
+ printf("c");
+ else if (S_ISFIFO(st.st_mode))
+ printf("f");
+ else if (S_ISREG(st.st_mode))
+ printf("-");
+ else
+ printf("?");
+
+ printf("%c%c%c%c%c%c%c%c",
+ st.st_mode & S_IRUSR ? 'r' : '-',
+ st.st_mode & S_IWUSR ? 'w' : '-',
+ st.st_mode & S_IXUSR ? 'x' : '-',
+ st.st_mode & S_IRGRP ? 'r' : '-',
+ st.st_mode & S_IWGRP ? 'w' : '-',
+ st.st_mode & S_IXGRP ? 'x' : '-',
+ st.st_mode & S_IROTH ? 'r' : '-',
+ st.st_mode & S_IWOTH ? 'w' : '-'
+ );
+
+ if (st.st_mode & S_ISVTX)
+ printf("t");
+ else
+ printf("%c", st.st_mode & S_IXOTH ? 'x' : '-');
+
+ printf(" i:%x ", de->d_ino);
+ printf(" %x ", st.st_size);
+ printf("%s%c", de->d_name, S_ISDIR(st.st_mode) ? '/' : ' ');
+ printf("\n");
}
return 0;
}