日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

UNIX_文件目录

發(fā)布時間:2024/4/17 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UNIX_文件目录 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

除了對文件進(jìn)行打開,讀寫等操作。文件系統(tǒng)還有其他的特征和性質(zhì)等著我們?nèi)パ芯颗丁?/span>

stat、fstat、lstat函數(shù)

#include <sys/stat.h> int stat(const char *restrice pathname, struct stat *restrict buf); int fstat(int fieldes, struct stat *buf); int lstat(const char *restrice pathname, struct stat *restrict buf);

成功,返回0;否則,返回-1。

第一個參數(shù),一旦給出pathname, stat函數(shù)就返回與此命名文件有關(guān)的信息結(jié)構(gòu)。

第二個參數(shù),buf是指針,指向一個結(jié)構(gòu)。結(jié)構(gòu)的基本形式如下:

struct stat {

? mode_t ? st_mode;? /* file type & mode (permissions) */

? ino_t ? st_ino;? /* i-node number (serial number) */

? dev_t ? st_dev; ? /* device number (file system) */

? dev_t ? st_rdev; ? /* device number for special files */

? nlink_t ? st_nlink; ? /* number of links */

? uid_t ? st_uid; ? /* user ID of owner */

? gid_t ? st_gid; ? /* group ID of owner */

? off_t ? st_size; ? /* size in bytes, for regular files */

? time_t ? st_atime; ? /* time of last access */

? time_t ? t_mtime;? /* time of last modification */

? time_t ? st_ctime; ? /* time of last file status change */

? blksize_t ? st_blksize; ? /* best I/O block size */

? blkcnt_t ? st_blocks; ? /* number of disk blocks allocated */

};

程序:對每個命令行參數(shù)打印文件類型

#include "apue.h"int main(int argc, char *argv[]) {int i;struct stat buf;char *ptr;for (i = 1; i < argc; i++) {printf("%s: ", argv[i]);if (lstat(argv[i], &buf) < 0) {err_ret("lstat error");continue;}if (S_ISREG(buf.st_mode))ptr = "regular";else if (S_ISDIR(buf.st_mode))ptr = "directory";else if (S_ISCHR(buf.st_mode))ptr = "character special";else if (S_ISBLK(buf.st_mode))ptr = "block special";else if (S_ISFIFO(buf.st_mode))ptr = "fifo";else if (S_ISLNK(buf.st_mode))ptr = "symbolic link";else if (S_ISSOCK(buf.st_mode))ptr = "socket";elseptr = "** unknown mode **";printf("%s\n", ptr);}exit(0); }

文件訪問權(quán)限

9個訪問權(quán)限位,可看做三類,u表示用戶(所有者user),g表示組(group),o表示其他(other)。每個類中三個訪問權(quán)限(即讀(R),寫(W),執(zhí)行(X))。

進(jìn)程是根據(jù)有效用戶ID判斷當(dāng)前用戶是否有無權(quán)限的。進(jìn)程每次打開,創(chuàng)建,刪除一個文件時,內(nèi)核就進(jìn)行文件訪問權(quán)限測試。 超級用戶的有效ID是0。

如果進(jìn)程擁有此文件,則按照用戶訪問權(quán)限批準(zhǔn)或拒絕該進(jìn)程對文件的訪問(不查看組訪問權(quán)限);若不擁有該文件,但進(jìn)程屬于某個適當(dāng)?shù)慕M,則按照組訪問權(quán)限批準(zhǔn)或拒絕該進(jìn)程對文件的訪問。

?access函數(shù)

#include <unistd.h> int access(const char* pathname, int mode);

成功,返回0;失敗,返回-1。

該函數(shù)按實(shí)際用戶ID和實(shí)際組ID進(jìn)行訪問權(quán)限測試,也就是想驗(yàn)證一個進(jìn)程的實(shí)際用戶能否訪問一個給定的文件。其中mode是如下所列常量的按位或。

R_OK 測試讀權(quán)限

W_OK 測試寫權(quán)限

X_OK 測試執(zhí)行權(quán)限

F_OK 測試文件是否存在

umask函數(shù)

mode_t ?umask(mode_t ?cmask)

cmask是由9個訪問權(quán)限位(S_IRUSR, S_IWUSR,...)中的若干個按位“或”構(gòu)成的。

該函數(shù)為進(jìn)程設(shè)置文件模式創(chuàng)建屏蔽字,也就是給一個文件設(shè)置權(quán)限,比如:禁止掉組和其他用戶的讀寫權(quán)限等, 并返回以前的值。該函數(shù)無出錯返回。

#include "apue.h" #include <fcntl.h>#define RWRWRW (S_IRUSR) | S_IWUSR | S_IRGRP | S_IROTH | S_IWOTH)int main() {umask(0); //創(chuàng)建第一個文件,umask為0if(creat("foo", RWRWRW) < 0)err_sys("creat error for foo");umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); //創(chuàng)建第二個,umask值禁止所有組和其他用戶的讀寫訪問權(quán)if(creat("bar", RWRWRW) < 0)err_sys("creat error for bar");exit(0); }

上面的程序創(chuàng)建兩個文件,創(chuàng)建第一個時,umask為0,這是任何用戶都可以讀文件;創(chuàng)建第二個時,umask值禁止所有組和其他用戶的讀寫訪問權(quán)限。

umask值是一個八進(jìn)制數(shù),每一位都代表一種要屏蔽的權(quán)限(u=rwx, g=rwx, o=rwx)。設(shè)置了相應(yīng)位之后,它所對應(yīng)的權(quán)限就會被拒絕。常用的是002(其他用戶寫),022(同組成員和其他用戶寫),027(同組成員寫和其他用戶讀、寫或執(zhí)行)。

Single UNIX Specification要求shell支持符號形式的umask命令。該格式與八進(jìn)制格式剛好相反,即設(shè)置了的相應(yīng)位表示非拒絕。

chmod、fchmod函數(shù)

這兩個函數(shù)用于更改現(xiàn)有文件的訪問權(quán)限。

#include <sys/stat.h> int chmod(const char *pathname, mode_t mode); int fchmod(int fieldes, mode_t mode);

成功,返回0;失敗,返回-1。

chmod在指定的文件上操作,fchmod則是對已經(jīng)打開的文件操作。

S_ISVTX(sticky bit) ?:保存文本(粘住位)。用于目錄,使多個用戶可以共享一個目錄而不會彼此影響。只有超級用戶才可以設(shè)置粘住位。現(xiàn)在不需要這種技術(shù)了。

?

文件系統(tǒng)

硬鏈接與軟鏈接(符號鏈接)

硬鏈接:每個i節(jié)點(diǎn)都有一個鏈接計數(shù),其值是指向該i節(jié)點(diǎn)的目錄項(xiàng)數(shù)。只有當(dāng)鏈接計數(shù)為0時,才可以刪除該文件,所以刪除文件用unlink, 不是delete。在stat結(jié)構(gòu)中,連接計數(shù)包含在st_nlink中。這種鏈接叫硬鏈接。硬鏈接說白了是一個指針,指向文件i節(jié)點(diǎn)。

符號鏈接:是指向一個文件的間接指針。建立軟鏈接就是建立了一個新文件。?軟鏈接文件有點(diǎn)類似于Windows的快捷方式。它實(shí)際上是特殊文件的一種。在符號連接中,文件實(shí)際上是一個文本文件,其中包含的有另一文件的位置信息,可以是任意文件或目錄,可以鏈接不同文件系統(tǒng)的文件。

引入符號鏈接是為了避開硬鏈接的限制:

1.硬鏈接通常要求鏈接和文件位于同一個文件系統(tǒng)中。

2.只有超級用戶才能創(chuàng)建指向目錄的硬鏈接。因?yàn)檫@樣做可能在文件系統(tǒng)中形成循環(huán)。軟連接中也能形成循環(huán),但是在軟鏈接中這種循環(huán)用unlink就很好消除。

如何形成循環(huán)的?如下:

$mkdir foo //創(chuàng)建目錄 $touch foo/a //創(chuàng)建0長文件 $ln -s ../foo foo/testdir //創(chuàng)建符號鏈接 $ls -l foo

這里創(chuàng)建了一個目錄foo,它包含一個名字為a的文件以及一個指向foo的符號鏈接。

下圖中,圓表示目錄,方表示文件。使用Solaris的標(biāo)準(zhǔn)函數(shù)ftw(3)以降序遍歷文件結(jié)構(gòu),則打印出的路徑名如下:

?因?yàn)閡nlink不跟隨軟連接,所以可以unlink文件foo/testdir,從而消除這個循環(huán)。

什么叫不跟隨軟連接呢?

當(dāng)使用以名字引用文件的函數(shù)時,我們應(yīng)當(dāng)了解函數(shù)是否跟隨這個軟鏈接到達(dá)它所鏈接的文件,也可以說是否處理符號鏈接,如果有這種功能,則其路徑名參數(shù)就引用這個軟連接指向的文件;否則就只是引用這個鏈接本身(就是個路徑名)。

link、symlink、readlink函數(shù)

#include <unistd.h> int link(const char *existingpath, const char *newpath); int unlink(const char *pathname)

?link產(chǎn)生硬鏈接,即鏈接文件與目標(biāo)文件是等價的,只是名字不同。目標(biāo)文件必須存在。通常目標(biāo)文件不允許是目錄,也不允許跨越文件系統(tǒng)。成功,返回0;失敗,返回-1.

#include <unistd.h> int symlink(const char *actualpath, const char *sympath); ssize_t readlink(const char* restrict pathname, char *restrict buf);

symlink產(chǎn)生軟鏈接,即鏈接文件是將目標(biāo)文件名作為字符序列存儲起來,因此對目標(biāo)文件沒有任何限制。可以用readlink讀取符號鏈接所存儲的目標(biāo)文件名.成功,返回0;失敗,返回-1.

讀目錄

?

DIR *opendir(const char *pathname);? // 返回值:NULL表示出錯,非空指針指向的對象為打開的目錄數(shù)據(jù)結(jié)構(gòu)(目錄流)。

struct dirent *readdir(DIR *dp);? // 返回值: NULL表示讀到目錄尾部或出錯,非空指針指向的對象為讀取的目錄項(xiàng)結(jié)構(gòu),目錄流的內(nèi)部指針指向下一個目錄項(xiàng)。

?一個dirent結(jié)構(gòu)體至少包含下列兩個成員:

struct ? dirent {? ? /*目錄項(xiàng)結(jié)構(gòu) */

? ino_t ? d_ino; ? /* i-結(jié)點(diǎn)號 */

? char ? d_name[NAME_MAX + 1]; /* null結(jié)尾的文件名 */

?}

void rewinddir(DIR *dp); ? // 使readdir從目錄的開頭讀(即目錄流的內(nèi)部指針指向第一個目錄項(xiàng))。

int closedir(DIR *dp);? // 返回值: 0 if OK, 1 on error.

?

DIR是一個內(nèi)部結(jié)構(gòu),上述6個函數(shù)用這個內(nèi)部結(jié)構(gòu)保存當(dāng)前正在被讀的目錄所在的有關(guān)信息。

opendir返回的指向DIR結(jié)構(gòu)的指針由另外的5個函數(shù)使用。

只包含 ... 的目錄為一個空目錄。

一個遞歸降序遍歷目錄層次結(jié)構(gòu),并按照文件類型計數(shù)的程序如下:

1 #include "apue.h" 2 #include <dirent.h> 3 #include <limits.h> 4 5 /* function type that is called for each filename */ 6 typedef int Myfunc(const char *, const struct stat *, int); 7 8 static Myfunc myfunc; 9 static int myftw(char *, Myfunc *); 10 static int dopath(Myfunc *); 11 12 static long nreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot; 13 14 int 15 main(int argc, char *argv[]) 16 { 17 int ret; 18 19 if (argc != 2) 20 err_quit("usage: ftw <starting-pathname>"); 21 22 ret = myftw(argv[1], myfunc); /* does it all */ 23 24 ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock; 25 if (ntot == 0) 26 ntot = 1; /* avoid divide by 0; print 0 for all counts */ 27 printf("regular files = %7ld, %5.2f %%\n", nreg, 28 nreg*100.0/ntot); 29 printf("directories = %7ld, %5.2f %%\n", ndir, 30 ndir*100.0/ntot); 31 printf("block special = %7ld, %5.2f %%\n", nblk, 32 nblk*100.0/ntot); 33 printf("char special = %7ld, %5.2f %%\n", nchr, 34 nchr*100.0/ntot); 35 printf("FIFOs = %7ld, %5.2f %%\n", nfifo, 36 nfifo*100.0/ntot); 37 printf("symbolic links = %7ld, %5.2f %%\n", nslink, 38 nslink*100.0/ntot); 39 printf("sockets = %7ld, %5.2f %%\n", nsock, 40 nsock*100.0/ntot); 41 exit(ret); 42 } 43 44 /* 45 * Descend through the hierarchy, starting at "pathname". 46 * The caller's func() is called for every file. 47 */ 48 #define FTW_F 1 /* file other than directory */ 49 #define FTW_D 2 /* directory */ 50 #define FTW_DNR 3 /* directory that can't be read */ 51 #define FTW_NS 4 /* file that we can't stat */ 52 53 static char *fullpath; /* contains full pathname for every file */ 54 static size_t pathlen; 55 56 static int /* we return whatever func() returns */ 57 myftw(char *pathname, Myfunc *func) 58 { 59 fullpath = path_alloc(&pathlen); /* malloc PATH_MAX+1 bytes */ 60 /* ({Prog pathalloc}) */ 61 if (pathlen <= strlen(pathname)) { 62 pathlen = strlen(pathname) * 2; 63 if ((fullpath = realloc(fullpath, pathlen)) == NULL) 64 err_sys("realloc failed"); 65 } 66 strcpy(fullpath, pathname); 67 return(dopath(func)); 68 } 69 70 /* 71 * Descend through the hierarchy, starting at "fullpath". 72 * If "fullpath" is anything other than a directory, we lstat() it, 73 * call func(), and return. For a directory, we call ourself 74 * recursively for each name in the directory. 75 */ 76 static int /* we return whatever func() returns */ 77 dopath(Myfunc* func) 78 { 79 struct stat statbuf; 80 struct dirent *dirp; 81 DIR *dp; 82 int ret, n; 83 84 if (lstat(fullpath, &statbuf) < 0) /* stat error */ 85 return(func(fullpath, &statbuf, FTW_NS)); 86 if (S_ISDIR(statbuf.st_mode) == 0) /* not a directory */ 87 return(func(fullpath, &statbuf, FTW_F)); 88 89 /* 90 * It's a directory. First call func() for the directory, 91 * then process each filename in the directory. 92 */ 93 if ((ret = func(fullpath, &statbuf, FTW_D)) != 0) 94 return(ret); 95 96 n = strlen(fullpath); 97 if (n + NAME_MAX + 2 > pathlen) { /* expand path buffer */ 98 pathlen *= 2; 99 if ((fullpath = realloc(fullpath, pathlen)) == NULL) 100 err_sys("realloc failed"); 101 } 102 fullpath[n++] = '/'; 103 fullpath[n] = 0; 104 105 if ((dp = opendir(fullpath)) == NULL) /* can't read directory */ 106 return(func(fullpath, &statbuf, FTW_DNR)); 107 108 while ((dirp = readdir(dp)) != NULL) { 109 if (strcmp(dirp->d_name, ".") == 0 || 110 strcmp(dirp->d_name, "..") == 0) 111 continue; /* ignore dot and dot-dot */ 112 strcpy(&fullpath[n], dirp->d_name); /* append name after "/" */ 113 if ((ret = dopath(func)) != 0) /* recursive */ 114 break; /* time to leave */ 115 } 116 fullpath[n-1] = 0; /* erase everything from slash onward */ 117 118 if (closedir(dp) < 0) 119 err_ret("can't close directory %s", fullpath); 120 return(ret); 121 } 122 123 static int 124 myfunc(const char *pathname, const struct stat *statptr, int type) 125 { 126 switch (type) { 127 case FTW_F: 128 switch (statptr->st_mode & S_IFMT) { 129 case S_IFREG: nreg++; break; 130 case S_IFBLK: nblk++; break; 131 case S_IFCHR: nchr++; break; 132 case S_IFIFO: nfifo++; break; 133 case S_IFLNK: nslink++; break; 134 case S_IFSOCK: nsock++; break; 135 case S_IFDIR: /* directories should have type = FTW_D */ 136 err_dump("for S_IFDIR for %s", pathname); 137 } 138 break; 139 case FTW_D: 140 ndir++; 141 break; 142 case FTW_DNR: 143 err_ret("can't read directory %s", pathname); 144 break; 145 case FTW_NS: 146 err_ret("stat error for %s", pathname); 147 break; 148 default: 149 err_dump("unknown type %d for pathname %s", type, pathname); 150 } 151 return(0); 152 } View Code

?

chdir、fchdir、getcwd函數(shù)

每個進(jìn)程都有一個當(dāng)前工作目錄,此目錄是搜索所有相對路徑的起點(diǎn)(不以斜杠開始的路徑為相對路徑)。

通過chdir和fchdir函數(shù)可以更改當(dāng)前工作路徑。

#include <unistd.h> int chdir(const char *pathname); int fchdir(int filedes);

成功,返回0;失敗,返回-1.

But,內(nèi)核為每個進(jìn)程只保存指向該目錄v節(jié)點(diǎn)的指針等目錄本身的信息,并不保存該目錄的完整路徑名。

Luckily,getcwd函數(shù)則提供了得到當(dāng)前工作目錄完整的絕對路徑名的功能。成功,返回buf; 失敗,返回NULL。

#include <unistd.h> char *getcwd(char *buf, size_t size);

第一個參數(shù)是緩沖地址buf, 第二是緩沖的長度size(單位:字節(jié))。該緩沖必須有足夠長度以容納絕對路徑名再加上一個null終止字符,否則返回出錯。

1 #include "apue.h" 2 3 int 4 main(void) 5 { 6 char *ptr; 7 size_t size; 8 9 if (chdir("/usr/spool/uucppublic") < 0) 10 err_sys("chdir failed"); 11 12 ptr = path_alloc(&size); /* our own function */ 13 if (getcwd(ptr, size) == NULL) 14 err_sys("getcwd failed"); 15 16 printf("cwd = %s\n", ptr); 17 exit(0); 18 }

在更換目錄之前我們可以先調(diào)用getcwd函數(shù)獲得路徑名,然后將這個路徑名作為調(diào)用參數(shù)傳送給chdir.

fchdir函數(shù)更便捷。在更換到文件系統(tǒng)的不同位置之前,使用open函數(shù)打開當(dāng)前工作目錄,然后保存文件描述符,當(dāng)希望回到原工作目錄時,只要將這個文件描述符傳遞給fchdir即可。

轉(zhuǎn)載于:https://www.cnblogs.com/beatrice7/p/4072167.html

總結(jié)

以上是生活随笔為你收集整理的UNIX_文件目录的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。