1. 程式人生 > >Unix系統編程()open,read,write和lseek的綜合練習

Unix系統編程()open,read,write和lseek的綜合練習

har ring strtol 開始 splay 進制 void oct unsigned

需求:程序的第一個命令行參數為將要打開的文件名稱,余下的參數則指定了文件上執行的輸入輸出操作。每個表示操作的參數都以一個字母開頭,緊跟以相關值(中間無空格分隔)。

soffet:從文件開始檢索到offset字節位置

rlength:在文件當前偏移量處,從文件中讀取length字節數據,並以文本形式顯式

Rlength:在當前文件偏移量處,從文件中讀取length字節數據,並以十六進制形式顯式

wstr:在當前文件偏移量處,由文件寫入由str指定的字符串

#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include 
"get_num.h" #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { size_t len; off_t offset; int fd, ap, j; char *buf; ssize_t numRead, numWritten; /* usage */ if(argc < 3 || strcmp(argv[1
], "--help") == 0) printf("%s file {r<length> | R<length> | w<string> | s<offset>} ...\n", argv[0]); /* open or create file */ fd = open(argv[1], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
| S_IWOTH); /* is system call success */ if(fd == -1) printf("open file error\n"); /* biz code */ for(ap = 2; ap < argc; ap++) { switch(argv[ap][0]) { case r: /* Display bytes at current offset, as text */ case R: /* Display bytes at current offset, in hex */ len = getLong(&argv[ap][1], GN_ANY_BASE, argv[ap]); /* alloc buffer */ buf = malloc(len); /* is alloc success */ if(buf == NULL) printf("malloc error\n"); numRead = read(fd, buf, len); if(numRead == -1) /* read fail */ printf("read\n"); /* end of file */ if(numRead == 0) printf("%s: end-of-file\n", argv[ap]); else { printf("%s: ", argv[ap]); for(j=0; j<numRead; j++) if(argv[ap][0] == r) printf("%c", isprint((unsigned char) buf[j]) ? buf[j] : ?); else printf("%O2x ", (unsigned int) buf[j]); printf("\n"); } /* free memory */ free(buf); break; case w: /* Write string at current offset */ numWritten = write(fd, &argv[ap][1], strlen(&argv[ap][1])); if(numWritten == -1) printf("write error\n"); printf("%s: wrote %ld bytes\n", argv[ap], (long) numWritten); break; case s: offset = getLong(&argv[ap][1], GN_ANY_BASE, argv[ap]); if(lseek(fd, offset, SEEK_SET) == -1) printf("lseek error!\n"); printf("%s: seek successed\n", argv[ap]); break; default: printf("Argument must start with [rRws]: %s\n", argv[ap]); } } exit(0); }

get_num.h

#ifndef GET_NUM_H
#define GET_NUM_H

#define GN_NONNEG          01   /* Value must be >= 0 */
#define GN_GT_0            02   /* Value must be > 0 */

                                /* By default, integers are decimal */
#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 */

long getLong(const char *arg, int flags, const char *name);

int getInt(const char *arg, int flags, const char *name);

#endif

get_num.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include "get_num.h"

static 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", name);

  if(arg != NULL && *arg != \0)
    fprintf(stderr, "        offending text: %s\n", arg);

  exit(EXIT_FAILURE);
}

static 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;
}

long getLong(const char *arg, int flags, const char *name)
{
  return getNum("getLong", arg, flags, name);
}

int getInt(const char *arg, int flags, const char *name)
{
  long res;

  res = getNum("getInt", arg, flags, name);
  if(res > INT_MAX || res < INT_MIN)
    gnFail("getInt", "integer out of range", arg, name);

  return (int) res;
}

Unix系統編程()open,read,write和lseek的綜合練習