SeismicUnix:filestat.c

/* Copyright (c) Colorado School of Mines, 2011.*/
/* All rights reserved.                       */

/*********************** self documentation **********************/
/***************************************************************************
FILESTAT - Functions to determine and output the type of a file from file
		 descriptor

filestat - determine type of file from file descriptor
printstat - print the FileType as a string

****************************************************************************
Function Prototypes:
FileType filestat(int fd);
char *printstat(int fd);

****************************************************************************
filestat:
Input:
fd		file descriptor

Returns:	FileType filestat(fd)

****************************************************************************
printstat:
Input:
fd		file descriptor

Returns:	char *printstat(fd)

****************************************************************************
Notes:

Example:
	FileType ftype;
	...
	ftype = filestat(STDOUT)
	if (ftype = TTY) {
		...


BADFILETYPE is the error return and it is up to the calling program to
check for it.

FileType is defined in par.h as:
typedef enum {BADFILETYPE = -1,
   TTY, DISK, DIRECTORY, TAPE, PIPE, FIFO, SOCKET, SYMLINK} FileType;

SOCKETS and SYMLINKS are unlikely to be used.

Rochkind's Advanced Unix Programming assures us that the link count
for a pipe is 0.  But it's an old book.  It seems that PIPES are
sometimes implemented as FIFOs.  In most cases, the number of links for
a pipe is 0, even so.  But on NeXT (at least) the link count is 1.
In the code, I test for PIPE first and FIFO second, so for a PIPE
you'll actually get FIFO on machines that do it NeXT's way.

Portability: the code assumes that /dev/rmt0 and /dev/mt0
are tape devices on your system.  If not, make the obvious changes.
/dev/null is handled as a special case and classified as a disk file.

The check on tapes allows either the raw or buffered version.
This is moot and easily changed.

If new types are added, the typedef "FileType" in par.h must be extended.


****************************************************************************
Authors:
SEP: Einar Kjartansson , Stew Levin
CWP: Jack Cohen
***************************************************************************/
/**************** end self doc ********************************/

#ifndef __USE_BSD
#define __USE_BSD 1
#endif

#include <sys/stat.h>
#include "par.h"


#ifdef __S_IFMT
#define S_IFMT __S_IFMT
#endif
#ifdef __S_IFREG
#define S_IFREG __S_IFREG
#endif
#ifdef __S_IFDIR
#define S_IFDIR __S_IFDIR
#endif
#ifdef __S_IFIFO
#define S_IFIFO __S_IFIFO
#endif
#ifdef __S_IFSOCK
#define S_IFSOCK __S_IFSOCK
#endif
#ifdef __S_IFLNK
#define S_IFLNK __S_IFLNK
#endif
#ifndef __APPLE__
#endif 

#ifndef major	/* major() is a macro for getting the major device number */
#include <sys/sysmacros.h>
#endif

/* determine type of file (DISK, PIPE, ...) */
FileType filestat(int fd)
{
	struct stat sfd;	/* for passed fd	*/
	struct stat sdn;	/* for /dev/null	*/
	struct stat smt;	/* for tape devices	*/


	if (-1 == fstat(fd, &sfd))  return BADFILETYPE;

	/* UNIX subroutine */
	if (isatty(fd))  return TTY;

	/* Standard stat test for regular file */
	if ((sfd.st_mode & S_IFMT) == S_IFREG) return DISK;

	/* Standard stat test for directory */
	if ((sfd.st_mode & S_IFMT) == S_IFDIR) return DIRECTORY;

	/* Only pipes have 0 links (might be FIFO too, so this test first) */
	if (!sfd.st_nlink) return PIPE;

	/* Standard stat test for FIFO */
	if ((sfd.st_mode & S_IFMT) == S_IFIFO) return FIFO;

	/* Standard stat test for socket */
	if ((sfd.st_mode & S_IFMT) == S_IFSOCK) return SOCKET;

	/* Standard stat test for symbolic link */
	if ((sfd.st_mode & S_IFMT) == S_IFLNK) return SYMLINK;

	/* Detect tape by comparing its major device number to	*/
	/* /dev/rmt0 (this is not quite portable).  		*/
	if (0 == stat("/dev/rmt0", &smt) &&
	     major(sfd.st_rdev) == major(smt.st_rdev)) return TAPE;
	if (0 == stat("/dev/mt0", &smt) &&
	     major(sfd.st_rdev) == major(smt.st_rdev)) return TAPE;

	/* Detect file as /dev/null by its device number and	*/
	/* classify it as a disk file.				*/
	if (0 == stat("/dev/null", &sdn) &&
		sfd.st_rdev == sdn.st_rdev) return DISK;

	/* error return */
	return BADFILETYPE;
}


/* Supply ascii string describing type of file */
char *printstat(int fd)
{
	switch (filestat(fd)) {
		case TTY:	return "TTY";
		case DISK:	return "DISK";
		case DIRECTORY:	return "DIRECTORY";
		case TAPE:	return "TAPE";
		case PIPE:	return "PIPE";
		case FIFO:	return "FIFO";
		case SOCKET:	return "SOCKET";
		case SYMLINK:	return "SYMLINK";
		default:	return "BADFILETYPE";
	}
}


#ifdef TEST

/* Test driver for function filestat
 *
 * Here are some tests using filestat to analyse STDIN, STDOUT and
 * the first command line argument along with the expected results:
 *	filestat filestat.c
 *		expect: TTY, TTY, DISK
 *	filestat <filestat.c /usr/local | cat
 *		expect: DISK, PIPE, DIRECTORY
 *	cat filestat.c | filestat filestat.c >/usr/tmp/junkxxx
 *		expect: PIPE, DISK, DISK
 *	filestat /dev/null
 *		expect: TTY, TTY, DISK
 *	filestat
 *		expect: TTY, TTY, "no filename given"
 */

main(int argc, char **argv)
{
	static FileType ftype;
	int fd;


	fprintf(stderr, "Checking filestat ...\n");
	/* Get FileType of stdin	*/
	switch (ftype = filestat(STDIN)) {
	case TTY:
		fprintf(stderr, "FileType(STDIN) = TTY\n");
	break;
	case DISK:
		fprintf(stderr, "FileType(STDIN) = DISK\n");
	break;
	case DIRECTORY:
		fprintf(stderr, "FileType(STDIN) = DIRECTORY\n");
	break;
	case TAPE:
		fprintf(stderr, "FileType(STDIN) = TAPE\n");
	break;
	case PIPE:
		fprintf(stderr, "FileType(STDIN) = PIPE\n");
	break;
	case FIFO:
		fprintf(stderr, "FileType(STDIN) = FIFO\n");
	break;
	case SOCKET:
		fprintf(stderr, "FileType(STDIN) = SOCKET\n");
	break;
	case SYMLINK:
		fprintf(stderr, "FileType(STDIN) = SYMLINK\n");
	break;
	case BADFILETYPE:
		fprintf(stderr, "FileType(STDIN) = BADFILETYPE\n");
	break;
	default:
	    fprintf(stderr, "filestat(stdin) failed: ftype = %d\n", ftype);
	}


	/* Get FileType of stdout	*/
	switch (ftype = filestat(STDOUT)) {
	case TTY:
		fprintf(stderr, "FileType(STDOUT) = TTY\n");
	break;
	case DISK:
		fprintf(stderr, "FileType(STDOUT) = DISK\n");
	break;
	case DIRECTORY:
		fprintf(stderr, "FileType(STDOUT) = DIRECTORY\n");
	break;
	case TAPE:
		fprintf(stderr, "FileType(STDOUT) = TAPE\n");
	break;
	case PIPE:
		fprintf(stderr, "FileType(STDOUT) = PIPE\n");
	break;
	case FIFO:
		fprintf(stderr, "FileType(STDIN) = FIFO\n");
	break;
	case SOCKET:
		fprintf(stderr, "FileType(STDIN) = SOCKET\n");
	break;
	case BADFILETYPE:
		fprintf(stderr, "FileType(STDOUT) = BADFILETYPE\n");
	break;
	default:
	    fprintf(stderr, "filestat(stdout) failed: ftype = %d\n", ftype);
	}

	/* Get FileType of argv[1]	*/
	if (argc == 1) {
		fprintf(stderr, "no filename given\n");
		exit(1);
	}
	if (-1 == (fd = open(argv[1], O_RDONLY))) {
		fprintf(stderr, "can't open %s", argv[1]);
		exit(2);
	}

	switch (ftype = filestat(fd)) {
	case TTY:
		fprintf(stderr, "FileType(fd) = TTY\n");
	break;
	case DISK:
		fprintf(stderr, "FileType(fd) = DISK\n");
	break;
	case DIRECTORY:
		fprintf(stderr, "FileType(fd) = DIRECTORY\n");
	break;
	case TAPE:
		fprintf(stderr, "FileType(fd) = TAPE\n");
	break;
	case PIPE:
		fprintf(stderr, "FileType(fd) = PIPE\n");
	break;
	case FIFO:
		fprintf(stderr, "FileType(STDIN) = FIFO\n");
	break;
	case SOCKET:
		fprintf(stderr, "FileType(STDIN) = SOCKET\n");
	break;
	case BADFILETYPE:
		fprintf(stderr, "FileType(argv[1]) = BADFILETYPE\n");
	break;
	default:
	    fprintf(stderr, "filestat(argv[1]) failed: ftype = %d\n", ftype);
	}


	fprintf(stderr, "Checking printstat ...\n");
	/* Print FileType of stdin	*/
	fprintf(stderr, "FileType(STDIN) = %s\n", printstat(STDIN));


	/* Print FileType of stdout	*/
	fprintf(stderr, "FileType(STDOUT) = %s\n", printstat(STDOUT));


	/* Print FileType of argv[1]	*/
	if (argc == 1) {
		fprintf(stderr, "no filename given\n");
		exit(1);
	}
	if (-1 == (fd = open(argv[1], O_RDONLY))) {
		fprintf(stderr, "can't open %s", argv[1]);
		exit(2);
	}

	fprintf(stderr, "FileType(fd) = %s\n", printstat(fd));

	exit(0);
}
#endif

 

已标记关键词 清除标记
【为什么还需要学习C++?】 你是否接触很多语言,但从来没有了解过编程语言的本质? 你是否想成为一名资深开发人员,想开发别人做不了的高性能程序? 你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹?   那么C++就是你个人能力提升,职业之路进阶的不二之选。 【课程特色】 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。 2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。 3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。 【学完后我将达到什么水平?】 1.对C++的各个知识能够熟练配置、开发、部署; 2.吊打一切关于C++的笔试面试题; 3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。 【面向人群】 1.希望一站式快速入门的C++初学者; 2.希望快速学习 C++、掌握编程要义、修炼内功的开发者; 3.有志于挑战更高级的开发项目,成为资深开发的工程师。 【课程设计】 本课程包含3大模块 基础篇 本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。 进阶篇 本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。 提升篇: 本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操作、异常处理、代码重用等内容。
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页