/* EGAD: io.cpp Navin Pokala and Tracy Handel Dept. of Molecular and Cell Biology University of California, Berkeley Copyright (C) 2003 Regents of the University of California GNU Public License Aug 12 2003 Absolutely no warranties are made or are implied with the use of this program or its parts. This file contains functions for I/O, such as opening files, creating directories, checking for file existence, and counting/extracting words from strings. */ #include "io.h" /* return 1 if it worked, return 0 if it already exists */ int make_directory(char *dir_name) { char *errorline=NULL; /* man 2 mkdir to get mkdir usage */ if(mkdir(dir_name, S_IRUSR | S_IWUSR | S_IXUSR | S_IROTH | S_IXOTH | S_IWOTH | S_IRGRP | S_IWGRP | S_IXGRP )!=0) { if(errno == EACCES || errno == EROFS || errno == EPERM || errno == EFAULT) { errorline = (char *)calloc(MAXLINE,sizeof(char)); sprintf(errorline,"IO_ERROR Write-permission not available for %s", dir_name); failure_report(errorline,"exit"); } if(errno == ENAMETOOLONG) { errorline = (char *)calloc(MAXLINE,sizeof(char)); sprintf(errorline,"IO_ERROR directory name too long %s", dir_name); failure_report(errorline,"exit"); } if(errno == ENOSPC) { errorline = (char *)calloc(MAXLINE,sizeof(char)); sprintf(errorline,"IO_ERROR Disk full!!"); failure_report(errorline,"exit"); } else return(0); } return(1); } /* return 0 if file does not exist, 1 if it does */ int does_this_file_exist(const char *filename) { int num_hits; glob_t globbuf; /* structure to hold glob's results */ globbuf.gl_offs = 0; /* don't reserve any slots in the return */ glob(filename, 0, /* (no special flags) */ NULL, /* (no IO_ERROR handler) */ &globbuf); /* store the results in globbuf */ num_hits = globbuf.gl_pathc; globfree(&globbuf); return(num_hits); } /* touches file filename, creating it or updating nfs */ void touch_file(char *filename) { static char *command=NULL; int ctr; char *errorline; if(command == NULL) command = (char *)calloc(MAXLINE,sizeof(char)); sprintf(command, "/bin/touch %s", filename); ctr=0; while(system(command)!=0) { if(ctr >= 5) { errorline = (char *)calloc(MAXLINE,sizeof(char)); sprintf(errorline,"IO_ERROR cannot touch %s", filename); failure_report(errorline,"exit"); } sleep(2); /* wait a sec and try again */ ++ctr; } } /* mv file name1 to file name2 */ void mv_file(char *name1, char *name2) { static char *command=NULL; int ctr; char *errorline; if(command == NULL) command = (char *)calloc(MAXLINE,sizeof(char)); sprintf(command, "/bin/mv -f %s %s", name1, name2); ctr=0; while(system(command)!=0) { // successful mv call that returned non-zero for some reason if(does_this_file_exist(name2) == 1) return; if(ctr >= 5) { errorline = (char *)calloc(MAXLINE,sizeof(char)); if(does_this_file_exist(name1) == 1) sprintf(errorline,"IO_ERROR %s exists but cannot be mv'd to %s", name1, name2); else sprintf(errorline,"IO_ERROR cannot mv %s %s; %s no longer exists", name1, name2, name1); failure_report(errorline,"warn"); free_memory(errorline); return; } sleep(2); /* wait a couple sec and try again */ ++ctr; } } /* cp file name1 to file name2 */ void cp_file(char *name1, char *name2) { static char *command=NULL; int ctr; char *errorline=NULL; if(command == NULL) command = (char *)calloc(MAXLINE,sizeof(char)); sprintf(command, "/bin/cp -f %s %s", name1, name2); ctr=0; while(system(command)!=0) { if(ctr >= 5) { errorline = (char *)calloc(MAXLINE,sizeof(char)); if(does_this_file_exist(name1) == 1) sprintf(errorline,"IO_ERROR %s exists but cannot be cp'd to %s", name1, name2); else sprintf(errorline,"IO_ERROR cannot cp %s %s; %s no longer exists", name1, name2, name1); failure_report(errorline,"warn"); free_memory(errorline); return; } sleep(2); /* wait a couple sec and try again */ ++ctr; } } /* append file name1 to the end of file name2 */ void append_file(char *name1, char *name2) { static char *command = NULL; int ctr; char *errorline=NULL; if(command == NULL) command = (char *)calloc(MAXLINE,sizeof(char)); sprintf(command, "/bin/cat %s >> %s", name1, name2); ctr=0; while(system(command)!=0) { if(ctr >= 5) { if(QUIET_FLAG==0) fprintf(stderr,"IO_ERROR cannot cat %s to %s\n", name1, name2); if(does_this_file_exist(name1) == 1) { errorline = (char *)calloc(MAXLINE,sizeof(char)); sprintf(errorline,"IO_ERROR %s exists but cannot be cat'd to %s", name1, name2); failure_report(errorline,"warn"); free_memory(errorline); return; } else { if(QUIET_FLAG==0) fprintf(stderr,"IO_ERROR %s no longer exists\n",name1); return; } } sleep(2); /* wait a sec and try again */ ++ctr; } } /* rm file name1 */ void rm_file(char *name1) { static char *command = NULL; int ctr; char *errorline=NULL; if(command == NULL) command = (char *)calloc(MAXLINE,sizeof(char)); if(does_this_file_exist(name1) == 1) { sprintf(command, "/bin/rm -f %s", name1); ctr=0; while(system(command)!=0) { if(ctr >= 5) { if(QUIET_FLAG==0) fprintf(stderr,"IO_ERROR cannot rm %s\n", name1); if(does_this_file_exist(name1) == 1) { errorline = (char *)calloc(MAXLINE,sizeof(char)); sprintf(errorline,"IO_ERROR %s exists but cannot be rm'd", name1); failure_report(errorline,"warn"); free_memory(errorline); return; } else { if(QUIET_FLAG==0) fprintf(stderr,"IO_ERROR %s no longer exists\n",name1); return; } } sleep(2); /* wait a sec and try again */ ++ctr; } } else if(QUIET_FLAG==0) fprintf(stderr,"IO_ERROR cannot rm %s because it does not exist\n", name1); } /* wrapper for fopen; usage exactly like fopen in */ FILE * fopen_file(const char *filename, const char *mode) { FILE *file_ptr; int ctr; char *errorline=NULL; file_ptr = NULL; file_ptr = fopen(filename,mode); ctr = 0; while(file_ptr == NULL) { file_ptr = fopen(filename,mode); if(ctr >= 25) { errorline = (char *)calloc(MAXLINE,sizeof(char)); if(does_this_file_exist(filename) == 0) { sprintf(errorline,"IO_ERROR cannot open %s because it does not exist", filename); failure_report(errorline,"warn"); free_memory(errorline); return(NULL); } else { sprintf(errorline,"IO_ERROR cannot open %s eventhough it exists", filename); failure_report(errorline,"exit"); } } sleep(2); /* wait a sec and try again */ ++ctr; } return(file_ptr); } /* returns the number of words (seperated by space or tab) in a string line (end w/ '\0') */ int word_count(char *line) { int i, word_count; i=0; word_count = 0; if(line[i] == 10) return(0); while(line[i] != 0 && line[i] != '#' && line[i] != '!') { if(line[i] > 32 && line[i] != ' ' && line[i] != '\t') { ++word_count; while(line[i] != ' ' && line[i] != 0 && line[i] != '\t') ++i; } else ++i; } return(word_count); } /* returns the number of words (seperated by space or tab) in a string line (end w/ '\0') places each word into string array **word; word[n] is the nth word in line. Memory for word must be allocated by the calling function */ int extract_words(char *line, char **word) { int i, j, word_count; if(word==NULL) { fprintf(stderr,"ERROR word not allocated for extract_words\n"); fprintf(stderr,"Dumping core....\n"); abort(); } i=0; word_count = 0; if(line[i] == 10) return(0); while(line[i] != 0 && line[i] != '#' && line[i] != '!') { if(line[i] > 32 && line[i] != ' ' && line[i] != '\t') { ++word_count; j=0; while(line[i] > 32 && line[i] != ' ' && line[i] != 0 && line[i] != '\t') { if(word[word_count]==NULL) { fprintf(stderr,"ERROR word[%d] not allocated for extract_words\n",word_count); fprintf(stderr,"Dumping core....\n"); abort(); } word[word_count][j] = line[i]; ++i; ++j; } word[word_count][j] = 0; } else ++i; } return(word_count); } /* creates directory directoryname inside of path */ int create_directory(char *directoryname, char *path) { char *actual_directory; int i; actual_directory = (char *)calloc(MAXLINE,sizeof(char)); sprintf(actual_directory,"%s/%s",path,directoryname); if(does_this_file_exist(actual_directory) == 0) { i = make_directory(actual_directory); free_memory(actual_directory); return(i); } else { free_memory(actual_directory); return(1); } } /* converts lower-case characters in string keyword to uppercase; useful for making input case-independent */ void convert_string_to_all_caps(char *keyword) { int i; i=0; while(keyword[i]!='\0') { if(keyword[i] >= 97 && keyword[i] <= 122) /* lower case */ keyword[i] = keyword[i] - 32; /* convert to uppercase */ ++i; } } /* returns 1 if the files are identical; 0 if they are different */ int are_these_files_identical(char *file1, char *file2) { char *command; int command_status; command = (char *)calloc(MXLINE_INPUT,sizeof(char)); sprintf(command,"/usr/bin/diff -q %s %s > /dev/null",file1, file2); command_status = system(command); free_memory(command); if(command_status == 0) return(1); else return(0); } /* this function is a wrapper for ssh for sending commands to remote machines. especially useful for parallel processing. If sending jobs to a batch queue master node, define BATCH_QUEUE_PREFIX in the inputfile or change the default in input_stuff.cpp and re-compile. returns value of ssh command (0= success). */ int ssh_command(char *hostname, char *remote_command) { extern char *BATCH_QUEUE_PREFIX; /* for batch queing systems */ char *command; int command_status; extern int NUM_SYSTEM_CPU; command = (char *)calloc(MXLINE_INPUT,sizeof(char)); if(NUM_SYSTEM_CPU > 0) sprintf(command,"%s &", remote_command); else { /* if(BATCH_QUEUE_PREFIX!=NULL) sprintf(command,"ssh %s \"%s %s \" &", hostname, BATCH_QUEUE_PREFIX, remote_command); else sprintf(command,"ssh %s \"%s \" &", hostname, remote_command); */ if(BATCH_QUEUE_PREFIX!=NULL) sprintf(command,"ssh %s \"limit coredumpsize unlimited; %s %s \" &", hostname, BATCH_QUEUE_PREFIX, remote_command); else sprintf(command,"ssh %s \"limit coredumpsize unlimited; %s \" &", hostname, remote_command); } command_status = system(command); free_memory(command); return(command_status); } /* writes message to FAILURE_LOG and stderr; exits or aborts as indicated */ void failure_report(char *message, char *fail_or_abort) { char *fail_filename; time_t now; FILE *file_ptr; extern char *INPUTFILENAME; extern int QUIET_FLAG; now = time(NULL); fail_filename = (char *)calloc(MAXLINE,sizeof(char)); sprintf(fail_filename,"%s.EGAD_MESSAGE_LOG",INPUTFILENAME); if(strcmp(fail_or_abort,"exit")==0 || strcmp(fail_or_abort,"e")==0) { if(QUIET_FLAG==0) { file_ptr = fopen_file(fail_filename,"a"); fprintf(stderr,"%s\t%s",message,ctime(&now)); fprintf(file_ptr,"%s\t%s",message,ctime(&now)); fprintf(stderr,"Exiting program\n"); fprintf(file_ptr,"Exiting program\n"); fclose(file_ptr); } exit(1); } else if(strcmp(fail_or_abort,"abort")==0 || strcmp(fail_or_abort,"a")==0) { file_ptr = fopen_file(fail_filename,"a"); fprintf(stderr,"%s\t%s",message,ctime(&now)); fprintf(file_ptr,"%s\t%s",message,ctime(&now)); fprintf(stderr,"Dumping core.....\n"); fprintf(file_ptr,"Dumping core.....\n"); fclose(file_ptr); abort(); } else if(strstr(fail_or_abort,"warn")!=0 || strcmp(fail_or_abort,"w")==0) { if(QUIET_FLAG==0) { file_ptr = fopen_file(fail_filename,"a"); fprintf(stderr,"%s\t%s",message,ctime(&now)); fprintf(file_ptr,"%s\t%s",message,ctime(&now)); fclose(file_ptr); } } free_memory(fail_filename); } /* If AVAILABLE_PROCESSORS_FILE!=NULL, ssh and execute commands on listed hosts; else run command on this host */ void launch_command(char *remote_dir, char *command) { FILE *avail_processor_file_ptr; char *host_name, *line, *command2; extern int NICE_SLAVE_FLAG; extern char *AVAILABLE_PROCESSORS_FILE; command2 = (char *)calloc(MAXLINE,sizeof(char)); if(AVAILABLE_PROCESSORS_FILE==NULL) /* run only on this cpu */ { sprintf(command2,"cd %s ; %s",remote_dir, command); ssh_command(getenv("HOST"),command2); free_memory(command2); return; } if(NICE_SLAVE_FLAG == 1) sprintf(command2,"cd %s ; nice %s",remote_dir, command); else sprintf(command2,"cd %s ; %s",remote_dir, command); host_name = (char *)calloc(MAXLINE,sizeof(char)); line = (char *)calloc(MAXLINE,sizeof(char)); avail_processor_file_ptr = fopen_file(AVAILABLE_PROCESSORS_FILE,"r"); while(fgets(line,MAXLINE,avail_processor_file_ptr)!=NULL) { sscanf(line,"%s",host_name); if(line[0] != '#' && line[0] != '!') { ssh_command(host_name, command2); sleep(5); } } fclose(avail_processor_file_ptr); free_memory(line); free_memory(host_name); free_memory(command2); } int grep_line_from_file(char *target, char *line, int sizeof_line, char *filename) { FILE *file_ptr; int flag,i; file_ptr = fopen_file(filename,"r"); fgets(line,sizeof_line,file_ptr); flag=1; while(flag==1) { i=0; while(line[i] != '\0' && line[i] != '#' && line[i] != '!') ++i; line[i] = '\0'; if(strstr(line,target)!=0) { flag=0; fclose(file_ptr); return(1); } if(fgets(line,sizeof_line,file_ptr)==NULL) { fclose(file_ptr); return(0); } } fclose(file_ptr); return(1); }