/* GetObjModDate * extract mod date from a path */ rc_t KDBGetObjModDate ( const KDirectory *dir, KTime_t *mtime ) { /* HACK ALERT - there needs to be a proper way to record modification times */ /* this only tells the last time the table was locked, which may be close to the last time it was modified */ rc_t rc = KDirectoryDate ( dir, mtime, "lock" ); if ( rc == 0 ) return 0; if ( GetRCState ( rc ) == rcNotFound ) { rc = KDirectoryDate ( dir, mtime, "sealed" ); if ( rc == 0 ) return 0; } /* get directory timestamp */ rc = KDirectoryDate ( dir, mtime, "." ); if ( rc == 0 ) return 0; * mtime = 0; return rc; }
static rc_t TarNode_Touch(const TarNode* cself) { rc_t rc = 0; if( cself->xml_path != NULL ) { KDirectory* dir = NULL; if( (rc = KDirectoryNativeDir(&dir)) == 0 ) { KTime_t dt; if( (rc = KDirectoryDate(dir, &dt, "%s", cself->xml_path)) == 0 ) { if( dt != cself->mtime ) { const KFile* kfile = NULL; DEBUG_MSG(8, ("%s: updating tar %s\n", __func__, cself->xml_path)); if( (rc = KDirectoryOpenFileRead(dir, &kfile, "%s", cself->xml_path)) == 0 ) { const KXMLMgr* xmlmgr; if( (rc = XML_MgrGet(&xmlmgr)) == 0 ) { const KXMLDoc* xmldoc = NULL; if( (rc = KXMLMgrMakeDocRead(xmlmgr, &xmldoc, kfile)) == 0 ) { const KXMLNodeset* ns = NULL; if( (rc = KXMLDocOpenNodesetRead(xmldoc, &ns, "/TAR")) == 0 ) { uint32_t count = 0; if( (rc = KXMLNodesetCount(ns, &count)) == 0 ) { if( count != 1 ) { rc = RC(rcExe, rcDoc, rcValidating, rcData, rcInvalid); } else { const KXMLNode* n = NULL; if( (rc = KXMLNodesetGetNodeRead(ns, &n, 0)) == 0 ) { char errmsg[4096]; const TarFileList* new_files; if( (rc = TarNode_MakeFileList(n, &new_files, errmsg, cself->rel_path, cself->node.name)) != 0 ) { LOGERR(klogErr, rc, errmsg); } else { TarFileList_Release(cself->files); ((TarNode*)cself)->files = new_files; ((TarNode*)cself)->mtime = dt; } ReleaseComplain(KXMLNodeRelease, n); } } } ReleaseComplain(KXMLNodesetRelease, ns); } ReleaseComplain(KXMLDocRelease, xmldoc); } } ReleaseComplain(KFileRelease, kfile); } } } ReleaseComplain(KDirectoryRelease, dir); } } return rc; }
/* ModDate * get modification date */ LIB_EXPORT rc_t CC KTableModDate ( const KTable *self, KTime_t *mtime ) { rc_t rc; if ( mtime == NULL ) rc = RC ( rcDB, rcTable, rcAccessing, rcParam, rcNull ); else { if ( self == NULL ) rc = RC ( rcDB, rcTable, rcAccessing, rcSelf, rcNull ); else { /* HACK ALERT - there needs to be a proper way to record modification times */ const KDirectory *dir = self -> dir; /* this only tells the last time the table was locked, which may be close to the last time it was modified */ rc = KDirectoryDate ( dir, mtime, "lock" ); if ( rc == 0 ) return 0; if ( GetRCState ( rc ) == rcNotFound ) { rc = KDirectoryDate ( dir, mtime, "sealed" ); if ( rc == 0 ) return 0; } /* get directory timestamp */ rc = KDirectoryDate ( dir, mtime, "." ); if ( rc == 0 ) return 0; } * mtime = 0; } return rc; }
static rc_t XMLThread( const KThread *self, void *data ) { KDirectory *dir = NULL; PLOGMSG(klogInfo, (klogInfo, "XML sync thread started with $(s) sec", PLOG_U32(s), g_xml_sync)); do { rc_t rc = 0; KTime_t dt = 0; DEBUG_MSG(8, ("XML sync thread checking %s\n", g_xml_path)); if( (rc = KDirectoryNativeDir(&dir)) == 0 ) { rc = KDirectoryDate(dir, &dt, "%s", g_xml_path); ReleaseComplain(KDirectoryRelease, dir); } if( rc == 0 ) { if( dt != g_xml_mtime ) { const FSNode* new_root = NULL; PLOGMSG(klogInfo, (klogInfo, "File $(f) changed ($(m) <> $(d)), updating...", PLOG_3(PLOG_S(f),PLOG_I64(m),PLOG_I64(d)), g_xml_path, g_xml_mtime, dt)); if( XML_Open(g_xml_path, &new_root) == 0 ) { if( (rc = XMLLock(true)) == 0 ) { const FSNode* old_root = g_root; g_root = new_root; g_xml_mtime = dt; XMLUnlock(); FSNode_Release(old_root); PLOGMSG(klogInfo, (klogInfo, "Data from $(f) updated successfully", PLOG_S(f), g_xml_path)); } } } else { DEBUG_MSG(8, ("XML sync thread up-to-date %s\n", g_xml_path)); } } else { LOGERR(klogErr, rc, g_xml_path); } SRAList_PostRefresh(); sleep(g_xml_sync); } while( g_xml_sync > 0 ); LOGMSG(klogInfo, "XML sync thread ended"); return 0; }
static rc_t VDBDependenciesReportDepend1(const VDBDependencies *self, const ReportFuncs *f, uint32_t count, uint32_t indent, bool toreport, uint32_t *missing) { KDirectory *dir = NULL; rc_t rc = 0; uint32_t i = ~0; assert(missing); *missing = 0; for (i = 0; i < count; ++i) { bool isMissing = false; bool local = false; const char* seq_id = ""; const char* path = NULL; rc = VDBDependenciesSeqId(self, &seq_id, i); if (rc != 0 && toreport) reportErrorStrInt(indent, rc, "VDBDependenciesSeqId", "origin", "VDatabaseListDependencies", "idx", i); if (rc == 0) { rc = VDBDependenciesLocal(self, &local, i); if (rc != 0 && toreport) { reportErrorStrInt(indent, rc, "VDBDependenciesLocal", "origin", "VDatabaseListDependencies", "idx", i); } } if (rc == 0) { rc = VDBDependenciesPath(self, &path, i); if (rc != 0 && toreport) { reportErrorStrInt(indent, rc, "VDBDependenciesPath", "origin", "VDatabaseListDependencies", "idx", i); } } if (rc == 0) { if (!local && (path == NULL || path[0] == '\0')) { isMissing = true; ++*missing; } if (toreport) { bool reported = false; if (!isMissing && !local) { rc_t rc = 0; bool readable = false; uint64_t size = ~0; KTime_t date = 0; bool ready = false; if (dir == NULL) { rc = KDirectoryNativeDir(&dir); } assert(!local && path && path[0]); if (dir != NULL) { rc = KDirectoryFileSize(dir, &size, "%s", path); if (rc == 0) { rc = KDirectoryDate(dir, &date, "%s", path); } if (rc == 0) { const KFile* f = NULL; rc = KDirectoryOpenFileRead(dir, &f, "%s", path); if (rc == 0) { char buffer[1024]; size_t num_read = 0; size_t bsize = size > sizeof buffer ? sizeof buffer : size; rc = KFileReadAll(f, 0, buffer, bsize, &num_read); if (rc == 0 && num_read != bsize) { rc = RC(rcVDB, rcFile, rcReading, rcBuffer, rcExcessive); } if (rc == 0) { readable = true; } } KFileRelease(f); } if (rc == 0) { ready = true; } } if (ready) { KTime kt; memset(&kt, 0, sizeof kt); KTimeLocal(&kt, date); report(indent, "Dependency", 7, "index", 'd', i, "seq_id", 's', seq_id, "local", 's', local ? "true" : "false", "path", 's', path, "size", 'u', size, "date", 'T', &kt, "readable", 's', readable ? "true" : "false"); reported = true; } else { report(indent, "Dependency", 5, "index", 'd', i, "seq_id", 's', seq_id, "local", 's', local ? "true" : "false", "path", 's', path, "error", 'R', rc); reported = true; } } if (!reported) { report(indent, "Dependency", 4, "index", 'd', i, "seq_id", 's', seq_id, "local", 's', local ? "true" : "false", "path", 's', path == NULL ? "" : path); } } } if (rc != 0 && !toreport) { break; } } RELEASE(KDirectory, dir); return rc; }
static rc_t FileToFile (const KDirectory * sd, const char * source, KDirectory *dd, const char * dest_, bool try_rename, char * base) { const KFile * infile; rc_t rc; uint32_t access; KTime_t date; bool is_tmp; char dest [MY_MAX_PATH + sizeof EncExt]; strcpy (dest, dest_); if (try_rename) NameFixUp (dest); if ((sd == dd) && (strcmp (source, dest) == 0)) return FileInPlace (dd, dest, try_rename); if (base == NULL) STSMSG (1, ("%scrypting file %s to %s", De, source, dest)); else STSMSG (1, ("%scrypting file %s to %s/%s", De, source, base, dest)); /* * A Hack to make stdin/stout work within KFS */ if (UseStdin) { const KFile * iinfile; rc = KFileMakeStdIn (&iinfile); if (rc == 0) { rc = KBufReadFileMakeRead (&infile, iinfile, 64 * 1024); KFileRelease (iinfile); if (rc == 0) { access = 0640; date = 0; goto stdin_shortcut; } LOGERR (klogErr, rc, "error wrapping stdin"); return rc; } } rc = 0; is_tmp = IsTmpFile (source); if (is_tmp) { TmpFoundFlag = true; if (ForceFlag) ; /* LOG OVERWRITE */ else ; /* LOG TMP */ } if (!is_tmp || ForceFlag) { rc = KDirectoryAccess (sd, &access, "%s", source); if (rc) LOGERR (klogErr, rc, "Error check permission of source"); else { rc = KDirectoryDate (sd, &date, "%s", source); if (rc) LOGERR (klogErr, rc, "Error check date of source"); else { rc = KDirectoryOpenFileRead (sd, &infile, "%s", source); if (rc) PLOGERR (klogErr, (klogErr, rc, "Error opening source file '$(S)'", "S=%s", source)); else { EncScheme scheme; stdin_shortcut: rc = EncryptionTypeCheck (infile, source, &scheme); if (rc == 0) { KFile * outfile; uint32_t kcm; /* * Hack to support stdout before VFS is complete enough to use here */ if (UseStdout) { rc = KFileMakeStdOut (&outfile); if (rc) LOGERR (klogErr, rc, "error wrapping stdout"); } else { kcm = ForceFlag ? kcmInit|kcmParents : kcmCreate|kcmParents; rc = KDirectoryCreateFile (dd, &outfile, false, 0600, kcm, "%s", dest); if (rc) PLOGERR (klogErr,(klogErr, rc, "error opening output '$(O)'", "O=%s", dest)); } if (rc == 0) { const KFile * Infile; KFile * Outfile; rc = CryptFile (infile, &Infile, outfile, &Outfile, scheme); if (rc == 0) { rc = CopyFile (Infile, Outfile, source, dest); if (rc == 0) { if (UseStdin || UseStdout) ; else { rc = KDirectorySetAccess (dd, false, access, 0777, "%s", dest); if (rc == 0 && date != 0) rc = KDirectorySetDate (dd, false, date, "%s", dest); } } KFileRelease (Infile); KFileRelease (Outfile); } KFileRelease (outfile); } } KFileRelease (infile); } } } } return rc; }
static rc_t FileInPlace (KDirectory * cwd, const char * leaf, bool try_rename) { rc_t rc; bool is_tmp; STSMSG (1, ("%scrypting file in place %s",De,leaf)); rc = 0; is_tmp = IsTmpFile (leaf); if (is_tmp) { STSMSG (1, ("%s is a vdb-decrypt/vdb-encrypt temporary file and will " "be ignored", leaf)); TmpFoundFlag = true; if (ForceFlag) ; /* LOG OVERWRITE */ else ; /* LOG TMP */ } if (!is_tmp || ForceFlag) { char temp [MY_MAX_PATH]; rc = KDirectoryResolvePath (cwd, false, temp, sizeof temp, ".%s%s", leaf, TmpExt); if (rc) PLOGERR (klogErr, (klogErr, rc, "unable to resolve '.$(S)$(E)'", "S=%s,E=%s",leaf,TmpExt)); else { KPathType kpt; uint32_t kcm; kcm = kcmCreate|kcmParents; kpt = KDirectoryPathType (cwd, temp); if (kpt != kptNotFound) { /* log busy */ if (ForceFlag) { kcm = kcmInit|kcmParents; /* log force */ kpt = kptNotFound; } } if (kpt == kptNotFound) { const KFile * infile; rc = KDirectoryOpenFileRead (cwd, &infile, "%s", leaf); if (rc) PLOGERR (klogErr, (klogErr, rc, "Unable to resolve '$(F)'", "F=%s",leaf)); else { EncScheme scheme; rc = EncryptionTypeCheck (infile, leaf, &scheme); if (rc == 0) { ArcScheme ascheme; bool changed; bool do_this_file; char new_name [MY_MAX_PATH + sizeof EncExt]; do_this_file = DoThisFile (infile, scheme, &ascheme); strcpy (new_name, leaf); if (try_rename) changed = NameFixUp (new_name); else changed = false; /* KOutMsg ("### %d \n", changed); */ if (!do_this_file) { if (changed) { STSMSG (1, ("renaming %s to %s", leaf, new_name)); rc = KDirectoryRename (cwd, false, leaf, new_name); } else STSMSG (1, ("skipping %s",leaf)); } else { KFile * outfile; rc = KDirectoryCreateExclusiveAccessFile (cwd, &outfile, false, 0600, kcm, temp); if (rc) ; else { const KFile * Infile; KFile * Outfile; rc = CryptFile (infile, &Infile, outfile, &Outfile, scheme); if (rc == 0) { STSMSG (1, ("copying %s to %s", leaf, temp)); rc = CopyFile (Infile, Outfile, leaf, temp); if (rc == 0) { uint32_t access; KTime_t date; rc = KDirectoryAccess (cwd, &access, "%s", leaf); if (rc == 0) rc = KDirectoryDate (cwd, &date, "%s", leaf); KFileRelease (infile); KFileRelease (outfile); KFileRelease (Infile); KFileRelease (Outfile); if (rc == 0) { STSMSG (1, ("renaming %s to %s", temp, new_name)); rc = KDirectoryRename (cwd, true, temp, new_name); if (rc) LOGERR (klogErr, rc, "error renaming"); else { if (changed) KDirectoryRemove (cwd, false, "%s", leaf); /*rc =*/ KDirectorySetAccess (cwd, false, access, 0777, "%s", new_name); KDirectorySetDate (cwd, false, date, "%s", new_name); /* gonna ignore an error here I think */ return rc; } } } } KFileRelease (outfile); } } } KFileRelease (infile); } } } } return rc; }
rc_t run_ascp(const char *path, const char *key, const char *src, const char *dest, const AscpOptions *opt) { const char *host = NULL; const char *user = NULL; const char *maxRate = NULL; bool cache_key = false; uint64_t heartbeat = 0; const char *acc = NULL; uint64_t srcSz = 0; uint64_t id = 0; TProgress *callback = NULL; TQuitting *quitting = NULL; rc_t rc = 0; pid_t nPid = 0; int pipeto[2]; /* pipe to feed the exec'ed program input */ int pipefrom[2]; /* pipe to get the exec'ed program output */ #define ARGV_SZ 64 char *argv[ARGV_SZ]; char extraOptions[4096] = ""; int i = 0; int ret = 0; i = 0; if (opt != NULL) { acc = opt->name; cache_key = opt->cache_key; callback = opt->callback; heartbeat = opt->heartbeat; host = opt->host; id = opt->id; quitting = opt->quitting; srcSz = opt->src_size; user = opt->user; if (opt->ascp_options != NULL) { size_t s = string_size(opt->ascp_options); if (s >= sizeof extraOptions) { LOGERR(klogErr, RC(rcExe, rcProcess, rcCreating, rcBuffer, rcInsufficient), "extra ascp options are ignored"); maxRate = opt->target_rate; } else { string_copy (extraOptions, sizeof extraOptions, opt->ascp_options, s); } } else { maxRate = opt->target_rate; } } if (acc == NULL) { acc = dest; } if (heartbeat > 0) { heartbeat /= 1000; if (heartbeat == 0) { heartbeat = 1; } } if (pipe(pipeto) != 0) { perror("pipe() to"); rc = RC(rcExe, rcFileDesc, rcCreating, rcFileDesc, rcFailed); LOGERR(klogErr, rc, "while pipe"); return rc; } if (pipe(pipefrom) != 0) { perror("pipe() from"); rc = RC(rcExe, rcFileDesc, rcCreating, rcFileDesc, rcFailed); LOGERR(klogErr, rc, "while pipe"); return rc; } argv[i++] = (char*)path; argv[i++] = "-i"; argv[i++] = (char*)key; argv[i++] = "-pQTk1"; if (maxRate != NULL && maxRate[0] != '\0') { argv[i++] = "-l"; argv[i++] = (char*)maxRate; } if (user != NULL) { argv[i++] = "--user"; argv[i++] = (char*)user; } if (host != NULL) { argv[i++] = "--host"; argv[i++] = (char*)user; } if (extraOptions[0] != '\0') { bool done = false; char *c = extraOptions; while (!done) { while (true) { if (*c == '\0') { break; } else if (isspace(*c)) { ++c; } else { break; } } if (*c == '\0') { break; } else { argv[i++] = c; } while (true) { if (*c == '\0') { done = true; break; } else if (isspace(*c)) { *(c++) = '\0'; break; } ++c; } if (i > ARGV_SZ - 4) { LOGERR(klogErr, RC(rcExe, rcProcess, rcCreating, rcBuffer, rcInsufficient), "too mary extra ascp options - some of them are ignored"); break; } } } argv[i++] = (char*)src; argv[i++] = (char*)dest; argv[i++] = NULL; logevp(path, argv); if (quitting) { rc = quitting(); } if (rc != 0) { return rc; } nPid = fork(); if (nPid < 0 ) { perror("fork() 1"); rc = RC(rcExe, rcProcess, rcCreating, rcProcess, rcFailed); LOGERR(klogErr, rc, "after fork"); return rc; } else if (nPid == 0) { /* dup pipe read/write to stdin/stdout */ dup2(pipeto [0], STDIN_FILENO); dup2(pipefrom[1], STDOUT_FILENO); dup2(pipefrom[1], STDERR_FILENO); close(pipeto[1]); ret = execvp(path, argv); STSMSG(STS_DBG, ("CHILD: Done %s %s %s = %d", path, src, dest, ret)); exit(EXIT_FAILURE); } else { bool progressing = false; bool writeFailed = false; EAscpState state = eStart; const char y[] = "y\n"; const char n[] = "n\n"; int status = 0; int w = 0; int fd = pipefrom[0]; const char *answer = n; String line; StringInit(&line, NULL, 0, 0); if (cache_key) { answer = y; } { int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); } close(pipeto[0]); close(pipefrom[1]); assert(sizeof y == sizeof n); { int hang = 0; uint64_t prev = 0; KTime_t tPrev = 0; char sfSrc = 'B'; uint64_t hSrc = humanize(srcSz, &sfSrc, NULL); int sig = 0; uint64_t i = 0; KDirectory *dir = NULL; rc_t rc = KDirectoryNativeDir(&dir); DISP_RC(rc, "KDirectoryNativeDir"); if (rc != 0) { return rc; } while (w == 0) { bool quit = false; w = waitpid(nPid, &status, WNOHANG); if (w == 0) { bool got = false; rc_t rc = 0; if (quitting) { rc = quitting(); } if (rc != 0 || quit) { if (sig == 0) { sig = SIGINT; } else if (sig >= SIGKILL) { break; } else { ++sig; } if (progressing) { OUTMSG(("\n")); } PLOGMSG(klogInfo, (klogInfo, "^C pressed: " "Senging $(sgn) to ascp", "sgn=%s", sig)); kill(nPid, sig); } while (true) { char buf[4096]; int s = read(fd, buf, sizeof buf); if (s == 0) { break; } else if (s < 0) { if (errno != EAGAIN) { if (progressing) { OUTMSG(("\n")); } perror("read(child)"); } break; } ascpParse(buf, s, dest, &state, &line); switch (state) { case eKeyEnd: write(pipeto[1], answer, sizeof y - 1); break; case eWriteFailed: writeFailed = true; break; default: break; } got = true; } if (!got) { sleep(1); ++i; if ((heartbeat > 0 && i >= heartbeat) || (i > 99)) { uint64_t size = 0; rc_t rc = KDirectoryFileSize(dir, &size, "%s", dest); if (rc != 0) { size = 0; } else { if (size != prev) { prev = size; tPrev = 0; hang = 0; } else { KTime_t date = 0; rc_t rc = KDirectoryDate(dir, &date, "%s", dest); if (rc == 0) { tPrev = date; if ((KTimeStamp() - date) > 60 * 99) { /* no file update during 99' */ if (hang == 0) { write(pipeto[1], answer, sizeof y - 1); ++hang; } else if (hang < 9) { ++hang; sig = 0; } else { if (sig == 0) { sig = SIGINT; } else { ++sig; } if (progressing) { OUTMSG(("\n")); } if (sig > SIGKILL) { rc = RC(rcExe, rcProcess, rcExecuting, rcProcess,rcDetached); return rc; } PLOGMSG(klogInfo, (klogInfo, "Senging $(sgn) to ascp", "sgn=%s", sig)); kill(nPid, sig); } } } } } if (heartbeat > 0) { if (callback) { quit = !callback(id, eAscpStateRunning, size, 0); } else { progress(acc, size, srcSz, hSrc, sfSrc, tPrev); } progressing = true; } i = 0; } } } } RELEASE(KDirectory, dir); } if (progressing) { OUTMSG(("\n")); } while (1) { char buf[4096]; int s = read(fd, buf, sizeof buf); if (s == 0) { break; } else if (s < 0) { if (errno != EAGAIN) { perror("read(child)"); break; } continue; } ascpParse(buf, s, dest, &state, &line); if (state == eWriteFailed) { writeFailed = true; } } STSMSG( STS_DBG, ("ascp exited with pid=%d status=%d", w, status)); if (WIFEXITED(status)) { STSMSG(STS_DBG, ("ascp exited with exit status %d", WEXITSTATUS(status))); } else { STSMSG(STS_DBG, ("ascp has not terminated correctly")); } if (w == -1) { perror("waitpid"); rc = RC(rcExe, rcProcess, rcWaiting, rcProcess, rcFailed); LOGERR(klogErr, rc, "after waitpid"); exit(EXIT_FAILURE); } if (WIFEXITED(status)) { if (WEXITSTATUS(status) == 0) { STSMSG(STS_DBG, ("ascp succeed")); if (callback) { callback(id, eAscpStateExitSuccess, 0, 0); } } else if (writeFailed) { rc = RC(rcExe, rcProcess, rcExecuting, rcMemory, rcExhausted); if (callback) { callback(id, eAscpStateExitWriteFailure, 0, 0); } } else { if (rc == 0) { rc = RC(rcExe, rcProcess, rcWaiting, rcProcess, rcFailed); } PLOGERR(klogErr, (klogErr, rc, "ascp failed with $(ret)", "ret=%d", WEXITSTATUS(status))); if (callback) { callback(id, eAscpStateExitFailure, 0, 0); } } } else if (WIFSIGNALED(status)) { if (rc == 0) { if (quitting) { rc = quitting(); if (rc == 0) { rc = RC(rcExe, rcProcess, rcWaiting, rcProcess, rcFailed); } } } if (rc != SILENT_RC(rcExe, rcProcess, rcExecuting, rcProcess, rcCanceled)) { PLOGERR(klogErr, (klogErr, rc, "ascp killed by signal $(sig)", "sig=%d", WTERMSIG(status))); if (callback) { callback(id, eAscpStateExitFailure, 0, 0); } } } } return rc; }
static rc_t CC list_action (const KDirectory * dir, const char * path, void * _adata) { rc_t rc; list_adata * data; list_item * item; KPathType type; uint32_t access; uint64_t size; uint64_t loc; KTime_t mtime; size_t pathlen; size_t linklen; char link [2 * 4096]; /* we'll truncate? */ rc = 0; data = _adata; loc = size = 0; pathlen = strlen (path); type = KDirectoryPathType (dir, path); if (type & kptAlias) { rc = KDirectoryVResolveAlias (dir, false, link, sizeof (link), path, NULL); if (rc == 0) linklen = strlen (link); } else { linklen = 0; switch (type & ~kptAlias) { case kptNotFound: rc = RC (rcExe, rcDirectory, rcAccessing, rcPath, rcNotFound); break; case kptBadPath: rc = RC (rcExe, rcDirectory, rcAccessing, rcPath, rcInvalid); break; case kptZombieFile: if ( ! long_list ) return 0; data->has_zombies = true; case kptFile: rc = KDirectoryFileSize (dir, &size, path); if (rc == 0) { if (size > data->max_size) data->max_size = size; rc = KDirectoryFileLocator (dir, &loc, path); if ((rc == 0) && (loc > data->max_loc)) data->max_loc = loc; } break; case kptDir: break; case kptCharDev: case kptBlockDev: case kptFIFO: /* shouldn't get here */ return 0; } } if (rc == 0) { rc = KDirectoryAccess (dir, &access, "%s", path); if (rc == 0) { rc = KDirectoryDate (dir, &mtime, "%s", path); if (rc == 0) { item = malloc (sizeof (*item) + pathlen + linklen + 2); /* usually one too many */ if (item == NULL) { rc = RC (rcExe, rcNoTarg, rcAllocating, rcMemory, rcExhausted); } else { item->type = type; item->access = access; item->size = size; item->loc = loc; item->mtime = mtime; item->path = (char *)(item+1); strcpy (item->path, path); if (type & kptAlias) { item->link = item->path + pathlen + 1; strcpy (item->link, link); } else item->link = NULL; DLListPushHead (&data->list, &item->dad); if (type == kptDir) rc = step_through_dir (dir, path, data->filter, data->fdata, list_action, data); } } } } return rc; }
static rc_t list_action (const KDirectory * dir, const char * path, void * _adata) { rc_t rc = 0; list_adata * data = _adata; list_item * item = NULL; KPathType type = KDirectoryPathType (dir, "%s", path); size_t pathlen = strlen (path); size_t linklen = 0; char link [2 * 4096]; /* we'll truncate? */ if (type & kptAlias) { rc = KDirectoryVResolveAlias (dir, false, link, sizeof (link), path, NULL); if (rc == 0) linklen = strlen (link); } if (rc == 0) { item = calloc (sizeof (*item) + pathlen + linklen + 2, 1); /* usually one too many */ if (item == NULL) { rc = RC (rcExe, rcNoTarg, rcAllocating, rcMemory, rcExhausted); } else { do { item->path = (char *)(item+1); strcpy (item->path, path); item->type = type; rc = KDirectoryAccess (dir, &item->access, "%s", path); if (rc) break; rc = KDirectoryDate (dir, &item->mtime, "%s", path); if (rc) break; if (type & kptAlias) { item->link = item->path + pathlen + 1; strcpy (item->link, link); } else switch (type & ~kptAlias) { case kptNotFound: rc = RC (rcExe, rcDirectory, rcAccessing, rcPath, rcNotFound); break; case kptBadPath: rc = RC (rcExe, rcDirectory, rcAccessing, rcPath, rcInvalid); break; case kptZombieFile: data->has_zombies = true; case kptFile: rc = KDirectoryFileSize (dir, &item->size, "%s", path); if (rc == 0) rc = KDirectoryFileLocator (dir, &item->loc, "%s", path); DBGMSG (DBG_APP, 1, ("%s: found file %s size %lu at %lu\n", __func__, item->path, item->size, item->loc)); break; case kptDir: DBGMSG (DBG_APP, 1, ("%s: found directory %s\n", __func__, item->path)); break; default: DBGMSG (DBG_APP, 1, ("%s: found unknown %s\n", __func__, item->path)); break; } } while (0); } } if (rc == 0) { VectorAppend (&data->list, NULL, item); VectorInsert (&data->sort, item, NULL, list_item_cmp); if (type == kptDir) rc = step_through_dir (dir, path, list_action, data); } return rc; }