<commit_before>#pragma once

#include "cpputil.hh"
#include "ns.hh"
#include "gc.hh"
#include <atomic>
#include "refcache.hh"
#include "condvar.h"
#include "semaphore.h"
#include "seqlock.hh"
#include "mfs.hh"

class dirns;

u64 namehash(const strbuf<DIRSIZ>&);

struct file : public rcu_freed {
  virtual int stat(struct stat*) { return -1; }
  virtual ssize_t read(char *addr, size_t n) { return -1; }
  virtual ssize_t write(const char *addr, size_t n) { return -1; }
  virtual ssize_t pread(char *addr, size_t n, off_t offset) { return -1; }
  virtual ssize_t pwrite(const char *addr, size_t n, off_t offset) { return -1; }

  virtual void inc() = 0;
  virtual void dec() = 0;

protected:
  file() : rcu_freed("file") {}

  void do_gc(void) override { delete this; }
};

struct file_inode : public refcache::referenced, public file {
public:
  file_inode(sref<mnode> i, bool r, bool w, bool a)
    : ip(i), readable(r), writable(w), append(a), off(0) {}
  NEW_DELETE_OPS(file_inode);

  void inc() override { refcache::referenced::inc(); }
  void dec() override { refcache::referenced::dec(); }

  sref<mnode> ip;
  const bool readable;
  const bool writable;
  const bool append;
  u32 off;

  int stat(struct stat*) override;
  ssize_t read(char *addr, size_t n) override;
  ssize_t write(const char *addr, size_t n) override;
  ssize_t pread(char* addr, size_t n, off_t off) override;
  ssize_t pwrite(const char *addr, size_t n, off_t offset) override;
  void onzero() override;
};

struct file_socket : public referenced, public file {
public:
  file_socket() : socket(0), localsock(nullptr),
                  wsem("file::wsem", 1), rsem("file::rsem", 1) {}
  NEW_DELETE_OPS(file_socket);

  void inc() override { referenced::inc(); }
  void dec() override { referenced::dec(); }

  int socket;
  struct localsock *localsock;
  char socketpath[UNIX_PATH_MAX];

  ssize_t read(char *addr, size_t n) override;
  ssize_t write(const char *addr, size_t n) override;
  void onzero() override;

private:
  // XXX This locking should be handled in net, not here.
  semaphore wsem, rsem;
};

struct file_pipe_reader : public refcache::referenced, public file {
public:
  file_pipe_reader(pipe* p) : pipe(p) {}
  NEW_DELETE_OPS(file_pipe_reader);

  void inc() override { refcache::referenced::inc(); }
  void dec() override { refcache::referenced::dec(); }

  ssize_t read(char *addr, size_t n) override;
  void onzero() override;

private:
  struct pipe* const pipe;
};

struct file_pipe_writer : public referenced, public file {
public:
  file_pipe_writer(pipe* p) : pipe(p) {}
  NEW_DELETE_OPS(file_pipe_writer);

  void inc() override { referenced::inc(); }
  void dec() override { referenced::dec(); }

  ssize_t write(const char *addr, size_t n) override;
  void onzero() override;

private:
  struct pipe* const pipe;
};

// in-core file system types
struct inode : public referenced, public rcu_freed
{
  void  init();
  void  link();
  void  unlink();
  short nlink();

  inode& operator=(const inode&) = delete;
  inode(const inode& x) = delete;

  void do_gc() override { delete this; }

  // const for lifetime of object:
  const u32 dev;
  const u32 inum;

  // const unless inode is reused:
  u32 gen;
  std::atomic<short> type;<commit_msg>fix file subclass operator delete<commit_after>#pragma once

#include "cpputil.hh"
#include "ns.hh"
#include "gc.hh"
#include <atomic>
#include "refcache.hh"
#include "condvar.h"
#include "semaphore.h"
#include "seqlock.hh"
#include "mfs.hh"

class dirns;

u64 namehash(const strbuf<DIRSIZ>&);

struct file : public rcu_freed {
  virtual int stat(struct stat*) { return -1; }
  virtual ssize_t read(char *addr, size_t n) { return -1; }
  virtual ssize_t write(const char *addr, size_t n) { return -1; }
  virtual ssize_t pread(char *addr, size_t n, off_t offset) { return -1; }
  virtual ssize_t pwrite(const char *addr, size_t n, off_t offset) { return -1; }

  virtual void inc() = 0;
  virtual void dec() = 0;

protected:
  file() : rcu_freed("file") {}
};

struct file_inode : public refcache::referenced, public file {
public:
  file_inode(sref<mnode> i, bool r, bool w, bool a)
    : ip(i), readable(r), writable(w), append(a), off(0) {}
  NEW_DELETE_OPS(file_inode);

  void inc() override { refcache::referenced::inc(); }
  void dec() override { refcache::referenced::dec(); }

  sref<mnode> ip;
  const bool readable;
  const bool writable;
  const bool append;
  u32 off;

  int stat(struct stat*) override;
  ssize_t read(char *addr, size_t n) override;
  ssize_t write(const char *addr, size_t n) override;
  ssize_t pread(char* addr, size_t n, off_t off) override;
  ssize_t pwrite(const char *addr, size_t n, off_t offset) override;
  void onzero() override;

protected:
  void do_gc(void) override { delete this; }
};

struct file_socket : public referenced, public file {
public:
  file_socket() : socket(0), localsock(nullptr),
                  wsem("file::wsem", 1), rsem("file::rsem", 1) {}
  NEW_DELETE_OPS(file_socket);

  void inc() override { referenced::inc(); }
  void dec() override { referenced::dec(); }

  int socket;
  struct localsock *localsock;
  char socketpath[UNIX_PATH_MAX];

  ssize_t read(char *addr, size_t n) override;
  ssize_t write(const char *addr, size_t n) override;
  void onzero() override;

protected:
  void do_gc(void) override { delete this; }

private:
  // XXX This locking should be handled in net, not here.
  semaphore wsem, rsem;
};

struct file_pipe_reader : public refcache::referenced, public file {
public:
  file_pipe_reader(pipe* p) : pipe(p) {}
  NEW_DELETE_OPS(file_pipe_reader);

  void inc() override { refcache::referenced::inc(); }
  void dec() override { refcache::referenced::dec(); }

  ssize_t read(char *addr, size_t n) override;
  void onzero() override;

protected:
  void do_gc(void) override { delete this; }

private:
  struct pipe* const pipe;
};

struct file_pipe_writer : public referenced, public file {
public:
  file_pipe_writer(pipe* p) : pipe(p) {}
  NEW_DELETE_OPS(file_pipe_writer);

  void inc() override { referenced::inc(); }
  void dec() override { referenced::dec(); }

  ssize_t write(const char *addr, size_t n) override;
  void onzero() override;

protected:
  void do_gc(void) override { delete this; }

private:
  struct pipe* const pipe;
};

// in-core file system types
struct inode : public referenced, public rcu_freed
{
  void  init();
  void  link();
  void  unlink();
  short nlink();

  inode& operator=(const inode&) = delete;
  inode(const inode& x) = delete;

  void do_gc() override { delete this; }

  // const for lifetime of object:
  const u32 dev;
  const u32 inum;

  // const unless inode is reused:
  u32 gen;
  std::atomic<short> type;
{'fraction_non_alphanumeric': 0.13181411974977658, 'fraction_numerical': 0.006255585344057194, 'mean_word_length': 4.308300395256917, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1404864', 'n_tokens_mistral': 2420, 'n_tokens_neox': 2342, 'n_words': 714}