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

Unix系統程式設計open,read,write和lseek的綜合練習

soffet:從檔案開始檢索到offset位元組位置

rlength:在檔案當前偏移量處,從檔案中讀取length位元組資料,並以文字形式顯式

Rlength:在當前檔案偏移量處,從檔案中讀取length位元組資料,並以十六進位制形式顯式

wstr:在當前檔案偏移量處,由檔案寫入由str指定的字串

main.c

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

寫個Makefile

# Edit the following for your installation

CC      =       /usr/bin/cc
CXX     =       /usr/bin/g++

#==============================================================
# Compiler and linker flags
CXXFLAGS=       -Wall -g
CFLAGS  =       -Wall -g
LFLAGS  =
INCPATH =
LIBS=
####### Implicit rules

.SUFFIXES: .o .c .cpp .cc .cxx .C

.cpp.o:
        $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"

.cc.o:
        $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"

.cxx.o:
        $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"

.C.o:
        $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"

.c.o:
        $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<"



#==============================================================
# This program's code files
prg             =       seektest
OBJS    =       main.o  get_num.o

#==============================================================
# File dependencies and rules

all:    $(prg)

$(prg): $(OBJS)
        $(CC) -o $@ $(LFLAGS) $(OBJS) $(LIBS)

clean:
        rm -f *~
        rm -f *.o
        rm -f core

cleanall:clean
        rm -f $(prg)