-
-
Save twslankard/780397 to your computer and use it in GitHub Desktop.
#include <assert.h> | |
#include <sys/stat.h> | |
#include <stdint.h> | |
#include <libgen.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
int main(int argc, char * argv[]) { | |
struct stat file_stat; | |
struct stat parent_stat; | |
char * file_name; | |
char * parent_name; | |
assert(argc == 2); | |
file_name = argv[1]; | |
/* get the parent directory of the file */ | |
parent_name = dirname(file_name); | |
/* get the file's stat info */ | |
if( -1 == stat(file_name, &file_stat) ) { | |
perror("Stat: "); | |
goto fail; | |
} | |
/* determine whether the supplied file is a directory | |
if it isn't, then it can't be a mountpoint. */ | |
if( !(file_stat.st_mode & S_IFDIR) ) { | |
printf("%s is not a directory.\n", file_name); | |
goto fail; | |
} | |
/* get the parent's stat info */ | |
if( -1 == stat(parent_name, &parent_stat) ) { | |
perror("Stat: "); | |
goto fail; | |
} | |
/* print out device ids and inodes for each file */ | |
printf("Parent directory: %s\n", parent_name); | |
printf("Files's dev ID: %u\n", file_stat.st_dev); | |
printf("Parent's dev ID: %u\n", parent_stat.st_dev); | |
printf("Files's inode: %llu\n", (uint64_t)file_stat.st_ino); | |
printf("Parent's inode: %llu\n", (uint64_t)parent_stat.st_ino); | |
/* if file and parent have different device ids, | |
then the file is a mount point | |
or, if they refer to the same file, | |
then it's probably the root directory '/' | |
and therefore a mountpoint */ | |
if( file_stat.st_dev != parent_stat.st_dev || | |
( file_stat.st_dev == parent_stat.st_dev && | |
file_stat.st_ino == parent_stat.st_ino | |
) | |
) { | |
printf("%s IS a mountpoint.\n", file_name); | |
} else { | |
printf("%s is NOT a mountpoint.\n", file_name); | |
} | |
free(parent_name); | |
return 0; | |
fail: | |
free(parent_name); | |
return 1; | |
} |
That code below would be the correct code. dirname modifies the file and makes the parent point to the same string. So no allocations happen here. The original code thus ends up stating the same file path for both itself and the parent. The code above works.
include <assert.h>
include <sys/stat.h>
include <stdint.h>
include <libgen.h>
include <stdio.h>
include <stdlib.h>
include <string.h>
int main(int argc, char * argv[]) {
struct stat file_stat;
struct stat parent_stat;
char * file_name;
char * parent_name;
char* orig_name;
assert(argc == 2);
file_name = argv[1];
orig_name = (char*)malloc(strlen(file_name) + 1);
memcpy(orig_name, file_name, strlen(file_name) + 1);
printf("orig_name = %s\n", orig_name);
// get the parent directory of the file
parent_name = dirname(orig_name);
printf("file name = %s\n", file_name);
// get the file's stat info
if( -1 == stat(file_name, &file_stat) ) {
perror("Stat: ");
goto fail;
}
//determine whether the supplied file is a directory
// if it isn't, then it can't be a mountpoint.
if( !(file_stat.st_mode & S_IFDIR) ) {
printf("%s is not a directory.\n", file_name);
goto fail;
}
// get the parent's stat info
if( -1 == stat(parent_name, &parent_stat) ) {
perror("Stat: ");
goto fail;
}
//print out device ids and inodes for each file
printf("Parent directory: %s\n", parent_name);
printf("Files's dev ID: %u\n", file_stat.st_dev);
printf("Parent's dev ID: %u\n", parent_stat.st_dev);
printf("Files's inode: %llu\n", (uint64_t)file_stat.st_ino);
printf("Parent's inode: %llu\n", (uint64_t)parent_stat.st_ino);
// if file and parent have different device ids,
// then the file is a mount point
// or, if they refer to the same file,
// then it's probably the root directory
// and therefore a mountpoint
if( file_stat.st_dev != parent_stat.st_dev ||
( file_stat.st_dev == parent_stat.st_dev &&
file_stat.st_ino == parent_stat.st_ino ) ) {
printf("%s IS a mountpoint.\n", file_name);
} else {
printf("%s is NOT a mountpoint.\n", file_name);
}
// Free the malloc'ed pointer.
free(orig_name);
return 0;
fail:
free(orig_name);
return 1;
}
Bug in the code:
Freeing un-allocated ptr parent_name in lines 64 and 69. We supply file_name as a command line argument and make the char* file_name ptr point to this. From my knowledge of the allocation of memory, kernel puts the args above the main's stack and inside main, we make the pointer point to it. So there is no dynamically allocated memory here. So freeing un-allocated memory results in an obvious seg fault.