summaryrefslogtreecommitdiff
path: root/include/mercury/kernel/vfile.hpp
blob: ce72bb11e8a26b86a114f611cde5ce8f01adb148 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#ifndef MERCURY_KERNEL_VFILE_HPP
#define MERCURY_KERNEL_VFILE_HPP

#include <mercury/kernel/storage.hpp>
#include <mercury/kernel/utility.hpp>

//TODO: mounts points.
//maybe a two-way map between mount points and targets? one mount point per
//target and vice versa. only directories may be mount points, and only file
//system roots (which must be directories) may be targets.

namespace mercury::kernel::vfile {

  //a canon path contains no . or empty directory names, and
  //contains no .. except for at the start of a relative path.
  struct canon_path {

    bool absolute;
    unsigned parent_count;
    utility::vector<utility::string> segments;

    canon_path() : absolute(false), parent_count(0), segments(8) {}

    void parent();
    void rel(const canon_path &r);

    utility::string to_string(bool trailing_slash) const;

  };

  void canonize_path(const utility::string &name, canon_path &out);

  struct vfile {

    //on followed symlinks, path is the source of the symlink and the
    //rest of these are the target. in any case, path should be absolute.
    canon_path path;
    storage::block_device *bd;
    storage::dir_entry dir_entry;

    //TODO: instead of passing root, use saved mount points.
    storage::fs_result follow_symlinks(
      const vfile &root, std::optional<vfile> &out) const;

    //dir_entry.type is assumed to be directory.
    storage::fs_result get_child(
      std::optional<vfile> &out, const utility::string &name) const;
    //dir_entry.type is assumed to be directory. out must be empty on entry.
    storage::fs_result get_children(utility::vector<vfile> &out) const;

    //assumes file is a regular file and [start, start + length)
    //is in bounds of file. start and length are in bytes.
    storage::fs_result read_file(
      uint64_t start, uint64_t length, void *into) const;

  };

  //path must be absolute. follows symlinks on all but the last node.
  //relative_to should be a directory to do the lookup inside; e.g.,
  //if relative_to is /a/b and path is c, then out becomes /a/b/c.
  //TODO: instead of passing root, use saved mount points.
  storage::fs_result lookup_path(
    const vfile &root, const canon_path &path, std::optional<vfile> &out);

}

#endif