IC221: Systems Programming (SP14)


Home Policy Calendar Syllabus Resources Piazza

Lab 10: Linking and File Seeking

Table of Contents

1 PART 1: File Linking

1.1 Task 1 Creating Linked Files

#!/bin/bash


touch a b c d e
mkdir dir1 dir2 dir3

#TODO: Add relevant linking commands

ln -s a s
ln -s s t

ln a dir1/a

ln a dir2/a

ln a dir3/a

cd dir3

ln -s ../d 

ln -s ../c

ln -s ../t gonavy

1.2 Task 2: Identifying Linked Files

#!/bin/bash

rm -f b c d
ln -s a b
ln -s a c
ln -s a d

cd dir1
rm -f f
ln -s ../a f
cd ..

cd dir2
rm g
ln -s ../a g
cd ..

cd dir3
rm -f j
ln -s i j
cd ..

rm -f k
ln -s e k

2 PART 2: File Seeking

2.1 Task 3: llines

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>

/* USAGE Information */
char USAGE[] = "llines [OPTIONS] [file]\n"
  "\n"
  "Will print the specified bytes to stdout.\n"
  "\n"
  "OPTIONS:\n"
  "  -s start_offset \t Specify the start offset\n"
  "  -e end_offset   \t Specify the end offset\n"
  "\n"
  "EXAMPLES:\n"
  "llines -s 10 -e 20 file : print between the bytes between offset 10 and 20\n"
  "llines -s 20 -e 10 file : ERROR: end offset can be greater than start offset\n"
  "llines -s 10 file : print bytes between offset 10 and the end of the file\n"
  "llines -e 10 file : print bytes from start of file until 10 from end\n"
  "llines file : print all bytes of file, like cat\n"
  "llines -e -10 : ERROR: cannot have negative offsets\n";


//OPTIONS
typedef struct{
  int start; //the start offset
  int end; //the end offset
  int f_index; //ignore
} opt_t;


//parsing commmand line options : DO NOT EDIT
void parse_args(int argc, char * argv[], opt_t * opts){
  int c;

  opts->start=-1;
  opts->end=-1;

  while((c = getopt(argc,argv, "hs:e:")) != -1){
      switch(c)
        {
        case 'h':
          printf("%s", USAGE);
          exit(0);
          break;
        case 's':
          if(sscanf(optarg,"%d",&(opts->start)) == 0){
            fprintf(stderr, "ERROR: Invlaid value for start_offset");
            fprintf(stderr, "USAGE");
            exit(1);
          }
          break;
        case 'e':
          if(sscanf(optarg,"%d",&(opts->end)) == 0){
            fprintf(stderr, "ERROR: Invlaid value for end_offset");
            fprintf(stderr, "USAGE");
            exit(1);
          }
          break;
        default:
          fprintf(stderr, "ERROR: Unknown option '%c' \n", c);
          exit(0);
          break;
        }
    }

  opts->f_index = optind;
}

int main(int argc, char * argv[]){

  opt_t opts;
  int fd, i;
  char c;

  parse_args(argc,argv,&opts);

  if(opts.f_index == argc){
    fprintf(stderr, "ERROR: Require a file argument\n");
    exit(1);
  }else{

    if( (fd = open(argv[opts.f_index], O_RDONLY)) < 0){
      fprintf(stderr, "ERROR: Invalid file\n");
      exit(1);
    }
  }


  //TODO: Complete the program based on the specification
  //
  //    YOU MUST USE lseek(), read(), and write()

  if( opts.end < 0){
    opts.end = lseek(fd,0,SEEK_END);
  }

  if(opts.start > 0){
    lseek(fd, opts.start, SEEK_SET);
  }

  if(opts.end < opts.start){
    fprintf(stderr, "ERROR: Invalid start and end (end < start)\n");
  }

  //from start to end
  if(opts.end > 0 && opts.start >= 0){
    for(i=0;i<opts.end - opts.start;i++){
      if( read(fd,&c,1) ){
        write(1,&c,1);
      }
    }
  }

  //from end to end
  if(opts.end > 0 && opts.start < 0){

    lseek(fd,-1 * opts.end, SEEK_END);

    while(1){
      if( read(fd,&c,1) ){
        write(1,&c,1);
      }else{
        break;
      }
    }
  }

  return 0;
}

2.2 Task 4: flines

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>

/* USAGE Information */
char USAGE[] = "flines [OPTIONS] [file]\n"
  "\n"
  "Will print the specified bytes to stdout..\n"
  "\n"
  "OPTIONS:\n"
  "  -s start_offset \t Specify the start offset\n"
  "  -e end_offset   \t Specify the end offset\n"
  "\n"
  "EXAMPLES:\n"
  "flines -s 10 -e 20 file : print between the bytes between offset 10 and 20\n"
  "flines -s 20 -e 10 file : ERROR: end offset can be greater than start offset\n"
  "flines -s 10 file : print bytes between offset 10 and the end of the file\n"
  "flines -e 10 file : print bytes from start of file until 10 from end\n"
  "flines file : print all bytes of file, like cat\n"
  "flines -e -10 : ERROR: cannot have negative offsets\n";


//OPTIONS
typedef struct{
  int start; //the start offset
  int end; //the end offset
  int f_index; //ignore
} opt_t;

//parsing commmand line options : DO NOT EDIT
void parse_args(int argc, char * argv[], opt_t * opts){
  int c;

  opts->start=-1;
  opts->end=-1;

  while((c = getopt(argc,argv, "hs:e:")) != -1){
      switch(c)
        {
        case 'h':
          printf("%s", USAGE);
          exit(0);
          break;
        case 's':
          if(sscanf(optarg,"%d",&(opts->start)) == 0){
            fprintf(stderr, "ERROR: Invlaid value for start_offset");
            fprintf(stderr, "USAGE");
            exit(1);
          }
          break;
        case 'e':
          if(sscanf(optarg,"%d",&(opts->end)) == 0){
            fprintf(stderr, "ERROR: Invlaid value for end_offset");
            fprintf(stderr, "USAGE");
            exit(1);
          }
          break;
        default:
          fprintf(stderr, "ERROR: Unknown option '%c' \n", c);
          exit(0);
          break;
        }
    }

  opts->f_index = optind;
}

int main(int argc, char * argv[]){

  opt_t opts;
  int i;
  FILE * file;
  char c;

  parse_args(argc,argv,&opts);

  if(opts.f_index == argc){
    fprintf(stderr, "ERROR: Require a file argument\n");
    exit(1);
  }else{

    if( (file = fopen(argv[opts.f_index], "r"))  == NULL){
      fprintf(stderr, "ERROR: Invalid file\n");
      exit(1);
    }
  }


  //TODO: Complete the program
  //
  //    YOU MUST USE fseek()! and apropriate reading and writing procedures

  if( opts.end < 0){

    fseek(file,0,SEEK_END);
    opts.end = ftell(file);
  }

  if(opts.start > 0){
    fseek(file, opts.start, SEEK_SET);
  }

  if(opts.end < opts.start){
    fprintf(stderr, "ERROR: Invalid start and end (end < start)\n");
  }

  //from start to end
  if(opts.end > 0 && opts.start >= 0){
    for(i=0;i<opts.end - opts.start;i++){
      if( (c = fgetc(file)) != EOF ){
        putchar(c);
      }
    }
  }

  //from end to end
  if(opts.end > 0 && opts.start < 0){

    fseek(file,-1 * opts.end, SEEK_END);

    while(1){
      if( (c = fgetc(file)) != EOF){
        putchar(c);
      }else{
        break;
      }
    }
  }

  return 0;
}