ソースを参照

Kernel: Begin fleshing out bind() syscall.

Andreas Kling 6 年 前
コミット
77177dbb76

+ 28 - 0
Kernel/LocalSocket.cpp

@@ -1,6 +1,8 @@
 #include <Kernel/LocalSocket.h>
 #include <Kernel/UnixTypes.h>
 #include <Kernel/Process.h>
+#include <Kernel/VirtualFileSystem.h>
+#include <LibC/errno_numbers.h>
 
 RetainPtr<LocalSocket> LocalSocket::create(int type)
 {
@@ -17,3 +19,29 @@ LocalSocket::~LocalSocket()
 {
 }
 
+bool LocalSocket::bind(const sockaddr* address, socklen_t address_size, int& error)
+{
+    if (address_size != sizeof(sockaddr_un)) {
+        error = -EINVAL;
+        return false;
+    }
+
+    if (address->sa_family != AF_LOCAL) {
+        error = -EINVAL;
+        return false;
+    }
+
+    const sockaddr_un& local_address = *reinterpret_cast<const sockaddr_un*>(address);
+    char safe_address[sizeof(local_address.sun_path) + 1];
+    memcpy(safe_address, local_address.sun_path, sizeof(local_address.sun_path));
+
+    kprintf("%s(%u) LocalSocket{%p} bind(%s)\n", current->name().characters(), current->pid(), safe_address);
+
+    auto descriptor = VFS::the().open(safe_address, error, O_CREAT | O_EXCL, S_IFSOCK | 0666, *current->cwd_inode());
+    if (!descriptor) {
+        if (error == -EEXIST)
+            error = -EADDRINUSE;
+        return error;
+    }
+    return true;
+}

+ 2 - 0
Kernel/LocalSocket.h

@@ -8,6 +8,8 @@ public:
     static RetainPtr<LocalSocket> create(int type);
     virtual ~LocalSocket() override;
 
+    virtual bool bind(const sockaddr*, socklen_t, int& error) override;
+
 private:
     explicit LocalSocket(int type);
 

+ 13 - 2
Kernel/Process.cpp

@@ -2262,9 +2262,20 @@ int Process::sys$socket(int domain, int type, int protocol)
     return fd;
 }
 
-int Process::sys$bind(int sockfd, const sockaddr* addr, socklen_t)
+int Process::sys$bind(int sockfd, const sockaddr* address, socklen_t address_length)
 {
-    return -ENOTIMPL;
+    if (!validate_read(address, address_length))
+        return -EFAULT;
+    auto* descriptor = file_descriptor(sockfd);
+    if (!descriptor)
+        return -EBADF;
+    if (!descriptor->is_socket())
+        return -ENOTSOCK;
+    auto& socket = *descriptor->socket();
+    int error;
+    if (!socket.bind(address, address_length, error))
+        return error;
+    return 0;
 }
 
 int Process::sys$listen(int sockfd, int backlog)

+ 3 - 0
Kernel/Socket.h

@@ -2,6 +2,7 @@
 
 #include <AK/Retainable.h>
 #include <AK/RetainPtr.h>
+#include <Kernel/UnixTypes.h>
 
 class Socket : public Retainable<Socket> {
 public:
@@ -12,6 +13,8 @@ public:
     int type() const { return m_type; }
     int protocol() const { return m_protocol; }
 
+    virtual bool bind(const sockaddr*, socklen_t, int& error) = 0;
+
 protected:
     Socket(int domain, int type, int protocol);
 

+ 1 - 0
Kernel/UnixTypes.h

@@ -314,6 +314,7 @@ struct sockaddr {
     char sa_data[14];
 };
 
+#define	S_IFSOCK 0140000
 #define UNIX_PATH_MAX 108
 
 struct sockaddr_un {

+ 8 - 3
Kernel/VirtualFileSystem.cpp

@@ -134,11 +134,16 @@ RetainPtr<FileDescriptor> VFS::open(const String& path, int& error, int options,
 {
     auto inode_id = resolve_path(path, base.identifier(), error, options);
     auto inode = get_inode(inode_id);
-    if (!inode) {
-        if (options & O_CREAT)
+    if (options & O_CREAT) {
+        if (!inode)
             return create(path, error, options, mode, base);
-        return nullptr;
+        else if (options & O_EXCL) {
+            error = -EEXIST;
+            return nullptr;
+        }
     }
+    if (!inode)
+        return nullptr;
     auto metadata = inode->metadata();
     if (!(options & O_DONT_OPEN_DEVICE) && metadata.is_character_device()) {
         auto it = m_character_devices.find(encoded_device(metadata.major_device, metadata.minor_device));

+ 2 - 0
LibC/errno_numbers.h

@@ -42,6 +42,8 @@
     __ERROR(ENOSYS,         "No such syscall") \
     __ERROR(ENOTIMPL,       "Not implemented") \
     __ERROR(EAFNOSUPPORT,   "Address family not supported") \
+    __ERROR(ENOTSOCK,       "Not a socket") \
+    __ERROR(EADDRINUSE,     "Address in use") \
     __ERROR(EWHYTHO,        "Failed without setting an error code (Bug!)") \
     __ERROR(EBADWINDOW,     "Bad window ID") \
     __ERROR(EBADBACKING,    "Bad backing store ID") \