Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

SnSDUtils.cpp

Committer:
uci1
Date:
2013-10-05
Revision:
40:1324da35afd4
Parent:
39:2f17131d22a5
Child:
47:fbe956b10a91

File content as of revision 40:1324da35afd4:

#include "SnSDUtils.h"

#include "mbed.h"
#include "SDFileSystem.h"
#include "FATDirHandle.h"
#include <string.h>
#include <string>

#include "SnConfigFrame.h"
#include "SnEventFrame.h"
#include "SnHeartbeatFrame.h"
#include "SnClockSetFrame.h"

#include "Watchdog.h"

//#define DEBUG

#define SUBDIRSEQ 100  // make a new subdir every X sequences

const char* const SnSDUtils::kSDdir     = "/sd";
const char* const SnSDUtils::kSDsubDir  = "/sd/data";
char              SnSDUtils::fgCurFileName[kFNBufSize]={0};
FILE*             SnSDUtils::fgCurFile  = 0;
uint16_t          SnSDUtils::fgCurSeq   = 0;
bool              SnSDUtils::fgNeedToInit = true;
const uint8_t     SnSDUtils::kIOvers    = 4;
const uint32_t    SnSDUtils::kMaxSizeOfFileHdr = 
    sizeof(uint8_t)+sizeof(uint64_t)+sizeof(uint32_t)+sizeof(uint16_t)
    +(sizeof(uint8_t)+(2u*sizeof(uint16_t))); // power frame v1

SnSDUtils::InitSDFcn SnSDUtils::fgDoInit = 0;

static const uint16_t __kMaxUShort = ~0;

void SnSDUtils::InitSDCard(const bool force) {
    if ((fgNeedToInit || force) && (fgDoInit!=0)) {
        (*fgDoInit)();
        fgNeedToInit = false;
    }
}

const char* SnSDUtils::GetSubDirFor(const uint32_t run, const uint16_t seq,
                                    uint32_t& slen, const bool useSeq) {
    // returns a STATIC string! (so make a copy of it before use)
    // sets slen to the length of this string (same as strlen)
    static const uint16_t tmplen = strlen(kSDsubDir)+50; 
    static char* tmpsd = new char[tmplen];
    slen = snprintf(tmpsd, tmplen, "%s/r%05ld", kSDsubDir, run);
    if (useSeq) {
        slen += snprintf(tmpsd+slen, tmplen-slen, "/s%05d", (seq/SUBDIRSEQ)*SUBDIRSEQ);
    }
    if (slen > tmplen) {
        slen = tmplen;
    }
    return tmpsd;
}

const char* SnSDUtils::GetOutFileName(const uint64_t macadr,
                                      const uint32_t run,
                                      const uint16_t seq) {
    // returns the formatted file name, or NULL if the directory is too long
    // and the full name cannot fit in the buffer
    // NOTE: this fcn uses a static buffer, and so should not be called
    // multiple times in the same line (that includes the calling of functions
    // that call this function!)
    //
    // filename = SnEvtsM[6-byte hex mac adr]r[6-digit run num]s[5-digit seq num].dat
    //  35 chars      7     +    12         +1+         5     +1+     5         + 4
    uint32_t sdlen(0);
    std::string subdirs( GetSubDirFor(run, seq, sdlen, true) );
    const char* subdir = subdirs.c_str();
    if (sdlen<(kFNBufSize-37)) {
        static char tbuf[kFNBufSize];
        memset(tbuf, 0, sizeof(char)*kFNBufSize);
        // if file name format changes, GetSeqNum must be changed too
        sprintf(tbuf, "%s/SnEvtsM%012llXr%05lds%05d.dat",
            subdir,
            macadr>>16, // 64 -> 48 bits
            run, seq);
        return tbuf;
    } else {
        return NULL;
    }
}

bool SnSDUtils::GetRunSeqFromFilename(const char* fn,
                                      uint32_t& run,
                                      uint16_t& seq) {
    bool ret = false;
    const int32_t ncomp = strrchr(fn, 'r') - fn;
#ifdef DEBUG
    printf("fn=%s, ncomp=%d\r\n",fn,ncomp);
#endif
    if ((ncomp<strlen(fn)) && (ncomp>0)) {
        if (sscanf(fn+ncomp,"r%lus%hu.dat",&run,&seq)==2) {
#ifdef DEBUG
            printf("run=%u, seq=%hu\r\n",run,seq);
#endif
            ret = true;
        }
    }
    return ret;
}
/*
uint16_t SnSDUtils::GetSeqNumFromFileName(const char* fn) {
    uint16_t seq=0;
    const uint32_t ncomp = strrchr(fn, 's') - fn;
    if (ncomp<strlen(fn)) {
        sscanf(fn+ncomp,"s%hu.dat",&seq);
    }
    return seq;
}
*/
DIR* SnSDUtils::OpenOrMakeDir(const char* dirname) {
#ifdef DEBUG
    printf("open dir %s\r\n",dirname);
#endif
    InitSDCard();

    DIR* rd( opendir(dirname) );
    if (rd==NULL) {
        // try making the directory
#ifdef DEBUG
        printf("making dir %s\r\n",dirname);
#endif
        mkdir(dirname, 0777);
#ifdef DEBUG
        printf("opening dir %s\r\n",dirname);
#endif
        rd = opendir(dirname);
    }
#ifdef DEBUG
        printf("returning rd=%p\r\n",(void*)rd);
#endif
    return rd;
}

uint16_t SnSDUtils::GetSeqNum(const uint64_t macadr,
                              const uint32_t run) {
    // count the files having expected filename format
    InitSDCard();
    
    // get the run dir
    uint32_t rdlen(0);
    std::string rdnms ( GetSubDirFor(run, 0, rdlen, false) );
    const char* rdnm = rdnms.c_str();
    // open/make the run directory
    FATDirHandle* rd(static_cast<FATDirHandle*>( OpenOrMakeDir(rdnm) ));
    struct dirent* rdent;
    uint16_t dseq(0), maxs(0);
#ifdef DEBUG
        printf("starting readdir loop over %p\r\n",(void*)rd);
#endif    
    while ( (rdent = readdir(rd))!=NULL ) {
#ifdef DEBUG
        printf("rdent = %p\r\n",(void*)rdent);
#endif    
        if ((rd->filinfo()->fattrib & AM_DIR)!=0) {
#ifdef DEBUG
            printf("is a dir\r\n");
#endif    
            // is a directory
            const int ncm = sscanf(rdent->d_name, "s%hu", &dseq);
            if (ncm==1) {
                if (dseq>maxs) {
                    maxs = dseq;
                }
            }
        }
#ifdef DEBUG
         else {
            printf("not a dir\r\n");
        }
#endif    
    }
#ifdef DEBUG
    printf("closing directory %p\r\n",(void*)rd);
#endif    
    closedir(rd);
#ifdef DEBUG
    printf("Found max seq dir num %hu for run %u\r\n",maxs,run);
#endif
    // open up the seq dir
    rdnms = GetSubDirFor(run, maxs, rdlen, true);
    rdnm = rdnms.c_str();
    // runXseq0 filename (fn points to a static buffer)
    const char* fn = GetOutFileName(macadr, run, maxs)
        + rdlen + 1; // take out dir and '/'s
    // don't compare seq#. don't use num of chars in case seq is >999
    const int32_t ncomp = strrchr(fn, 's') - fn;
    // open (or make) the run/seq dir
    rd = static_cast<FATDirHandle*>( OpenOrMakeDir(rdnm) );
    // get the new sequence number (ok if it overflows this seq "bin")
    maxs=0;
    while ( (rdent = readdir(rd))!=NULL ) {
        Watchdog::kick(); // don't reset
        if ((rd->filinfo()->fattrib & AM_DIR)==0) {
            // is a file.
            // don't just count files, in case one seq was
            // transferred and erased in the middle of a run
            if (strncmp(rdent->d_name, fn, ncomp)==0) {
                // allow for deleted files to make gaps.
                // search for highest seq number and increase that
                if (sscanf((rdent->d_name)+ncomp,"s%hu.dat",&dseq)==1) {
#ifdef DEBUG
                    printf("dn=%s, seq=%hu, __kMaxUShort=%hu\r\n",
                        rdent->d_name, dseq, __kMaxUShort);
#endif
                    if (dseq==__kMaxUShort) {
                        maxs = dseq;
                        break;
                    }
                    if (dseq>=maxs) {
                        maxs=dseq+1;
                    }
                    if (maxs==__kMaxUShort) {
                        break;
                    }
                }
            }
        }
    }
    closedir(rd);

#ifdef DEBUG
    printf("return maxs=%hu\r\n",maxs);
#endif
    return maxs;
}

FILE* SnSDUtils::OpenExistingFile(const char* name, const bool setcurrent,
                                  const bool redoDir) {
    InitSDCard();
    FILE* f = 0;
    //if ((name!=NULL) && ((*name)!=0) ) { // simple check if filename not set
    if (name!=NULL) { // simple check if filename not set
#ifdef DEBUG
        printf("opening SD file. name=[%s]\r\n",name);
#endif
        f = OpenSDFile(name, "rb", redoDir);
        /*
        if (setcurrent) {
            fgCurFile = f;
            strncpy(fgCurFileName, name, kFNBufSize-1);
            fgCurSeq = GetSeqNumFromFileName(fgCurFileName);
        }
        */
    }
    return f;
}

bool SnSDUtils::GetFullFilename(const char* name, std::string& ffn) {
#ifdef DEBUG
    printf("GetFullFilename (%s)\r\n",name);
#endif
    bool ret = false;
    uint32_t run(0);
    uint16_t seq(0);
    const char* fn = strrchr(name, '/');
#ifdef DEBUG
    printf("w/o / : %s\r\n",fn);
#endif
    if (fn!=NULL) {
        ++fn; // remove the /
    } else {
        fn = name;
    }
    ffn = "";
    if (GetRunSeqFromFilename(fn, run, seq)) {
#ifdef DEBUG
        printf("got run=%d, seq=%hu\r\n",run,seq);
#endif
        uint32_t sdlen(0);
        std::string subds( GetSubDirFor(run,seq,sdlen, true) );
        const char* subd = subds.c_str();
#ifdef DEBUG
        printf("subd=%s\r\n",subd);
#endif
        ffn = subd;
        ffn += "/";
        ret = true;
    }
    ffn += fn;
#ifdef DEBUG
    printf("ffn=%s, ret=%d\r\n",ffn.c_str(),(int)ret);
#endif
    return ret;
}

FILE* SnSDUtils::OpenSDFile(const char* name, const char* mode,
                            const bool redoDir) {
    // TODO: check if we have memory?
#ifdef DEBUG
    printf("OpenSDFile: Trying to open %s.\r\n",name);
#endif
    InitSDCard();

    std::string ffn;
    FILE* f = 0;
    bool ok = true;
#ifdef DEBUG
    printf("redoDir=%d\r\n",(int)redoDir);
#endif
    if (redoDir) {
#ifdef DEBUG
        printf("calling GetFullFilename\r\n");
#endif
        ok = GetFullFilename(name, ffn);
#ifdef DEBUG
        printf("ffn=%s\r\n",ffn.c_str());
#endif
    } else {
#ifdef DEBUG
        printf("looking for /\r\n");
#endif
        // make sure the directory exists
        const char* ld = strrchr(name, '/');
#ifdef DEBUG
        printf("ld=%p, ld-name = %d\r\n",ld,(int)(ld-name));
#endif
        if ((ld!=0) && (ld>name)) {
            std::string dn(name, ld-name);
            DIR* d = OpenOrMakeDir(dn.c_str());
#ifdef DEBUG
        printf("d=%p\r\n",d);
#endif
            if (d!=NULL) {
                closedir(d);
            }
        }
        // now just copy the (already-) full name
        ffn = name;
    }
    if ( ok && ffn.size()>0 ) {
#ifdef DEBUG
        printf("OpenSDFile: %s, mode %s\r\n",ffn.c_str(),mode);
#endif
        f = fopen(ffn.c_str(), mode);
        //setvbuf(f, 0, _IONBF, 0); // no buffering
#ifdef DEBUG
        printf("OpenSDFile: f=%p\r\n",(void*)f);
#endif
    }
#ifdef DEBUG
    printf("ffn=%s\r\n",ffn.c_str());
#endif
    return f;
}

FILE* SnSDUtils::OpenNewOutputFile(const uint64_t macadr,
                                   const uint32_t run,
                                   const uint16_t minseq) {
    // opens a new file in the specified directory and writes this
    // this mbed's mac address as the first sizeof(uint64_t) bytes (i.e. 4 bytes)
    //
#ifdef DEBUG
    printf("getting seq num for run %u, minseq %hu\r\n",
        run, minseq);
#endif
    InitSDCard();

    fgCurSeq = GetSeqNum(macadr, run);
    if (fgCurSeq<minseq) {
        fgCurSeq=minseq;
    }
#ifdef DEBUG
    printf("fgCurSeq=%hu\r\n",fgCurSeq);
    printf("getting output file name\r\n");
#endif
    memset(fgCurFileName, 0, sizeof(char)*kFNBufSize);
    strncpy(fgCurFileName,GetOutFileName(macadr, run, fgCurSeq),kFNBufSize-1);
    //fprintf(stderr,"cur file = %s (%hu)\n\r",fgCurFileName,fgCurSeq);
#ifdef DEBUG
    printf("fgCurFileName=%s\r\n",fgCurFileName);
#endif
    fgCurFile = 0;
    if (fgCurFileName!=NULL) {
#ifdef DEBUG
        printf("opening SD file\r\n");
#endif
        fgCurFile = OpenSDFile(fgCurFileName, "wb", false);
        if (fgCurFile!=NULL && ferror(fgCurFile)==0) {
#ifdef DEBUG
            printf("Writing file header\r\n");
#endif
            WriteFileHeader(fgCurFile, macadr, run, fgCurSeq);
        }
    }
#ifdef DEBUG
    printf("fgCurFile=%p\r\n",(void*)fgCurFile);
#endif
    return fgCurFile;
}

void SnSDUtils::PrintFilesInDirs(const char* dirname) {
    InitSDCard();

    DIR* d;
    struct dirent* dent;
    Watchdog::kick(); // don't reset
    if ( (d = opendir( dirname ))!=NULL ) {
        FATDirHandle* dir = static_cast<FATDirHandle*>(d);
        while ( (dent = readdir(d))!=NULL ) {
            printf("dn=%s. datr=%02x. dir=%d\r\n",
                dent->d_name,
                dir->filinfo()->fattrib,
                dir->filinfo()->fattrib & AM_DIR);
            if ( (dir->filinfo()->fattrib & AM_DIR)!=0 ) {
                std::string dnm(dirname);
                dnm += "/";
                dnm += dent->d_name;
                PrintFilesInDirs(dnm.c_str());
            }
        }
    }

}

float SnSDUtils::GetFreeBytes() {
    InitSDCard();

    FATFS* fs;
    DWORD fre_clust;
    f_getfree("0:",&fre_clust,&fs);
    const float frs = static_cast<float>(fs->csize)
        *static_cast<float>(fs->free_clust)
#if _MAX_SS != 512
        *(fs->ssize);
#else
        *512;
#endif
#ifdef DEBUG
    printf("free space = %g b (%g GB, %g MB, %g KB)\r\n",
        frs, frs/1073741824.0, frs/1048576.0, frs/1024.0);
#endif
    return frs;
}

void SnSDUtils::GetDirProps(const char* dirname,
                            uint32_t& nfiles,
                            float& totbytes) {
    InitSDCard();

    nfiles = 0;
    totbytes = 0;
    struct dirent* dent;
    FATDirHandle* d = static_cast<FATDirHandle*>( opendir(dirname) );
    if (d!=0) {
        while ( (dent = readdir(d))!=NULL ) {
            Watchdog::kick(); // don't reset
            if ( (d->filinfo()->fattrib & AM_DIR)!=0 ) {
                // a subdirectory
                std::string dnm(dirname);
                dnm += "/";
                dnm += dent->d_name;
                uint32_t sdnf;
                float    sdtb;
                GetDirProps(dnm.c_str(), sdnf, sdtb);
                nfiles += sdnf;
                totbytes += sdtb;
             } else {
                // a file
                ++nfiles;
                totbytes += d->filinfo()->fsize;
             }
        }
        closedir(d);
    }
#ifdef DEBUG
    printf("GetDirProps: %s :: nf=%u, tb=%g\r\n",
        dirname, nfiles, totbytes);
#endif
}

bool SnSDUtils::WriteHeartbeatTo(FILE* file,
                                 const uint32_t time,
                                 const uint32_t num) {
    if (file!=0) {
        InitSDCard();
    
        const bool r1 =
            SnHeaderFrame::WriteTo(file, SnHeaderFrame::kHeartbeatCode,
                         SnHeartbeatFrame::SizeOf(SnHeartbeatFrame::kIOVers));
        const bool r2 = 
            SnHeartbeatFrame::WriteTo(file, time, num);
        return (r1 && r2);
    } else {
        return false;
    }
}

bool SnSDUtils::WriteTrigWaitWinTime(FILE* file,
                                     SnClockSetFrame& clkset,
                                     const bool isStart) {
    if (file!=0) {
        InitSDCard();
    
        bool ok = SnHeaderFrame::WriteTo(file,
                (isStart) ? (SnHeaderFrame::kFileTrgStrtCode)
                          : (SnHeaderFrame::kFileTrgStopCode),
                clkset.SizeOf());
        ok &= (SnCommWin::kOkMsgSent == clkset.WriteTo(file));
        return ok;
    } else {
        return false;
    }
}

bool SnSDUtils::WriteEventTo(FILE* efile, char* const evtBuf,
                             const SnEventFrame& evt,
                             const SnConfigFrame& conf) {
    // write event to SD card
        
    if (efile!=0) {
        InitSDCard();
        
        uint8_t sLoseLSB=0, sLoseMSB=0;
        uint16_t sWvBase=0;
        conf.GetPackParsFor(SnConfigFrame::kSDcard, sLoseLSB, sLoseMSB, sWvBase);
        SnHeaderFrame::WriteTo(efile, SnHeaderFrame::kEventCode, 
                               evt.SizeOf(SnEventFrame::kIOVers, sLoseLSB, sLoseMSB));
        const bool ret = evt.WriteTo(efile, evtBuf, sLoseLSB, sLoseMSB, sWvBase);
        fflush(efile);
        return ret;
    } else {
        return false;
    }
}

bool SnSDUtils::WriteConfig(FILE* efile,
                            const SnConfigFrame& conf) {
    if (efile!=0) {
        InitSDCard();

        SnHeaderFrame::WriteTo(efile, SnHeaderFrame::kConfigCode, 
                           conf.SizeOf(SnConfigFrame::kIOVers));
        conf.WriteTo(efile);
        return true;
    } else {
        return false;
    }
}

void SnSDUtils::DeleteFile(FILE*& f, const char* fname) {
#ifdef DEBUG
    printf("try to delete %s at %p\r\n",fname,f);
#endif
    InitSDCard();

    if (f!=0) {
        fclose(f);
        f=0;
    }
    std::string fn("");
    if (GetFullFilename(fname, fn)) {
#ifdef DEBUG
        printf("calling remove [%s]\r\n",fn.c_str());
#endif
        remove(fn.c_str());
    }
}

void SnSDUtils::DeleteFilesOfRun(const uint32_t run) {
#ifdef DEBUG
    printf("deleteing files of run %lu\r\n",run);
#endif
    uint32_t rdlen(0);
    std::string rdnm( GetSubDirFor(run, 0, rdlen, false) );
    DeleteAllFiles(rdnm.c_str());
}

void SnSDUtils::DeleteAllFiles(const char* dirname) {
#ifdef DEBUG
    printf("deleting ALL files in %s\r\n",dirname);
#endif
    InitSDCard();

    DIR* d;
    struct dirent* dent;
    if ( (d = opendir( dirname ))!=NULL ) {
        FATDirHandle* dir = static_cast<FATDirHandle*>(d);
        while ( (dent = readdir(d))!=NULL ) {
            Watchdog::kick(); // don't reset
            if ( (dir->filinfo()->fattrib & AM_DIR)!=0 ) {
                // a subdirectory
                std::string dnm(dirname);
                dnm += "/";
                dnm += dent->d_name;
                // delete all the files in this new subdir
#ifdef DEBUG
                printf("call DeleteAllFiles(%s)\r\n",dnm.c_str());
#endif
                DeleteAllFiles(dnm.c_str());
            } else if (strncmp(dent->d_name, "SnEvts", 6)==0) {
                // a data file (delete it)
                const bool isCurFile = 
                    (strcmp(dent->d_name, GetCurFileName())==0);
                if (isCurFile==false) { // don't delete the current file
                    FILE* f(0); // dummy
                    DeleteFile(f, dent->d_name);
                }
            }
        } // loop over stuff in this dir
        closedir(d);
        DeleteDirIfEmpty(dirname);
    }
}

void SnSDUtils::DeleteDirIfEmpty(const char* dirname) {
#ifdef DEBUG
    printf("DeleteDirIfEmpty(%s)\r\n",dirname);
#endif
    InitSDCard();

    DIR* d;
    struct dirent* dent;
    if ( (d = opendir(dirname))!=NULL ) {
        dent = readdir(d);
        bool doDel = false;
        if ( dent==NULL ) {
            // then this directory is empty
            static const size_t subdsz = strlen(kSDsubDir);
            // just double check that this directory is
            // a subdirectory of the data dir
            if (strlen(dirname)>subdsz) {
                doDel = true;
            }
        } // else this dir isn't empty
        closedir(d);
        if (doDel) {
#ifdef DEBUG
            printf("removing directory [%s]\r\n",dirname);
#endif
            remove(dirname);
        }
    }
}

SnCommWin::ECommWinResult SnSDUtils::SendAllOfRun(SnCommWin* comm,
                                                  const uint32_t timeout,
                                                  char* const buf,
                                                  const uint32_t bsize,
                                                  const SnConfigFrame& curConf,
                                                  SnEventFrame& evt,
                                                  SnPowerFrame& pow,
                                                  const uint32_t runnum) {
    // send all files in a run

    // get the run dir
    uint32_t rdlen(0);
    std::string rdnms ( GetSubDirFor(runnum, 0, rdlen, false) );
    return SendAllFiles(comm, timeout, buf, bsize, curConf, evt, pow,
                        rdnms.c_str());
}

SnCommWin::ECommWinResult SnSDUtils::SendAllFiles(SnCommWin* comm,
                                                  const uint32_t timeout,
                                                  char* const buf,
                                                  const uint32_t bsize,
                                                  const SnConfigFrame& curConf,
                                                  SnEventFrame& evt,
                                                  SnPowerFrame& pow,
                                                  const char* dirname) {
    // send all files in the specified directory
    
    InitSDCard();

    SnCommWin::ECommWinResult rs  = SnCommWin::kOkMsgSent;

    DIR* d;
    struct dirent* dent;
    if ( (d = opendir( dirname ))!=NULL ) {
        FATDirHandle* dir = static_cast<FATDirHandle*>(d);
        while ( (dent = readdir(d))!=NULL ) {
            Watchdog::kick(); // don't reset
            SnCommWin::ECommWinResult res = rs;
            if ( (dir->filinfo()->fattrib & AM_DIR)!=0 ) {
                // a subdirectory
                std::string dnm(dirname);
                dnm += "/";
                dnm += dent->d_name;
                // send all the files in this new subdir
                res = SendAllFiles(comm, timeout, buf, bsize, 
                             curConf, evt, pow,
                             dnm.c_str());
            } else if (strncmp(dent->d_name, "SnEvts", 6)==0) {
                // a data file (send it)
                const bool isCurFile = 
                    (strcmp(dent->d_name, GetCurFileName())==0);
                FILE* f(0);
                if (isCurFile) {
                    // file must already be written out!
                    f = GetCurFile();
                } else {
                    std::string ffn(dirname);
                    ffn += "/";
                    ffn += dent->d_name;
                    f = OpenExistingFile(ffn.c_str(), false, false);
                }
#ifdef DEBUG
                printf("calling senddata: f=%p (cur %p), fn=%s\r\n",
                    f, GetCurFile(), dent->d_name);
#endif
                uint8_t hndres = SnHeaderFrame::kHnShFailNonCode;
                if (f!=0) {
                    res = comm->SendDataFromFile(f, dent->d_name,
                                         curConf, evt, pow, buf, bsize,
                                         0, timeout,
                                         &hndres);

                    if (isCurFile) {
                        // move (back) to the end of the file
                        // altho hopefully no writing will happen after this
                        fseek(fgCurFile, 0, SEEK_END);
                    }
                }                
#ifdef DEBUG
                printf("isCurFile=%d, res=%d, deleting=%d, hndres=%02x\r\n",
                    (int)isCurFile, (int)res, (int)(curConf.IsDeletingFiles()),
                    hndres);
#endif
                
            }
            if ((res<rs) || (res==SnCommWin::kOkStopComm)) {
                rs = res;
            }
            // don't necessarily stop if rs is bad. don't want one bad file to
            // prevent sending the others
            if (rs<=SnCommWin::kFailTimeout) {
                break;
            } else if (rs==SnCommWin::kOkStopComm) {
                break;
            }
        } // loop over stuff in this directory
        closedir(d);
        // see if we need to remove this directory now
        if (curConf.IsDeletingFiles()) {
            DeleteDirIfEmpty(dirname);
        }
    }
    
    return rs;
}