Kaynağa Gözat

Kernel: Add Inode::truncate(size).

- Use this to implement the O_TRUNC open flag.
- Fix creat() to pass O_CREAT | O_TRUNC | O_WRONLY.
- Make sure we truncate wherever appropriate.
Andreas Kling 6 yıl önce
ebeveyn
işleme
0058da734e

+ 10 - 0
Kernel/Ext2FileSystem.cpp

@@ -1391,6 +1391,16 @@ KResult Ext2FSInode::chown(uid_t uid, gid_t gid)
     return KSuccess;
 }
 
+KResult Ext2FSInode::truncate(int size)
+{
+    LOCKER(m_lock);
+    if (m_raw_inode.i_size == size)
+        return KSuccess;
+    m_raw_inode.i_size = size;
+    set_metadata_dirty(true);
+    return KSuccess;
+}
+
 unsigned Ext2FS::total_block_count() const
 {
     LOCKER(m_lock);

+ 1 - 0
Kernel/Ext2FileSystem.h

@@ -42,6 +42,7 @@ private:
     virtual size_t directory_entry_count() const override;
     virtual KResult chmod(mode_t) override;
     virtual KResult chown(uid_t, gid_t) override;
+    virtual KResult truncate(int) override;
 
     void populate_lookup_cache() const;
 

+ 1 - 0
Kernel/FileSystem.h

@@ -103,6 +103,7 @@ public:
     virtual size_t directory_entry_count() const = 0;
     virtual KResult chmod(mode_t) = 0;
     virtual KResult chown(uid_t, gid_t) = 0;
+    virtual KResult truncate(int) { return KSuccess; }
 
     LocalSocket* socket() { return m_socket.ptr(); }
     const LocalSocket* socket() const { return m_socket.ptr(); }

+ 9 - 3
Kernel/VirtualFileSystem.cpp

@@ -170,7 +170,10 @@ KResultOr<Retained<FileDescriptor>> VFS::open(const String& path, int options, m
     if (inode_or_error.is_error())
         return inode_or_error.error();
 
-    auto metadata = inode_or_error.value()->metadata();
+    auto inode = inode_or_error.value();
+    auto metadata = inode->metadata();
+
+    bool should_truncate_file = false;
 
     // NOTE: Read permission is a bit weird, since O_RDONLY == 0,
     //       so we check if (NOT write_only OR read_and_write)
@@ -183,6 +186,7 @@ KResultOr<Retained<FileDescriptor>> VFS::open(const String& path, int options, m
             return KResult(-EACCES);
         if (metadata.is_directory())
             return KResult(-EISDIR);
+        should_truncate_file = options & O_TRUNC;
     }
 
     if (metadata.is_device()) {
@@ -193,10 +197,12 @@ KResultOr<Retained<FileDescriptor>> VFS::open(const String& path, int options, m
         auto descriptor_or_error = (*it).value->open(options);
         if (descriptor_or_error.is_error())
             return descriptor_or_error.error();
-        descriptor_or_error.value()->set_original_inode(Badge<VFS>(), *inode_or_error.value());
+        descriptor_or_error.value()->set_original_inode(Badge<VFS>(), *inode);
         return descriptor_or_error;
     }
-    return FileDescriptor::create(*inode_or_error.value());
+    if (should_truncate_file)
+        inode->truncate(0);
+    return FileDescriptor::create(*inode);
 }
 
 KResultOr<Retained<FileDescriptor>> VFS::create(const String& path, int options, mode_t mode, Inode& base)

+ 1 - 1
LibC/unistd.cpp

@@ -146,7 +146,7 @@ pid_t getpgrp()
 
 int creat(const char* path, mode_t mode)
 {
-    return open(path, O_CREAT, mode);
+    return open(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
 }
 
 int open(const char* path, int options, ...)

+ 1 - 1
LibGUI/GTextEditor.cpp

@@ -645,7 +645,7 @@ void GTextEditor::Line::truncate(int length)
 
 bool GTextEditor::write_to_file(const String& path)
 {
-    int fd = open(path.characters(), O_WRONLY | O_CREAT, 0666);
+    int fd = open(path.characters(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
     if (fd < 0) {
         perror("open");
         return false;

+ 1 - 1
SharedGraphics/Font.cpp

@@ -143,7 +143,7 @@ RetainPtr<Font> Font::load_from_file(const String& path)
 
 bool Font::write_to_file(const String& path)
 {
-    int fd = open(path.characters(), O_WRONLY | O_CREAT, 0644);
+    int fd = creat(path.characters(), 0644);
     if (fd < 0) {
         perror("open");
         return false;

+ 2 - 2
Userland/cp.cpp

@@ -34,7 +34,7 @@ int main(int argc, char** argv)
         return 1;
     }
 
-    int dst_fd = open(dst_path.characters(), O_WRONLY | O_CREAT, 0666);
+    int dst_fd = creat(dst_path.characters(), 0666);
     if (dst_fd < 0) {
         if (errno != EISDIR) {
             perror("open dst");
@@ -45,7 +45,7 @@ int main(int argc, char** argv)
         builder.append('/');
         builder.append(FileSystemPath(src_path).basename());
         dst_path = builder.to_string();
-        dst_fd = open(dst_path.characters(), O_WRONLY | O_CREAT, 0666);
+        dst_fd = creat(dst_path.characters(), 0666);
         if (dst_fd < 0) {
             perror("open dst");
             return 1;