-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrmdir.c
More file actions
131 lines (115 loc) · 3.36 KB
/
Copy pathrmdir.c
File metadata and controls
131 lines (115 loc) · 3.36 KB
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
#ifndef RMDIR
#define RMDIR
#include "type.h"
#include "util.c"
int rm_child(MINODE *pmip, char *name)
{
// (1) search parent INODE's data block(s) for the entry of name
char buf[BLKSIZE];
get_block(pmip->dev, pmip->INODE.i_block[0], buf);
DIR *dp = (DIR *)buf;
int prev_rec_len = dp->rec_len;
int total_len = dp->rec_len;
while(strncmp(dp->name, name, strlen(name)))
{
prev_rec_len = dp->rec_len;
dp = (char *)dp + dp->rec_len;
total_len += dp->rec_len;
}
// (2) delete name entry from parent directory
if (total_len == 1024)
{
// (2.1) last entry
int last_rec_len = dp->rec_len;
dp = (char *)dp - prev_rec_len;
dp->rec_len += last_rec_len;
}
else
{
// (2.2) intermediate entry
int shift_rec_len = dp->rec_len;
dp = (char *)dp + dp->rec_len;
while(dp < (buf + BLKSIZE))
{
int ideal_length = 4 * ( (8 + dp->name_len + 3) / 4 );
if (ideal_length < dp->rec_len)
{
dp->rec_len += shift_rec_len;
}
int dpCurRecLen = dp->rec_len;
memcpy((char *)dp - shift_rec_len, dp, dp->rec_len);
dp = (char *)dp + dpCurRecLen;
}
}
// (3) update block of pmip
put_block(pmip->dev, pmip->INODE.i_block[0], buf);
}
int my_rmdir(char *pathname)
{
char buf[BLKSIZE];
// (1) get in-memory INODE of pathname
int ino = getino(pathname);
if (ino == 0)
{
printf("rmdir> pathname: %s does not exist\n", pathname);
return -1;
}
MINODE *mip = iget(dev, ino);
// check permission
if (running->uid != mip->INODE.i_uid)
{
printf("rmdir> UID %d is not the owner of %s\n", running->uid, pathname);
iput(mip);
return -1;
}
// (2) verify MINODE is not busy and INODE is a DIR
if (!S_ISDIR(mip->INODE.i_mode))
{
printf("rmdir> pathname: %s is not a directory\n", pathname);
iput(mip);
return -1;
}
if (mip->refCount > 1)
{
printf("rmdir> pathname: %s is busy with %d references\n", pathname, mip->refCount);
iput(mip);
return -1;
}
get_block(mip->dev, mip->INODE.i_block[0], buf);
int count = 0;
char temp[256];
DIR *dp = (DIR *)buf;
printf(" ino rlen nlen name\n");
while (dp < buf + BLKSIZE)
{
strncpy(temp, dp->name, dp->name_len); // dp->name is NOT a string
temp[dp->name_len] = 0; // temp is a STRING
printf("%4d %4d %4d %s\n",
dp->inode, dp->rec_len, dp->name_len, temp);
count++;
dp = (char*)dp + dp->rec_len;
}
if (count > 2)
{
printf("rmdir> %s has %d entries\n", pathname, count);
iput(mip);
return -1;
}
// (3) get parent's ino and INODE
int pino = findino(mip, &ino);
MINODE *pmip = iget(mip->dev, pino);
// (4) get name from parent DIR
char name[256];
findmyname(pmip, ino, name);
// (5) remove name from parent DIR
rm_child(pmip, name);
// (6) decrement parent links_count and mark parent MINODE as dirty
pmip->INODE.i_links_count--;
pmip->dirty = 1;
iput(pmip);
// (7) deallocate pathname's data blocks and INODE
bdalloc(mip->dev, mip->INODE.i_block[0]);
idalloc(mip->dev, mip->ino);
iput(mip);
}
#endif