Skip to content

Commit fe1beb5

Browse files
authored
Fix errors in the C code (#129)
Thank you! :)
1 parent 7d5e461 commit fe1beb5

File tree

2 files changed

+31
-26
lines changed

2 files changed

+31
-26
lines changed

08_VirtualFileSystem/02_VirtualFileSystem.md

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ As we anticipated earlier in this chapter we are going to use a linked list to k
6161
So we assume that functions to handle list of mountpoints are present (their implementation is left as exercise), from now on we assume the following functions are present:
6262

6363
```c
64-
mountpoint_t *create_mountpoint(...)
64+
mountpoint_t *create_mountpoint(...);
6565
mountpoint_t *add_mountpoint(mountpoint_t* mountpoint);
6666
void remove_mountpoint(mountpoint_t* mountpoint);
6767
```
@@ -77,16 +77,15 @@ Let's call this new structure `mountpoint_t` and start to fill in some fields:
7777
```c
7878
#define VFS_TYPE_LENGTH 32
7979
#define VFS_PATH_LENGTH 64
80-
struct {
80+
typedef struct {
8181
8282
char type[VFS_TYPE_LENGTH];
83-
char mountpoint[VFS_TYPE_LENGTH];
83+
char device[VFS_PATH_LENGTH];
84+
char mountpoint[VFS_PATH_LENGTH];
8485
8586
fs_operations_t operations;
8687
8788
} mountpoint_t;
88-
89-
typedef struct mountpoint_t mountpoint_t;
9089
```
9190

9291
The next thing is to have a variable to store those mountpoints, since we are using a linked list it is going to be just a pointer to its root, this will be the first place where we will look whenever we want to access a folder or a file:
@@ -114,7 +113,7 @@ There can be others of course configuration parameters like access permission, d
114113
int ustar_open(char *path, int flags);
115114
int ustar_close(int ustar_fd);
116115
void ustar_read(int ustar_fd, void *buffer, size_t count);
117-
int ustar_close(int ustar_fd)
116+
int ustar_close(int ustar_fd);
118117
```
119118

120119
For the mount and umount operation we will need two functions:
@@ -129,10 +128,12 @@ int vfs_mount(char *device, char *target, char *fs_type);
129128
Once called it will simply create and add a new item to the mountpoints list, and will populate the data structure with the information provided, for example inside the function to create a mountpoint (in our example `create_mountpoint`) we are going to have something like the following code:
130129
```c
131130
mountpoint_t *new_mountpoint = malloc(sizeof(mountpoint_t)); // We assume a kind of malloc is present
132-
new_mountpoint.device = device;
133-
new_mountpoint.type = type;
134-
new_mountpoint.mountpoint = target;
135-
new_mountpoint.operations = NULL
131+
if(new_mountpoint == NULL)
132+
return -1;
133+
strcpy(new_mountpoint->device, device);
134+
strcpy(new_mountpoint->type, type);
135+
strcpy(new_mountpoint->mountpoint, target);
136+
new_mountpoint->operations = NULL;
136137
```
137138
138139
the last line will be populated soon, for now let's leave it to `NULL`.
@@ -219,13 +220,16 @@ After having implemented all the functions to load file systems and identify giv
219220
Let's quickly recap on how we usually read a file in C:
220221

221222
```C
222-
int fd;
223-
char *buffer = (char *) calloc(11, sizeof(char));
223+
int file_descriptor;
224+
char *buffer = calloc(11, sizeof(char));
225+
if (buffer == NULL) {
226+
return -1;
227+
}
224228
int file_descriptor = open("/path/to/file/to_open", O_RDONLY);
225-
int sz = read(file_descriptor, buffer, 10)
229+
int sz = read(file_descriptor, buffer, 10);
226230
buffer[sz] = '\0';
227231
printf("%s", buffer);
228-
close(file_pointer);
232+
close(file_descriptor);
229233
```
230234
231235
The code snippet above is using the C stdlib file handling libraries, what the it does is:
@@ -234,7 +238,7 @@ The code snippet above is using the C stdlib file handling libraries, what the i
234238
* If the file is found and the fd value is not -1, than we can read it
235239
* It now reads 10 bytes from the opened file (the `read` function will access it via the fd field), and store the output in the buffer. The read function returns the number of bytes read.
236240
* If we want to print the string read we need to append the EndOfLine symbol after the last byte read.
237-
* Now we can close the file_pointer (destroying the file descriptor associated with the id if it is possible, otherwise -1 will be returned).
241+
* Now we can close the file_descriptor (destroying the file descriptor associated with the id if it is possible, otherwise -1 will be returned).
238242
239243
As we can see there are no instructions where we specify the file system type, or the driver to use this is all managed by the vfs layer. The above functions will avail of kernel system calls open/read/close, they usually sits somewhere above the kernel VFS layer, in our _naive_ implementation they we are not going to create new system calls, and let them to be our VFS layer, and where needed make a simpler version of them.
240244
@@ -265,21 +269,21 @@ The flags value is a bitwise operator, and there are other possible values to be
265269
The return value of the function is the file descriptor id. We have already seen how to parse a path and get the mountpoint id if it is available. But what about the file descriptor and its id? What is it? File descriptors represents a file that has been opened by the VFS, and contain information on how to access it (i.e. mountpoint_id), the filename, the various pointers to keep track of current read/write positions, eventual locks, etc. So before proceed let's outline a very simple file descriptor struct:
266270

267271
```c
268-
struct {
272+
typedef struct {
269273
uint64_t fs_file_id;
270274
int mountpoint_id;
271275
char *filename;
272276
int buf_read_pos;
273277
int buf_write_pos;
274278
int file_size;
275279
char *file_buffer;
276-
} file_descriptor_t
280+
} file_descriptor_t;
277281
```
278282

279283
We need to declare a variable that contains the opened file descriptors, as usual we are using a naive approach, and just use an array for simplicity, this means that we will have a limited number of files that can be opened:
280284

281285
```c
282-
struct file_descriptors_t vfs_opened_files[MAX_OPENED_FILES]
286+
struct file_descriptors_t vfs_opened_files[MAX_OPENED_FILES];
283287
```
284288

285289
Where the `mountpoint_id` fields is the id of the mounted file system that is containing the requested file. The `fs_file_id` is the fs specific id of the fs opened by the file descriptor, `buf_read_pos` and `buf_write_pos` are the current positions of the buffer pointer for the read and write operations and `file_size` is the size of the opened file.
@@ -308,16 +312,16 @@ The basic idea is that once mountpoint_id has been found, the vfs will use the m
308312
int open(const char *path, int flags){
309313
mountpoint_t *mountpoint = get_mountpoint(pathname);
310314

311-
if (mountpoint != NULL`) {
315+
if (mountpoint != NULL) {
312316
char *rel_path = get_rel_path(mountpoint, path);
313-
int fs_specific_id = mountpoint.operations.open(rel_path, flags);
317+
int fs_specific_id = mountpoint->operations.open(rel_path, flags);
314318
if (fs_specific_id != ERROR) {
315319
/* IMPLEMENTATION LEFT AS EXERCISE */
316320
// Get a new vfs descriptor id vfs_id
317321
vfs_opened_files[vfs_id] = //fill the file descriptor entry at position
318322
}
319323
}
320-
return vfs_id
324+
return vfs_id;
321325
}
322326
```
323327
@@ -340,7 +344,7 @@ int close(int fildes) {
340344
mountpoint_id = vfs_opened_files[fildes].mountpoint_id;
341345
mountpoint_t *mountpoint = get_mountpoint_by_id(mountpoint_id);
342346
fs_file_id = vfs_opened_files[fildes].fs_file_id;
343-
fs_close_result = mountpoint.close(fs_file_id);
347+
fs_close_result = mountpoint->operations.close(fs_file_id);
344348
if(fs_close_result == 0) {
345349
vfs_opened_files[fildes].fs_file_id = -1;
346350
return 0;
@@ -381,9 +385,9 @@ Text example of a file...
381385
And we have the following code:
382386
383387
```c
384-
char *buffer[5]
385-
int sz = read(file_descriptor, buffer, 5)
386-
sz = read(file_descriptor, buffer, 5)
388+
char *buffer[5];
389+
int sz = read(file_descriptor, buffer, 5);
390+
sz = read(file_descriptor, buffer, 5);
387391
```
388392

389393
The `buffer` content of the first read will be: `Text `, and the second one `examp`. This is the purpose `buf_read_pos` variable in the file descriptor, so it basically needs to be incremented of nbytes, of course only if `buf_read_pos + nbytes < file_size` .
@@ -393,7 +397,7 @@ The pseudocode for this function is going to be similar to the open/close:
393397
ssize_t read(int fildes, void *buf, size_t nbytes) {
394398
if (vfs_opened_files[fildes].fs_fildes_id != -1) {
395399
int mountpoint_id = vfs_opened_files[fildes].mountpoint_id;
396-
mountpoint_t *mountpoint = get_mountpoint_by_id(mountpoint_id)
400+
mountpoint_t *mountpoint = get_mountpoint_by_id(mountpoint_id);
397401
int fs_file_id = vfs_opened_files[fildes].fs_file_id;
398402
int bytes_read = mountpoints.read(fs_file_id, buf, nbytes)
399403
if (opened_files[fildes].buf_read_pos + nbytes < opened_files[fildes].file_size) {

99_Appendices/I_Acknowledgments.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ In no particular order:
2828
- @sudw1n ([https://github.com/sudw1n](https://github.com/sudw1n))
2929
- @alexdev404 ([https://github.com/AlexDev404](https://github.com/AlexDev404))
3030
- @frischerZucker ([https://github.com/frischerZucker](https://github.com/frischerZucker))
31+
- @oito8bits ([https://github.com/oito8bits](https://github.com/oito8bits))

0 commit comments

Comments
 (0)