題目描述:
使用文件系統調用編寫一個文件工具 filetools,使其具有以下功能:
- 1.創建新文件
- 2.寫文件
- 3.讀文件
- 4.修改文件權限
- 5.查看當前文件權限
- 0.退出
- 提示用戶輸入功能號,並根據用戶輸入的功能選擇相應的功能。
文件按可變記錄文件組織,具體記錄內容自行設計。
算法設計:
打開/新建文件(open)
調用open可以打開或創建一個文件。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int oflag, ... /* mode_t mode */);
返回若成功為文件描述符,若出錯為- 1
參數:
第一個參數**pathname*
是要打開或創建的文件的名字。
第二個參數oflag參數可用來說明此函數的多個選擇項。用下列一個或多個常數進行或運算構成oflag*
參數(這些常數定義在< fcntl . h >頭文件中, 在這三個常數中應當只指定一個):
O_RDONLY 只讀打開
O_WRONLY 只寫打開
O_RDWR 讀、寫打開
第三個可選參數:
O_APPEND 每次寫時都加到文件的尾端。
O_CREAT 若此文件不存在則創建它。使用此選擇項時,需同時說明第三個參數mode,用其說明該新文件的存取許可權位。
O_EXCL 如果同時指定了O_CREAT,而文件已經存在,則出錯。這可測試一個文件是否存在。
O_TRUNC 如果此文件存在,而且為只讀或只寫成功打開,則將其長度截短為0。
O_NONBLOCK 如果pathname指的是一個FIFO、一個塊特殊文件或一個字符特殊文件,則此選擇項為此文件的本次打開操作和后續的I /
O操作設置非阻塞方式。
O_SYNC 使每次write都等到物理I / O操作完成。
讀文件(read)
#include <unistd.h>
ssize_t read(int fd, void *buff, size_t nbytes) ;
返回:讀到的字節數,若已到文件尾為0,若出錯為-1
寫文件(write)
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t nbytes) ;
- 返回:若成功為已寫的字節數,若出錯為-1
- 對於普通文件,寫操作從文件的當前位移量處開始。如果在打開該文件時,指定了O_APPEND選擇項,則在每次寫操作之前,將文件位移量設置在文件的當前結尾處。在一次成功寫之后,該文件位移量增加實際寫的字節數。
查權限
char* pargv[4]={"ls","-l","file1",NULL};
顯示文件權限 execv("/bin/ls",pargv);
- 所以查詢文件權限只需要:
1.pargv[2]改為待操作的文件名
2.執行execv("/bin/ls",pargv);
由於進程執行完execv后會退出而無法執行其他邏輯,於是fork一個子進程來作查權限的操作,主進程調用wait等子進程結束即可。
int p =fork();
if(p==0)
check_file_mod();
else
wait(NULL);
改權限chmod
- linux下的文件權限分三級:owner,group,others三類。每類占權限位的三位。
- r 表示可讀取,w 表示可寫入,x 表示可執行,X 表示只有當該檔案是個子目錄或者該檔案已經被設定過為可執行。
- 其中:r=4,w=2,x=1
例如:若要rwx屬性則4+2+1=7;
若要rw-屬性則4+2=6;
若要r-x屬性則4+1=7。 - 常見權限:
-rw------- (600) – 只有屬主有讀寫權限。
-rw-r–r-- (644) – 只有屬主有讀寫權限;而屬組用戶和其他用戶只有讀權限。
-rwx------ (700) – 只有屬主有讀、寫、執行權限。
-rwxr-xr-x (755) – 屬主有讀、寫、執行權限;而屬組用戶和其他用戶只有讀、執行權限。
-rwx–x--x (711) – 屬主有讀、寫、執行權限;而屬組用戶和其他用戶只有執行權限。
-rw-rw-rw- (666) – 所有用戶都有文件讀、寫權限。這種做法不可取。
-rwxrwxrwx (777) – 所有用戶都有讀、寫、執行權限。更不可取的做法。
lseek調用
每個打開的文件都有一個與其相關聯的“當前文件位移量”。它是一個非負整數,用以度量從文件開始處計算的字節數。通常,讀、寫操作都從當前文件位移量處開始,並使位移量增加所讀或寫的字節數。按系統默認,當打開一個文件時,除非指定O_APPEND選擇項,否則該位移量被設置為0。
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence) ;
參數offset 的解釋與參數whence的值有關
若whence是SEEK_SET,則將該文件的位移量設置為距文件開始處offset 個字節
若whence是SEEK_CUR,則將該文件的位移量設置為其當前值加offset, offset可為正或負
若whence是SEEK_END,則將該文件的位移量設置為文件長度加offset, offset可為正或負
具體代碼:
/* 1. open 打開文件 creat 創建新文件 close 關閉文件描述字 read 讀文件 write 寫文件 */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
int C_fd; //文件描述符
char filename[100]; //文件名
int isopen = 0; //打開狀態
char *pargv[4] = {"ls", "-l", NULL, NULL};
void Open_Creat_file()
{
printf("請輸入要打開/創建的文件名: ");
scanf("%s", filename);
C_fd = open(filename, O_RDWR, 0666);
if (C_fd >= 0)
{
isopen = 1, printf("%s已存在,打開成功\n", filename);
pargv[2] = (char *)malloc(50);
strcpy(pargv[2], filename);
}
else
{
C_fd = open(filename, O_CREAT, 0666);
if (C_fd >= 0)
isopen = 1, printf("%s不存在,新建成功\n", filename);
else
isopen = 0, printf("打開/新建%s失敗\n", filename);
}
//close(fd);
}
void read_file()
{
if (!isopen)
{
printf("沒有打開的文件,請先打開一個文件\n");
return;
}
else
printf("當前處理的文件是:%s\n", filename);
char buffer[100];
lseek(C_fd, 0, SEEK_SET); //從頭開始讀
int t = read(C_fd, buffer, 1024);
if (t != -1)
printf("文件內容為:%s\n", buffer);
else
printf("讀取失敗\n");
}
void write_file()
{
if (!isopen)
{
printf("沒有打開的文件,請先打開一個文件\n");
return;
}
else
printf("當前處理的文件是:%s\n", filename);
char buffer[1024];
printf("請輸入待寫入內容:\n");
scanf("%s", buffer);
int t = write(C_fd, buffer, strlen(buffer));
if (t == -1)
printf("寫入失敗!\n");
else
printf("寫入成功!\n");
}
void change_file_mod()
{
if (!isopen)
{
printf("沒有打開的文件,請先打開一個文件\n");
return;
}
else
printf("當前處理的文件是:%s\n", filename);
int new_mode;
printf("輸入新的模式(十進制)");
scanf("%d", &new_mode);
int mode_u = new_mode / 100;
int mode_g = new_mode / 10 % 10;
int mode_o = new_mode % 10;
new_mode = (mode_u * 8 * 8) + (mode_g * 8) + mode_o; //八進制轉換
int t = chmod(filename, new_mode);
if (t == -1)
printf("改變模式失敗!\n");
else{
printf("成功改變模式!\n");
printf("新模式:%d\n",new_mode);
}
}
void check_file_mod()
{
if (!isopen)
{
printf("沒有打開的文件,請先打開一個文件\n");
return;
}
else
printf("當前處理的文件是:%s\n", filename);
printf("文件權限為");
int t = execv("/bin/ls", pargv);
if (t == -1)
printf("查看失敗\n");
}
int main()
{
printf("-----------------CC_File_Tools--------------\n");
printf("1.打開(不存在則新建) 2.寫文件 3.讀文件 \n");
printf("4.改權限 5.查權限 0.退出 \n");
//printf("------------------------------------\n");
int choice = -1;
while (1)
{
printf("-------------請輸入選擇:-----------\n");
scanf("%d", &choice);
switch (choice)
{
case 0:
{
printf("\n\t感謝使用!\n\n");
return 0;
}
case 1:
{
Open_Creat_file();
break;
}
case 2:
{
write_file();
break;
}
case 3:
{
read_file();
break;
}
case 4:
{
change_file_mod();
break;
}
case 5:
{
int p =fork();
if(p==0)
check_file_mod();
else
wait(NULL);
break;
}
default:
{
printf("您的輸入有誤,請重新輸入!!!\n");
}
}
}
return 0;
}