jeudi 26 février 2015

Converting images in child processes with fork in C



I realize this is a stretch but I can't for the life of my figure out what's wrong with my code. I'm simply trying to convert files in an input folder using a built in "convert" command, and output them as jpgs in an output folder, as specified in the cmd line. Which images are converted is dependant on process IDs generated with fork. For some reason, my code converts most of the files in my input_dir just as I'd expect, but leaves out a random few each time. (I'm using simclist for list structure) Any help would be greatly appreciated. Code is as follows: argv[2] is the input path and argv[3] is the output path.



#include<errno.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<string.h>
#include<sys/stat.h>
#include<dirent.h>
#include "simclist.h"

#define MAX_DIR_PATH 2048 // Maximal full path length we support

list_t
findfile (char *pattern, char *directory) //**From recitation**
{
DIR *dir; // Pointer to the scanned directory
struct dirent *entry; // Pointer to one directory entry
char cwd[MAX_DIR_PATH + 1]; // Current working directory
struct stat dir_stat; // Used by stat()
list_t mylist;
list_init(&mylist);

// First, save the path of current working directory

if (!getcwd (cwd, MAX_DIR_PATH + 1))
{
perror ("getcwd:");
return;
}


// Open the directory to read

dir = opendir (directory);
if (!dir)
{
fprintf (stderr, "Cannot read directory '%s': ", cwd);
perror ("");
return;
}

while ((entry = readdir (dir)))
{
// Check if the pattern matches

if (entry->d_name && strstr (entry->d_name, pattern))
{
list_append(& mylist, & entry->d_name); /* add an element to the list */
//printf ("%s/%s\n", cwd, entry->d_name);
}

// Check if the given entry is a directory

if (stat (entry->d_name, &dir_stat) == -1)
{
//perror ("stat:");
continue;
}

// Skip the "." and ".." entries, to avoid loops

if (strcmp (entry->d_name, ".") == 0)
continue;

if (strcmp (entry->d_name, "..") == 0)
continue;

/* Is this a directory? */
if (S_ISDIR (dir_stat.st_mode))
{
/* Change into the new directory */
if (chdir (entry->d_name) == -1)
{
fprintf (stderr, "Cannot chdir into '%s': ", entry->d_name);
perror ("");
continue;
}

/* check this directory */
findfile (pattern, directory);

/* Finally, restore the original working directory. */

if (chdir ("..") == -1)
{
fprintf (stderr, "Cannot chdir back to '%s': ", cwd);
perror ("");
exit (1);
}
}
}
return mylist;
} // End findfile()





int main(int argc, char *argv[])
{
pid_t currentpid;
char* fullpath_in_png;
char* fullpath_out_png;
char* fullpath_in_gif;
char* fullpath_out_gif;
char* fullpath_in_bmp;
char* fullpath_out_bmp;
const char s[2] = ".";
int convertCount = 0;

list_t pngList;
list_init(&pngList);
list_t gifList;
list_init(&gifList);
list_t bmpList;
list_init(&bmpList);

if (argc != 4)
{
fprintf(stderr, "Usage %s wrong number of parameters\n", argv[0]);
return 1;
}

//method for checking if output directory exists, creating it if not (referenced stackoverflow user arnaud576875)
struct stat st = {0};

if (stat(argv[3], &st) == -1) {
mkdir(argv[3], 0700);
}

pngList = findfile(".png",argv[2]);
printf("The png list now holds %u elements.\n", list_size(& pngList));
gifList = findfile(".gif",argv[2]);
printf("The gif list now holds %u elements.\n", list_size(& gifList));
bmpList = findfile(".bmp",argv[2]);
printf("The bmp list now holds %u elements.\n", list_size(& bmpList));

//printf((char*)list_get_at(& bmpList, 0));
//printf("\n");

int counter = 0;
int isParent = 1;

while (!(list_size(& gifList) == 0 && list_size(& bmpList) == 0 && list_size(& pngList) == 0) && isParent!= 0)
{

if (list_size(& pngList) > 0){
fullpath_in_png = malloc(1048); //PNGs: concatonates the path to the image name
strcpy(fullpath_in_png,argv[2]);
strcat(fullpath_in_png,(char*)list_get_at(& pngList, 0));
fullpath_out_png = malloc(1048);
strcpy(fullpath_out_png,argv[3]);
strcat(fullpath_out_png,(char*)list_get_at(& pngList, 0));
fullpath_out_png = strtok(fullpath_out_png, s);
strcat(fullpath_out_png, ".jpg");
}

if (list_size(& gifList) > 0){
fullpath_in_gif = malloc(1048); //GIFs: concatonates the path to the image name
strcpy(fullpath_in_gif,argv[2]);
strcat(fullpath_in_gif,(char*)list_get_at(& gifList, 0));
fullpath_out_gif = malloc(1048);
strcpy(fullpath_out_gif,argv[3]);
strcat(fullpath_out_gif,(char*)list_get_at(& gifList, 0));
fullpath_out_gif = strtok(fulConvertinglpath_out_gif, s);
strcat(fullpath_out_gif, ".jpg");
}

if (list_size(& bmpList) > 0){
fullpath_in_bmp = malloc(1048); //BMPs: concatonates the path to the image name
strcpy(fullpath_in_bmp,argv[2]);
strcat(fullpath_in_bmp,(char*)list_get_at(& bmpList, 0));
fullpath_out_bmp = malloc(1048);
strcpy(fullpath_out_bmp,argv[3]);
strcat(fullpath_out_bmp,(char*)list_get_at(& bmpList, 0));
fullpath_out_bmp = strtok(fullpath_out_bmp, s);
strcat(fullpath_out_bmp, ".jpg");
}

convertCount++;
printf("Converting file %d\n",convertCount);
//printf(fullpath_input);
//printf("\n");
currentpid = fork();
isParent = currentpid;
int status;
waitpid(currentpid, &status, 0);
if (currentpid != 0)
{
if (list_size(& pngList) > 0 && currentpid % 2 == 0){
printf(fullpath_in_png);
printf("\n");
list_delete_at(& pngList, 0);
}
else if (list_size(& bmpList) > 0 && currentpid % 3 == 0){
printf(fullpath_in_bmp);
printf("\n");
list_delete_at(& bmpList, 0);
}
else if (list_size(& gifList) > 0){
printf(fullpath_in_gif);
printf("\n");
list_delete_at(& gifList, 0);
}
}
else if (currentpid == 0 && (getpid() % 2 == 0)){
if (list_size(& pngList) > 0){
//printf(fullpath_in_png);
//printf("\n");
//printf("The png list now holds %u elements.\n", list_size(& pngList));
execl("/usr/bin/convert", "convert", fullpath_in_png, fullpath_out_png);
}
else kill(getpid(), SIGKILL);
}
else if (currentpid == 0 && (getpid() % 3 == 0)){
if (list_size(& bmpList) > 0){
execl("/usr/bin/convert", "convert", fullpath_in_bmp, fullpath_out_bmp);
}
else kill(getpid(), SIGKILL);
}
else{
if (list_size(& gifList) > 0){
execl("/usr/bin/convert", "convert", fullpath_in_gif, fullpath_out_gif);
}
else kill(getpid(), SIGKILL);
}
counter++;
printf("The png list now holds %u elements.\n", list_size(& pngList));
printf("The gif list now holds %u elements.\n", list_size(& gifList));
printf("The bmp list now holds %u elements.\n", list_size(& bmpList));
}



//Testing with ./parallel_convert 1 input_dir/ output_dir/

return 0;

}



Aucun commentaire:

Enregistrer un commentaire