/* NB: not portable! assumes little endian (and probably other things) */
#define NIPB (512/sizeof(DInode))
#define NDPB (512/sizeof(Dirent))
typedef struct Filsys Filsys
;
int16 s_isize
; /* size in blocks of I list */
int16 s_fsize
; /* size in blocks of entire volume */
int16 s_nfree
; /* number of in core free blocks (0-100) */
int16 s_free
[100]; /* in core free blocks */
int16 s_ninode
; /* number of in core I nodes (0-100) */
int16 s_inode
[100]; /* in core free I nodes */
uint8 s_flock
; /* lock during free list manipulation */
uint8 s_ilock
; /* lock during I list manipulation */
uint8 s_fmod
; /* super block modified flag */
uint8 s_ronly
; /* mounted read-only flag */
int16 s_time
[2]; /* current date of last update */
/* v6 and PWB/1.0 disk inode */
typedef struct Dirent Dirent
;
#define ISIZE(ip) ((ip)->i_size0<<16 | (ip)->i_size1)
ui
= up
[1]<<24 | up
[0]<<16 | up
[3]<<8 | up
[2];
setpdplong(void *p
, int32 i
)
setint24(void *p
, int32 i
)
void *bget(int n
) { return &fsdata
[n
*512]; }
/* returns a free block or 0 */
if(filesys
->s_nfree
< 0 || filesys
->s_nfree
>= 100){
printf("bad free count\n");
bno
= filesys
->s_free
[filesys
->s_nfree
];
filesys
->s_free
[filesys
->s_nfree
] = 0;
if(bno
< filesys
->s_isize
+2 || bno
>= filesys
->s_fsize
){
printf("bad free block (%d)\n", bno
);
if(filesys
->s_nfree
<= 0){
filesys
->s_free
[i
] = b
[i
+1];
printf("freeing block\n");
if(filesys
->s_nfree
>= 100){
b
[i
+1] = filesys
->s_free
[i
];
filesys
->s_free
[filesys
->s_nfree
] = bno
;
memset(bget(bn
), 0, 512);
/* returns a free inode or 0 */
if(filesys
->s_ninode
<= 0){
for(i
= 0; i
< filesys
->s_isize
; i
++)
for(j
= 0; j
< NIPB
; j
++){
filesys
->s_inode
[filesys
->s_ninode
++] = ino
;
if(filesys
->s_ninode
>= 100)
if(filesys
->s_ninode
> 0){
ino
= filesys
->s_inode
[--filesys
->s_ninode
];
printf("freeing inode\n");
if(filesys
->s_ninode
>= 100)
filesys
->s_inode
[filesys
->s_ninode
++] = ino
;
uint16
*bp
, *cp
, *dp
, *ep
;
if(ip
->i_mode
& (IFCHR
|IFBLK
))
bp
= bget(ip
->i_addr
[i
]);
for(cp
= &bp
[255]; cp
>= bp
; cp
--)
for(ep
= &dp
[255]; ep
>= dp
; ep
--)
setint24(&ip
->i_size0
, 0);
bmap(DInode
*ip
, uint bn
)
if((ip
->i_mode
& ILARG
) == 0){
/* small file, direct fetch */
/* large file, 7 indirect blocks */
/* huge file, double indirect last block */
getblock(DInode
*ip
, uint bn
)
dinodes
= (DInode
*)bget(2) - 1;
ni
= filesys
->s_isize
*NIPB
+ 1;
inodes
= malloc(ni
*sizeof(Inode
));
inodes
[i
].i
= &dinodes
[i
];
fs_open(uint ino
, int flags
)
if((ip
->i_mode
& IFMT
) == IFDIR
)
// if((flags & 3) != O_RDONLY)
fs_stat(uint ino
, struct stat
*stbuf
)
if((ip
->i_mode
& IFMT
) == IFDIR
)
stbuf
->st_mode
= S_IFDIR
;
else if((ip
->i_mode
& IFMT
) == IFCHR
)
stbuf
->st_mode
= S_IFCHR
;
else if((ip
->i_mode
& IFMT
) == IFBLK
)
stbuf
->st_mode
= S_IFBLK
;
stbuf
->st_mode
= S_IFREG
;
stbuf
->st_mode
|= ip
->i_mode
& 0777;
stbuf
->st_nlink
= ip
->i_nlink
;
stbuf
->st_size
= ISIZE(ip
);
if((ip
->i_mode
& IFMT
) == IFCHR
||
(ip
->i_mode
& IFMT
) == IFBLK
)
stbuf
->st_rdev
= makedev(ip
->i_addr
[0]>>8 & 0xFF, ip
->i_addr
[0]&0xFF);
stbuf
->st_uid
= ip
->i_uid
;
stbuf
->st_gid
= ip
->i_gid
;
stbuf
->st_atime
= pdplong(ip
->i_atime
);
stbuf
->st_mtime
= pdplong(ip
->i_mtime
);
fs_atime(uint ino
, int32 time
)
setpdplong(ip
->i_atime
, time
);
fs_mtime(uint ino
, int32 time
)
setpdplong(ip
->i_mtime
, time
);
fs_uid(uint ino
, int32 uid
)
fs_gid(uint ino
, int32 gid
)
fs_read(uint ino
, void *vdst
, int offset
, int len
)
/* TODO: handle gracefully */
memcpy(dst
, b
+offset
, len
);
memcpy(dst
, b
+offset
, 512-offset
);
/* TODO: handle gracefully */
memcpy(dst
, b
, len
> 512 ? 512 : len
);
n
+= len
> 512 ? 512 : len
;
fs_write(uint ino
, void *vsrc
, int offset
, int len
)
// TODO: make this better:
setint24(&ip
->i_size0
, offset
+len
);
/* TODO: handle gracefully */
memcpy(b
+offset
, src
, len
);
memcpy(b
+offset
, src
, 512-offset
);
/* TODO: handle gracefully */
memcpy(b
, src
, len
> 512 ? 512 : len
);
n
+= len
> 512 ? 512 : len
;
/* return a malloc'd array of dirents for a given inode */
if((ip
->i_mode
& IFDIR
) == 0)
ndes
= size
/sizeof(Dirent
);
des
= malloc((ndes
+1)*sizeof(struct dirent
));
while(fs_read(ino
, &de
, offset
, sizeof(Dirent
)) == sizeof(Dirent
)){
memcpy(dp
->d_name
, de
.name
, 14);
offset
+= sizeof(Dirent
);
lookup(uint ino
, const char *name
, Dirent
*de
)
while(fs_read(ino
, de
, offset
, sizeof(Dirent
)) == sizeof(Dirent
)){
if(strcmp(de
->name
, name
) == 0)
offset
+= sizeof(Dirent
);
memset(de
, 0, sizeof(Dirent
));
while(fs_read(ino
, &de
, offset
, sizeof(Dirent
)) == sizeof(Dirent
)){
offset
+= sizeof(Dirent
);
memset(&de
, 0, sizeof(Dirent
));
fs_write(ino
, &de
, offset
, sizeof(Dirent
));
fs_link(uint ino
, uint parent
, const char *name
)
offset
= allocdirent(parent
);
/* TODO: can't happen right now */
memset(&de
, 0, sizeof(Dirent
));
strncpy(de
.name
, name
, 14);
fs_write(parent
, &de
, offset
, sizeof(de
));
fs_mtime(ino
, time(nil
));
fs_atime(ino
, time(nil
));
fs_mknod(uint parent
, const char *name
, mode_t mode
, dev_t rdev
, uint
*newino
)
// TODO: support more files
if((mode
& S_IFMT
) != S_IFREG
&&
(mode
& S_IFMT
) != S_IFDIR
)
memset(ip
, 0, sizeof(DInode
));
ip
->i_mode
= (mode
&0777) | IALLOC
;
if((mode
& S_IFMT
) == S_IFDIR
)
else if((mode
& S_IFMT
) == S_IFCHR
)
else if((mode
& S_IFMT
) == S_IFBLK
)
if((ip
->i_mode
& IFMT
) == IFCHR
||
(ip
->i_mode
& IFMT
) == IFBLK
)
major(rdev
)<<8 & 0xFF00 | minor(rdev
) & 0xFF;
assert((ipp
->i_mode
& IFMT
) == IFDIR
);
offset
= allocdirent(parent
);
/* TODO: can't happen right now */
memset(&de
, 0, sizeof(Dirent
));
strncpy(de
.name
, name
, 14);
fs_write(parent
, &de
, offset
, sizeof(de
));
fs_mtime(ino
, time(nil
));
fs_atime(ino
, time(nil
));
printf("making node %s %o\n", name
, mode
);
fs_mkdir(uint parent
, const char *name
, mode_t mode
)
/* Make sure we have space */
ret
= fs_mknod(parent
, name
, mode
| S_IFDIR
, 0, &ino
);
memset(des
, 0, 2*sizeof(Dirent
));
strcpy(des
[0].name
, ".");
strcpy(des
[1].name
, "..");
dinodes
[parent
].i_nlink
++;
fs_write(ino
, des
, 0, 2*sizeof(Dirent
));
printf("truncating inode %d (%d)\n", ip
->ino
, ip
->i
->i_nlink
);
fs_unlink(uint parent
, const char *name
)
offset
= lookup(parent
, name
, &de
);
dinodes
[de
.inode
].i_nlink
--;
fs_write(parent
, &de
, offset
, sizeof(Dirent
));