|
CS456 - Systems Programming
Spring 2026
|
Displaying ./code/h4/filetypev2.c
/*
This takes a file, and depending on it's attributes, something happens
We're going to take what we did in Assignment h3 and make some changes
Here, we're going to do stuff with regular files
- regular files:
- what this does depends on whether or not you have execute permission
- if you do, execute the program using the fork and exec functions (but if someone passes
in this very program as an argument, do NOT let it execute!)
- if you don't, print the file's contents to stdout
you will also modify extras.h to get the printType function to work. That will
handle files other than regular files or directories.
*/
// header files
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <fcntl.h>
//our custom header file
#include "extras.h"
int main(int argc, char **argv){
//prints usage statement if file not provided
if(argc < 2){
fprintf(stderr, "Usage %s file\n", argv[0]);
exit(1);
}
// call stat on the file we're passing in
struct stat st;
int rt = lstat(argv[1], &st);
if (rt < 0){
perror("Error: stat failed");
exit(-1);
}
//check what type of file we have here
//if it's a regular file, we're going to do something based on permission values
if(S_ISREG(st.st_mode)){
//check if owner has execute permission
// feel free to use the "check Permissions function I wrote in extras.h"
// hint: you'll be passing in the mode and the mask value for "owner has execute permission"
int perm = checkPermissions(st.st_mode, S_IXUSR);
//if it does, try to execute it, but don't let it execute itself
// otherwise just print contents to stdout
if(perm == 1){
//need to compare device and inode values of this executable and the one passed in
// make sure this doesn't try to run it's own executable
// hint use the fileMatchStr function in extras.h to determine this:
if(fileMatchStr(argv[0], argv[1])){
printf("Looks like you're tryimg to run this very program through this one\n");
exit(2);
}
//inform user what program they're executing
//call fork, store in pid
//check return value of pid
//if pid > 0 we are in the parent process
//we'll have a child, so get the exit code
// if pid == 0 we are in the child process
//use a variant of exec to execute the program
} else {
// if it's not executable, so we're just printing the contents
// essentally implementing the cat command here
//declare char buffer for content
//open file for reading
//checking return value of open
//setting up read/write loop
//close file once done
}
}
//if it's a directory,
// print the contents but not hidden files
// print the count of total files as well as hidden files
} else if(S_ISDIR(st.st_mode)){
DIR *mydir; //defining pointer to directory
struct dirent *file; //accessing the dirent struct, defined in dirent.h
mydir = opendir(argv[1]); //opening a directory
//check return value of opendir
if(mydir == NULL){
perror("opendir failed");
exit(-2);
}
//keep counts of files
int count = 0;
int hidden = 0;
//reading through directory
while((file = readdir(mydir)) != NULL){
count++;
// checking if this is a hidden file ,
// denoted by a '.' period character in the first chaacter of filename
if(file->d_name[0] == '.'){
hidden++;
continue;
}
printf("%s\n", file->d_name);
}
printf("The directory %s has %d files, of which %d are hidden\n", argv[1], count, hidden);
closedir(mydir);
//anything else, just print the name along with it's type in octal
} else {
//get what filetype this file is
int type = getType(st.st_mode);
//print filename
printf("Name: %s\n", argv[1]);
//print the filetype
printType(type);
}
return 0;
}
|