summaryrefslogtreecommitdiff
path: root/klm/util/file.hh
blob: be88431dd1b0be8b4ed24f039c2b8a99bcd1b613 (plain)
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#ifndef UTIL_FILE__
#define UTIL_FILE__

#include "util/exception.hh"

#include <cstddef>
#include <cstdio>
#include <string>

#include <stdint.h>

namespace util {

class scoped_fd {
  public:
    scoped_fd() : fd_(-1) {}

    explicit scoped_fd(int fd) : fd_(fd) {}

    ~scoped_fd();

    void reset(int to = -1) {
      scoped_fd other(fd_);
      fd_ = to;
    }

    int get() const { return fd_; }

    int operator*() const { return fd_; }

    int release() {
      int ret = fd_;
      fd_ = -1;
      return ret;
    }

  private:
    int fd_;

    scoped_fd(const scoped_fd &);
    scoped_fd &operator=(const scoped_fd &);
};

class scoped_FILE {
  public:
    explicit scoped_FILE(std::FILE *file = NULL) : file_(file) {}

    ~scoped_FILE();

    std::FILE *get() { return file_; }
    const std::FILE *get() const { return file_; }

    void reset(std::FILE *to = NULL) {
      scoped_FILE other(file_);
      file_ = to;
    }

    std::FILE *release() {
      std::FILE *ret = file_;
      file_ = NULL;
      return ret;
    }

  private:
    std::FILE *file_;
};

/* Thrown for any operation where the fd is known. */
class FDException : public ErrnoException {
  public:
    explicit FDException(int fd) throw();

    virtual ~FDException() throw();

    // This may no longer be valid if the exception was thrown past open.
    int FD() const { return fd_; }

    // Guess from NameFromFD.
    const std::string &NameGuess() const { return name_guess_; }

  private:
    int fd_;

    std::string name_guess_;
};

// End of file reached.
class EndOfFileException : public Exception {
  public:
    EndOfFileException() throw();
    ~EndOfFileException() throw();
};

// Open for read only.  
int OpenReadOrThrow(const char *name);
// Create file if it doesn't exist, truncate if it does.  Opened for write.   
int CreateOrThrow(const char *name);

// Return value for SizeFile when it can't size properly.  
const uint64_t kBadSize = (uint64_t)-1;
uint64_t SizeFile(int fd);
uint64_t SizeOrThrow(int fd);

void ResizeOrThrow(int fd, uint64_t to);

std::size_t PartialRead(int fd, void *to, std::size_t size);
void ReadOrThrow(int fd, void *to, std::size_t size);
std::size_t ReadOrEOF(int fd, void *to_void, std::size_t size);
// Positioned: unix only for now.  
void PReadOrThrow(int fd, void *to, std::size_t size, uint64_t off);

void WriteOrThrow(int fd, const void *data_void, std::size_t size);
void WriteOrThrow(FILE *to, const void *data, std::size_t size);

void FSyncOrThrow(int fd);

// Seeking
void SeekOrThrow(int fd, uint64_t off);
void AdvanceOrThrow(int fd, int64_t off);
void SeekEnd(int fd);

std::FILE *FDOpenOrThrow(scoped_fd &file);
std::FILE *FDOpenReadOrThrow(scoped_fd &file);

// Temporary files
// Append a / if base is a directory.
void NormalizeTempPrefix(std::string &base);
int MakeTemp(const std::string &prefix);
std::FILE *FMakeTemp(const std::string &prefix);

// dup an fd.
int DupOrThrow(int fd);

/* Attempt get file name from fd.  This won't always work (i.e. on Windows or
 * a pipe).  The file might have been renamed.  It's intended for diagnostics
 * and logging only.
 */
std::string NameFromFD(int fd);

} // namespace util

#endif // UTIL_FILE__