- 论坛徽章:
- 11
|
本帖最后由 superwujc 于 2012-12-18 17:57 编辑
下列代码有些又臭又长,摘自《The Linux Programming Interface》第4章,Page84,文件名为seek_io.c;我把它拼凑到了一起,没办法,小弟水平太菜,不知道怎样发问
先说一下代码功能:验证Linux系统调用open(),read(),write()和lseek(),第一个命令行参数指定将要被打开的文件,其余的参数指定将要在文件上执行的IO操作,每个操作包含一个 字母+数值 的形式
s表示偏移量,r表示从当前偏移量读取并以文本形式打印,R表示从当前偏移量读取并以十六进制形式打印,这3个参数都后跟表示字节长度的数值,w表示写入字符,后跟指定的字符串
如,seek_io myfile wxyz s1 r2 表示打开(或新建)myfile文件,在当前偏移量写入字符xyz,从文件开始处设置1字节的偏移量后,读取2个字节
由于里面细节有些复杂,说一下具体疑问:
在main()中执行到if (-1 == fd)判断文件是否打开或创建成功时,调用了errExit()函数,而errExit()函数又调用了outputError()函数,但是想不通这个outputError()函数是干什么用的,为什么直接调用先前定义的Boolean类型,而且是直接使用TRUE
烦请哪位大神,帮忙解释一下if (-1 == fd)时,调用errExit()函数和outputError()函数处理的具体思路和具体步骤吗?不胜感激!!!
头文件和函数声明部分- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <string.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <stdarg.h>
- #include "ename.c.inc"
- #include <ctype.h> //declaration for character test & map function
- #define GN_NONNEG 01 /* Value must be >= 0 */
- #define GN_GT_0 02 /* Value must be > 0 */
- #define GN_ANY_BASE 0100 /* Can use any base - like strtol(3) */
- #define GN_BASE_8 0200 /* Value is expressed in octal */
- #define GN_BASE_16 0400 /* Value is expressed in hexadecimal */
- typedef enum { FALSE, TRUE } Boolean;
- void usageErr(const char *format, ...);
- void errExit(const char *format, ...);
- void cmdLineErr(const char *format, ...);
- static void terminate(Boolean useExit3);
- static void outputError(Boolean useErr, int err, Boolean flushStdout,
- const char *format, va_list ap);
- static void gnFail(const char *fname, const char *msg, const char *arg, const char *name);
- long getLong(const char *arg, int flags, const char *name);
- static long getNum(const char *fname, const char *arg, int flags, const char *name);
复制代码 ename.c.inc部分- static char *ename[] = {
- /* 0 */ "",
- /* 1 */ "EPERM", "ENOENT", "ESRCH", "EINTR", "EIO", "ENXIO",
- /* 7 */ "E2BIG", "ENOEXEC", "EBADF", "ECHILD",
- /* 11 */ "EAGAIN/EWOULDBLOCK", "ENOMEM", "EACCES", "EFAULT",
- /* 15 */ "ENOTBLK", "EBUSY", "EEXIST", "EXDEV", "ENODEV",
- /* 20 */ "ENOTDIR", "EISDIR", "EINVAL", "ENFILE", "EMFILE",
- /* 25 */ "ENOTTY", "ETXTBSY", "EFBIG", "ENOSPC", "ESPIPE",
- /* 30 */ "EROFS", "EMLINK", "EPIPE", "EDOM", "ERANGE",
- /* 35 */ "EDEADLK/EDEADLOCK", "ENAMETOOLONG", "ENOLCK", "ENOSYS",
- /* 39 */ "ENOTEMPTY", "ELOOP", "", "ENOMSG", "EIDRM", "ECHRNG",
- /* 45 */ "EL2NSYNC", "EL3HLT", "EL3RST", "ELNRNG", "EUNATCH",
- /* 50 */ "ENOCSI", "EL2HLT", "EBADE", "EBADR", "EXFULL", "ENOANO",
- /* 56 */ "EBADRQC", "EBADSLT", "", "EBFONT", "ENOSTR", "ENODATA",
- /* 62 */ "ETIME", "ENOSR", "ENONET", "ENOPKG", "EREMOTE",
- /* 67 */ "ENOLINK", "EADV", "ESRMNT", "ECOMM", "EPROTO",
- /* 72 */ "EMULTIHOP", "EDOTDOT", "EBADMSG", "EOVERFLOW",
- /* 76 */ "ENOTUNIQ", "EBADFD", "EREMCHG", "ELIBACC", "ELIBBAD",
- /* 81 */ "ELIBSCN", "ELIBMAX", "ELIBEXEC", "EILSEQ", "ERESTART",
- /* 86 */ "ESTRPIPE", "EUSERS", "ENOTSOCK", "EDESTADDRREQ",
- /* 90 */ "EMSGSIZE", "EPROTOTYPE", "ENOPROTOOPT",
- /* 93 */ "EPROTONOSUPPORT", "ESOCKTNOSUPPORT",
- /* 95 */ "EOPNOTSUPP/ENOTSUP", "EPFNOSUPPORT", "EAFNOSUPPORT",
- /* 98 */ "EADDRINUSE", "EADDRNOTAVAIL", "ENETDOWN", "ENETUNREACH",
- /* 102 */ "ENETRESET", "ECONNABORTED", "ECONNRESET", "ENOBUFS",
- /* 106 */ "EISCONN", "ENOTCONN", "ESHUTDOWN", "ETOOMANYREFS",
- /* 110 */ "ETIMEDOUT", "ECONNREFUSED", "EHOSTDOWN", "EHOSTUNREACH",
- /* 114 */ "EALREADY", "EINPROGRESS", "ESTALE", "EUCLEAN",
- /* 118 */ "ENOTNAM", "ENAVAIL", "EISNAM", "EREMOTEIO", "EDQUOT",
- /* 123 */ "ENOMEDIUM", "EMEDIUMTYPE", "ECANCELED", "ENOKEY",
- /* 127 */ "EKEYEXPIRED", "EKEYREVOKED", "EKEYREJECTED",
- /* 130 */ "EOWNERDEAD", "ENOTRECOVERABLE", "ERFKILL"
- };
- #define MAX_ENAME 132
复制代码 main部分- int main (int argc, char *argv[])
- {
- size_t len;
- off_t offset;
- int fd, ap, j;
- char *buf;
- ssize_t numRead, numWritten;
- if (argc < 3 || 0 == strcmp(argv[1], "--help"))
- {
- usageErr ("%s file {r<length>|R<length>|w<string>|s<offset>}...\n", argv[0]);//only two arguments
- }
- fd = open (argv[1], O_RDWR | O_CREAT,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);//rw-rw-rw
-
- if (-1 == fd)
- {
- errExit ("open");
- }
-
- for (ap = 2; ap < argc; ap++)
- {
- switch (argv[ap][0])
- {
- case 'r':
- case 'R':
- len = getLong (&argv[ap][1], GN_ANY_BASE, argv[ap]);
- buf = malloc (len);
- if (NULL == buf)
- {
- errExit ("malloc");
- }
- numRead = read (fd, buf, len);
- if (-1 == numRead)
- {
- errExit ("read");
- }
- if (0 == numRead)
- {
- printf ("%s: end-of-file\n", argv[ap]);
- } else
- {
- printf ("%s: ", argv[ap]);
- for (j = 0; j < numRead; j++)
- {
- if ('r' == argv[ap][0])
- {
- printf ("%c", isprint((unsigned char) buf[j]) ?
- buf[j] : '?');
- } else
- {
- printf ("%02x ", (unsigned int) buf[j]);
- }
- }
- printf ("\n");
- }
- free (buf);
- break;
- case 'w':
- numWritten = write (fd, &argv[ap][1], strlen (&argv[ap][1]));
- if (-1 == numWritten)
- {
- errExit ("write");
- }
- printf ("%s: wrote %ld bytes\n", argv[ap], (long) numWritten);
- break;
- case 's':
- offset = getLong (&argv[ap][1], GN_ANY_BASE, argv[ap]);
- if (-1 == lseek (fd, offset, SEEK_SET))
- {
- errExit ("lseek");
- }
- printf ("%s: seek succeeded\n", argv[ap]);
- break;
- default:
- cmdLineErr ("Argument must start with [rRws]: %s\n", argv[ap]);
- }
- }
- exit (EXIT_SUCCESS);
- }
复制代码 其他函数部分- void usageErr(const char *format, ...)
- {
- va_list argList;
- fflush(stdout); /* Flush any pending stdout */
- fprintf(stderr, "Usage: ");
- va_start(argList, format);
- vfprintf(stderr, format, argList);
- va_end(argList);
- fflush(stderr); /* In case stderr is not line-buffered */
- exit(EXIT_FAILURE);
- }
- void errExit(const char *format, ...)
- {
- va_list argList;
- va_start(argList, format);
- outputError(TRUE, errno, TRUE, format, argList);
- va_end(argList);
- terminate(TRUE);
- }
- void terminate(Boolean useExit3)
- {
- char *s;
- /* Dump core if EF_DUMPCORE environment variable is defined and
- is a nonempty string; otherwise call exit(3) or _exit(2),
- depending on the value of 'useExit3'. */
- s = getenv("EF_DUMPCORE");
- if (s != NULL && *s != '\0')
- abort();
- else if (useExit3)
- exit(EXIT_FAILURE);
- else
- _exit(EXIT_FAILURE);
- }
- void cmdLineErr(const char *format, ...)
- {
- va_list argList;
- fflush(stdout); /* Flush any pending stdout */
- fprintf(stderr, "Command-line usage error: ");
- va_start(argList, format);
- vfprintf(stderr, format, argList);
- va_end(argList);
- fflush(stderr); /* In case stderr is not line-buffered */
- exit(EXIT_FAILURE);
- }
- long getNum(const char *fname, const char *arg, int flags, const char *name)
- {
- long res;
- char *endptr;
- int base;
- if (arg == NULL || *arg == '\0')
- gnFail(fname, "null or empty string", arg, name);
- base = (flags & GN_ANY_BASE) ? 0 : (flags & GN_BASE_8) ? 8 :
- (flags & GN_BASE_16) ? 16 : 10;
- errno = 0;
- res = strtol(arg, &endptr, base);
- if (errno != 0)
- gnFail(fname, "strtol() failed", arg, name);
- if (*endptr != '\0')
- gnFail(fname, "nonnumeric characters", arg, name);
- if ((flags & GN_NONNEG) && res < 0)
- gnFail(fname, "negative value not allowed", arg, name);
- if ((flags & GN_GT_0) && res <= 0)
- gnFail(fname, "value must be > 0", arg, name);
- return res;
- }
- void gnFail(const char *fname, const char *msg, const char *arg, const char *name)
- {
- fprintf(stderr, "%s error", fname);
- if (name != NULL)
- fprintf(stderr, " (in %s)", name);
- fprintf(stderr, ": %s\n", msg);
- if (arg != NULL && *arg != '\0')
- fprintf(stderr, " offending text: %s\n", arg);
- exit(EXIT_FAILURE);
- }
- void outputError(Boolean useErr, int err, Boolean flushStdout,
- const char *format, va_list ap)
- {
- #define BUF_SIZE 500
- char buf[BUF_SIZE], userMsg[BUF_SIZE], errText[BUF_SIZE];
- vsnprintf(userMsg, BUF_SIZE, format, ap);
- if (useErr)
- snprintf(errText, BUF_SIZE, " [%s %s]",
- (err > 0 && err <= MAX_ENAME) ?
- ename[err] : "?UNKNOWN?", strerror(err));
- else
- snprintf(errText, BUF_SIZE, ":");
- snprintf(buf, BUF_SIZE, "ERROR%s %s\n", errText, userMsg);
- if (flushStdout)
- fflush(stdout); /* Flush any pending stdout */
- fputs(buf, stderr);
- fflush(stderr); /* In case stderr is not line-buffered */
- }
- long getLong(const char *arg, int flags, const char *name)
- {
- return getNum("getLong", arg, flags, name);
- }
复制代码 |
|