summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Applications/ProcessManager/ProcessTableModel.cpp17
-rw-r--r--LibGUI/GFile.cpp56
-rw-r--r--LibGUI/GFile.h22
-rw-r--r--LibGUI/GIODevice.cpp89
-rw-r--r--LibGUI/GIODevice.h53
-rw-r--r--LibGUI/Makefile2
6 files changed, 230 insertions, 9 deletions
diff --git a/Applications/ProcessManager/ProcessTableModel.cpp b/Applications/ProcessManager/ProcessTableModel.cpp
index df9320b7b3..58277b5dd0 100644
--- a/Applications/ProcessManager/ProcessTableModel.cpp
+++ b/Applications/ProcessManager/ProcessTableModel.cpp
@@ -1,4 +1,5 @@
#include "ProcessTableModel.h"
+#include <LibGUI/GFile.h>
#include <fcntl.h>
#include <stdio.h>
#include <pwd.h>
@@ -121,10 +122,11 @@ GVariant ProcessTableModel::data(const GModelIndex& index, Role role) const
void ProcessTableModel::update()
{
- FILE* fp = fopen("/proc/all", "r");
- if (!fp) {
- perror("failed to open /proc/all");
+ GFile file("/proc/all");
+ if (!file.open(GIODevice::ReadOnly)) {
+ fprintf(stderr, "ProcessManager: Failed to open /proc/all: %s\n", file.error_string());
exit(1);
+ return;
}
unsigned last_sum_nsched = 0;
@@ -134,11 +136,10 @@ void ProcessTableModel::update()
HashTable<pid_t> live_pids;
unsigned sum_nsched = 0;
for (;;) {
- char buf[BUFSIZ];
- char* ptr = fgets(buf, sizeof(buf), fp);
- if (!ptr)
+ auto line = file.read_line(1024);
+ if (line.is_empty())
break;
- auto parts = String(buf, Chomp).split(',');
+ auto parts = String((const char*)line.pointer(), line.size() - 1, Chomp).split(',');
if (parts.size() < 17)
break;
bool ok;
@@ -178,8 +179,6 @@ void ProcessTableModel::update()
live_pids.set(pid);
}
- int rc = fclose(fp);
- ASSERT(rc == 0);
m_pids.clear();
Vector<pid_t> pids_to_remove;
diff --git a/LibGUI/GFile.cpp b/LibGUI/GFile.cpp
new file mode 100644
index 0000000000..45b083191c
--- /dev/null
+++ b/LibGUI/GFile.cpp
@@ -0,0 +1,56 @@
+#include <LibGUI/GFile.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+GFile::GFile(const String& filename)
+ : m_filename(filename)
+{
+}
+
+GFile::~GFile()
+{
+ if (mode() != NotOpen)
+ close();
+}
+
+bool GFile::open(GIODevice::OpenMode mode)
+{
+ int flags = 0;
+ if ((mode & GIODevice::ReadWrite) == GIODevice::ReadWrite) {
+ flags |= O_RDWR | O_CREAT;
+ } else if (mode & GIODevice::ReadOnly) {
+ flags |= O_RDONLY;
+ } else if (mode & GIODevice::WriteOnly) {
+ flags |= O_WRONLY | O_CREAT;
+ }
+ if (mode & GIODevice::Append)
+ flags |= O_APPEND;
+ if (mode & GIODevice::Truncate)
+ flags |= O_TRUNC;
+ if (mode & GIODevice::MustBeNew)
+ flags |= O_EXCL;
+ int fd = ::open(m_filename.characters(), flags, 0666);
+ if (fd < 0) {
+ set_error(errno);
+ return false;
+ }
+
+ set_fd(fd);
+ set_mode(mode);
+ return true;
+}
+
+bool GFile::close()
+{
+ if (fd() < 0 || mode() == NotOpen)
+ return false;
+ int rc = ::close(fd());
+ if (rc < 0) {
+ set_error(rc);
+ return false;
+ }
+ set_fd(-1);
+ set_mode(GIODevice::NotOpen);
+ return true;
+}
diff --git a/LibGUI/GFile.h b/LibGUI/GFile.h
new file mode 100644
index 0000000000..de7325fb93
--- /dev/null
+++ b/LibGUI/GFile.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <LibGUI/GIODevice.h>
+#include <AK/AKString.h>
+
+class GFile final : public GIODevice {
+public:
+ GFile() { }
+ explicit GFile(const String&);
+ virtual ~GFile() override;
+
+ String filename() const { return m_filename; }
+ void set_filename(const String& filename) { m_filename = filename; }
+
+ virtual bool open(GIODevice::OpenMode) override;
+ virtual bool close() override;
+
+ virtual const char* class_name() const override { return "GFile"; }
+
+private:
+ String m_filename;
+};
diff --git a/LibGUI/GIODevice.cpp b/LibGUI/GIODevice.cpp
new file mode 100644
index 0000000000..d62d36622f
--- /dev/null
+++ b/LibGUI/GIODevice.cpp
@@ -0,0 +1,89 @@
+#include <LibGUI/GIODevice.h>
+#include <unistd.h>
+
+GIODevice::GIODevice(GObject* parent)
+ : GObject(parent)
+{
+}
+
+GIODevice::~GIODevice()
+{
+}
+
+const char* GIODevice::error_string() const
+{
+ return strerror(m_error);
+}
+
+ByteBuffer GIODevice::read(int max_size)
+{
+ if (m_fd < 0)
+ return { };
+ if (!max_size)
+ return { };
+ auto buffer = ByteBuffer::create_uninitialized(max_size);
+ auto* buffer_ptr = (char*)buffer.pointer();
+ int remaining_buffer_space = buffer.size();
+ if (!m_buffered_data.is_empty()) {
+ int taken_from_buffered = min(remaining_buffer_space, m_buffered_data.size());
+ memcpy(buffer_ptr, m_buffered_data.data(), taken_from_buffered);
+ Vector<byte> new_buffered_data;
+ new_buffered_data.append(m_buffered_data.data() + taken_from_buffered, m_buffered_data.size() - taken_from_buffered);
+ m_buffered_data = move(new_buffered_data);
+ remaining_buffer_space -= taken_from_buffered;
+ buffer_ptr += taken_from_buffered;
+ }
+ if (!remaining_buffer_space)
+ return buffer;
+ int nread = ::read(m_fd, buffer_ptr, remaining_buffer_space);
+ if (nread < 0) {
+ set_error(errno);
+ return { };
+ }
+ buffer.trim(nread);
+ return buffer;
+}
+
+ByteBuffer GIODevice::read_line(int max_size)
+{
+ if (m_fd < 0)
+ return { };
+ if (!max_size)
+ return { };
+ auto line = ByteBuffer::create_uninitialized(max_size);
+ int line_index = 0;
+ while (line_index < line.size()) {
+ if (line_index >= m_buffered_data.size()) {
+ if (!populate_read_buffer())
+ return { };
+ }
+ byte ch = m_buffered_data[line_index];
+ line[line_index++] = ch;
+ if (ch == '\n') {
+ Vector<byte> new_buffered_data;
+ new_buffered_data.append(m_buffered_data.data() + line_index, m_buffered_data.size() - line_index);
+ m_buffered_data = move(new_buffered_data);
+ line.trim(line_index);
+ return line;
+ }
+ }
+ return { };
+}
+
+bool GIODevice::populate_read_buffer()
+{
+ if (m_fd < 0)
+ return false;
+ auto buffer = ByteBuffer::create_uninitialized(1024);
+ int nread = ::read(m_fd, buffer.pointer(), buffer.size());
+ if (nread < 0) {
+ set_error(errno);
+ return false;
+ }
+ if (nread == 0) {
+ set_eof(true);
+ return false;
+ }
+ m_buffered_data.append(buffer.pointer(), buffer.size());
+ return true;
+}
diff --git a/LibGUI/GIODevice.h b/LibGUI/GIODevice.h
new file mode 100644
index 0000000000..744e1997d0
--- /dev/null
+++ b/LibGUI/GIODevice.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#include <LibGUI/GObject.h>
+#include <AK/ByteBuffer.h>
+
+class GIODevice : public GObject {
+public:
+ enum OpenMode {
+ NotOpen = 0,
+ ReadOnly = 1,
+ WriteOnly = 2,
+ ReadWrite = 3,
+ Append = 4,
+ Truncate = 8,
+ MustBeNew = 16,
+ };
+
+ virtual ~GIODevice() override;
+
+ int fd() const { return m_fd; }
+ unsigned mode() const { return m_mode; }
+ bool eof() const { return m_eof; }
+
+ int error() const { return m_error; }
+ const char* error_string() const;
+
+ bool has_error() const { return m_error != 0; }
+
+ ByteBuffer read(int max_size);
+ ByteBuffer read_line(int max_size);
+
+ virtual bool open(GIODevice::OpenMode) = 0;
+ virtual bool close() = 0;
+
+ virtual const char* class_name() const override { return "GIODevice"; }
+
+protected:
+ explicit GIODevice(GObject* parent = nullptr);
+
+ void set_fd(int fd) { m_fd = fd; }
+ void set_mode(OpenMode mode) { m_mode = mode; }
+ void set_error(int error) { m_error = error; }
+ void set_eof(bool eof) { m_eof = eof; }
+
+private:
+ bool populate_read_buffer();
+
+ int m_fd { -1 };
+ int m_error { 0 };
+ bool m_eof { false };
+ OpenMode m_mode { NotOpen };
+ Vector<byte> m_buffered_data;
+};
diff --git a/LibGUI/Makefile b/LibGUI/Makefile
index 9e1d100c1a..c39478d130 100644
--- a/LibGUI/Makefile
+++ b/LibGUI/Makefile
@@ -7,6 +7,8 @@ SHAREDGRAPHICS_OBJS = \
../SharedGraphics/Color.o
LIBGUI_OBJS = \
+ GIODevice.o \
+ GFile.o \
GButton.o \
GCheckBox.o \
GEventLoop.o \