Code:
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#define FS_FILE 0x01
#define FS_DIRECTORY 0x02
char *get_name_from_path (char *dest, char *path);
struct initrd_file_ptr
{
unsigned char magic;
char name[128];
unsigned int offset;
unsigned int length;
unsigned int type;
};
struct mydirent // One of these is returned by the readdir call, according to POSIX.
{
char name[128]; // Filename.
};
unsigned int file_num;
FILE *ffstream;
char *initrdfile = "./initrd.img";
unsigned int off;
int main(char argc, char **argv)
{
int root_file_num = (argc-1)/2;
file_num = 0;
int i;
for (i=1; i<=root_file_num; i++)
{
if (*argv[i*2-1] == 'f')
{
file_num++;
}
else if (*argv[i*2-1] == 'd')
{
iterate_dir_fcount(argv[i*2]);
}else
printf("Usage: ./filesystem_generator [d|f] file1 [[d|f] file2 ..]\n");
}
printf("file number: %i\n",file_num);
off = sizeof(int) + sizeof(struct initrd_file_ptr)*file_num;
file_num = 0;
struct initrd_file_ptr headers[file_num];
for (i=1; i<=root_file_num; i++)
{
if (*argv[i*2-1] == 'f')
{
char lfname[strlen (argv[i*2])];
lfname[0] = '\0';
get_name_from_path (lfname, argv[i*2]);
make_reg_header (lfname, argv[i*2], file_num, headers);
file_num++;
}
else if (*argv[i*2-1] == 'd')
{
printf("argv_value:%i\n", (int)*argv[i*2-1]);//outputs 100
iterate_dir(argv[i*2], headers, argv[i*2-1]);
printf("argv_value:%i\n", (int)*argv[i*2-1]);//outputs 0
}else
printf("2.Usage: ./filesystem_generator [d|f] file1 [[d|f] file2 ..]\n");
}
ffstream = fopen (initrdfile, "w");
fwrite (&file_num, sizeof (unsigned int), 1, ffstream);
fwrite (headers, sizeof (struct initrd_file_ptr), file_num, ffstream);
file_num = 0;
i = 1;
for (i=1; i<=root_file_num; i++)
{
if (*argv[i*2-1] == 'f')
{
write_reg_data (argv[i*2], file_num, headers);
file_num++;
}
else if (*argv[i*2-1] == 'd')
{
iterate_dir_write(argv[i*2], headers);
}else
printf("3.Usage: ./filesystem_generator [d|f] file1 [[d|f] file2 ..]:%i\n", (int) *argv[i*2-1]);
}
fclose(ffstream);
return 0;
}
int iterate_dir_fcount(char *dir)
{
DIR *directory;
struct dirent *finfo;
directory = opendir (dir);
if (directory != NULL)
{
file_num++;
while (finfo = readdir (directory))
{
if(finfo->d_type == DT_REG){
file_num++;
printf("%i: reg file: %s\n", file_num, finfo->d_name);
}
else if (finfo->d_type == DT_DIR){
if (strcmp (finfo->d_name, ".") != 0 && strcmp (finfo->d_name, "..") != 0){
char tmp[strlen(dir)+strlen(finfo->d_name)+1];
tmp[0]='\0';
strcat (tmp,dir);
strcat (tmp, "/");
strcat (tmp, finfo->d_name);
printf("%i: dir: %s\n", file_num+1, tmp);
iterate_dir_fcount (tmp);
}
}
else
printf("%s: invalid file type\n", finfo->d_name);
}
closedir (directory);
}else
printf("failed to open directory: %s\n", dir);
return 0;
}
void iterate_dir(char *dir, struct initrd_file_ptr *headers, char *arg)
{
DIR *directory;
struct dirent *finfo;
directory = opendir (dir);
if (directory != NULL)
{
unsigned int tmpfcount = file_num;
while (finfo = readdir (directory))
{
if(finfo->d_type == DT_REG){
char tmp[strlen (dir) + strlen (finfo->d_name) + 2];
tmp[0]='\0';
strcat (tmp,dir);
strcat (tmp, "/");
strcat (tmp, finfo->d_name);
make_reg_header (finfo->d_name, tmp, file_num, headers);
file_num++;
}
else if (finfo->d_type == DT_DIR){
if (strcmp (finfo->d_name, ".") != 0 && strcmp (finfo->d_name, "..") != 0){
char tmp[strlen(dir) + strlen(finfo->d_name) + 2];
tmp[0]='\0';
strcat (tmp,dir);
strcat (tmp, "/");
strcat (tmp, finfo->d_name);
iterate_dir (tmp, headers, arg);
}
}
}
char ldname[strlen (dir)+1];
ldname[0] = "\0";
get_name_from_path (ldname, dir);
make_dir_header (ldname, file_num, file_num - tmpfcount, headers);
file_num++;
closedir(directory);
printf("the argument:%i\n", (int)*arg); //outputs 100
}
printf("the argument:%i\n", (int)*arg); //outputs 0
}
int iterate_dir_write(char *dir, struct initrd_file_ptr *headers)
{
DIR *directory;
struct dirent *finfo;
directory = opendir (dir);
if (directory != NULL)
{
unsigned int tmpfcount = file_num;
while (finfo = readdir (directory))
{
if(finfo->d_type == DT_REG){
char tmp[strlen (dir) + strlen (finfo->d_name) + 1];
tmp[0]='\0';
strcat (tmp,dir);
strcat (tmp, "/");
strcat (tmp, finfo->d_name);
write_reg_data (tmp, file_num, headers);
file_num++;
}
else if (finfo->d_type == DT_DIR){
if (strcmp (finfo->d_name, ".") != 0 && strcmp (finfo->d_name, "..") != 0){
char tmp[strlen(dir) + strlen(finfo->d_name) + 1];
tmp[0]='\0';
strcat (tmp,dir);
strcat (tmp, "/");
strcat (tmp, finfo->d_name);
iterate_dir_write (tmp, headers);
}
}
}
write_dir_data (file_num-tmpfcount, file_num, headers);
file_num++;
closedir(directory);
}
return 0;
}
int make_reg_header (char *fname, char *fpath, unsigned int n, struct initrd_file_ptr *headers)
{
strcpy (headers[n].name, fname);
headers[n].offset = off;
FILE *stream = fopen (fpath, "r");
if (stream != 0){
fseek (stream, 0, SEEK_END);
headers[n].length = ftell(stream);
off += headers[n].length;
headers[n].magic = 0xBF;
headers[n].type = FS_FILE;
fclose(stream);
}else
printf("Error -> hole in headers...\n");
return 0;
}
int make_dir_header (char *fname, unsigned int n, unsigned int nfiles, struct initrd_file_ptr *headers)
{
strcpy (headers[n].name, fname);
headers[n].offset = off;
headers[n].length = nfiles;
off += nfiles * sizeof(struct mydirent);
headers[n].magic = 0xBF;
headers[n].type = FS_DIRECTORY;
return 0;
}
int write_reg_data (char *fpath, int n, struct initrd_file_ptr *headers)
{
FILE *stream = fopen(fpath, "r");
unsigned char *buf = (unsigned char *)malloc(headers[n].length);
fread(buf, 1, headers[n].length, stream);
fwrite(buf, 1, headers[n].length, ffstream);
fclose(stream);
free(buf);
return 0;
}
int write_dir_data (unsigned int files_count, int n, struct initrd_file_ptr *headers)
{
struct mydirent dir_listing[files_count];
int i;
for (i = 0; i<files_count; i++)
{
strcpy (dir_listing[i].name, headers[n-(i+1)].name);
}
fwrite(dir_listing, sizeof(struct mydirent), files_count, ffstream);
return 0;
}
char *get_name_from_path (char *dest, char *path)
{
int i;
int last_index = -1;
for (i = 0;; i++)
{
if (path[i] == '/')
last_index = i;
if (path[i] == '\0')
break;
}
strcpy (dest, &path[last_index+1]);
return dest;
}
dracayr