-
Notifications
You must be signed in to change notification settings - Fork 0
/
file.c
executable file
·168 lines (154 loc) · 4.29 KB
/
file.c
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include "filesys/file.h"
#include <debug.h>
#include "filesys/inode.h"
#include "threads/malloc.h"
/* An open file. */
struct file
{
struct inode *inode; /* File's inode. */
off_t pos; /* Current position. */
bool deny_write; /* Has file_deny_write() been called? */
};
/* Opens a file for the given INODE, of which it takes ownership,
and returns the new file. Returns a null pointer if an
allocation fails or if INODE is null. */
struct file *
file_open (struct inode *inode)
{
struct file *file = calloc (1, sizeof *file);
if (inode != NULL && file != NULL)
{
file->inode = inode;
file->pos = 0;
file->deny_write = false;
return file;
}
else
{
inode_close (inode);
free (file);
return NULL;
}
}
/* Opens and returns a new file for the same inode as FILE.
Returns a null pointer if unsuccessful. */
struct file *
file_reopen (struct file *file)
{
return file_open (inode_reopen (file->inode));
}
/* Closes FILE. */
void
file_close (struct file *file)
{
if (file != NULL)
{
file_allow_write (file);
inode_close (file->inode);
free (file);
}
}
/* Returns the inode encapsulated by FILE. */
struct inode *
file_get_inode (struct file *file)
{
return file->inode;
}
/* Reads SIZE bytes from FILE into BUFFER,
starting at the file's current position.
Returns the number of bytes actually read,
which may be less than SIZE if end of file is reached.
Advances FILE's position by the number of bytes read. */
off_t
file_read (struct file *file, void *buffer, off_t size)
{
off_t bytes_read = inode_read_at (file->inode, buffer, size, file->pos);
file->pos += bytes_read;
return bytes_read;
}
/* Reads SIZE bytes from FILE into BUFFER,
starting at offset FILE_OFS in the file.
Returns the number of bytes actually read,
which may be less than SIZE if end of file is reached.
The file's current position is unaffected. */
off_t
file_read_at (struct file *file, void *buffer, off_t size, off_t file_ofs)
{
return inode_read_at (file->inode, buffer, size, file_ofs);
}
/* Writes SIZE bytes from BUFFER into FILE,
starting at the file's current position.
Returns the number of bytes actually written,
which may be less than SIZE if end of file is reached.
(Normally we'd grow the file in that case, but file growth is
not yet implemented.)
Advances FILE's position by the number of bytes read. */
off_t
file_write (struct file *file, const void *buffer, off_t size)
{
off_t bytes_written = inode_write_at (file->inode, buffer, size, file->pos);
file->pos += bytes_written;
return bytes_written;
}
/* Writes SIZE bytes from BUFFER into FILE,
starting at offset FILE_OFS in the file.
Returns the number of bytes actually written,
which may be less than SIZE if end of file is reached.
(Normally we'd grow the file in that case, but file growth is
not yet implemented.)
The file's current position is unaffected. */
off_t
file_write_at (struct file *file, const void *buffer, off_t size,
off_t file_ofs)
{
return inode_write_at (file->inode, buffer, size, file_ofs);
}
/* Prevents write operations on FILE's underlying inode
until file_allow_write() is called or FILE is closed. */
void
file_deny_write (struct file *file)
{
ASSERT (file != NULL);
if (!file->deny_write)
{
file->deny_write = true;
inode_deny_write (file->inode);
}
}
/* Re-enables write operations on FILE's underlying inode.
(Writes might still be denied by some other file that has the
same inode open.) */
void
file_allow_write (struct file *file)
{
ASSERT (file != NULL);
if (file->deny_write)
{
file->deny_write = false;
inode_allow_write (file->inode);
}
}
/* Returns the size of FILE in bytes. */
off_t
file_length (struct file *file)
{
ASSERT (file != NULL);
return inode_length (file->inode);
}
/* Sets the current position in FILE to NEW_POS bytes from the
start of the file. */
void
file_seek (struct file *file, off_t new_pos)
{
ASSERT (file != NULL);
ASSERT (new_pos >= 0);
file->pos = new_pos;
}
/* Returns the current position in FILE as a byte offset from the
start of the file. */
off_t
file_tell (struct file *file)
{
ASSERT (file != NULL);
return file->pos;
}