要求:
具体代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#define umask 18 //0000010010
#define mode_read 256 //0100000000
#define mode_write 128 //0010000000
#define mode_execute 64 //0001000000
/*权限部分:模仿unix的权限,文件创建、文件读写权限检查函数
the / directory is only allowed uid=0 to creat the dire
*/
struct f_position
{
char dev_name[32];
int start_pos;
int block_num;
int length_bytes;
};
struct f_logic_structure
{
//0:stream file; 1:record file
char type;
int num_record;
//0:fixed length record; 1:variable length record
char type_record;
};
struct current_use_info
{
int num_of_processes;
//0:unlock;1:lock
char locked;
char modified;
};
/*
struct inode{
int uid;
int gid;
//0:relugar file,1:direcotry file,2:special file
char type;
int privilege;
int addr[13];
int length;
int count;
int time_process;
int time_modified;
int time_inode_modified;
}
*/
struct inode
{
struct f_position position;
struct f_logic_structure f_l_structure;
//0:sequence file,1:chain-connected file,2:index file
int f_physical_structure;
int privilege;
int date_create;
int time_create;
int date_modify;
int time_modify;
struct current_use_info use_info;
int f_uid;
int f_gid;
};
struct fcb
{
char file_name[32];
struct inode f_inode;
};
/*
struct node
{
char name[32];
struct node *sbiling;
struct node *parent;
struct node *child;
struct fcb pointer_fcb;
//0:directory;1:file
char type;
};
*/
struct node
{
char name[32];
//-1: no sbiling
int sbiling;
int parent;
int child;
struct fcb pointer_fcb;
//0:directory;1:file
char type;
};
int *unused;
int *fat[260111];
void *other;
int uid,gid;
int check_permission(struct node *p,int mode){
if(uid!=0){
int m;
m=mode;
if(uid==p->pointer_fcb.f_inode.f_uid){
if((m&p->pointer_fcb.f_inode.privilege&448)!=m){//user can't write0 010 000 000,448 0111000000
return 0;
}
}
else if(gid==p->pointer_fcb.f_inode.f_gid){
m = m >>3;
if((m&p->pointer_fcb.f_inode.privilege&56)!=m){//user can't write, 0000111000
return 0;
}
}
else{
m = m >>6;
if((m&p->pointer_fcb.f_inode.privilege&7)!=m){//user can't write, 0000000111
return 0;
}
}
}
return 1;
}
void
directory_read (struct node *p, int first_block);
void
file_write (int first_block, int pos, void *value, int len);
int f_chmod(struct node *current_directory,int mode,char name[32]){
struct node tmpnode2;
directory_read(&tmpnode2,current_directory->child);
if(strncmp(tmpnode2.name,name,strlen(tmpnode2.name)>strlen(name)?strlen(tmpnode2.name):strlen(name))==0){
int target_node_block;
struct node target_node;
target_node_block=current_directory->child;
memcpy(&target_node,&tmpnode2,sizeof(struct node));
//
if(uid!=target_node.pointer_fcb.f_inode.f_uid){
return -1;//not the owner
}
else{
int privilege;
privilege=((mode/100)<<6)+((mode/10%10)<<3)+(mode%10);
void *p1,*p2;
p1=&target_node;
p2=&target_node.pointer_fcb.f_inode.privilege;
file_write(target_node_block,p2-p1,&privilege,sizeof(int));
return 1;
}
//
}
else{
int r;
r=tmpnode2.sbiling;
directory_read(&tmpnode2,r);
int target_node_block;
struct node target_node;
while(1){
if(strncmp(tmpnode2.name,name,strlen(tmpnode2.name)>strlen(name)?strlen(tmpnode2.name):strlen(name))==0){
target_node_block=r;
directory_read(&target_node,r);
break;
}
r=tmpnode2.sbiling;
directory_read(&tmpnode2,r);
}
//未进行错误判断,目录必须存在
//
if(uid!=target_node.pointer_fcb.f_inode.f_uid){//user can't cd
return -1;//not the owner
}
else{
int privilege;
privilege=((mode/100)<<6)+((mode/10%10)<<3)+(mode%10);
void *p1,*p2;
p1=&target_node;
p2=&target_node.pointer_fcb.f_inode.privilege;
file_write(target_node_block,p2-p1,&privilege,sizeof(int));
return 1;
}
//
}
}
int
directory_create (char directory_name[32], int current_directory_block)
{
//check the permission is allowed?
if(current_directory_block==-1){
if(uid!=0){
return -3;//the previlege is not sufficient
}
}
else{
struct node tmpnode2;
directory_read(&tmpnode2,current_directory_block);
if(check_permission(&tmpnode2,mode_write)!=1){//user can't write0 010 000 000
return -3;
}
}
//if ==-1,used for creating the root
if(current_directory_block!=-1){
struct node tmpnode;
directory_read(&tmpnode,current_directory_block);
if(tmpnode.child!=-1){
directory_read(&tmpnode,tmpnode.child);
if(strncmp(tmpnode.name,directory_name,strlen(tmpnode.name)>strlen(directory_name)?strlen(tmpnode.name):strlen(directory_name))==0){
//this name is same to an existed name, direct child
return -2;
}
while(tmpnode.sbiling!=-1){
directory_read(&tmpnode,tmpnode.sbiling);
if(strncmp(tmpnode.name,directory_name,strlen(tmpnode.name)>strlen(directory_name)?strlen(tmpnode.name):strlen(directory_name))==0){
return -2;
}
}
}
}
int m;
if (sizeof (struct node) % 512 == 0)
{
m = sizeof (struct node) / 512;
}
else
{
m = sizeof (struct node) / 512 + 1;
}
struct node sample_node;
if (m <= *unused)
{
//the first 1M is used for FAT
//struct node sample_node;
memset (&sample_node, 0x00, sizeof (struct node));
strncpy (sample_node.name, directory_name, strlen (directory_name));
sample_node.sbiling = -1;
sample_node.parent = current_directory_block;
sample_node.child = -1;
sample_node.pointer_fcb.f_inode.privilege=511-umask;//0 111 111 111 - umask
sample_node.pointer_fcb.f_inode.f_uid=uid;
sample_node.pointer_fcb.f_inode.f_gid=gid;
sample_node.type = 0;
int i;
int m_counter, temp;
temp = 0;
void *p;
p = &sample_node;
m_counter = 0;
int position;
for (i = 0; i < 26011; i++)
{
if (*fat[i] == 0)
{
if (m_counter == 0)
{
//sample_node.pointer_fcb.f_inode.position.start_pos = i;
position=i;
}
if (m == 1)
{
memcpy (other + i * 512, p, sizeof (struct node));
*fat[i] = -1;
break;
}
else if (m > 1 && m_counter < m)
{
if (temp != 0)
{
*fat[temp] = i;
}
temp = i;
memcpy (other + i * 512, p, 512);
m_counter++;
p = p + 512;
}
else if (m_counter == m)
{
memcpy (other + i * 512, p,
sizeof (struct node) - (m - 1) * 512);
*fat[i] = -1;
break;
}
else
{
}
}
}
*unused = *unused - m;
//return sample_node.pointer_fcb.f_inode.position.start_pos;
return position;
}
else
{
//printf ("no enough space.\n");
return -1;
}
}
int
file_node_create (char file_name[32], int current_directory_block)
{
//check permission
if(current_directory_block==-1){
if(uid!=0){
return -3;//the previlege is not sufficient
}
}
else{
struct node tmpnode2;
directory_read(&tmpnode2,current_directory_block);
if(check_permission(&tmpnode2,mode_write)!=1){user can't write0 010 000 000
return -3;
}
}
struct node tmpnode;
directory_read(&tmpnode,current_directory_block);
if(tmpnode.child!=-1){
directory_read(&tmpnode,tmpnode.child);
if(strncmp(tmpnode.name,file_name,strlen(tmpnode.name)>strlen(file_name)?strlen(tmpnode.name):strlen(file_name))==0){
//this name is same to an existed name, direct child
return -2;
}
while(tmpnode.sbiling!=-1){
directory_read(&tmpnode,tmpnode.sbiling);
if(strncmp(tmpnode.name,file_name,strlen(tmpnode.name)>strlen(file_name)?strlen(tmpnode.name):strlen(file_name))==0){
return -2;
}
}
}
int m;
if (sizeof (struct node) % 512 == 0)
{
m = sizeof (struct node) / 512;
}
else
{
m = sizeof (struct node) / 512 + 1;
}
struct node sample_node;
if (m <= *unused)
{
//the first 1M is used for FAT
//struct node sample_node;
memset (&sample_node, 0x00, sizeof (struct node));
strncpy (sample_node.name, file_name, strlen (file_name));
sample_node.sbiling = -1;
sample_node.parent = current_directory_block;
sample_node.child = -1;
sample_node.pointer_fcb.f_inode.privilege=511-umask;
sample_node.pointer_fcb.f_inode.position.length_bytes=0;
sample_node.type = 1;
int i;
int m_counter, temp;
temp = 0;
void *p;
p = &sample_node;
m_counter = 0;
int position;
for (i = 0; i < 26011; i++)
{
if (*fat[i] == 0)
{
if (m_counter == 0)
{
//sample_node.pointer_fcb.f_inode.position.start_pos = i;
position=i;
}
if (m == 1)
{
memcpy (other + i * 512, p, sizeof (struct node));
*fat[i] = -1;
break;
}
else if (m > 1 && m_counter < m)
{
if (temp != 0)
{
*fat[temp] = i;
}
temp = i;
memcpy (other + i * 512, p, 512);
m_counter++;
p = p + 512;
}
else if (m_counter == m)
{
memcpy (other + i * 512, p,
sizeof (struct node) - (m - 1) * 512);
*fat[i] = -1;
break;
}
else
{
}
}
}
*unused = *unused - m;
//return sample_node.pointer_fcb.f_inode.position.start_pos;
return position;
}
else
{
//printf ("no enough space.\n");
return -1;
}
}
//return the file node's block
int file_open(char file_name[32],struct node *current_directory,int current_directory_block){
struct node tmpnode;
directory_read(&tmpnode,current_directory->child);
if(tmpnode.type==1){
if(strncmp(tmpnode.name,file_name,strlen(tmpnode.name)>strlen(file_name)?strlen(tmpnode.name):strlen(file_name))==0){
return current_directory->child;
}
}
else{
int t;
t=tmpnode.sbiling;
directory_read(&tmpnode,t);
while(1){
if(tmpnode.type==1){
if(strncmp(tmpnode.name,file_name,strlen(tmpnode.name)>strlen(file_name)?strlen(tmpnode.name):strlen(file_name))==0){
return t;
}
}
t=tmpnode.sbiling;
directory_read(&tmpnode,t);
}
}
}
//the length is 2^16,so 2GB file
int
file_content_create (int file_node_block,char *file_content, int length)
{
//check permission
struct node tmpnode;
directory_read(&tmpnode,file_node_block);
if(check_permission(&tmpnode,mode_write)!=1){user can't write0 010 000 000
return -3;
}
int m;
if (length % 512 == 0)
{
m = length / 512;
}
else
{
m = length / 512 + 1;
}
if (m <= *unused)
{
int i;
int m_counter, temp;
temp = 0;
m_counter = 0;
int position;
for (i = 0; i < 26011; i++)
{
if (*fat[i] == 0)
{
if (m_counter == 0)
{
struct node sample_node;
void *p1,*p2;
p1=&sample_node;
p2=&sample_node.pointer_fcb.f_inode.position.start_pos;
//sample_node.pointer_fcb.f_inode.position.start_pos = i;
file_write(file_node_block,p2-p1,&i,sizeof(int));
p2=&sample_node.pointer_fcb.f_inode.position.block_num;
file_write(file_node_block,p2-p1,&m,sizeof(int));
p2=&sample_node.pointer_fcb.f_inode.position.length_bytes;
file_write(file_node_block,p2-p1,&length,sizeof(int));
position=i;
}
if (m == 1)
{
memcpy (other + i * 512, file_content, length);
*fat[i] = -1;
break;
}
else if (m > 1 && m_counter < m)
{
if (temp != 0)
{
*fat[temp] = i;
}
temp = i;
memcpy (other + i * 512, file_content, 512);
m_counter++;
file_content = file_content+ 512;
}
else if (m_counter == m)
{
memcpy (other + i * 512, file_content,
length - (m - 1) * 512);
*fat[i] = -1;
break;
}
else
{
}
}
}
*unused = *unused - m;
//return sample_node.pointer_fcb.f_inode.position.start_pos;
return position;
}
else
{
//printf ("no enough space.\n");
return -1;
}
}
int file_append(int file_node_block,char *append_content,int append_length){
struct node file;
directory_read(&file,file_node_block);
int length;
length=file.pointer_fcb.f_inode.position.length_bytes+append_length;
int m;
if (length % 512 == 0)
{
m = length / 512;
}
else
{
m = length / 512 + 1;
}
m=m-file.pointer_fcb.f_inode.position.block_num;
if (m <= *unused)
{
int i;
int m_counter;
m_counter = 1;
int t,y;
t=file.pointer_fcb.f_inode.position.start_pos;
y=*fat[t];
while(y!=-1){
t=y;
y=*fat[y];
}
for (i = 0; i < 26011; i++)
{
if (*fat[i] == 0)
{
if (m == 0)
{
break;
}
else if (m > 0 && m_counter < m)
{
*fat[t] = i;
t = i;
m_counter++;
}
else if (m_counter == m)
{
*fat[t] = i;
*fat[i] = -1;
break;
}
else
{
}
}
}
*unused = *unused - m;
//return sample_node.pointer_fcb.f_inode.position.start_pos;
}
else
{
//printf ("no enough space.\n");
return -1;
}
file_write(file.pointer_fcb.f_inode.position.start_pos,file.pointer_fcb.f_inode.position.length_bytes,append_content,append_length);
void *p1,*p2;
p1=&file;
p2=&file.pointer_fcb.f_inode.position.block_num;
m=m+file.pointer_fcb.f_inode.position.block_num;
file_write(file_node_block,p2-p1,&m,sizeof(int));
file.pointer_fcb.f_inode.position.block_num=m;
p2=&file.pointer_fcb.f_inode.position.length_bytes;
file_write(file_node_block,p2-p1,&length,sizeof(int));
file.pointer_fcb.f_inode.position.length_bytes=length;
return 0;
}
int file_truncate(int file_node_block,int new_length){
//check permission
struct node tmpnode;
directory_read(&tmpnode,file_node_block);
if(check_permission(&tmpnode,mode_write)!=1){user can't write0 010 000 000
return -3;
}
int m;
if(new_length%512==0){
m=new_length/512;
}
if(new_length%512!=0){
m=new_length/512+1;
}
//struct node tmpnode;
//directory_read(&tmpnode,file_node_block);
int t,y;
t=tmpnode.pointer_fcb.f_inode.position.start_pos;
int n;
n=m;
if(m==0){
while(*fat[t]!=-1){
y=*fat[t];
*fat[t]=0;
t=y;
}
*fat[t]=0;
tmpnode.pointer_fcb.f_inode.position.block_num=n;
void *p1,*p2;
p1=&tmpnode;
p2=&tmpnode.pointer_fcb.f_inode.position.block_num;
file_write(file_node_block,p2-p1,&n,sizeof(int));
tmpnode.pointer_fcb.f_inode.position.length_bytes=new_length;
p2=&tmpnode.pointer_fcb.f_inode.position.length_bytes;
file_write(file_node_block,p2-p1,&new_length,sizeof(int));
return 0;
}
while(m>0){
y=t;
t=*fat[t];
m--;
}
if(t==-1){
//the block num is same
tmpnode.pointer_fcb.f_inode.position.length_bytes=new_length;
void *p1,*p2;
p1=&tmpnode;
p2=&tmpnode.pointer_fcb.f_inode.position.length_bytes;
file_write(file_node_block,p2-p1,&new_length,sizeof(int));
return 0;
}
else{
*fat[y]=-1;
while(*fat[t]!=-1){
y=*fat[t];
*fat[t]=0;
t=y;
}
*fat[t]=0;
tmpnode.pointer_fcb.f_inode.position.block_num=n;
void *p1,*p2;
p1=&tmpnode;
p2=&tmpnode.pointer_fcb.f_inode.position.block_num;
file_write(file_node_block,p2-p1,&n,sizeof(int));
tmpnode.pointer_fcb.f_inode.position.length_bytes=new_length;
p2=&tmpnode.pointer_fcb.f_inode.position.length_bytes;
file_write(file_node_block,p2-p1,&new_length,sizeof(int));
return 0;
}
}
void
directory_read (struct node *p, int first_block)
{
int i;
i = 0;
int next, current;
current = first_block;
next = *fat[current];
while (1)
{
if (next == -1)
{
memcpy (p + i * 512, other + 512 * current,
sizeof (struct node) - i * 512);
break;
}
else
{
memcpy (p + i * 512, other + 512 * current, 512);
i++;
current = next;
next = *fat[current];
}
}
}
void
file_write (int first_block, int pos, void *value, int len)
{
int m = 0, i, written_block_start = first_block;
while (pos / 512 > 1)
{
m++;
pos = pos - 512;
}
for (i = 0; i < m; i++)
{
written_block_start = *fat[written_block_start];
}
while (1)
{
if (len > 512 - pos)
{
memcpy (other + 512 * written_block_start + pos, value, 512 - pos);
len = len - (512 - pos);
value = value + 512 - pos;
pos = 0;
written_block_start = *fat[written_block_start];
}
else
{
memcpy (other + 512 * written_block_start + pos, value, len);
break;
}
}
}
void
file_read (int first_block, int pos, void *s, int len)
{
int m = 0, i, read_block_start = first_block;
while (pos / 512 > 1)
{
m++;
pos = pos - 512;
}
for (i = 0; i < m; i++)
{
read_block_start = *fat[read_block_start];
}
while (1)
{
if (len > 512 - pos)
{
memcpy (s, other + 512 * read_block_start + pos, 512 - pos);
len = len - (512 - pos);
s = s + 512 - pos;
pos = 0;
read_block_start = *fat[read_block_start];
}
else
{
memcpy (s, other + 512 * read_block_start + pos, len);
break;
}
}
}
int directory_delete(struct node *current_directory,int current_directory_block,char dirname[32]){
//check for permission?
if(check_permission(current_directory,mode_write|mode_execute)!=1){//user can't delete th dir
return -3;
}
struct node tmpnode;
directory_read(&tmpnode,current_directory->child);
if(strncmp(tmpnode.name,dirname,strlen(dirname)>strlen(tmpnode.name)?strlen(dirname):strlen(tmpnode.name))==0){
int z,tmp;
tmp=current_directory->child;
void *p1,*p2;
p1=&tmpnode;
p2=&tmpnode.child;
file_write(current_directory_block,p2-p1,&tmpnode.sbiling,sizeof(int));
current_directory->child=tmpnode.sbiling;//don't forget to update this always-exist variable
while(*fat[tmp]!=-1){
z=*fat[tmp];
*fat[tmp]=0;
tmp=z;
}
*fat[tmp]=0;
}
else{
int t,y;
y=current_directory->child;
t=tmpnode.sbiling;
directory_read(&tmpnode,t);
while(strncmp(tmpnode.name,dirname,strlen(dirname)>strlen(tmpnode.name)?strlen(dirname):strlen(tmpnode.name))!=0){
y=t;
t=tmpnode.sbiling;
directory_read(&tmpnode,t);
}
void *p1,*p2;
p1=&tmpnode;
p2=&tmpnode.sbiling;
file_write(y,p2-p1,&tmpnode.sbiling,sizeof(int));
int z;
while(*fat[t]!=-1){
z=*fat[t];
*fat[t]=0;
t=z;
}
*fat[t]=0;
}
}
int file_delete(char file_name[32],struct node * current_directory,int current_directory_block){
//check permission
if(check_permission(current_directory,mode_write|mode_execute)!=1){//user can't delete th file
return -3;
}
struct node tmpnode;
directory_read(&tmpnode,current_directory->child);
if(strncmp(tmpnode.name,file_name,strlen(file_name)>strlen(tmpnode.name)?strlen(file_name):strlen(tmpnode.name))==0){
int z,tmp;
tmp=current_directory->child;
void *p1,*p2;
p1=&tmpnode;
p2=&tmpnode.child;
file_write(current_directory_block,p2-p1,&tmpnode.sbiling,sizeof(int));
current_directory->child=tmpnode.sbiling;//don't forget to update this always-exist variable
//
while(*fat[tmp]!=-1){
z=*fat[tmp];
*fat[tmp]=0;
tmp=z;
}
*fat[tmp]=0;
//then delete the file content
if(tmpnode.pointer_fcb.f_inode.position.length_bytes>0){
int tmp_content;
tmp_content=tmpnode.pointer_fcb.f_inode.position.start_pos;
while(*fat[tmp_content]!=-1){
z=*fat[tmp_content];
*fat[tmp_content]=0;
tmp_content=z;
}
*fat[tmp_content]=0;
}
}
else{
int t,y;
y=current_directory->child;
t=tmpnode.sbiling;
directory_read(&tmpnode,t);
while(strncmp(tmpnode.name,file_name,strlen(file_name)>strlen(tmpnode.name)?strlen(file_name):strlen(tmpnode.name))!=0){
y=t;
t=tmpnode.sbiling;
directory_read(&tmpnode,t);
}
void *p1,*p2;
p1=&tmpnode;
p2=&tmpnode.sbiling;
file_write(y,p2-p1,&tmpnode.sbiling,sizeof(int));
int z;
while(*fat[t]!=-1){
z=*fat[t];
*fat[t]=0;
t=z;
}
*fat[t]=0;
//then delete the file content
if(tmpnode.pointer_fcb.f_inode.position.length_bytes>0){
int t_content;
t_content=tmpnode.pointer_fcb.f_inode.position.start_pos;
while(*fat[t_content]!=-1){
z=*fat[t_content];
*fat[t_content]=0;
t_content=z;
}
*fat[t_content]=0;
}
}
}
int cat(char file_name[32],struct node * current_directory,int current_directory_block){
int file_node_block;
file_node_block=file_open(file_name,current_directory,current_directory_block);
struct node tmpnode;
file_read(file_node_block,0,&tmpnode,sizeof(struct node));
//check permission in fact,need the parent direc has execute privilege
if(check_permission(&tmpnode,mode_read)!=1){//user can't read th file
return -3;
}
void *p;
p=malloc(tmpnode.pointer_fcb.f_inode.position.length_bytes);
file_read(tmpnode.pointer_fcb.f_inode.position.start_pos,0,p,tmpnode.pointer_fcb.f_inode.position.length_bytes);
int i;
for(i=0;i<tmpnode.pointer_fcb.f_inode.position.length_bytes;i++){
printf("%c", *(char *)(p+i));
}
printf("\n");
free(p);
}
int test(struct node *current_directory,int current_directory_block){
int length=256;
int m,n;
if (sizeof (struct node) % 512 == 0)
{
m = sizeof (struct node) / 512;
}
else
{
m = sizeof (struct node) / 512 + 1;
}
if (length % 512 == 0)
{
n = length / 512;
}
else
{
n = length / 512 + 1;
}
if(m+n>*unused){
//no enough space
printf("no enough space\n");
return -1;
}
int file_node_block;
file_node_block=file_node_create("test1",current_directory_block);
if(file_node_block==-1){
return -1;
}
else if (file_node_block==-2){
printf("this name is same to an existed name.\n");
return -2;
}
else if (file_node_block==-3){
printf("infufficient privilege.\n");
return -3;
}
else{
newdirectory->parent=current_directory_block;
if (current_directory->child == -1)
{
struct node tmpnode;
void *p1, *p2;
p1 = &tmpnode;
p2 = &tmpnode.child;
file_write (current_directory_block, p2 - p1, &file_node_block,
sizeof (int));
///directory_read(¤t_directory,current_directory_block);
current_directory->child = file_node_block;
}
else
{
int tmpnode_block;
struct node tmpnode;
tmpnode_block = current_directory->child;
while (1)
{
directory_read (&tmpnode, tmpnode_block);
if (tmpnode.sbiling != -1)
{
tmpnode_block = tmpnode.sbiling;
}
else
{
break;
}
}
void *p3, *p4;
p3 = &tmpnode;
p4 = &tmpnode.sbiling;
file_write (tmpnode_block, p4 - p3, &file_node_block, sizeof (int));
tmpnode.sbiling = file_node_block;
}
char file[256];
memset(file,0x31,256);
int t;
t=file_content_create(file_node_block,file,256);
if(t==-3){
printf("file_content_create(): insufficient privilege\n");
return -3;
}
struct node tt;
//这里的file_open不同于linux kernel中的fopen
file_node_block=file_open("test1",current_directory,current_directory_block);
file_read(file_node_block,0,&tt,sizeof(struct node));
printf("%d\n",tt.pointer_fcb.f_inode.position.length_bytes);
char s[32];
memset(s,0x32,32);
file_append(file_node_block,s,32);
file_read(file_node_block,0,&tt,sizeof(struct node));
printf("%d\n",tt.pointer_fcb.f_inode.position.length_bytes);
if(-3==file_truncate(file_node_block,160)){
printf("file_truncate(): insufficient privilege\n");
return -3;
}
file_read(file_node_block,0,&tt,sizeof(struct node));
printf("%d\n",tt.pointer_fcb.f_inode.position.length_bytes);
return t;
}
}
main (int argc, char *argv[])
{
int fd;
fd = open (argv[1], O_RDWR);
void *fs;
if (fd == -1)
{
//128M file
fs = malloc (134217728);
memset (fs, 0x00, 134217728);
fd = open (argv[1], O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
write (fd, fs, 134217728);
close (fd);
free (fs);
fd = open (argv[1], O_RDWR);
}
off_t pa_offset;
pa_offset = 0 & ~(sysconf (_SC_PAGE_SIZE) - 1);
fs =
mmap (NULL, 134217728 - pa_offset, PROT_WRITE | PROT_READ, MAP_SHARED, fd,
pa_offset);
unused = fs - pa_offset;
//452 unused space
//1040444 bytes:fat
//133176832 bytes:fs
int i;
for (i = 0; i < 260111; i++)
{
fat[i] = fs - pa_offset + 452 + 4 * i;
}
//here we think format always uses the first block to set the root directory
if (*fat[0]==0)
{
*unused = 260111;
}
other = fs - pa_offset + 452 + 1040444;
//struct node *root;
int root;
//root=fs - pa_offset +452;
root = 0;
//uid,gid is declared in the global
uid=atoi(argv[2]);
gid=0;
struct node current_directory;
int current_directory_block;
if (*unused == 260111)
{
directory_create ("/", -1);
}
current_directory_block = 0;
//directory_read不应该负责权限的检查
directory_read (¤t_directory, root);
while (1)
{
printf ("newfs>");
char option[16];
memset (option, 0x00, 16);
fgets (option, 16, stdin);
//int i;
for (i = 0; i < 15; i++)
{
if (option[i] == '\n')
{
option[i] = '\0';
break;
}
}
if (strncmp (option, "help", 4) == 0)
{
printf("help\n");
printf("ls\n");
printf("mkdir\n");
printf("rmdir\n");
printf("cd\n");
printf("f_chmod\n");
printf("test\n");
printf("rm\n");
printf("cat\n");
printf("format\n");
printf("quit\n");
continue;
}
if (strncmp (option, "format", 6) == 0)
{//to decrease the working load, not the standard procedure
if(uid!=0){
printf("only uid=0 can format\n");
continue;
}
*unused = 260111;
for(i=0;i<260111;i++){
if(*fat[i]!=0){
*fat[i]=0;
}
}
current_directory_block = 0;
directory_create ("/", -1);
directory_read (¤t_directory, root);
continue;
}
if (strncmp (option, "ls", 2) == 0)
{
//check pwd +x +r permission?
if(check_permission(¤t_directory,mode_read|mode_execute)!=1){//user can't ls
printf("insufficient privilege\n");
continue;
}
//struct node *fsnode;
int fsnode, flag = 0;
fsnode = current_directory.child;
if (fsnode != -1)
{
flag = 1;
}
while (fsnode != -1)
{
struct node tmpnode;
i = 0;
int next, current;
current = fsnode;
next = *fat[fsnode];
while (1)
{
if (next == -1)
{
memcpy (&tmpnode + i * 512, other + 512 * current,
sizeof (struct node) - i * 512);
break;
}
else
{
memcpy (&tmpnode + i * 512, other + 512 * current, 512);
i++;
current = next;
next = *fat[current];
//memcpy(&tmpnode+i*512,other+512*next,512);
}
}
printf ("%s\t", tmpnode.name);
fsnode = tmpnode.sbiling;
}
if (flag == 1)
{
printf ("\n");
}
continue;
}
if (strncmp (option, "cd", 2) == 0)
//open.c:428 according to test,only x needs
{
char dirname2[32];
memset (dirname2, 0x00, 32);
strncpy (dirname2, option + 3, strlen (option) - 3);
if(strncmp(dirname2,"..",2)==0){
//check permission? ?
int target_directory_block;
struct node target_directory;
target_directory_block=current_directory.parent;
directory_read(&target_directory,target_directory_block);
if(check_permission(&target_directory,mode_execute)!=1){//user can't cd
printf("insufficient privilege\n");
continue;
}
current_directory_block=current_directory.parent;
memcpy(¤t_directory,&target_directory,sizeof(struct node));
continue;
}
struct node tmpnode2;
directory_read(&tmpnode2,current_directory.child);
if(tmpnode2.type==0){
if(strncmp(tmpnode2.name,dirname2,strlen(tmpnode2.name)>strlen(dirname2)?strlen(tmpnode2.name):strlen(dirname2))==0){
int target_directory_block;
struct node target_directory;
target_directory_block=current_directory.child;
memcpy(&target_directory,&tmpnode2,sizeof(struct node));
//
if(check_permission(&target_directory,mode_execute)!=1){//user can't cd
printf("insufficient privilege\n");
continue;
}
//
current_directory_block=target_directory_block;
memcpy(¤t_directory,&tmpnode2,sizeof(struct node));
continue;
}
}
//this logic should be removed
//else{
int r;
r=tmpnode2.sbiling;
directory_read(&tmpnode2,r);
int target_directory_block;
struct node target_directory;
while(1){
if(tmpnode2.type==0){
if(strncmp(tmpnode2.name,dirname2,strlen(tmpnode2.name)>strlen(dirname2)?strlen(tmpnode2.name):strlen(dirname2))==0){
target_directory_block=r;
directory_read(&target_directory,r);
break;
}
}
r=tmpnode2.sbiling;
directory_read(&tmpnode2,r);
}
//
if(check_permission(&target_directory,mode_execute)!=1){//user can't cd
printf("permission insufficient\n");
continue;
}
//
current_directory_block=r;
memcpy(¤t_directory,&tmpnode2,sizeof(struct node));
//未进行错误判断,目录必须存在
continue;
}
if (strncmp (option, "mkdir", 5) == 0)
{
char dirname[32];
memset (dirname, 0x00, 32);
strncpy (dirname, option + 6, strlen (option) - 6);
int newnode;
newnode = directory_create (dirname, current_directory_block);
if(newnode==-1){
printf("no enough space.\n");
continue;
}
if(newnode==-2){
printf("this name is same to an existed name.\n");
continue;
}
if(newnode==-3){
printf("insufficient privilege.\n");
continue;
}
newdirectory->parent=current_directory_block;
if (current_directory.child == -1)
{
void *p1, *p2;
p1 = ¤t_directory;
p2 = ¤t_directory.child;
file_write (current_directory_block, p2 - p1, &newnode,
sizeof (int));
///directory_read(¤t_directory,current_directory_block);
current_directory.child = newnode;
}
else
{
int tmpnode_block;
struct node tmpnode;
tmpnode_block = current_directory.child;
while (1)
{
directory_read (&tmpnode, tmpnode_block);
if (tmpnode.sbiling != -1)
{
tmpnode_block = tmpnode.sbiling;
}
else
{
break;
}
}
void *p3, *p4;
p3 = &tmpnode;
p4 = &tmpnode.sbiling;
file_write (tmpnode_block, p4 - p3, &newnode, sizeof (int));
tmpnode.sbiling = newnode;
}
continue;
}
if (strncmp (option, "rmdir", 5) == 0){
char dirname[32];
memset (dirname, 0x00, 32);
strncpy (dirname, option + 6, strlen (option) - 6);
if(-3==directory_delete(¤t_directory,current_directory_block,dirname)){
printf("insufficient privilege!\n");
}
continue;
}
if (strncmp (option, "test", 4) == 0)
{
test(¤t_directory,current_directory_block);
continue;
}
if (strncmp (option, "rm", 2) == 0)
{
char file_name[32];
memset (file_name, 0x00, 32);
strncpy (file_name, option + 3, strlen (option) - 3);
if(-3==file_delete(file_name,¤t_directory,current_directory_block)){
printf("file_delete(): insufficient privilege\n");
}
continue;
}
if (strncmp (option, "cat", 3) == 0)
{
char filename[32];
memset (filename, 0x00, 32);
strncpy (filename, option + 4, strlen (option) - 4);
if(cat(filename,¤t_directory,current_directory_block)==-3){
printf("cat(): insufficient privilege\n");
}
continue;
}
if(strncmp(option,"f_chmod",7)==0){
char *p1,*p2;
p1=strchr(option,' ');
p1++;// is mode
p2=strrchr(option,' ');
memset(p2,0x00,1);
p2++;// is node's name
if(-1==f_chmod(¤t_directory,atoi(p1),p2)){
printf("not the owner.\n");
}
continue;
}
if (strncmp (option, "su", 2) == 0)
{
char id[6];
memset (id, 0x00, 6);
strncpy (id, option + 3, strlen (option) - 3);
uid=atoi(id);
continue;
}
if (strncmp (option, "quit", 4) == 0)
{
break;
}
}
munmap (fs, 134217728 - pa_offset);
close (fd);
}
说明:按照题目要求,支持mkdir
rmdir
cd
rm
ls
文件的打开、读、写、删除、追加、
为了测试多用户,增加了f_chown(模仿linux中的chown,因为stat.h中有chown()函数,不能重名,所以改名为f_chown),su
具体使用,
./prog 用来测试的文件名(如果没有,会自动创建) 用户id
test是一个测试文件操作的测试函数
内置命令的使用说明:
rm rmdir cd命令不要输入不存在文件名,否则程序会报错
fchown:f_chown 777 文件名 (这里的权限位与linux一样)
su: su id,将全局uid切换成id