1. 文件類型
文件包含以下幾種類型:1)普通文件 2)目錄文件 3)塊特殊文件(帶緩衝的訪問文件,每次訪問以固定長度爲單位進行)4)字符特殊文件(不帶緩衝的訪問文件,訪問長度可變)5) FIFO 6)套接字(socket) 7) 符號鏈接。
S_ISREG()--->普通文件 S_ISDIR()-->目錄文件 S_ISCHR-->字符特殊文件 S_ISBLK()-->塊特殊文件 S_ISFIFO-->管道或FIFO S_ISLNK()-->符號鏈接 S_ISSOCK-->套接字。
#include <stdio.h>
#include <sys/stat.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 ){
printf("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";
else
ptr = "** unknown mode ** ";
printf("%s\n", ptr );
}
return 0;
}
程序輸出:
2. 文件權限
通過access函數來查看文件的訪問權限。
#include <stdio.h>
#include <fcntl.h>
int main( int argc, char *argv[] )
{
if ( argc != 2 )
printf("usage:a.out <pathname>");
if ( access( argv[ 1 ], R_OK ) < 0 )
printf( "access error for %s\n", argv[ 1 ] );
else
printf("read access OK\n");
if ( open(argv[ 1 ], O_RDONLY ) < 0 )
printf("open error for %s\n", argv[ 1 ] );
else
printf("open for reading OK\n");
return 0;
}
程序輸出:
3. 創建屏蔽字
umask函數爲進程設置文件模式創建屏蔽字。
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#define RWRWRW (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
int main( void )
{
umask( 0 );
if ( creat("foo", RWRWRW ) < 0 )
printf("creat error for foo\n");
umask( S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
if ( creat("bar", RWRWRW ) < 0 )
printf("creat error for bar\n");
return 0;
}
程序輸出:
4. 修改文件的訪問權限
#include <stdio.h>
#include <sys/stat.h>
int main( void )
{
struct stat statbuf;
if ( stat( "foo", &statbuf ) < 0 )
printf("stat error for foo\n" );
if ( chmod("foo", ( statbuf.st_mode & ~S_IXGRP ) | S_ISGID ) < 0 )
printf("chmod error for foo\n");
if ( chmod("bar", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) < 0 )
printf("chmod error for bar\n" );
return 0;
}
程序輸出:
5. 更改文件的用戶ID和組ID
只有超級用戶才能進行修改,或者擁有此文件的用戶才能進行修改(這種情況下只能修改到你所屬於的組裏面的用戶ID)
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
int main( void )
{
struct stat buf;
if ( stat( "foo", &buf ) < 0 ){
printf("stat error\n");
return 1;
}
printf( "uid is:%d, gid is:%d\n", buf.st_uid, buf.st_gid );
if ( chown( "foo", 0, 0 ) < 0 ){
printf("chown error\n");
return 1;
}
if ( stat( "foo", &buf ) < 0 ){
printf("stat error\n" );
return 1;
}
printf("now uid is:%d, gid is:%d\n", buf.st_uid, buf.st_gid );
return 0;
}
通過root用戶執行,則程序輸出:
6. 刪除鏈接文件
#include <stdio.h>
#include <fcntl.h>
int main( void )
{
if ( open("tempfile", O_RDWR ) < 0 )
printf("open error\n");
if ( unlink( "tempfile") < 0 )
printf("unlink error\n" );
printf("file unlinked\n");
sleep( 30 );
printf("done\n");
return 0;
}
只有當進程完全退出的時候,才能徹底刪除文件。請比較進程退出後/home的大小和進程退出前/home的大小(多了8字節):
7. 符號鏈接
符號鏈接是指向一個文件的間接指針,而link的硬鏈接直接指向文件的i節點。引入符號鏈接的原因是爲了避開硬鏈接的一些限制:
1) 硬鏈接通常要求鏈接和文件位於同一文件系統中
2) 只有超級用戶才能創建指向目錄的硬鏈接
以下命令可學習符號鏈接的基本知識:
8. 遍歷一個目錄
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
static long nreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot;
void myftw( char *, char * );
int main( int argc, char *argv[] )
{
if ( argc != 2 ){
printf("input error\n");
return 1;
}
myftw( "", argv[ 1 ] );
ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock;
if ( 0 == ntot ){
ntot = 1;
}
printf("regular files=%7ld, %5.2f%%\n", nreg, nreg * 100.0 / ntot );
printf("directory=%7ld, %5.2f%%\n", ndir, ndir * 100.0 / ntot );
printf("block special=%7ld, %5.2f%%\n", nblk, nblk * 100.0 / ntot );
printf("char special=%7ld, %5.2f%%\n", nchr, nchr * 100.0 / ntot );
printf("FIFOs=%7ld, %5.2f%%\n", nfifo, nfifo * 100.0 / ntot );
printf("symbolic links=%7ld, %5.2f%%\n", nslink, nslink * 100.0 / ntot );
printf("sockets=%7ld, %5.2f%%\n", nsock, nsock * 100.0 / ntot );
return 0;
}
void myftw( char *curPath, char *path )
{
struct stat statbuf;
DIR *dp;
struct dirent *dirp;
char fullPath[ 256 ];
if ( strcmp( curPath, "" ) != 0 ){
strncpy( fullPath, curPath, strlen( curPath ) );
fullPath[ strlen( curPath ) ] = '/';
strncpy( fullPath + strlen( curPath ) + 1, path, strlen( path ) );
fullPath[ strlen( curPath ) + strlen( path ) + 1 ] = '\0';
}
else{
strncpy( fullPath, path, strlen( path ) );
fullPath[ strlen( path ) ] = '\0';
}
if ( lstat( fullPath, &statbuf ) < 0 ){
printf("lstat error:%s\n", fullPath);
return;
}
if ( S_ISREG( statbuf.st_mode ) )
nreg++;
else if ( S_ISDIR( statbuf.st_mode ) ){
ndir++;
if ( ( dp = opendir( fullPath ) ) == NULL ){
printf("can't open %s\n", fullPath );
return;
}
while ( ( dirp = readdir( dp ) ) != NULL ){
if ( strcmp( dirp->d_name, "." ) == 0 ||
strcmp( dirp->d_name, ".." ) == 0 ){
continue;
}
myftw( fullPath, dirp->d_name );
}
}
else if ( S_ISCHR( statbuf.st_mode ) )
nchr++;
else if ( S_ISBLK( statbuf.st_mode ) )
nblk++;
else if ( S_ISFIFO( statbuf.st_mode ) )
nfifo++;
else if ( S_ISLNK( statbuf.st_mode ) )
nslink++;
else if ( S_ISSOCK( statbuf.st_mode ) )
nsock++;
else
printf("file error\n");
}
程序輸出:
9. 設備特殊文件
#include <stdio.h>
#include <sys/stat.h>
#ifdef SOLARIS
#include <sys/mkdev.h>
#endif
#include <sys/sysmacros.h>
int main( int argc, char *argv[] )
{
int i;
struct stat buf;
for ( i = 1; i < argc; i++ ){
printf("%s: ", argv[ i ] );
if ( stat( argv[ i ], &buf ) < 0 ){
printf("stat error\n");
continue;
}
printf("dev=%d/%d", major( buf.st_dev), minor( buf.st_dev));
if ( S_ISCHR( buf.st_mode ) || S_ISBLK(buf.st_mode)){
printf("(%s) rdev = %d/%d",
( S_ISCHR( buf.st_mode)) ? "character" : "block", major( buf.st_rdev), minor( buf.st_rdev));
}
printf("\n");
}
return 0;
}
程序輸出: