-
Notifications
You must be signed in to change notification settings - Fork 6
/
dir.c
113 lines (84 loc) · 2.16 KB
/
dir.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
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "dir.h"
int dir_add(struct node *dirnode, struct direntry *entry, int replace, int *added) {
struct direntry **dir = (struct direntry **) &dirnode->data;
struct direntry *existing_entry;
if(dir_find(dirnode, entry->name, strlen(entry->name), &existing_entry)) {
if(replace) {
*added = 0;
existing_entry->node = entry->node;
return 1;
} else {
errno = EEXIST;
return 0;
}
}
*added = 1;
if(*dir == NULL) {
*dir = entry;
entry->next = NULL;
} else {
entry->next = *dir;
*dir = entry;
}
// The entry is now linked in the directory
entry->node->vstat.st_nlink++;
// If the entry is a directory, .. is an implicit hardlink to the parent
// directory.
if(S_ISDIR(entry->node->vstat.st_mode)) {
dirnode->vstat.st_nlink++;
}
return 1;
}
int dir_add_alloc(struct node *dirnode, const char *name, struct node *node, int replace) {
struct direntry *entry = malloc(sizeof(struct direntry));
int added;
if(!entry) {
errno = ENOMEM;
return 0;
}
strcpy(entry->name, name);
entry->node = node;
if(!dir_add(dirnode, entry, replace, &added)) {
free(entry);
return 0;
}
if(!added) free(entry);
return 1;
}
int dir_remove(struct node *dirnode, const char *name) {
struct direntry **dir = (struct direntry **) &dirnode->data;
struct direntry *ent = *dir;
struct direntry **ptr = dir;
while(ent != NULL) {
if(strcmp(ent->name, name) == 0) {
*ptr = ent->next;
// See dir_add for details
if(S_ISDIR(ent->node->vstat.st_mode)) {
dirnode->vstat.st_nlink--;
}
free(ent);
return 1;
}
ptr = &ent->next;
ent = ent->next;
}
errno = ENOENT;
return 0;
}
int dir_find(struct node *dirnode, const char *name, int namelen, struct direntry **entry) {
struct direntry *ent = (struct direntry *) dirnode->data;
while(ent != NULL) {
if(strlen(ent->name) == namelen) {
if(strncmp(ent->name, name, namelen) == 0) {
if(entry != NULL) *entry = ent;
return 1;
}
}
ent = ent->next;
}
errno = ENOENT;
return 0;
}