Loading [MathJax]/extensions/tex2jax.js
CS350 COS
COS
All Data Structures Files Functions Variables Typedefs Macros
newfs_o2fs.c File Reference
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <getopt.h>
#include <o2fs.h>
Include dependency graph for newfs_o2fs.c:

Go to the source code of this file.

Macros

#define ROUND_UP(_a, _b)   (((_a) + (_b) - 1)/(_b))
 
#define MAXBLOCKSIZE   (64*1024*1024)
 
#define TOKEN_EOF   0
 
#define TOKEN_DIR   1
 
#define TOKEN_END   2
 
#define TOKEN_FILE   3
 
#define TOKEN_STRING   4
 

Functions

void LoadManifest (const char *manifest)
 
int GetToken ()
 
void FlushBlock (uint64_t offset, const void *buf, size_t len)
 
uint64_t AppendBlock (const void *buf, size_t len)
 
uint64_t AppendEmpty (void)
 
ObjIDAddFile (const char *file)
 
ObjIDAddDirectory ()
 
void BlockBitmap ()
 
void Superblock (ObjID *objid)
 
void usage ()
 
int main (int argc, char *const *argv)
 

Variables

char tempbuf [MAXBLOCKSIZE]
 
char zerobuf [MAXBLOCKSIZE]
 
bool verbose = false
 
bool hasManifest = false
 
uint64_t diskSize = 0
 
uint64_t diskOffset = 0
 
uint64_t blockSize = 16*1024
 
uint64_t bitmapSize
 
int diskfd
 
struct stat diskstat
 
char * tokenBuf
 
char * tokenCur
 
char tokenString [512]
 

Macro Definition Documentation

◆ MAXBLOCKSIZE

#define MAXBLOCKSIZE   (64*1024*1024)

Definition at line 20 of file newfs_o2fs.c.

◆ ROUND_UP

#define ROUND_UP (   _a,
  _b 
)    (((_a) + (_b) - 1)/(_b))

Definition at line 18 of file newfs_o2fs.c.

◆ TOKEN_DIR

#define TOKEN_DIR   1

Definition at line 35 of file newfs_o2fs.c.

◆ TOKEN_END

#define TOKEN_END   2

Definition at line 36 of file newfs_o2fs.c.

◆ TOKEN_EOF

#define TOKEN_EOF   0

Definition at line 34 of file newfs_o2fs.c.

◆ TOKEN_FILE

#define TOKEN_FILE   3

Definition at line 37 of file newfs_o2fs.c.

◆ TOKEN_STRING

#define TOKEN_STRING   4

Definition at line 38 of file newfs_o2fs.c.

Function Documentation

◆ AddDirectory()

ObjID * AddDirectory ( )

Definition at line 171 of file newfs_o2fs.c.

172{
173 int tok;
174 BDirEntry *entries = malloc(128 * sizeof(BDirEntry));
175 int entry = 0;
176 ObjID *id = malloc(sizeof(ObjID));
177 BNode node;
178
179 while (1)
180 {
181 memset(&entries[entry], 0, sizeof(BDirEntry));
182 tok = GetToken();
183 if (tok == TOKEN_FILE) {
184 tok = GetToken();
185 printf("FILE %s\n", tokenString);
186 strncpy((char *)entries[entry].name, tokenString, MAXNAMELEN);
187
188 tok = GetToken();
189 ObjID *fobj = AddFile(tokenString);
190 memcpy(&entries[entry].objId, fobj, sizeof(ObjID));
191 free(fobj);
192 } else if (tok == TOKEN_DIR) {
193 tok = GetToken();
194 printf("DIR %s\n", tokenString);
195 strncpy((char *)entries[entry].name, tokenString, MAXNAMELEN);
196 ObjID *dobj = AddDirectory();
197 memcpy(&entries[entry].objId, dobj, sizeof(ObjID));
198 free(dobj);
199 } else if (tok == TOKEN_END) {
200 printf("END\n");
201 break;
202 } else if (tok == TOKEN_EOF) {
203 printf("Unexpected end of file\n");
204 exit(1);
205 } else {
206 printf("Unknown token '%s'\n", tokenString);
207 exit(1);
208 }
209
210 memcpy(entries[entry].magic, BDIR_MAGIC, 8);
211 // entries[entry].size ...
212 entries[entry].flags = 0;
213 entries[entry].ctime = (uint64_t)time(NULL);
214 entries[entry].mtime = (uint64_t)time(NULL);
215 strncpy((char *)entries[entry].user, "root", MAXUSERNAMELEN);
216 strncpy((char *)entries[entry].group, "root", MAXUSERNAMELEN);
217
218 entry++;
219 }
220
221 // Write Directory
222
223 // Make sure we fit into a single indirect
224 // block to simplify the logic below.
225 uint64_t size = entry * sizeof(BDirEntry);
227 uint64_t offset = AppendBlock(entries, size);
228
229 // Write Inode
230 memset(&node, 0, sizeof(node));
231 memcpy(node.magic, BNODE_MAGIC, 8);
234 node.size = size;
235 node.direct[0].device = 0;
236 node.direct[0].offset = offset;
237 uint64_t nodeoff = AppendBlock(&node, sizeof(node));
238
239 memset(id, 0, sizeof(*id));
240 id->device = 0;
241 id->offset = nodeoff;
242
243 return id;
244}
#define assert(_expr)
Definition: assert.h:7
time_t time(time_t *t)
Definition: time.c:20
uint32_t size
Definition: multiboot.h:0
ObjID * AddFile(const char *file)
Definition: newfs_o2fs.c:125
#define TOKEN_DIR
Definition: newfs_o2fs.c:35
ObjID * AddDirectory()
Definition: newfs_o2fs.c:171
uint64_t blockSize
Definition: newfs_o2fs.c:29
uint64_t AppendBlock(const void *buf, size_t len)
Definition: newfs_o2fs.c:109
#define TOKEN_FILE
Definition: newfs_o2fs.c:37
#define TOKEN_END
Definition: newfs_o2fs.c:36
int GetToken()
Definition: newfs_o2fs.c:63
#define TOKEN_EOF
Definition: newfs_o2fs.c:34
char tokenString[512]
Definition: newfs_o2fs.c:42
uint64_t flags
Definition: o2fs.h:103
uint8_t magic[8]
Definition: o2fs.h:84
#define BDIR_MAGIC
Definition: o2fs.h:112
uint64_t offset
Definition: o2fs.h:71
#define MAXNAMELEN
Definition: o2fs.h:23
uint16_t versionMinor
Definition: o2fs.h:86
#define MAXUSERNAMELEN
Definition: o2fs.h:22
uint64_t device
Definition: o2fs.h:70
#define BNODE_MAGIC
Definition: o2fs.h:93
uint64_t mtime
Definition: o2fs.h:105
uint64_t ctime
Definition: o2fs.h:104
#define O2FS_VERSION_MINOR
Definition: o2fs.h:31
uint64_t size
Definition: o2fs.h:88
uint16_t versionMajor
Definition: o2fs.h:85
BPtr direct[O2FS_DIRECT_PTR]
Definition: o2fs.h:90
#define O2FS_VERSION_MAJOR
Definition: o2fs.h:30
Definition: o2fs.h:99
Definition: o2fs.h:83
Definition: o2fs.h:36
#define NULL
Definition: stddef.h:6
int printf(const char *fmt,...)
Definition: printf.c:212
void free(void *buf)
Definition: malloc.c:169
void exit(int status)
Definition: exit.c:36
void * malloc(size_t sz)
Definition: malloc.c:160
char * strncpy(char *to, const char *from, size_t len)
Definition: string.c:34
void * memset(void *dst, int c, size_t len)
Definition: string.c:164
void * memcpy(void *dst, const void *src, size_t len)
Definition: string.c:177
unsigned long uint64_t
Definition: types.h:13
Here is the call graph for this function:
Here is the caller graph for this function:

◆ AddFile()

ObjID * AddFile ( const char *  file)

Definition at line 125 of file newfs_o2fs.c.

126{
127 int i = 0;
128 int fd;
129 ObjID *id = malloc(sizeof(ObjID));
130 BNode node;
131
132 memset(id, 0, sizeof(*id));
133 memset(&node, 0, sizeof(node));
134 memcpy(node.magic, BNODE_MAGIC, 8);
137
138 // Copy file
139 fd = open(file, O_RDONLY);
140 if (fd < 0) {
141 perror("Cannot open file");
142 exit(1);
143 }
144 while (1) {
145 int len = read(fd, tempbuf, blockSize);
146 if (len < 0) {
147 perror("File read error");
148 exit(1);
149 }
150 if (len == 0) {
151 break;
152 }
153
154 node.direct[i].device = 0;
155 node.direct[i].offset = AppendBlock(tempbuf, len);
156 node.size += (uint64_t)len;
157 i += 1;
158 }
159 close(fd);
160
161 // Construct BNode
162 uint64_t offset = AppendBlock(&node, sizeof(node));
163
164 // Construct ObjID
165 id->device = 0;
166 id->offset = offset;
167
168 return id;
169}
uint64_t len
Definition: multiboot.h:2
char tempbuf[MAXBLOCKSIZE]
Definition: newfs_o2fs.c:22
Here is the call graph for this function:
Here is the caller graph for this function:

◆ AppendBlock()

uint64_t AppendBlock ( const void *  buf,
size_t  len 
)

Definition at line 109 of file newfs_o2fs.c.

110{
111 uint64_t offset = lseek(diskfd, 0, SEEK_CUR);
112
113 FlushBlock(offset, buf, len);
114 lseek(diskfd, blockSize, SEEK_CUR);
115
116 return offset;
117}
static char buf[4096]
Definition: ethdump.c:10
int diskfd
Definition: newfs_o2fs.c:31
void FlushBlock(uint64_t offset, const void *buf, size_t len)
Definition: newfs_o2fs.c:96
#define SEEK_CUR
Definition: stdio.h:15
Here is the call graph for this function:
Here is the caller graph for this function:

◆ AppendEmpty()

uint64_t AppendEmpty ( void  )

Definition at line 120 of file newfs_o2fs.c.

121{
122 return AppendBlock(NULL, 0);
123}
Here is the call graph for this function:

◆ BlockBitmap()

void BlockBitmap ( )

Definition at line 246 of file newfs_o2fs.c.

247{
248 off_t off = lseek(diskfd, 0, SEEK_CUR) / blockSize;
249
250 /* Code below only supports using the first 16K blocks */
251 assert(off < blockSize);
252
254
255 /* Mark the blocks in use up to the current offset */
256 assert(off > 8);
257 for (off_t i = 0; i < (off / 8); i++) {
258 tempbuf[i] = 0xFF;
259 }
260 for (off_t i = 0; i < (off % 8); i++) {
261 tempbuf[off / 8] |= 1 << i;
262 }
263
264 for (int i = 0; i < bitmapSize; i++)
266}
uint64_t bitmapSize
Definition: newfs_o2fs.c:30
#define MAXBLOCKSIZE
Definition: newfs_o2fs.c:20
int64_t off_t
Definition: types.h:20
Here is the call graph for this function:
Here is the caller graph for this function:

◆ FlushBlock()

void FlushBlock ( uint64_t  offset,
const void *  buf,
size_t  len 
)

Definition at line 96 of file newfs_o2fs.c.

97{
98 assert(offset % blockSize == 0);
100
101 pwrite(diskfd, buf, len, offset);
102 if (len != blockSize) {
103 pwrite(diskfd, zerobuf, blockSize - len, offset + len);
104 }
105}
char zerobuf[MAXBLOCKSIZE]
Definition: newfs_o2fs.c:23
Here is the caller graph for this function:

◆ GetToken()

int GetToken ( )

Definition at line 63 of file newfs_o2fs.c.

64{
65 int i;
66
67 while (*tokenCur == ' ' || *tokenCur == '\t' ||
68 *tokenCur == '\n' || *tokenCur == '\r')
69 tokenCur++;
70
71 for (i = 0; i < 512; i++)
72 {
73 tokenString[i] = tokenCur[i];
74 if (tokenCur[i] == ' ' || tokenCur[i] == '\t' ||
75 tokenCur[i] == '\n' || tokenCur[i] == '\r' ||
76 tokenCur[i] == '\0')
77 {
78 tokenString[i] = '\0';
79 tokenCur += i;
80 break;
81 }
82 }
83
84 if (strcmp(tokenString, "") == 0)
85 return TOKEN_EOF;
86 if (strcmp(tokenString, "DIR") == 0)
87 return TOKEN_DIR;
88 if (strcmp(tokenString, "END") == 0)
89 return TOKEN_END;
90 if (strcmp(tokenString, "FILE") == 0)
91 return TOKEN_FILE;
92 return TOKEN_STRING;
93}
char * tokenCur
Definition: newfs_o2fs.c:41
#define TOKEN_STRING
Definition: newfs_o2fs.c:38
int strcmp(const char *s1, const char *s2)
Definition: string.c:81
Here is the call graph for this function:
Here is the caller graph for this function:

◆ LoadManifest()

void LoadManifest ( const char *  manifest)

Definition at line 44 of file newfs_o2fs.c.

45{
46 int fd = open(manifest, O_RDONLY);
47 struct stat manifeststat;
48
49 if (fd < 0) {
50 perror("Cannot open manifest");
51 exit(1);
52 }
53
54 fstat(fd, &manifeststat);
55 tokenBuf = malloc(manifeststat.st_size + 1);
56 read(fd, tokenBuf, manifeststat.st_size);
57 tokenBuf[manifeststat.st_size] = '\0';
58
60 tokenString[0] = '\0';
61}
char * tokenBuf
Definition: newfs_o2fs.c:40
Definition: stat.h:5
Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char *const *  argv 
)

Definition at line 297 of file newfs_o2fs.c.

298{
299 int ch;
300 int status;
301
302 // Sanity check
303 assert(sizeof(BDirEntry) == 512);
304
305 struct option longopts[] = {
306 { "manifest", required_argument, NULL, 'm' },
307 { "size", required_argument, NULL, 's' },
308 { "verbose", no_argument, NULL, 'v' },
309 { "help", no_argument, NULL, 'h' },
310 { NULL, 0, NULL, 0 }
311 };
312
313 while ((ch = getopt_long(argc, argv, "m:s:vh", longopts, NULL)) != -1)
314 {
315 switch (ch) {
316 case 'm':
317 hasManifest = true;
318 LoadManifest(optarg);
319 break;
320 case 's':
321 diskSize = atol(optarg) * 1024 * 1024;
322 break;
323 case 'v':
324 verbose = true;
325 break;
326 case 'h':
327 usage();
328 return 0;
329 default:
330 usage();
331 return 1;
332 }
333 }
334
335 argc -= optind;
336 argv += optind;
337
338 if (argc != 1) {
339 usage();
340 return 1;
341 }
342
343 diskfd = open(argv[0], O_RDWR | O_CREAT, 0660);
344 if (diskfd < 0) {
345 perror("Cannot open special device or disk image");
346 return 1;
347 }
348
349 status = fstat(diskfd, &diskstat);
350 if (status < 0) {
351 perror("Cannot fstat special device or disk image");
352 return 1;
353 }
354
355 if (diskstat.st_size == 0 && diskSize == 0) {
356 printf("Error: Must specify size for disk images\n");
357 usage();
358 return 1;
359 }
360
361 if (diskstat.st_size == 0)
363
364 /* Skip superblock */
366 lseek(diskfd, diskOffset, SEEK_SET);
368
369 /* Zero the bitmap (and skip past it) */
371 for (int i = 0; i < bitmapSize; i++)
373
374 ObjID *root = NULL;
375 if (hasManifest) {
376 int tok;
377
378 tok = GetToken();
379 if (tok != TOKEN_DIR) {
380 printf("Expected 'DIR' token, but found '%s'\n", tokenString);
381 exit(1);
382 }
383 tok = GetToken();
384 if (tok != TOKEN_STRING || strcmp(tokenString, "/") != 0) {
385 printf("Expected '/' token\n");
386 exit(1);
387 }
388
389 root = AddDirectory();
390 tok = GetToken();
391 if (tok != TOKEN_EOF) {
392 printf("Expected end-of-file, but found '%s'\n", tokenString);
393 exit(1);
394 }
395 }
396
397 /* Write bitmap */
398 BlockBitmap();
399
400 Superblock(root);
401 free(root);
402
403 close(diskfd);
404}
void Superblock(ObjID *objid)
Definition: newfs_o2fs.c:268
struct stat diskstat
Definition: newfs_o2fs.c:32
void usage()
Definition: newfs_o2fs.c:287
void LoadManifest(const char *manifest)
Definition: newfs_o2fs.c:44
bool hasManifest
Definition: newfs_o2fs.c:26
uint64_t diskSize
Definition: newfs_o2fs.c:27
void BlockBitmap()
Definition: newfs_o2fs.c:246
bool verbose
Definition: newfs_o2fs.c:25
#define ROUND_UP(_a, _b)
Definition: newfs_o2fs.c:18
uint64_t diskOffset
Definition: newfs_o2fs.c:28
off_t st_size
Definition: stat.h:11
#define SEEK_SET
Definition: stdio.h:14
Here is the call graph for this function:

◆ Superblock()

void Superblock ( ObjID objid)

Definition at line 268 of file newfs_o2fs.c.

269{
270 SuperBlock sb;
271
272 memset(&sb, 0, sizeof(sb));
277 sb.blockSize = blockSize;
280
281 if (objid)
282 memcpy(&sb.root, objid, sizeof(ObjID));
283
284 FlushBlock(0, &sb, sizeof(sb));
285}
#define SUPERBLOCK_MAGIC
Definition: o2fs.h:63
uint8_t magic[8]
Definition: o2fs.h:47
ObjID root
Definition: o2fs.h:58
uint64_t blockCount
Definition: o2fs.h:52
uint16_t versionMinor
Definition: o2fs.h:49
uint16_t versionMajor
Definition: o2fs.h:48
uint64_t bitmapSize
Definition: o2fs.h:54
uint64_t blockSize
Definition: o2fs.h:53
uint64_t bitmapOffset
Definition: o2fs.h:55
Here is the call graph for this function:
Here is the caller graph for this function:

◆ usage()

void usage ( )

Definition at line 287 of file newfs_o2fs.c.

288{
289 printf("Usage: newfs_o2fs [OPTIONS] special-device\n");
290 printf("Options:\n");
291 printf(" -m, --manifest Manifest of files to copy to file system\n");
292 printf(" -s, --size Size in megabytes of device or disk image\n");
293 printf(" -v, --verbose Verbose logging\n");
294 printf(" -h, --help Print help message\n");
295}
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ bitmapSize

uint64_t bitmapSize

Definition at line 30 of file newfs_o2fs.c.

◆ blockSize

uint64_t blockSize = 16*1024

Definition at line 29 of file newfs_o2fs.c.

◆ diskfd

int diskfd

Definition at line 31 of file newfs_o2fs.c.

◆ diskOffset

uint64_t diskOffset = 0

Definition at line 28 of file newfs_o2fs.c.

◆ diskSize

uint64_t diskSize = 0

Definition at line 27 of file newfs_o2fs.c.

◆ diskstat

struct stat diskstat

Definition at line 32 of file newfs_o2fs.c.

◆ hasManifest

bool hasManifest = false

Definition at line 26 of file newfs_o2fs.c.

◆ tempbuf

char tempbuf[MAXBLOCKSIZE]

Definition at line 22 of file newfs_o2fs.c.

◆ tokenBuf

char* tokenBuf

Definition at line 40 of file newfs_o2fs.c.

◆ tokenCur

char* tokenCur

Definition at line 41 of file newfs_o2fs.c.

◆ tokenString

char tokenString[512]

Definition at line 42 of file newfs_o2fs.c.

◆ verbose

bool verbose = false

Definition at line 25 of file newfs_o2fs.c.

◆ zerobuf

char zerobuf[MAXBLOCKSIZE]

Definition at line 23 of file newfs_o2fs.c.