Linux文件系統實驗(C語言實現新建、打開、關閉、讀寫文件以及查改文件權限)


題目描述:

使用文件系統調用編寫一個文件工具 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;
}

運行結果:

在這里插入圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM