IC221: Systems Programming (SP14)


Home Policy Calendar Syllabus Resources Piazza

Lab 05: Makefiles and File Statistic System Calls (SOLUTION)

Table of Contents

Part 1: Makefiles

Task 1: simple

all: compileme

compileme: compileme.c
        clang -g -Wall compileme.c -o compileme

clean: 
        rm -f compileme

Task 2: multi

all: runme dontrunme

runme: runme.o library.o
        clang runme.o library.o -o runme

library.o: library.c library.h
        clang -c library.c -o library.o

runme.o: runme.c
        clang -c runme.c -o runme.o

dontrunme: dontrunme.o library.o fun.o
        clang dontrunme.o library.o fun.o -o dontrunme

fun.o: fun.c fun.h
        clang -c fun.c -o fun.o

dontrunme.o: dontrunme.c
        clang -c dontrunme.c -o dontrunme.o

clean:
        rm -f runme dontrunme *.o *~

Part 2: Task 3: mycp

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/errno.h>
#include <fcntl.h>

#define BUFFSIZE 4096

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

  char buf[BUFFSIZE];
  int n, fd_src, fd_dest;
  struct stat fs;

  //check for invalid arguments
  if( argc != 3 ){
    fprintf(stderr, "%s: Invalid number of arguments\n", argv[0]);
    return 1;
  }

  //open the source file, fail if can't read
  if ( (fd_src = open(argv[1], O_RDONLY)) < 0 ){
    perror(argv[0]);
    return 1;
  }

  //stat the fd to get info
  if ( (fstat( fd_src, &fs)) < 0 ){
    perror(argv[0]);
    return 1;
  }

  //report error if is a directory
  if( S_ISDIR(fs.st_mode) ){
    fprintf(stderr, "%s: %s: Is a directory\n", argv[0], argv[1]);
    return 1;
  }


  //open the destination with the right Oring and mode
  if ( (fd_dest = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 
                       fs.st_mode & 0777)) < 0){
    perror(argv[0]);
    return 1;
  }


  //chmod of the dest to the mode of the src
  if( fchmod(fd_dest, fs.st_mode) < 0){
    perror(argv[0]);
    return 1;
  }

  //perform the read/write loop with the BUFFSIZE
  while( (n = read(fd_src, buf, BUFFSIZE)) > 0){
    if (write(fd_dest, buf, n) < 0){
      perror(argv[0]);
      break;
    }
  }

  //error condition on read
  if( n < 0){
    perror(argv[0]);
  }

  //close file descriptors
  close(fd_dest);
  close(fd_src);

  //SUCCESS!

  return 0;
}

Part 3: Task 4: myls

#include <dirent.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <bsd/string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/errno.h>
#include <time.h>
#include <pwd.h>
#include <pwd.h>
#include <grp.h>


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

  DIR * dir_p;
  struct dirent * entry;

  struct stat filestat;
  struct passwd * pwd;
  struct group * grp;
  char mode_str[12];

  //open the directory to read each of the entries
  if( (dir_p = opendir(".")) == NULL){
    fprintf(stderr, "ERROR: diropen: %s\n", strerror(errno));
    return 1;
  }

  //foreach entry in the directory
  while( NULL != (entry = readdir(dir_p)) ){

    //get stat
    if( (stat( entry->d_name, &filestat)) < 0){
      fprintf(stderr, "ERROR: stat: %s: %s\n", entry->d_name, strerror(errno));
      return 1;
    }    

    //get username
    if( (pwd = getpwuid(filestat.st_uid)) == NULL){
      fprintf(stderr, "ERROR: pwuid: %s\n", strerror(errno));
      return 1;
    }

    //get groupname
    if( (grp = getgrgid(filestat.st_gid)) == NULL){
      fprintf(stderr, "ERROR: getgrgid: %s\n", strerror(errno));
      return 1;
    }

    //get the mode as a string
    strmode(filestat.st_mode, mode_str);

    //print the line
    printf("%s\t%s\t%s\t%s\t%d\t%s", mode_str, entry->d_name, pwd->pw_name, 
           grp->gr_name, (int) filestat.st_size, ctime(&(filestat.st_mtime)));
  }

  closedir(dir_p);
}

Part 4: Task 5: mytouch

#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>

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

  struct stat sb;
  struct timeval tv[2];

  if(argc == 1){ return 1;}

  //get current file stats
  if( stat(argv[1], &sb) < 0  ){
    perror(argv[0]);
    return 1;
  }

  //print the last modified time
  printf("Last Modified: %s", ctime(&(sb.st_mtime)));

  //get current time, store in tv[0]
  if(gettimeofday(&(tv[0]), NULL) < 0){
    perror(argv[0]);
    return 1;
  }

  //set tv[1] to tv[0], both the same
  tv[1] = tv[0];

  //update the times
  if(utimes(argv[1], tv) <  0){
    perror(argv[0]);
    return 1;
  }

  //get new file stats
  if( stat(argv[1], &sb) < 0  ){
    perror(argv[0]);
    return 1;
  }

  //print the new new modified time
  printf("New Modified: %s", ctime(&(sb.st_mtime)));


  return 0;
}