改變目錄或文件的訪問權限:
#include <sys/stat.h>
int chmod(const char* path, mode_t mode);
//path 參數指定的文件被修改爲具有 mode 參數給出的訪問權限
獲取、改變當前目錄:
#include <unistd.h> //頭文件
char *getcwd(char *buf, size_t size); //獲取當前目錄,相當於 pwd 命令
int chdir(const char *path); //修改當前目錄,即切換目錄,相當於 cd 命令
getcwd()函數: 將當前的工作目錄絕對路徑複製到參數 buf 所指的內存空間, 參數 size 爲 buf
的空間大小。倘若參數 buf 爲 NULL,getcwd()會依參數 size 的大小自動配置內存(使用malloc()),如果參數 size 也爲 0,則 getcwd()會 依工作目錄絕對路徑的字符串程度來決定所配置的內存大小,進程可以在使用完此字符串後自動利用 free()來釋放此空間。所以常用的形式:getcwd(NULL, 0)。
chdir()函數:用來將當前的工作目錄改變成以參數 path 所指的目錄。
#include<unistd.h>
int main()
{
chdir(“/tmp”);
printf(“current working directory: %s\n”,getcwd(NULL,0));
return 0;
}
創建和刪除目錄:
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int mkdir(const char *pathname, mode_t mode); //創建目錄,mode 是目錄權限
int rmdir(const char *pathname); //刪除目錄
獲取目錄信息:
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name); //打開一個目錄
struct dirent *readdir(DIR *dir); //讀取目錄的一項信息,並返回該項信息的結構體指針
void rewinddir(DIR *dir); //重新定位到目錄文件的頭部
void seekdir(DIR *dir,off_t offset); //用來設置目錄流目前的讀取位置
off_t telldir(DIR *dir); //返回目錄流當前的讀取位置
int closedir(DIR *dir); //關閉目錄文件
seekdir()用來設置參數dir目錄流讀取位置,在調用readdir()時便從此新位置開始讀取。參數offset 代表距離目錄文件開頭的偏移量。
讀取目錄信息的步驟爲:
1、用 opendir 函數打開目錄;
2、使用 readdir 函數迭代讀取目錄的內容,如果已經讀取到目錄末尾,又想重新開始讀,則可以使用 rewinddir 函數將文件指針重新定位到目錄文件的起始位置;
3、用 closedir 函數關閉目錄
案例:
#include <func.h>
int main(int argc, char* argv[])
{
ARGS_CHECK(argc, 2);
DIR* dir;
dir = opendir(argv[1]);
ERROR_CHECK(dir, NULL, "opendir");
struct dirent *p;
while(p = readdir(dir))
{
printf("Ino = %ld len = %d type = %d filename = %s\n", p->d_ino, p->d_reclen, p->d_type, p->d_name);
}
closedir(dir);
return 0;
}
案例:
#include <func.h>
int main(int argc, char* argv[])
{
ARGS_CHECK(argc, 2);
DIR* dir;
dir = opendir(argv[1]); //打開一個目錄,返回指向該目錄流DIR的指針
ERROR_CHECK(dir, NULL, "opendir");
struct dirent *p;
off_t pos;
while(p = readdir(dir)) //讀取目錄的一項信息,並返回該項信息的結構體指針
{
printf("Ino = %ld len = %d type = %d filename = %s\n", p->d_ino, p->d_reclen, p->d_type, p->d_name);
if(!strcmp(p->d_name,"a.out"))
{
pos = telldir(dir); //返回目錄流當前的讀取位置
}
}
seekdir(dir,pos); //重新設置目錄流目前的讀取位置
printf("~~~~~~~~~~~~~~~~~~~~\n");
p = readdir(dir);
printf("Ino = %ld len = %d type = %d filename = %s\n", p->d_ino, p->d_reclen, p->d_type, p->d_name);
closedir(dir); //關閉目錄文件
return 0;
}
DIR的結構體定義如下:
struct __dirstream {
void *__fd; /* `struct hurd_fd' pointer for descriptor. */
char *__data;
int __entry_data;
char *__ptr;
int __entry_ptr;
size_t __allocation;
size_t __size;
__libc_lock_define (, __lock)
};
typedef struct __dirstream DIR; //DIR的定義
DIR爲目錄流,類似於於FILE,這種文件包含了其他文件的名稱和指向其他文件的文件描述符。通過opendir可以打開該目錄流的接口。
opendir()用來打開參數 name 指定的目錄,並返回 DIR*形態的目錄流,和文件操作函數 open()類
似,接下來對目錄的讀取和搜索都要使用此返回值。函數失敗則返回 NULL。
readdir()函數用來讀取目錄的信息,並返回一個結構體指針,該指針保存了目錄的相關信息。有
錯誤發生或者讀取到目錄文件尾則返回 NULL。
struct dirent
{
ino_t d_ino; /* inode number(此目錄進入點的 inode) */
off_t d_off; /* offset to the next dirent(目錄開頭到進入點的位移) */
unsigned short d_reclen; /* length of this record(目錄名的長度) */
unsigned char d_type; /* type of file(所指的文件類型) */
char d_name[256]; /* filename(文件名) */
};
所有的dirent信息構成的鏈表(順序表)爲DIR,存在一個指針定位當前所在的鏈表結點。
每次readdir會移動到鏈表的下一結點,readdir讀取信息後,指針向後偏移,d_off指的是下一個結點的位置。經常用seekdir回到某個位置,而用telldir記錄一個位置。
seekdir()函數用來設置目錄流目前的讀取位置,再調用 readdir()函數時,便可以從此新位置開始
讀取。參數 offset 代表距離目錄文件開頭的偏移量。
telldir()函數用來返回目錄流當前的讀取位置。
獲取文件信息
可以通過 fstat 和 stat 函數獲取文件信息,調用完畢後,文件信息被填充到結構體 struct stat
變量中,函數原型爲:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *file_name, struct stat *buf); //文件名 stat 結構體指針
int fstat(int fd, struct stat *buf); //文件描述符 stat 結構體指針
結構體 stat 的定義爲:
struct stat {
dev_t st_dev; /*如果是設備,返回設備表述符,否則爲 0*/
ino_t st_ino; /* i 節點號 */
mode_t st_mode; /* 文件類型 */ 無符號短整型
nlink_t st_nlink; /* 鏈接數 */
uid_t st_uid; /* 屬主 ID */
gid_t st_gid; /* 組 ID */
dev_t st_rdev; /* 設備類型*/
off_t st_size; /* 文件大小,字節表示 */
blksize_t st_blksize; /* 塊大小*/
blkcnt_t st_blocks; /* 塊數 */
time_t st_atime; /* 最後訪問時間*/
time_t st_mtime; /* 最後修改時間*/
time_t st_ctime; /* 最後權限修改時間 */
};
對於結構體的成員 st_mode,有一組宏可以進行文件類型的判斷:
S_ISLNK(mode) 判斷是否是符號鏈接
S_ISREG(mode) 判斷是否是普通文件
S_ISDIR(mode) 判斷是否是目錄
S_ISCHR(mode) 判斷是否是字符型設備
S_ISBLK(mode) 判斷是否是塊設備
S_ISFIFO(mode) 判斷是否是命名管道
S_ISSOCK(mode) 判斷是否是套接字
案例:
#include<sys/stat.h>
#include<unistd.h>
int main()
{
struct stat buf;
stat (“/etc/passwd”,&buf);
printf(“/etc/passwd file size = %d \n”,buf.st_size);//st_size 可以得到文件大小
return 0;
}
//如果用 fstat 函數實現,如下:
int fd = open (“/etc/passwd”,O_RDONLY); //先獲得文件描述符
fstat(fd, &buf);
案例:以樹形結構的形式輸出指定目錄下面的所有文件
#include <func.h> //自定義的頭文件
int printDir(char *path, int width)
{
DIR* dir;
dir = opendir(path);
ERROR_CHECK(dir, NULL, "opendir"); //自定義的宏
struct dirent *p;
char buf[1024]={0};
while(p = readdir(dir))
{
if (!strcmp(p->d_name, ".")||!strcmp(p->d_name, ".."))
{
continue;
}
printf("%*s%s\n",width,"",p->d_name);
sprintf(buf,"%s%s%s",path,"/",p->d_name);
if(4 == p->d_type)
{
printDir(buf, width+4);
}
}
closedir(dir);
}
int main(int argc, char* argv[])
{
ARGS_CHECK(argc, 2); //自定義的宏
puts(argv[1]);
printDir(argv[1], 4);
return 0;
}
案例:傳遞任意一個目錄路徑,能夠顯示該目錄的ls -l的效果
#include <func.h>
void printState(char* argv)
{
int ret;
struct stat buf;
ret = stat(argv,&buf); //傳出參數
//打印文件類型
char file_type = '0';
if(S_ISLNK(buf.st_mode)) file_type = 'l';
else if( S_ISREG(buf.st_mode) ) file_type = '-';
else if( S_ISDIR(buf.st_mode) ) file_type = 'd';
else if( S_ISCHR(buf.st_mode) ) file_type = 'c';
else if( S_ISBLK(buf.st_mode) ) file_type = 'b';
else if( S_ISFIFO(buf.st_mode) ) file_type = 'p';
else if( S_ISSOCK(buf.st_mode) ) file_type = 's';
printf("%c ",file_type);
//打印文件權限
char buffer[10]={0};
char tmp_buf[] = "rwxrwxrwx";
for(int i=0;i<9;i++)
{
if(buf.st_mode & (1<<(8-i)))
{
buffer[i] = tmp_buf[i];
}
else
{
buffer[i] = '-';
}
}
printf("%s",buffer);
printf("%ld %s %s %ld %s ",buf.st_nlink,getpwuid(buf.st_uid)->pw_name,getgrgid(buf.st_gid)->gr_name
,buf.st_size,ctime(&buf.st_mtime));
}
int printDir(char *path)
{
DIR* dir;
dir = opendir(path);
ERROR_CHECK(dir, NULL, "opendir");
struct dirent *p;
char buf[1024]={0};
// char buf_t[1024]={0};
while(p = readdir(dir))
{
if (!strcmp(p->d_name, ".")||!strcmp(p->d_name, ".."))
{
continue;
}
sprintf(buf,"%s%s%s",path,"/",p->d_name);
char *argv = buf;
printState(argv);
printf("%s\n",p->d_name);
// sprintf(buf,"%s%s%s",path,"/",p->d_name);
if(4 == p->d_type)
{
printDir(buf);
}
}
closedir(dir);
}
int main(int argc, char* argv[])
{
ARGS_CHECK(argc, 2);
printDir(argv[1]);
return 0;
}