/* * Traverse() walks the logical directory structure specified by the argv list * in the order specified by the mastercmp() comparison function. During the * traversal it passes linked lists of structures to display() which represent * a superset (may be exact set) of the files to be displayed. */ static void traverse(int argc, char *argv[], int options) { FTS *ftsp; FTSENT *p, *chp; int ch_options; if ((ftsp = fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL) err(EXIT_FAILURE, NULL); display(NULL, fts_children(ftsp, 0)); if (f_listdir) return; /* * If not recursing down this tree and don't need stat info, just get * the names. */ ch_options = !f_recursive && options & FTS_NOSTAT ? FTS_NAMEONLY : 0; while ((p = fts_read(ftsp)) != NULL) switch (p->fts_info) { case FTS_DC: warnx("%s: directory causes a cycle", p->fts_name); break; case FTS_DNR: case FTS_ERR: warnx("%s: %s", p->fts_name, strerror(p->fts_errno)); rval = EXIT_FAILURE; break; case FTS_D: if (p->fts_level != FTS_ROOTLEVEL && p->fts_name[0] == '.' && !f_listdot) break; /* * If already output something, put out a newline as * a separator. If multiple arguments, precede each * directory with its name. */ if (output) (void)printf("\n%s:\n", p->fts_path); else if (argc > 1) { (void)printf("%s:\n", p->fts_path); output = 1; } chp = fts_children(ftsp, ch_options); display(p, chp); if (!f_recursive && chp != NULL) (void)fts_set(ftsp, p, FTS_SKIP); break; } if (errno) err(EXIT_FAILURE, "fts_read"); }
///////////////////////////////////////////////////////////// // Count the number of files for header length calculation ///////////////////////////////////////////////////////////// static int countFiles(char **source) { FTS *ftsp; FTSENT *p, *chp; int fts_options = FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR; if ((ftsp = fts_open(source, fts_options, NULL)) == NULL) { warn("fts_open"); return -1; } /* Initialize ftsp with as many argv[] parts as possible. */ chp = fts_children(ftsp, 0); if (chp == NULL) { return 0; /* no files to traverse */ } while ((p = fts_read(ftsp)) != NULL) { switch (p->fts_info) { case FTS_F: if(strstr(p->fts_path, "DS_Store") == NULL) //wasn't a DS_Store file. { //increment the file count fileCountForHeader++; } break; default: break; } } fts_close(ftsp); return 0; }
static int remove_dir_recursively(char *dirname) { FTS *ftsp; FTSENT *p, *chp; int fts_options = FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR; if ((ftsp = fts_open(&dirname, fts_options, NULL)) == NULL) { perror("fts_open"); return -1; } chp = fts_children(ftsp, 0); if (chp == NULL) { fts_close(ftsp); rmdir(dirname); return 0; } while ((p = fts_read(ftsp)) != NULL) { switch (p->fts_info) { case FTS_D: if (strcmp(dirname, p->fts_path)) { remove_dir_recursively(p->fts_path); rmdir(p->fts_path); } break; case FTS_F: unlink(p->fts_path); break; default: break; } } fts_close(ftsp); rmdir(dirname); return 0; }
void runSuccess() { char* argv[] = {anystring(), anystring(), NULL}; //@ assert \exists int i; (argv[i] == \null); FTS* fts = fts_open(argv, anyint(), NULL); if (fts != NULL) { fts_children(fts, anyint()); } }
/* using fts library to traverse file hierarchies */ static void traverse(int argc, char **argv, int options) { FTS *dp; FTSENT *p, *chp; more=0; if ((dp=fts_open(argv, options, f_notsort ? NULL : comp))==NULL) err(-1, NULL); /** * print minus 1 level's children, if -d is specified * print files and directories, or only print files */ chp=fts_children(dp, 0); display(NULL, chp); while (!f_plaintext && (p=fts_read(dp))!=NULL) switch (p->fts_info) { case FTS_DNR: case FTS_ERR: warn("%s", p->fts_path); break; case FTS_DC: warn("%s directory causes a cycle", p->fts_path); break; case FTS_D: /* do not jump over dot-start root provided to ls command */ if (p->fts_level!=0 && p->fts_name[0]=='.' && !f_allentry) { fts_set(dp, p, FTS_SKIP); break; } if (more) printf("\n%s:\n", p->fts_path); else if (argc>1 || f_recurse) printf("%s:\n", p->fts_path); display(p, fts_children(dp, 0)); if (!f_recurse) fts_set(dp, p, FTS_SKIP); break; default: break; } fts_close(dp); }
bool platform_directory_delete(const utf8 *path) { log_verbose("Recursively deleting directory %s", path); FTS *ftsp; FTSENT *p, *chp; // fts_open only accepts non const paths, so we have to take a copy char* ourPath = (char*)malloc(strlen(path) + 1); strcpy(ourPath, path); utf8* const patharray[2] = {ourPath, NULL}; if ((ftsp = fts_open(patharray, FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR, NULL)) == NULL) { log_error("fts_open returned NULL"); free(ourPath); return false; } chp = fts_children(ftsp, 0); if (chp == NULL) { log_verbose("No files to traverse, deleting directory %s", path); if (remove(path) != 0) { log_error("Failed to remove %s, errno = %d", path, errno); } free(ourPath); return true; // No files to traverse } while ((p = fts_read(ftsp)) != NULL) { switch (p->fts_info) { case FTS_DP: // Directory postorder, which means // the directory is empty case FTS_F: // File if(remove(p->fts_path)) { log_error("Could not remove %s", p->fts_path); fts_close(ftsp); free(ourPath); return false; } break; case FTS_ERR: log_error("Error traversing %s", path); fts_close(ftsp); free(ourPath); return false; } } free(ourPath); fts_close(ftsp); return true; }
int openAndIndexDirectory(char *dir) { char *directory; directory = (char *) malloc (BUFSIZ); directory[0] = '\0'; strcat(directory, dir); /*We need this to conform to how fts works*/ /*fts needs an array of char arrays for some reason*/ char *directoryArg[2]; directoryArg[0] = directory; directoryArg[1] = NULL; FTS *ftsp; FTSENT *parent, *chp; int fts_options = FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR; printf("DIR ARG IS %s\n",directoryArg); if((ftsp = fts_open(directoryArg, fts_options, NULL)) == NULL) { warn("fts_open"); return -1; } /*If no children in directory, return */ chp = fts_children(ftsp, 0); if (chp == NULL) return 0; char *fullPath; while ((parent = fts_read(ftsp)) != NULL ) { switch(parent->fts_info) { case FTS_F: fullPath = (char *) malloc( BUFSIZ+1 ); snprintf(fullPath, BUFSIZ, "%s", parent->fts_path); /* strncat(fullPath, parent->fts_name, BUFSIZ - 1); */ printf("FILE HERE:%s\n",fullPath); openAndIndexFile(fullPath); break; default: printf("HMM...\n"); break; } } fts_close(ftsp); if (fullPath) free (fullPath); return 0; }
void testValues() { f = 2; char* argv[] = {anystring(), anystring(), NULL}; //@ assert \exists int i; (argv[i] == \null); FTS* fts = fts_open(argv, anyint(), NULL); if (fts != NULL) { FTSENT* ftsent = fts_children(fts, anyint()); //@ assert ftsent != \null ==> ftsent->fts_level > -1; //@ assert ftsent != \null ==> ftsent->fts_number == 0; //@ assert ftsent != \null ==> valid_string(ftsent->fts_path); //@ assert ftsent != \null ==> ftsent->fts_link == \null || \valid(ftsent->fts_link); } //@ assert f == 2; //@ assert vacuous: \false; }
/* In order to get a description of each file located in /usr/include using * fts.h, the code would be as follows: */ int ftw_simple(char *argv[]) { /* assume the path "/usr/include" has been passed through argv[3] */ FTS *fileStruct; FTSENT *dirList; int ftsResult; fileStruct = fts_open(&argv[3], FTS_COMFOLLOW, 0); dirList = fts_children(fileStruct, FTS_NAMEONLY); do { FTSENT *fileInfo; void *result; fileInfo = (FTSENT *)fts_read((FTS *)dirList->fts_pointer); /* dummy condition to use value stored to 'fileInfo': */ if (fileInfo == 0) { ; } result = malloc(sizeof(int (*)(const FTSENT **, const FTSENT **))); /* at this point, you should be able to extract information from the * FTSENT returned by fts_read(): */ fileStruct = fts_open((char * const *)dirList->fts_link->fts_name, FTS_PHYSICAL, (void *)result); /* TODO: write an actual compar() function to use in the 3rd argument * here (see the following quote from the manpage for fts_open() for * reference: "The argument compar() specifies a user-defined function * which may be used to order the traversal of the hierarchy. It takes * two pointers to pointers to FTSENT structures as arguments and should * return a negative value, zero, or a positive value to indicate if the * file referenced by its first argument comes before, in any order with * respect to, or after, the file referenced by its second argument.") */ /* (started a stub for it below) */ } while (dirList->fts_link != NULL); ftsResult = fts_close(fileStruct); return ftsResult; }
int main(int argc, char* const argv[]) { FTS* fs = NULL; FTSENT* child = NULL; FTSENT* parent = NULL; if (argc<2) { printf("Usage: %s <path-spec>\n", argv[0]); exit(255); } fs = fts_open(argv + 1,FTS_COMFOLLOW | FTS_NOCHDIR,&compare); if (NULL != fs) { while( (parent = fts_read(fs)) != NULL) { child = fts_children(fs,0); if (errno != 0) { perror("fts_children"); } while ((NULL != child) && (NULL != child->fts_link)) { child = child->fts_link; // char* s = concat(child->fts_path, child->fts_name); fd = open(child->fts_name, O_RDONLY); fdatasync(fd); posix_fadvise(fd, 0,0,POSIX_FADV_DONTNEED); printf("%s%s -> POSIX_FADV_DONTNEED\n", child->fts_path,child->fts_name); close(fd); } } fts_close(fs); } return 0; }
static void children (FTS *fts) { FTSENT *child = fts_children (fts, 0); if (child == NULL && errno != 0) { printf ("FAIL: fts_children: %m\n"); exit (1); } while (child != NULL) { short level = child->fts_level; const char *name = child->fts_name; if (child->fts_info == FTS_F || child->fts_info == FTS_NSOK) { files++; printf ("%*s%s\n", 2 * level, "", name); } child = child->fts_link; } }
/* * Traverse() walks the logical directory structure specified by the argv list * in the order specified by the mastercmp() comparison function. During the * traversal it passes linked lists of structures to display() which represent * a superset (may be exact set) of the files to be displayed. */ static void traverse(int argc, char *argv[], int options) { FTS *ftsp; FTSENT *p, *chp; int ch_options; if ((ftsp = fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL) err(1, "fts_open"); /* * We ignore errors from fts_children here since they will be * replicated and signalled on the next call to fts_read() below. */ chp = fts_children(ftsp, 0); if (chp != NULL) display(NULL, chp, options); if (f_listdir) return; /* * If not recursing down this tree and don't need stat info, just get * the names. */ ch_options = !f_recursive && !f_label && options & FTS_NOSTAT ? FTS_NAMEONLY : 0; while ((p = fts_read(ftsp)) != NULL) switch (p->fts_info) { case FTS_DC: warnx("%s: directory causes a cycle", p->fts_name); break; case FTS_DNR: case FTS_ERR: warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); rval = 1; break; case FTS_D: if (p->fts_level != FTS_ROOTLEVEL && p->fts_name[0] == '.' && !f_listdot) break; /* * If already output something, put out a newline as * a separator. If multiple arguments, precede each * directory with its name. */ if (output) { putchar('\n'); (void)printname(p->fts_path); puts(":"); } else if (argc > 1) { (void)printname(p->fts_path); puts(":"); output = 1; } chp = fts_children(ftsp, ch_options); display(p, chp, options); if (!f_recursive && chp != NULL) (void)fts_set(ftsp, p, FTS_SKIP); break; default: break; } if (errno) err(1, "fts_read"); }
static int packageSourceFolder(char **source, char *desintation, char *extensions[], int extCount) { FTS *ftsp; FTSENT *p, *chp; int fts_options = FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR; int rval = 0; // remove if unused! char line[512]; FILE *pakFile; FILE *file; unsigned int start_offset= 0; unsigned int f_index=0; // file index if (file = fopen(desintation, "r")) { printf("File exists, would you like to overwrite it y/n ? "); int answer; int loop=1; fclose(file); while (loop){ answer = getchar(); switch(answer){ case 'y': loop=0; break; case 'n': printf("Please run Bundle again with the correct output path.\n"); exit(1); case 10: // \n break; default: printf("not sure ? ;) \n (y/n) >"); } } }else { fclose(file); } pakFile = fopen(desintation,"wb+"); printf("\n----------------\n"); // initialize header with nuber of files if ((start_offset=header_init(pakFile, fileCountForHeader)) == -1){ // perror("bundler_header"); fprintf(stderr, "Cannot initialize header...exiting\n"); return 0; } size_t header_size = fileCountForHeader* HEADER_OFFSET_SIZE + sizeof(int); if ((ftsp = fts_open(source, fts_options, NULL)) == NULL) { warn("fts_open"); return -1; } /* Initialize ftsp with as many argv[] parts as possible. */ chp = fts_children(ftsp, 0); if (chp == NULL) { return 0; /* no files to traverse */ } printf("\nCreating the Bundle\n\n"); while ((p = fts_read(ftsp)) != NULL) { int tempFileExists = 0; //used to flag temp file for deletion switch (p->fts_info) { case FTS_D: printf(">dir: %s\n\n", p->fts_path); printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n"); printData(pakFile, p->fts_path); break; case FTS_F: if((strstr(p->fts_path, ".DS_Store") != NULL)//ignore DS_Store and exe || (strstr(p->fts_path, ".exe") != NULL)) { printf("Found file to ignore: %s\n", p->fts_path); printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n"); } else { printf("\t>file: %s\n", p->fts_path); printData(pakFile, p->fts_path); FILE *tempFile; if(shouldCompressFileType(p->fts_path, extensions, extCount) == 1) { /* compress the fts_path file and write the compressed data one to pak file */ compress_one_file(p->fts_path, "temp.txt"); tempFile = fopen("temp.txt","rb"); tempFileExists = 1; } else { tempFile = fopen(p->fts_path,"rb"); } char byte; fseek(pakFile, 0L, SEEK_END); off_t offset = ftell(pakFile); //get the size of the file fseek(tempFile, 0L, SEEK_END); long size = ftell(tempFile); fseek(tempFile, 0L, SEEK_SET); offset= offset;//-HEADER_OFFSET_SIZE; char *fileName = p->fts_path; char *tempFileName = strdup(fileName); //update header //offset_p off= malloc(HEADER_OFFSET_SIZE); header_offset off; off.hash = __ac_X31_hash_string( filename(fileName) ); off.size= size; off.offset_start= offset; header_write_offset(pakFile, &off, f_index++); // print the file info if(tempFileName) { printf("\t>The offset for %s is %d\n", tempFileName, (unsigned int)offset); printf("\t>The written size of %s is %lu\n", basename(tempFileName), size); printf("\t>%s was added to the bundle\n\n", basename(tempFileName)); printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n"); free(tempFileName); } // copy the data from the temp compressed file to the pak file // fseek(pakFile, start_offset, SEEK_SET); //fseek(pakFile, 0L, SEEK_SET); fseek(pakFile, 0L, SEEK_END); int d= 0; while (!feof(tempFile)) { fread(&byte, sizeof(char), 1, tempFile); fwrite(&byte, sizeof(char), 1, pakFile); } fclose(tempFile); // done! //delete the temporary file if(tempFileExists == 1) { if (remove("temp.txt") == -1) perror("Error in deleting temp file"); } break; } default: break; } } fclose(pakFile); fts_close(ftsp); return 0; }
int main(int argc, char **argv) { int c; char *blkszptr; char **path_argv; char *default_dot_path[] = {".", NULL}; struct winsize win; FTS* ftsptr; FTSENT *argv_list; FTSENT *cur; FTSENT *read; int fts_options = FTS_PHYSICAL; int (* comp)(const FTSENT** obj1, const FTSENT** obj2); /* * get term width * refers to NetBSD's implementation */ if (isatty(STDOUT_FILENO)) { if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == 0 &&win.ws_col > 0) { win_width = win.ws_col; } } comp = sortbyname; setprogname(argv[0]); /* some default setting */ if (isatty(STDOUT_FILENO)) { all_flags.qflag = 1; all_flags.Cflag = 1; } else { all_flags.wflag = 1; all_flags.oneflag = 1; } /*-A always set for super user*/ if (getuid() == 0) { all_flags.Aflag = 1; } while( (c = getopt(argc, argv, "AacdFfhiklnqRrSstuw1xC")) != -1 ) { switch(c) { case 'A': all_flags.Aflag = 1; break; case 'a': all_flags.aflag = 1; break; case 'd': all_flags.dflag = 1; break; case 'f': comp = NULL; all_flags.fflag = 1; break; case 'F': all_flags.Fflag = 1; break; case 'R': all_flags.Rflag = 1; break; case 'i': all_flags.iflag = 1; break; case 'l': //overwrite all_flags.nflag = 0; all_flags.oneflag = 0; all_flags.Cflag = 0; all_flags.xflag = 0; all_flags.lflag = 1; break; case 'n': //overwrite all_flags.lflag = 0; all_flags.oneflag = 0; all_flags.Cflag = 0; all_flags.xflag = 0; all_flags.nflag = 1; break; case 's': all_flags.sflag = 1; break; case 'S': comp = sortbysize; all_flags.Sflag = 1; break; case 'q': all_flags.wflag = 0; all_flags.qflag = 1; break; case 'w': all_flags.qflag = 0; all_flags.wflag = 1; break; case 't': comp = sortbytime; all_flags.tflag = 1; break; case '1': all_flags.lflag = 0; all_flags.nflag = 0; all_flags.oneflag = 1; break; case 'c': all_flags.uflag = 0; all_flags.cflag = 1; break; case 'x': //overwirte all_flags.oneflag = 0; all_flags.lflag = 0; all_flags.nflag = 0; all_flags.Cflag = 0; all_flags.xflag = 1; break; case 'C': //overwrite all_flags.oneflag = 0; all_flags.lflag = 0; all_flags.nflag = 0; all_flags.xflag = 0; all_flags.Cflag = 1; break; case 'u': all_flags.cflag = 0; all_flags.uflag = 1; break; case 'k': all_flags.hflag = 0; all_flags.kflag = 1; break; case 'h': all_flags.kflag = 0; all_flags.hflag = 1; break; case 'r': all_flags.rflag = 1; break; default: usage(); break; } } argc -= optind; argv += optind; cldlist_init(); path_argv = (argc == 0) ? default_dot_path : argv; /*set block size, blksize_t shall be signed integer*/ if ( (blkszptr = getenv("BLOCKSIZE")) != NULL ) { blocksize = atoi(blkszptr); } else { blocksize = DEFAULT_BLOCKSIZE; } if (all_flags.kflag) { divide_term = 1024; } if (all_flags.aflag) { fts_options = fts_options | FTS_SEEDOT; } if (all_flags.rflag) { if (all_flags.Sflag) { comp = sortbyrsize; } else if (all_flags.tflag) { comp = sortbyrsize; } else { comp = sortbyname; } } if ( (ftsptr = fts_open(path_argv, fts_options, comp)) == NULL) { if (errno != 0) { (void)fprintf(stderr, "%s: fts_open error %s\n", getprogname(), strerror(errno)); exit(EXIT_FAILURE); } } /*the special use case of fts_children, go through all files in the argv list*/ if ( (argv_list = fts_children(ftsptr, 0)) == NULL ) { if (errno != 0) { (void)fprintf(stderr, "%s: fts_open error %s\n", getprogname(), strerror(errno)); exit(EXIT_FAILURE); } } /* * refer to NetBSD implementation * here we handle all `non-directory` files and error, * leave the directory for the fts_read below */ for (cur = argv_list; cur != NULL; cur = cur->fts_link) { if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS || cur->fts_info == FTS_DNR) { warnx("can't access %s: %s",cur->fts_name, strerror(cur->fts_errno)); /* * because error message also consider as an output * `outputnum++` will make the directory to output its path name */ outputnum++; continue; } if (!all_flags.dflag && cur->fts_info == FTS_D) { /*leave the directory to the fts_read below*/ outputnum++; continue; } outputentnum++; outputnum++; cook_entry(cur); } //Parent = NULL means it's at root level traverse_children(NULL); do{ if (all_flags.dflag) { break; } /* * handle the directory entry */ while( (read = fts_read(ftsptr)) != NULL) { unsigned short info = read->fts_info; if (info == FTS_DC) { warnx("%s causes a cycle in the tree ",read->fts_path); continue; } if (info == FTS_DNR || info == FTS_ERR) { warnx("can't access %s: %s",read->fts_path, strerror(read->fts_errno)); continue; } if (info == FTS_D) { FTSENT* childrenptr; childrenptr = fts_children(ftsptr,0); if (childrenptr == NULL && errno != 0) { /* * if error heppen we don't do anything this moment * error will be printed at the postorder visit */ continue; } config_output(childrenptr); // cook_multi_cols(); traverse_children(read); if (!all_flags.Rflag && childrenptr != NULL) { if (fts_set(ftsptr, read, FTS_SKIP) != 0) { (void)fprintf(stderr, "%s: fts_set error %s\n", getprogname(), strerror(errno)); exit(EXIT_FAILURE); } } } } }while(0); if (read == NULL && errno != 0) { (void)fprintf(stderr, "%s: fts_read error %s\n", getprogname(), strerror(errno)); exit(EXIT_FAILURE); } cldlist_clear(); return 0; }
static int traverseFolder(char * const argv[]) { FTS *ftsp; FTSENT *p, *chp; int fts_options = FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR; //***************** FILE *fpRead; FILE *fpWrite; FILE *fpFileNames; char current_line[MAX_CHARS_PER_LINE]; char new_line [MAX_CHARS_PER_LINE]; int currentFileID = 0; char currOutputName [MAX_PATH_LENGTH]; int currentLineLength = 0; int lineResult = 0; long totalCharacters = 0; if ((ftsp = fts_open(argv, fts_options, NULL)) == NULL) { warn("fts_open"); return -1; } // Initialize ftsp with as many argv[] parts as possible. chp = fts_children(ftsp, 0); if (chp == NULL) { return 0; /* no files to traverse */ } // Open file names file for writing - to map each input file name to its correponding file number if(!(fpFileNames= fopen ( "inputs/FILE_NAMES" , "w" ))) { printf("Could not open FILE_NAMES file for writing \n"); return (-1); } while ((p = fts_read(ftsp)) != NULL) { if(p->fts_info == FTS_F) { printf("processing file %d: %s\n", currentFileID, p->fts_name); int filenamelength = strlen(p->fts_name); char lastchar=p->fts_name[filenamelength-1]; if(DEBUG_MODE) printf("last char = %c\n",lastchar); // opening file for reading //ignore backup files if(lastchar!='~') { //open file for reading if(!(fpRead= fopen ( p->fts_path , "r" ))) { printf("Could not open file \"%s\" for reading \n", p->fts_path); return (-1); } //Record file name into INFO file fprintf(fpFileNames, "%s\n", p->fts_name); sprintf(currOutputName,"inputs/input_%d", currentFileID++); // opening file for writing if(!(fpWrite= fopen ( currOutputName , "w" ))) { printf("Could not open file \"%s\" for writing \n", currOutputName); return (-1); } totalCharacters =0; //reading lines while( fgets (current_line, MAX_CHARS_PER_LINE-10, fpRead)!=NULL ) { //this will replace valid characters a,c,g,t or A,C,G,T with lower case, //and in case there are invalid characters will return false and this line will be ignored lineResult = prepareLine(current_line,new_line,¤tLineLength); //writing concatenated content into a new file if(lineResult) { if(DEBUG_MODE) printf("%s\n",new_line); totalCharacters+=currentLineLength; if(totalCharacters<=MAX_FILE_SIZE_BYTES) //add to current file fprintf(fpWrite, "%s\n", new_line); else //open a new file and write there { //close open output file fclose(fpWrite); //Record file name into INFO file - repeatingly fprintf(fpFileNames, "%s\n", p->fts_name); sprintf(currOutputName,"inputs/input_%d", currentFileID++); // opening new file for writing if(!(fpWrite= fopen ( currOutputName , "w" ))) { printf("Could not open file \"%s\" for writing \n", currOutputName); return (-1); } totalCharacters =currentLineLength; fprintf(fpWrite, "%s\n", new_line); } } } fclose(fpRead); fclose(fpWrite); } } } fclose(fpFileNames); fts_close(ftsp); printf("Total %d new input files\n",currentFileID); return 0; }
/* update database */ void update_database(char *db_path, char *input_path, int exe_inst) { FTS *ftsp; FTSENT *p, *chp; int fts_options = FTS_NOSTAT | FTS_COMFOLLOW | FTS_PHYSICAL; char *target[2]; DB *dbp; int ret; bitshred_t *vdb = NULL; FILE *fp = NULL; int nfile = 0; int nvirus = 0; int i; uint64_t t_filesize = 0; uint64_t t_secsize = 0; struct timeval t_stime, t_etime; double sec_elapsed = 0; char buf[64]; sprintf(buf, "%s", db_path); if(access(buf, F_OK)) mkdir(buf, S_IRWXU|S_IXGRP|S_IRGRP|S_IROTH|S_IXOTH); gettimeofday(&t_stime, NULL); /* initialize ftsp */ target[0] = input_path; target[1] = NULL; if ((ftsp = fts_open(target, fts_options, NULL))==NULL) { bs_errmsg("[!] fts_open(): %s\n", input_path); exit(EXIT_FAILURE); } if ((chp = fts_children(ftsp, 0))==NULL) { return; // No files to traverse } /* open DB */ if((ret = db_create(&dbp, NULL, 0)) != 0){ bs_errmsg("[!] db_create(): %s\n", db_strerror(ret)); exit(EXIT_FAILURE); } sprintf(buf, "%s/vdb", db_path); //if((ret = dbp->open(dbp, NULL, vdb_path, NULL, DB_RECNO, DB_CREATE | DB_TRUNCATE, 0664)) != 0){ if((ret = dbp->open(dbp, NULL, buf, NULL, DB_RECNO, DB_CREATE, 0664)) != 0){ dbp->err(dbp, ret, "[!] %s", buf); exit(EXIT_FAILURE); } /* # virus in DB before update */ sprintf(buf, "%s/vdb_nvir.txt", db_path); if(access(buf, F_OK) == 0) { if((fp = fopen(buf, "r")) == NULL) { bs_errmsg("[!] fopen(): %s\n", buf); exit(EXIT_FAILURE); } if((fgets(buf, 64, fp)) == NULL) { bs_errmsg("[!] fgets(): vdb_nvir.txt\n"); exit(EXIT_FAILURE); } nvirus = atoi(buf); if((fgets(buf, 64, fp)) == NULL) { bs_errmsg("[!] fgets(): vdb_nvir.txt\n"); exit(EXIT_FAILURE); } nvirus += atoi(buf); fclose(fp); } else { nvirus = 0; } /* list of input files */ sprintf(buf, "%s/vdb_list.txt", db_path); if((fp = fopen(buf, "a")) == NULL) { bs_errmsg("[!] fopen(): %s\n", buf); exit(EXIT_FAILURE); } if((vdb = malloc(sizeof(bitshred_t))) == NULL){ bs_errmsg("[!] malloc(): vdb\n"); exit(EXIT_FAILURE); } bs_verbosemsg("[-] Updating database...\n"); /* traverse input files */ if (exe_inst==EXE_ADD_BIN) { // binary files while ((p = fts_read(ftsp)) != NULL) { switch (p->fts_info) { case FTS_F: case FTS_NSOK: update_vdb_bin(dbp, fp, p->fts_name, vdb, nvirus, &nfile, &t_filesize, &t_secsize); break; default: break; } } } else if (exe_inst==EXE_ADD_TXT) { // text files while ((p = fts_read(ftsp)) != NULL) { switch (p->fts_info) { case FTS_F: case FTS_NSOK: update_vdb_txt(dbp, fp, p->fts_name, vdb, nvirus, &nfile, &t_filesize, &t_secsize); break; default: break; } } } /* close DB */ dbp->close(dbp, 0); fts_close(ftsp); free(vdb); fclose(fp); gettimeofday(&t_etime, NULL); sec_elapsed = time_diff(t_etime, t_stime); /* # virus in DB after update */ sprintf(buf, "%s/vdb_nvir.txt", db_path); if((fp = fopen(buf, "w")) == NULL) { bs_errmsg("[!] fopen(): %s\n", buf); exit(EXIT_FAILURE); } fprintf(fp, "%d\n%d\n", nvirus, nfile); fclose(fp); /* report statistics */ if((fp = fopen("/proc/self/status", "r")) == NULL) { bs_errmsg("[!] fopen(): /proc/self/status\n"); exit(EXIT_FAILURE); } for(i=0; i<11; i++) { if((fgets(buf, 64, fp)) == NULL) { bs_errmsg("[!] fgets(): /proc/self/status\n"); exit(EXIT_FAILURE); } } fclose(fp); bs_msg("\n--------------- Updating Database ---------------\n" "Processed files : %u\n" "File size : %.2f MiB\n" "Section size : %.2f MiB (executable)\n" "Fingerprint size : %.2f MiB (considering only FP size w/o metadata)\n " "%s" "Time : %umin %.3fsec\n\n" , nfile, (double)t_filesize/(1024*1024), (double)t_secsize/(1024*1024), (double)(FP_SIZE*nfile)/(1024*1024), buf, ((unsigned int)sec_elapsed / 60), ((sec_elapsed-(unsigned int)sec_elapsed)+(unsigned int)sec_elapsed%60) ); }
/* query nearest neighbors */ void neighbor(char *db_path, char *input_path) { FTS *ftsp; FTSENT *p, *chp; int fts_options = FTS_NOSTAT | FTS_COMFOLLOW | FTS_PHYSICAL; char *target[2]; DB *vdbp; int ret; bitshred_t *vdb = NULL; FILE *fp = NULL; int nfile = 0; unsigned int ncmp = 0; uint64_t t_filesize = 0; uint64_t t_secsize = 0; struct timeval t_stime, t_etime; double sec_elapsed = 0; char buf[64]; int i, nvirus; gettimeofday(&t_stime, NULL); /* initialize ftsp */ target[0] = input_path; target[1] = NULL; if ((ftsp = fts_open(target, fts_options, NULL))==NULL) { bs_errmsg("[!] fts_open(): %s\n", input_path); exit(EXIT_FAILURE); } if ((chp = fts_children(ftsp, 0))==NULL) { return; // No files to traverse } /* open DB */ if((ret = db_create(&vdbp, NULL, 0)) != 0){ bs_errmsg("[!] db_create(): %s\n", db_strerror(ret)); exit(EXIT_FAILURE); } sprintf(buf, "%s/vdb", db_path); if((ret = vdbp->open(vdbp, NULL, buf, NULL, DB_RECNO, DB_RDONLY, 0664)) != 0){ vdbp->err(vdbp, ret, "[!] %s", buf); exit(EXIT_FAILURE); } /* # virus in DB */ sprintf(buf, "%s/vdb_nvir.txt", db_path); if((fp = fopen(buf, "r")) == NULL) { bs_errmsg("[!] fopen(): %s\n", buf); exit(EXIT_FAILURE); } if((fgets(buf, 64, fp)) == NULL) { bs_errmsg("[!] fgets(): vdb_nvir.txt\n"); exit(EXIT_FAILURE); } nvirus = atoi(buf); if((fgets(buf, 64, fp)) == NULL) { bs_errmsg("[!] fgets(): vdb_nvir.txt\n"); exit(EXIT_FAILURE); } nvirus += atoi(buf); fclose(fp); if((vdb = malloc(sizeof(bitshred_t))) == NULL){ bs_errmsg("[!] malloc(): vdb\n"); exit(EXIT_FAILURE); } /* list of neighbors found */ if((fp = fopen("neighbor_list.txt", "w")) == NULL) { bs_errmsg("[!] fopen(): neighbor_list.txt\n"); exit(EXIT_FAILURE); } while ((p = fts_read(ftsp)) != NULL) { switch (p->fts_info) { case FTS_F: case FTS_NSOK: neighbor_vdb(vdbp, fp, p->fts_path, vdb, nvirus, &nfile, &ncmp, &t_filesize, &t_secsize); break; default: break; } } /* DB close */ vdbp->close(vdbp, 0); fts_close(ftsp); free(vdb); fclose(fp); gettimeofday(&t_etime, NULL); sec_elapsed = time_diff(t_etime, t_stime); /* report statistics */ if((fp = fopen("/proc/self/status", "r")) == NULL) { bs_errmsg("[!] fopen(): /proc/self/status\n"); exit(EXIT_FAILURE); } for(i=0; i<11; i++) { if((fgets(buf, 64, fp)) == NULL) { bs_errmsg("[!] fgets(): /proc/self/status\n"); exit(EXIT_FAILURE); } } fclose(fp); bs_msg("\n--------------- Querying NN ---------------\n" "Processed files : %u\n" "File size : %.2f MiB\n" "Section size : %.2f MiB (.text or .CODE)\n" "# of comparison : %u\n" "%s" "Time : %umin %.3fsec\n\n" , nfile, (double)t_filesize/(1024*1024), (double)t_secsize/(1024*1024), ncmp, buf, ((unsigned int)sec_elapsed / 60), ((sec_elapsed-(unsigned int)sec_elapsed)+(unsigned int)sec_elapsed%60) ); }
int main(int argc, char **argv) { char *log_file = NULL; char *queue_dir = NULL; char *list[2]; int num_to_send = DEFAULT_NUM, chunk; int fd; FTS *fts; FTSENT *ftsent; int piece, npieces; char filename[PATH_MAX]; err_prog_name(argv[0]); OPTIONS("[-l log] [-n num] queuedir") NUMBER('n', num_to_send) STRING('l', log_file) ENDOPTS if (argc != 2) usage(); if (log_file) err_set_log(log_file); queue_dir = argv[1]; list[0] = queue_dir; list[1] = NULL; fts = fts_open(list, FTS_PHYSICAL|FTS_COMFOLLOW, fts_sort); if (fts == NULL) { err("fts failed on `%s'", queue_dir); exit(1); } ftsent = fts_read(fts); if (ftsent == NULL || ftsent->fts_info != FTS_D) { err("not a directory: %s", queue_dir); exit(1); } ftsent = fts_children(fts, 0); if (ftsent == NULL && errno) { err("*ftschildren failed"); exit(1); } for (chunk = 1; ftsent != NULL; ftsent = ftsent->fts_link) { /* * Skip non-files and ctm_smail tmp files (ones starting with `.') */ if (ftsent->fts_info != FTS_F || ftsent->fts_name[0] == '.') continue; sprintf(filename, "%s/%s", queue_dir, ftsent->fts_name); fd = open(filename, O_RDONLY); if (fd < 0) { err("*open: %s", filename); exit(1); } if (run_sendmail(fd)) exit(1); close(fd); if (unlink(filename) < 0) { err("*unlink: %s", filename); exit(1); } /* * Deduce the delta, piece number, and number of pieces from * the name of the file in the queue. Ideally, we should be * able to get the mail alias name too. * * NOTE: This depends intimately on the queue name used in ctm_smail. */ npieces = atoi(&ftsent->fts_name[ftsent->fts_namelen-3]); piece = atoi(&ftsent->fts_name[ftsent->fts_namelen-7]); err("%.*s %d/%d sent", ftsent->fts_namelen-8, ftsent->fts_name, piece, npieces); if (chunk++ == num_to_send) break; } fts_close(fts); return(0); }
static int statd(FTS *t, FTSENT *parent, uid_t *puid, gid_t *pgid, mode_t *pmode) { FTSENT *p; gid_t sgid; uid_t suid; mode_t smode; struct group *gr; struct passwd *pw; gid_t savegid = *pgid; uid_t saveuid = *puid; mode_t savemode = *pmode; int maxgid; int maxuid; u_short maxmode; gid_t g[MAXGID]; uid_t u[MAXUID]; mode_t m[MAXMODE]; static int first = 1; if ((p = fts_children(t, 0)) == NULL) { if (errno) error("%s: %s", RP(parent), strerror(errno)); return (1); } bzero(g, sizeof(g)); bzero(u, sizeof(u)); bzero(m, sizeof(m)); maxuid = maxgid = maxmode = 0; for (; p; p = p->fts_link) { if (!dflag || (dflag && S_ISDIR(p->fts_statp->st_mode))) { smode = p->fts_statp->st_mode & MBITS; if (smode < MAXMODE && ++m[smode] > maxmode) { savemode = smode; maxmode = m[smode]; } sgid = p->fts_statp->st_gid; if (sgid < MAXGID && ++g[sgid] > maxgid) { savegid = sgid; maxgid = g[sgid]; } suid = p->fts_statp->st_uid; if (suid < MAXUID && ++u[suid] > maxuid) { saveuid = suid; maxuid = u[suid]; } } } /* * If the /set record is the same as the last one we do not need to output * a new one. So first we check to see if anything changed. Note that we * always output a /set record for the first directory. */ if ((((keys & F_UNAME) | (keys & F_UID)) && (*puid != saveuid)) || (((keys & F_GNAME) | (keys & F_GID)) && (*pgid != savegid)) || ((keys & F_MODE) && (*pmode != savemode)) || (first)) { first = 0; if (dflag) (void)printf("/set type=dir"); else (void)printf("/set type=file"); if (keys & F_UNAME) { if ((pw = getpwuid(saveuid)) != NULL) (void)printf(" uname=%s", pw->pw_name); else error("could not get uname for uid=%u", saveuid); } if (keys & F_UID) (void)printf(" uid=%u", saveuid); if (keys & F_GNAME) { if ((gr = getgrgid(savegid)) != NULL) (void)printf(" gname=%s", gr->gr_name); else error("could not get gname for gid=%u", savegid); } if (keys & F_GID) (void)printf(" gid=%u", savegid); if (keys & F_MODE) (void)printf(" mode=%#o", savemode); if (keys & F_NLINK) (void)printf(" nlink=1"); (void)printf("\n"); *puid = saveuid; *pgid = savegid; *pmode = savemode; } return (0); }
int openDirectory(char *dir){ char *tempDir; tempDir = (char*)malloc((sizeof(char))*100); tempDir[0] = '\0'; //null char so we know when we end strcat(tempDir, dir); //attempting to use FTS for traversing directories char *directoryArray[2]; //create array of char array directoryArray[0] = tempDir; directoryArray[1] = NULL; FTS *ftsPtr; // create pointer of file hierarchy FTSENT *parent, *child; //file structure repreentations /* typedef struct _ftsent { unsigned short fts_info; // flags for FTSENT structure char *fts_accpath; // access path char *fts_path; // root path short fts_pathlen; // strlen(fts_path) char *fts_name; // filename short fts_namelen; // strlen(fts_name) short fts_level; // depth (-1 to N) int fts_errno; // file errno long fts_number; // local numeric value void *fts_pointer; // local address value struct ftsent *fts_parent; // parent directory struct ftsent *fts_link; // next file structure/ struct ftsent *fts_cycle; // cycle structure struct stat *fts_statp; // stat(2) information/ } FTSENT; */ // options for fts_open /* There are a number of options, at least one of which (either FTS_LOGICAL or FTS_PHYSICAL) must be specified. The options are selected by ORing the following values: FTS_COMFOLLOW This option causes any symbolic link specified as a root path to be followed immediately whether or not FTS_LOGICAL is also specified. FTS_LOGICAL This option causes the fts routines to return FTSENT structures for the targets of symbolic links instead of the symbolic links themselves. If this option is set, the only symbolic links for which FTSENT structures are returned to the application are those referencing nonexistent files. Either FTS_LOGICAL or FTS_PHYSICAL must be provided to the fts_open() function. FTS_NOCHDIR As a performance optimization, the fts functions change directories as they walk the file hierarchy. This has the side-effect that an application cannot rely on being in any particular directory during the traversal. The FTS_NOCHDIR option turns off this optimization, and the fts functions will not change the current directory. Note that applications should not themselves change their current directory and try to access files unless FTS_NOCHDIR is specified and absolute pathnames were provided as arguments to fts_open(). FTS_NOSTAT By default, returned FTSENT structures reference file characteristic information (the statp field) for each file visited. This option relaxes that requirement as a performance optimization, allowing the fts functions to set the fts_info field to FTS_NSOK and leave the contents of the statp field undefined. FTS_PHYSICAL This option causes the fts routines to return FTSENT structures for symbolic links themselves instead of the target files they point to. If this option is set, FTSENT structures for all symbolic links in the hierarchy are returned to the application. Either FTS_LOGICAL or FTS_PHYSICAL must be provided to the fts_open() function. FTS_SEEDOT By default, unless they are specified as path arguments to fts_open(), any files named "." or ".." encountered in the file hierarchy are ignored. This option causes the fts routines to return FTSENT structures for them. */ int ftsOptions = FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR; // | FTS_NOSTAT | FTS_PHYSICAL | FTS_SEEDOT; printf("we are in DIR %s\n",directoryArray); if((ftsPtr = fts_open(directoryArray, ftsOptions, NULL))==NULL){ printf("error in fts\n"); //error return -1; } //no children /*fts_children() The fts_children() function returns a pointer to an FTSENT structure describing the first entry in a NULL-terminated linked list of the files in the directory represented by the FTSENT structure most recently returned by fts_read(). The list is linked through the fts_link field of the FTSENT structure, and is ordered by the user- specified comparison function, if any. Repeated calls to fts_children() will re-create this linked list. */ child = fts_children(ftsPtr,0); if(child == NULL) return 0; char *fullPathName; while((parent = fts_read(ftsPtr))!= NULL){ switch(parent->fts_info){ //FTS_F A regular file. case FTS_F: fullPathName = (char*)malloc((sizeof(char))*100); fullPathName = parent->fts_path; openFile(fullPathName); break; default: printf("bad file\n"); break; } } //close and free fts_close(ftsPtr); free(fullPathName); }
static int statd(FTS *t, FTSENT *parent, uid_t *puid, gid_t *pgid, mode_t *pmode, u_long *pflags) { FTSENT *p; gid_t sgid; uid_t suid; mode_t smode; u_long sflags; struct group *gr; struct passwd *pw; gid_t savegid = *pgid; uid_t saveuid = *puid; mode_t savemode = *pmode; u_long saveflags = *pflags; u_short maxgid, maxuid, maxmode, maxflags; u_short g[MAXGID], u[MAXUID], m[MAXMODE], f[MAXFLAGS]; char *fflags; static int first = 1; if ((p = fts_children(t, 0)) == NULL) { if (errno) err(1, "%s", RP(parent)); return (1); } bzero(g, sizeof(g)); bzero(u, sizeof(u)); bzero(m, sizeof(m)); bzero(f, sizeof(f)); maxuid = maxgid = maxmode = maxflags = 0; for (; p; p = p->fts_link) { if (!dflag || (dflag && S_ISDIR(p->fts_statp->st_mode))) { smode = p->fts_statp->st_mode & MBITS; if (smode < MAXMODE && ++m[smode] > maxmode) { savemode = smode; maxmode = m[smode]; } sgid = p->fts_statp->st_gid; if (sgid < MAXGID && ++g[sgid] > maxgid) { savegid = sgid; maxgid = g[sgid]; } suid = p->fts_statp->st_uid; if (suid < MAXUID && ++u[suid] > maxuid) { saveuid = suid; maxuid = u[suid]; } /* * XXX * note that the below will break when file flags * are extended beyond the first 4 bytes of each * half word of the flags */ #define FLAGS2IDX(f) ((f & 0xf) | ((f >> 12) & 0xf0)) sflags = p->fts_statp->st_flags; if (FLAGS2IDX(sflags) < MAXFLAGS && ++f[FLAGS2IDX(sflags)] > maxflags) { saveflags = sflags; maxflags = f[FLAGS2IDX(sflags)]; } } } /* * If the /set record is the same as the last one we do not need to output * a new one. So first we check to see if anything changed. Note that we * always output a /set record for the first directory. */ if ((((keys & F_UNAME) | (keys & F_UID)) && (*puid != saveuid)) || (((keys & F_GNAME) | (keys & F_GID)) && (*pgid != savegid)) || ((keys & F_MODE) && (*pmode != savemode)) || ((keys & F_FLAGS) && (*pflags != saveflags)) || (first)) { first = 0; if (dflag) (void)printf("/set type=dir"); else (void)printf("/set type=file"); if (keys & F_UNAME) { pw = getpwuid(saveuid); if (pw != NULL) (void)printf(" uname=%s", pw->pw_name); else if (wflag) warnx( "Could not get uname for uid=%u", saveuid); else errx(1, "Could not get uname for uid=%u", saveuid); } if (keys & F_UID) (void)printf(" uid=%lu", (u_long)saveuid); if (keys & F_GNAME) { gr = getgrgid(savegid); if (gr != NULL) (void)printf(" gname=%s", gr->gr_name); else if (wflag) warnx("Could not get gname for gid=%u", savegid); else errx(1, "Could not get gname for gid=%u", savegid); } if (keys & F_GID) (void)printf(" gid=%lu", (u_long)savegid); if (keys & F_MODE) (void)printf(" mode=%#o", savemode); if (keys & F_NLINK) (void)printf(" nlink=1"); if (keys & F_FLAGS) { fflags = flags_to_string(saveflags); (void)printf(" flags=%s", fflags); free(fflags); } (void)printf("\n"); *puid = saveuid; *pgid = savegid; *pmode = savemode; *pflags = saveflags; } return (0); }
int ftwalk(const char* path, int (*userf)(Ftw_t*), int flags, int (*comparf)(Ftw_t*, Ftw_t*)) { register FTS* f; register FTSENT* e; register int children; register int rv; int oi; int ns; int os; int nd; FTSENT* x; FTSENT* dd[2]; flags ^= FTS_ONEPATH; if (flags & FTW_TWICE) flags &= ~(FTS_NOPREORDER|FTS_NOPOSTORDER); else if (flags & FTW_POST) flags |= FTS_NOPREORDER; else flags |= FTS_NOPOSTORDER; if (children = flags & FTW_CHILDREN) flags |= FTS_SEEDOT; state.comparf = comparf; if (!(f = fts_open((char* const*)path, flags, comparf ? ftscompare : 0))) { if (!path || !(flags & FTS_ONEPATH) && !(path = (const char*)(*((char**)path)))) return -1; ns = strlen(path) + 1; if (!(e = newof(0, FTSENT, 1, ns))) return -1; e->fts_accpath = e->fts_name = e->fts_path = strcpy((char*)(e + 1), path); e->fts_namelen = e->fts_pathlen = ns; e->fts_info = FTS_NS; e->parent = e; e->parent->link = e; rv = (*userf)((Ftw_t*)e); free(e); return rv; } rv = 0; if (children && (e = fts_children(f, 0))) { nd = 0; for (x = e; x; x = x->link) if (x->info & FTS_DD) { x->statb = *x->fts_statp; x->info &= ~FTS_DD; dd[nd++] = x; if (nd >= elementsof(dd)) break; } e->parent->link = e; rv = (*userf)((Ftw_t*)e->parent); e->parent->link = 0; while (nd > 0) dd[--nd]->info |= FTS_DD; for (x = e; x; x = x->link) if (!(x->info & FTS_D)) x->status = FTS_SKIP; } while (!rv && (e = fts_read(f))) { oi = e->info; os = e->status; ns = e->status = e->path == e->fts_accpath ? FTW_PATH : FTW_NAME; nd = 0; switch (e->info) { case FTS_D: case FTS_DNX: if (children) for (x = fts_children(f, 0); x; x = x->link) if (x->info & FTS_DD) { x->statb = *x->fts_statp; x->info &= ~FTS_DD; dd[nd++] = x; if (nd >= elementsof(dd)) break; } break; case FTS_DOT: continue; case FTS_ERR: case FTS_SLNONE: e->info = FTS_NS; break; case FTS_NSOK: e->info = FTS_NSOK; break; } rv = (*userf)((Ftw_t*)e); e->info = oi; if (e->status == ns) e->status = os; while (nd > 0) dd[--nd]->info |= FTS_DD; } fts_close(f); return rv; }
int main ( int argc, char ** argv ) { int ch; FTS * ftsp; FTSENT *p, *chp, *cur; char * curr_dir = "."; int stat_ret; struct stat stat_buf; DIR * dp; struct dirent * dirp; /* -A is always set for the super user */ if ( !getuid() ) f_A_option = 1; /* The tzset() function initializes the tzname variable from the TZ environment variable. */ tzset(); /* parse options */ while ( ( ch = getopt(argc, argv, "AaCcdFfhiklnqRrSstuwx1") ) != -1 ) { switch (ch) { case 'A': f_A_option = 1; break; case 'a': f_a_option = 1; break; case 'C': f_C_option = 1; f_x_option = 0; f_l_option = 0; f_n_option = 0; break; case 'c': f_c_option = 1; f_u_option = 0; /* override -u */ break; case 'd': f_d_option = 1; break; case 'F': f_F_option = 1; break; case 'f': f_f_option = 1; break; case 'h': f_h_option = 1; f_k_option = 0; /* override -k */ break; case 'i': f_i_option = 1; break; case 'k': f_k_option = 1; f_h_option = 0; /* override -h */ break; case 'l': f_l_option = 1; f_1_option = 0; /* override */ f_C_option = 0; f_x_option = 0; break; case 'n': f_n_option = 1; f_C_option = 0; f_x_option = 0; break; case 'q': f_q_option = 1; f_w_option = 0; break; case 'R': f_R_option = 1; break; case 'r': f_r_option = 1; break; case 'S': f_S_option = 1; break; case 's': f_s_option = 1; break; case 't': f_t_option = 1; break; case 'u': f_u_option = 1; f_c_option = 0; /* override -c */ break; case 'w': f_w_option = 1; f_q_option = 0; break; case 'x': f_x_option = 1; f_C_option = 0; f_l_option = 0; f_n_option = 0; break; case '1': f_1_option = 1; f_l_option = 0; break; default: usage(); exit(1); } } argc -= optind; argv += optind; /* parse file argument(s) */ /* If no operands are given, the contents of the current directory ( "." ) are displayed. */ if ( argc == 0 ) { /* -d */ if ( f_d_option ) { stat_ret = lstat ( curr_dir, &stat_buf ); if ( stat_ret < 0 ) { fprintf ( stderr, "stat error\n" ); exit (1); } record_stat ( &stat_buf, curr_dir ); print_file_info_list (); exit (0); } /* non-recursive */ if ( ! f_R_option ) { /* read directory NAME, and list the files in it */ if ( ( dp = opendir(curr_dir) ) == NULL ) { fprintf ( stderr, "can't open '%s'\n", curr_dir ); exit(1); } /* enter directory */ if ( chdir(curr_dir) == -1 ) { fprintf ( stderr, "can't chdir to '%s': %s\n", curr_dir, strerror(errno) ); exit (1); } while ( ( dirp = readdir(dp) ) != NULL ) { if ( lstat ( dirp->d_name, &stat_buf ) < 0 ) { fprintf ( stderr, "lstat() error" ); exit (1); } record_stat ( &stat_buf, dirp->d_name ); } if ( closedir(dp) < 0 ) { fprintf ( stderr, "can't close directory\n" ); exit(1); } print_file_info_list(); exit (0); } /* -R : recursive */ else { if ( ( ftsp = fts_open ( &curr_dir, FTS_LOGICAL, NULL ) ) == NULL ) { fprintf ( stderr, "fts_open() error" ); fts_close ( ftsp ); exit(1); } while ( ( p = fts_read ( ftsp ) ) != NULL ) { switch ( p->fts_info ) { /* directory */ case FTS_D: #ifdef DEBUG printf ( "^^%s\n", p->fts_name ); #endif /* print directory path */ printf ( "%s:\n", p->fts_path ); // get files contained in a directory chp = fts_children ( ftsp, 0 ); // loop directory's files for ( cur = chp; cur; cur = cur->fts_link ) { #ifdef DEBUG printf ( "\t@@ %s\n", cur->fts_name ); #endif record_stat ( cur->fts_statp, cur->fts_name ); } print_file_info_list(); printf ( "\n" ); /* RE-initialize head of file_info linked list */ file_info_list_head = NULL; break; default: break; } } if ( fts_close ( ftsp ) == -1 ) { fprintf ( stderr, "fts_close() error.\n" ); exit (1); } exit (0); } } /* loop file arguments */ /* save current directory path */ char save_current_dir [255]; getcwd ( save_current_dir, sizeof(save_current_dir) / sizeof(save_current_dir[0]) ); while (argc-- > 0) { #ifdef DEBUG printf ( "\n## processing argv : %s\n", *argv ); #endif /* enter original working directory */ if ( chdir(save_current_dir) == -1 ) { fprintf ( stderr, "can't chdir to '%s': %s\n", save_current_dir, strerror(errno) ); exit (1); } /* RE-initialize head of file_info linked list */ file_info_list_head = NULL; stat_ret = lstat ( *argv, &stat_buf ); if ( stat_ret < 0 ) { fprintf ( stderr, "stat error for %s\n", *argv ); argv++; continue; /* to process the next argv */ } /* argument is a file */ if ( S_ISREG ( stat_buf.st_mode ) ) { record_stat ( &stat_buf, *argv ); print_file_info_list(); } /* argument is a directory */ else if ( S_ISDIR ( stat_buf.st_mode ) ) { /* -d means we need just print directory info (not recursively) */ if ( f_d_option ) { stat_ret = lstat ( *argv, &stat_buf ); if ( stat_ret < 0 ) { fprintf ( stderr, "lstat error\n" ); argv++; continue; } record_stat ( &stat_buf, *argv ); print_file_info_list (); argv++; continue; } /* non-recursive */ if ( ! f_R_option ) { /* read directory NAME, and list the files in it */ if ( ( dp = opendir(*argv) ) == NULL ) { fprintf ( stderr, "can't open '%s'\n", *argv ); exit(1); } /* enter directory */ if ( chdir(*argv) == -1 ) { fprintf ( stderr, "can't chdir to '%s': %s\n", *argv, strerror(errno) ); exit (1); } while ( ( dirp = readdir(dp) ) != NULL ) { if ( lstat ( dirp->d_name, &stat_buf ) < 0 ) { fprintf ( stderr, "stat() error" ); exit (1); } record_stat ( &stat_buf, dirp->d_name ); } if ( closedir(dp) < 0 ) { fprintf ( stderr, "can't close directory\n" ); exit(1); } print_file_info_list(); } /* -R : recursive */ else { if ( ( ftsp = fts_open ( &*argv, FTS_LOGICAL, NULL ) ) == NULL ) { // BUG, never executed!!! fprintf ( stderr, "fts_open error %s", strerror(errno) ); argv++; continue; } while ( ( p = fts_read ( ftsp ) ) != NULL ) { switch ( p->fts_info ) { /* directory */ case FTS_D: /* print directory path */ printf ( "%s:\n", p->fts_path ); // get files contained in a directory chp = fts_children ( ftsp, 0 ); // loop directory's files for ( cur = chp; cur; cur = cur->fts_link ) { record_stat ( cur->fts_statp, cur->fts_name ); } print_file_info_list(); printf ( "\n" ); /* RE-initialize head of file_info linked list */ file_info_list_head = NULL; break; default: break; } } if ( -1 == fts_close ( ftsp ) ) { fprintf ( stderr, "fts_close() error.\n" ); argv++; continue; } print_file_info_list(); } } printf ( "\n" ); argv++; } /* endof while ( argc-- > 0 ) */ /* return with success */ exit(0); } /* end of main() */
/* * Traverse the file hierarchy by specified options. single_argc is used * for formatting output. */ static void traverse(int single_argc, char * const *argv, int options) { FTS *handle; FTSENT *file, *child; if ((handle = fts_open(argv, options, f_nosort ? NULL : fts_cmp)) == NULL) { err(EXIT_FAILURE, "Failed to traverse"); } if ((child = fts_children(handle, 0)) == NULL) { if (errno != 0) err(EXIT_FAILURE, "Failed to search the operands"); } print_file(ROOT, child); if (f_dir) goto end; while ((file = fts_read(handle)) != NULL) { if (file->fts_info == FTS_ERR || file->fts_info == FTS_NS) { warnx("%s: file error: %s", file->fts_name, strerror(file->fts_errno)); return_val = EXIT_FAILURE; } else if (file->fts_info == FTS_DC) { warnx("%s: directory error: %s", file->fts_name, strerror(file->fts_errno)); return_val = EXIT_FAILURE; } else if (file->fts_info == FTS_D) { /* * Skip hidden directories if -a or -A not specified, * except the hidden directories are the operands. */ if (!f_listall && file->fts_level != ROOT && file->fts_name[0] == '.') { if (fts_set(handle, file, FTS_SKIP) == -1) { warn("%s: failed to skip", file->fts_name); return_val = EXIT_FAILURE; } continue; } if (single_argc != SINGLE_ARG) printf("\n%s:\n",file->fts_path); else single_argc = 0; if ((child = fts_children(handle, 0)) == NULL) { if (errno != 0) { warn("%s: failed to search", file->fts_name); return_val = EXIT_FAILURE; continue; } } print_file(CHILD, child); /* stop searching subdirectories when -R not set */ if (!f_recursive) if (fts_set(handle, file, FTS_SKIP) == -1) { warn("%s: failed to skip", file->fts_name); return_val = EXIT_FAILURE; } } } /* fts_read return NULL and errno is set */ if (errno != 0) { warn("FTS read error"); return_val = EXIT_FAILURE; } end: (void)fts_close(handle); }
static int statd(FTS *t, FTSENT *parent, uid_t *puid, gid_t *pgid, mode_t *pmode, u_long *pflags) { FTSENT *p; gid_t sgid; uid_t suid; mode_t smode; u_long sflags = 0; const char *name; gid_t savegid; uid_t saveuid; mode_t savemode; u_long saveflags; u_short maxgid, maxuid, maxmode, maxflags; u_short g[MTREE_MAXGID], u[MTREE_MAXUID], m[MTREE_MAXMODE], f[MTREE_MAXFLAGS]; static int first = 1; savegid = *pgid; saveuid = *puid; savemode = *pmode; saveflags = *pflags; if ((p = fts_children(t, 0)) == NULL) { if (errno) mtree_err("%s: %s", RP(parent), strerror(errno)); return (1); } memset(g, 0, sizeof(g)); memset(u, 0, sizeof(u)); memset(m, 0, sizeof(m)); memset(f, 0, sizeof(f)); maxuid = maxgid = maxmode = maxflags = 0; for (; p; p = p->fts_link) { smode = p->fts_statp->st_mode & MBITS; if (smode < MTREE_MAXMODE && ++m[smode] > maxmode) { savemode = smode; maxmode = m[smode]; } sgid = p->fts_statp->st_gid; if (sgid < MTREE_MAXGID && ++g[sgid] > maxgid) { savegid = sgid; maxgid = g[sgid]; } suid = p->fts_statp->st_uid; if (suid < MTREE_MAXUID && ++u[suid] > maxuid) { saveuid = suid; maxuid = u[suid]; } #if HAVE_STRUCT_STAT_ST_FLAGS sflags = FLAGS2INDEX(p->fts_statp->st_flags); if (sflags < MTREE_MAXFLAGS && ++f[sflags] > maxflags) { saveflags = p->fts_statp->st_flags; maxflags = f[sflags]; } #endif } /* * If the /set record is the same as the last one we do not need to * output a new one. So first we check to see if anything changed. * Note that we always output a /set record for the first directory. */ if (((keys & (F_UNAME | F_UID)) && (*puid != saveuid)) || ((keys & (F_GNAME | F_GID)) && (*pgid != savegid)) || ((keys & F_MODE) && (*pmode != savemode)) || ((keys & F_FLAGS) && (*pflags != saveflags)) || first) { first = 0; printf("/set type=file"); if (keys & (F_UID | F_UNAME)) { if (keys & F_UNAME && (name = user_from_uid(saveuid, 1)) != NULL) printf(" uname=%s", name); else /* if (keys & F_UID) */ printf(" uid=%lu", (u_long)saveuid); } if (keys & (F_GID | F_GNAME)) { if (keys & F_GNAME && (name = group_from_gid(savegid, 1)) != NULL) printf(" gname=%s", name); else /* if (keys & F_UID) */ printf(" gid=%lu", (u_long)savegid); } if (keys & F_MODE) printf(" mode=%#lo", (u_long)savemode); if (keys & F_NLINK) printf(" nlink=1"); if (keys & F_FLAGS) printf(" flags=%s", flags_to_string(saveflags, "none")); printf("\n"); *puid = saveuid; *pgid = savegid; *pmode = savemode; *pflags = saveflags; } return (0); }
void runFailure() { fts_children(NULL, anyint()); }