/** * Function to process arguments on the command line. Primarily the * arguments processed are non-option arguments. This processing may * have an effect on options already set. * * @param twp_o an AppOptions structure * * @return Zero is returned if there are issues with processing * the given AppOptions structure. Otherwise non-zero is * returned. */ int treewalk_process_args(AppOptions *twp_o) { if(strIsBlank(twp_o->start_path) && !twp_o->argc) { // Check that we have root dir to walk fprintf(stderr,"No tree given to walk!\n"); return 0; } if(strIsBlank(twp_o->start_path)) { strcpy(twp_o->start_path, twp_o->args[0]); twp_o->args++; // move the argument array up by one if(!(twp_o->argc--)) // reduce argument count by 1 twp_o->args = (char **)NULL; // make sure don't go off end of args array } return 1; }
/** * Function to process a file, based on type of operation being * performed. By default, this prints the path. Stat information * for the file may be printed if the verbose option is turned * on. Output from this function can be turned off with the quiet * option. Then only statistics are reported by the treewalk. * * @param infile a FileInfo structure containing the * file name and stat information * @param perf a PerfStat structure to be used to * record any statistics resulting from * processing a file * @param o the options structure holding the global * options values and other shared variables * * @return zero is returned if there are no problems process the * file. Non-zero is returned if there are! */ int treewalk_process_file(FileInfo *infile, PerfStat *perf, options o) { AppOptions *twp_o = (AppOptions *)o.app_ops; // Treewalk options if(twp_o->quiet) return(0); // don't want any output, so simply return if(!infile || strIsBlank(infile->path)) { fprintf(stderr,"Worker Rank %d: treewalk_process_file() cannot print path. Blank path or no file information\n",o.rank); return(-1); } if(!twp_o->verbose) // No verbose -> just want the path printf("%s\n",infile->path); else { // stat info in ls-like format if(infile->exists < 0) // if exists flag < 0 -> no stat structure printf("[ no stat information! ] %s\n", infile->path); else { // print the whole enchilada struct tm sttm; char modebuf[15], timebuf[30]; printmode(infile->st.st_mode, modebuf); memcpy(&sttm, localtime(&infile->st.st_mtime), sizeof(sttm)); strftime(timebuf, sizeof(timebuf), "%a %b %d %Y %T", &sttm); printf("%s %6d %6d %21zd %s %s\n", modebuf, infile->st.st_uid, infile->st.st_gid, (size_t) infile->st.st_size, timebuf, infile->path); } } return(0); }
/** * This function populates a CTM (Chunk Transfer Metadata) structure. * This structure holds infromation as to what chunks of a file have * been transferred. * * Note that this function manages extended attributes on the * transferred file, so that the information about what chunks need * to be transferred, can be maintained through transfer failures. * * @param ctmptr pointer to a CTM structure to * populate. It is an OUT parameter. * @param numchunks a parameter that is looked at * in the case of a new transfer. * @param chunksize a parameter that is used in * the case of a new transfer * * @return a positive number if the population of the structure is * completed. Otherwise a negative result is returned. (-1) * means that the ctmptr was invalid. (-ENOTSUP) means that * the xattr entries could not be read. */ int populateCTA(CTM *ctmptr, long numchunks, size_t chunksize) { ssize_t axist; // hold the size of the returned chunknum xattr. Acts as a flag long anumchunks; // value of number of chunks from the xattr size_t achunksize; // value of chunk size from the xattr size_t arrysz; // the size of the chunk flag bit array buffer in bytes if(!ctmptr || strIsBlank(ctmptr->chnkfname)) // make sure we have a valid structure return(-1); // if xattrs cannot be retieved ... if((axist = getxattr(ctmptr->chnkfname, CTA_CHNKNUM_XATTR, (void *)&anumchunks, sizeof(long))) < 0) { int syserr = errno; // preserve errno if(syserr == ENOATTR) { // no xattr for chnknum exists for file anumchunks = numchunks; // use the parameters passed in achunksize = chunksize; } else return(-(syserr)); // any other error at this point is not handled } // xattrs exist -> read chunk size else if(getxattr(ctmptr->chnkfname, CTA_CHNKSZ_XATTR, (void *)&achunksize, sizeof(size_t)) < 0) return(-ENOTSUP); // error at this point means there are other issue -> return any error ctmptr->chnknum = anumchunks; // now assign number of chunks to CTM structure ctmptr->chnksz = achunksize; // assign chunk size to CTM structure if((arrysz=allocateCTMFlags(ctmptr)) <= 0) // allocate the chunk flag bit array return(-1); // problems? -> return an error if(axist >= 0) { // if first call to getxattr() >= 0 -> can read the chunk flags if(getxattr(ctmptr->chnkfname, CTA_CHNKFLAGS_XATTR, (void *)(ctmptr->chnkflags), arrysz) < 0) return(-ENOTSUP); // error at this point means there are other issue -> return any error } return(1); }
/** * Converts a string to a size_t. Typically, the * input string should have "byte units" included in it. * These "units" are read and used to compute the returned * size_t. * * Note that on most linux systems, size_t is the type used * to store file sizes or values associated with files and * offsets into files. * * @param ss the input string to be converted * * @return negative size_t if string could not be converted to * size_t. The correct size_t is returned if the conversion * was successful. */ size_t str2Size(char* ss) { size_t sizeNoUnits; // return value int ii; int minusOne = FALSE; // flag to indicate that string specified as <num><units>-1 (i.e. 20MB-1) int nn; // length of unprocessed string #define TMP_STR_MAX 64 char tmpStr[TMP_STR_MAX]; struct unitsTblStruct { char* name; /* units name */ size_t mult; /* multiplier associated with units */ }; static struct unitsTblStruct unitsTbl[] = { {"p", 1000L*1000L*1000L*1000L*1000L}, {"t", 1000L*1000L*1000L*1000L}, {"g", 1000*1000*1000}, {"m", 1000*1000}, {"k", 1000}, {"P", 1024L*1024L*1024L*1024L*1024L}, {"T", 1024L*1024L*1024L*1024L}, {"G", 1024*1024*1024}, {"M", 1024*1024}, {"K", 1024}, {0, 1}, }; if(strIsBlank(ss)) return((size_t)(-1)); // No conversion took place strncpy(tmpStr, ss, TMP_STR_MAX); nn = strlen(tmpStr); // handle "<num><units>-1" if (tmpStr[nn-1] == '1' && nn > 1 && tmpStr[nn-2] == '-') { tmpStr[nn-2] = 0; nn -= 2; minusOne = TRUE; } if (tmpStr[nn-1] == 'B' || tmpStr[nn-1] == 'b') { // strip off any trailing "B" in units tmpStr[nn-1] = 0; nn--; } for (ii=0; unitsTbl[ii].name; ii++) { // translate unit name if (tmpStr[nn - 1] == unitsTbl[ii].name[0]) { tmpStr[nn - 1] = 0; break; } } // Now form the size_t errno = 0; // Clear any previous errors sizeNoUnits = (size_t)strtoul(tmpStr,NULL,10); // convert to a numeric type if(errno) return((size_t)(-1)); // Problems converting to numeric format sizeNoUnits *= unitsTbl[ii].mult; // Multiply by multiplier if (minusOne) sizeNoUnits--; return (sizeNoUnits); }
/** * This removes a CTM xattrs from a file's metadata entry. * * @param chnkfname name of the file to test if * xattrs need to be remove. * * @return 0 if file was removed. otherwise a number * corresponding to errno is returned. */ int deleteCTA(const char *chnkfname) { int rc = 0; // return code for function if(strIsBlank(chnkfname)) return(EINVAL); // Nothing to delete, because nofile name was given if(removexattr(chnkfname, CTA_CHNKNUM_XATTR) < 0) // remove the xattr for number of chunks rc = errno; // problems? -> assign the rc if(removexattr(chnkfname, CTA_CHNKSZ_XATTR) < 0) // remove the xattr for chunksize rc = (!rc)?errno:rc; // assign only of not previously assigned if(removexattr(chnkfname, CTA_CHNKFLAGS_XATTR) < 0) // remove the xattr for chunk flags rc = (!rc)?errno:rc; // assign only of not previously assigned return(rc); }
/** * This function stores a CTM structure into extended attributes. Note that * the field chnkstore is used to allow for CTA_CHNKNUM_XATTR and * CTA_CHNKSZ_XATTR to be stored only on the first invocation of this * function. Subsequent calls will only update the chunk flags. * * @param ctmptr pointer to a CTM structure to * store. * * @return 0 if there are no problems store the structure * information into the xattrs. Otherwise a number corresponding * to errno is returned. It may be a negative value. */ int storeCTA(CTM *ctmptr) { int rc = 0; // return code for function int n; // number of bytes written to CTA file if(!ctmptr || strIsBlank(ctmptr->chnkfname)) return(EINVAL); // Nothing to write, because there is no structure, or it is invalid! if(setxattr(ctmptr->chnkfname, CTA_CHNKFLAGS_XATTR, (void *)(ctmptr->chnkflags), SizeofBitArray(ctmptr), 0) < 0) rc = errno; if(!ctmptr->chnkstore && !rc) { // if these xattrs have not been stored, store them now if(setxattr(ctmptr->chnkfname, CTA_CHNKNUM_XATTR, (void *)&(ctmptr->chnknum), sizeof(long), 0) < 0) rc = errno; if(!rc && (setxattr(ctmptr->chnkfname, CTA_CHNKSZ_XATTR, (void *)&(ctmptr->chnksz), sizeof(size_t), 0) < 0)) rc = errno; if(!rc) ctmptr->chnkstore = TRUE; // no errors? -> mark chkstore as done. } return(rc); }