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