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