-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfs.c
130 lines (119 loc) · 2.81 KB
/
fs.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
// implementation of the vfs that deal with i-nodes
#include "defs.h"
#include "common.h"
#include "param.h"
#include "fs.h"
#include "spinlock.h"
#include "file.h"
#include "initrd.h"
struct devsw devsw[3];
struct {
struct spinlock lock;
struct inode inode[NINODE];
} icache;
extern struct proc *cp;
// Find the inode with number inum on device dev
// and return the in-memory copy. Does not lock
// the inode and does not read it from disk.
struct inode* iget(uint32_t dev, uint32_t inum)
{
//kprintf("iget: icache loc: %h", &icache);
// check if already in inode cache, if so fetch it
struct inode *ip, *empty;
empty = 0;
for (ip = &icache.inode[0] ; ip < &icache.inode[NINODE] ; ip++){
if (ip->ref > 0 && ip->dev == dev && ip->inum == inum ) {
ip->ref++;
return ip;
}
if (empty == 0 && ip->ref == 0 ){
// remember empty slot
empty = ip;
//kprintf("iget: empty: %h", empty);
}
}
// if not allocate a cache entry
if (empty == 0 )
PANIC("iget: no free slot in icache!");
ip = empty;
ip->dev = dev;
ip->inum = inum;
ip->ref = 1;
//memset(ip->addrs, 0, sizeof(uint32_t[NDIRECT+1]));
//kprintf("iget: loc of ip: %h", ip);
return ip;
}
// read the inode from disk
void ilock(struct inode *ip)
{
getinitrd(ip);
}
int readi(struct inode *ip, char *dst, uint32_t off, uint32_t n)
{
struct rdbuf *b;
uint32_t tot, m;
if (ip->dev == 0){
// console
consoleread(ip, dst, n);
} else if (ip->dev == 1) {
for(tot = 0; tot < n; tot += m, off += m, dst += m ){
b = readinitrd(ip, off, 512);
m = min(n - tot, 512);
memmove(dst, b->data, m);
rdrelse(b);
}
return n;
}
}
struct inode* dirlookup(struct inode *dp, char *name)
{
struct dirent de;
int off, inum;
if (dp->type != T_DIR)
PANIC("dirlookup: inode not a dir");
//kprintf("dirlookup: sizeof de: %d", sizeof(de));
for(off = 0; off <= dp->size ; off +=sizeof(de) ) {
//fb_write("testing");
if(readi(dp, &de, off, sizeof(de)) == -1)
PANIC("dirlookup: readi failed!");
if(strncmp(de.name, name, DIRSIZ) == 0) {
// match
inum = de.inum;
fb_write("dirlookup: found, ");
fb_write(name);
fb_write("\n");
return iget(dp->dev, inum);
}
}
PANIC("dirlookup: name not found");
}
// commits an in memory inode to disk
void iupdate(struct inode *ip)
{
updateinitrd(ip);
}
// returns the inode for the given path
struct inode* namei(char *path)
{
// initially get it working for the initrd (no subdirs)
char *name[DIRSIZ];
char *s;
int len;
struct inode *dp, *ip;
if (1==1) // curently, only 1 dir so always root
dp = iget(ROOTDEV, ROOTINO);
else
dp = cp->cwd;
while (*path == '/')
path++;
s = path;
while (*path != '/' && *path != 0)
path++;
len = path - s;
memset(name, 0, sizeof(name));
memcpy(name, s, len);
name[len] = 0;
if((ip = dirlookup(dp, name)) == 0)
PANIC("namei: cannot find file");
return ip;
}