/* Init */ static rc_t KColumnIdx2Init ( KColumnIdx2 *self, uint64_t idx2_eof ) { rc_t rc; #if 0 memset(&self->cstorage,0,sizeof(self->cstorage)); self->cstorage.elem_bits = sizeof(KColumnIdx2BlockCache)*8; self->last = 0; #endif rc = KFileSize ( self -> f, & self -> eof ); if ( rc == 0 ) { if ( self -> eof < idx2_eof ) rc = RC ( rcDB, rcColumn, rcConstructing, rcIndex, rcCorrupt ); else { self -> eof = idx2_eof; return 0; } } KFileRelease ( self -> f ); self -> f = NULL; return rc; }
/* ---------------------------------------------------------------------- * CCNodeSraDirFileSize * returns size in bytes of target file * * "path" [ IN ] - NUL terminated string in directory-native * character set denoting target file * * "size" [ OUT ] - return parameter for file size * NOTE: Does not meet a design target of on stack (localized variable) allocation of single 4kb path */ static rc_t CC CCNodeSraDirFilePhysicalSize (const CCNodeSraDir *self, uint64_t *size, const char *path_fmt, va_list args) { char path[4096]; int path_size; assert (self != NULL); assert (size != NULL); assert (path_fmt != NULL); path_size = args ? vsnprintf ( path, sizeof path, path_fmt, args ) : snprintf ( path, sizeof path, "%s", path_fmt ); if ( path_size < 0 || path_size >= (int) sizeof path ) return RC (rcFS, rcNoTarg, rcAccessing, rcPath, rcExcessive ); if (CCNodeSraDirLegalPath (self, path)) return (KFileSize (self->file, size)); /* we have to assume physical and logical size are the same */ *size = 0; return RC (rcFS, rcNoTarg, rcAccessing, rcPath, rcNotFound); }
static rc_t CC KLoaderFile_Size(const KLoaderFile *self, uint64_t *size) { if( self && self->kfile ) { return KFileSize(self->kfile, size); } return KDirectoryFileSize(self ? self->dir : NULL, size, "%s", self->realname); }
static rc_t LogFileSize_timed ( const LogFile *self, uint64_t *size ) { KTimeMs_t ms = KTimeMsStamp (); rc_t rc = KFileSize ( self -> wrapped, size ); ms = KTimeMsStamp () - ms; WriteToRecorder ( self -> rec, "S\t%lu\t%lu\n", *size, ms ); return rc; }
rc_t CC TCheckFileContent ( struct KFile * file, const uint8_t* filler, size_t filler_size ) { rc_t rc = 0; uint64_t content_size; rc = KFileSize ( file, &content_size ); if (rc != 0) { return rc; } if (content_size == 0) { // do nothing return rc; } const size_t buffer_size = 32*1024; uint8_t buffer[buffer_size], reference_buffer[buffer_size]; size_t filler_sizes_in_buffer = buffer_size / filler_size; assert(buffer_size % filler_size == 0); assert(buffer_size / filler_size > 0); for (size_t i = 0; i < filler_sizes_in_buffer; ++i) { memmove(reference_buffer + i*filler_size, filler, filler_size); } uint64_t num_read_total = 0; size_t num_read; while (num_read_total < content_size) { size_t to_read = content_size - num_read_total; if (to_read > buffer_size) { to_read = buffer_size; } rc = KFileReadAll ( file, num_read_total, buffer, to_read, &num_read ); if (rc != 0) { break; } assert(num_read == to_read); if (memcmp(reference_buffer, buffer, num_read) != 0) { return RC( rcKrypto, rcFile, rcValidating, rcEncryption, rcCorrupt ); } num_read_total += num_read; } return rc; }
static rc_t copy_file (const KFile * fin, KFile *fout) { rc_t rc; uint8_t buff [64 * 1024]; size_t num_read; uint64_t inpos; uint64_t outpos; uint64_t fsize; assert (fin != NULL); assert (fout != NULL); inpos = 0; outpos = 0; rc = KFileSize (fin, &fsize); if (rc != 0) return rc; do { rc = KFileRead (fin, inpos, buff, sizeof (buff), &num_read); if (rc != 0) { PLOGERR (klogErr, (klogErr, rc, "Failed to read from directory structure in creating archive at $(P)", PLOG_U64(P), inpos)); break; } else if (num_read > 0) { size_t to_write; inpos += (uint64_t)num_read; to_write = num_read; while (to_write > 0) { size_t num_writ; rc = KFileWrite (fout, outpos, buff, num_read, &num_writ); if (rc != 0) { PLOGERR (klogErr, (klogErr, rc, "Failed to write to archive in creating archive at $(P)", PLOG_U64(P), outpos)); break; } outpos += num_writ; to_write -= num_writ; } } if (rc != 0) break; } while (num_read != 0); return rc; }
static uint64_t get_file_size( const char * path, bool remotely ) { uint64_t res = 0; const KFile * f; rc_t rc = ( remotely ) ? make_remote_file( &f, path ) : make_local_file( &f, path ); if ( rc == 0 ) { KFileSize ( f, &res ); KFileRelease( f ); } return res; }
rc_t CC TCopyFile ( struct KFile * file_dst, struct KFile * file_src ) { rc_t rc = 0; uint64_t size_src; rc = KFileSize ( file_src, &size_src ); if (rc != 0) { return rc; } if (size_src == 0) { // do nothing return rc; } const size_t buffer_size = 32*1024; uint8_t buffer[buffer_size]; uint64_t num_copied_total = 0; size_t num_read, num_written; while (num_copied_total < size_src) { size_t to_copy = size_src - num_copied_total; if (to_copy > buffer_size) { to_copy = buffer_size; } rc = KFileReadAll ( file_src, num_copied_total, buffer, to_copy, &num_read ); if (rc != 0) { break; } assert(num_read == to_copy); rc = KFileWriteAll ( file_dst, num_copied_total, buffer, to_copy, &num_written ); if (rc != 0) { break; } assert(num_written == to_copy); num_copied_total += num_written; } return rc; }
/* ---------------------------------------------------------------------- * Size * returns size in bytes of file * * "size" [ OUT ] - return parameter for file size */ static rc_t CC KWGAEncFileSize (const KWGAEncFile *self, uint64_t *size) { uint64_t esize; rc_t rc; assert (self != NULL); assert (self->encrypted != NULL); assert (size != NULL); *size = 0; rc = KFileSize (self->encrypted, &esize); if (rc == 0) *size = esize - sizeof (KWGAEncFileHeader); return rc; }
static uint64_t get_file_size( const char * path ) { uint64_t res = 0; KDirectory * dir; rc_t rc = KDirectoryNativeDir( &dir ); if ( rc == 0 ) { const KFile * f; rc = KDirectoryOpenFileRead( dir, &f, "%s", path ); if ( rc == 0 ) { KFileSize ( f, &res ); KFileRelease( f ); } KDirectoryRelease( dir ); } return res; }
/* Init */ static rc_t KColumnIdx2Init ( KColumnIdx2 *self, uint64_t idx2_eof ) { rc_t rc = KFileSize ( self -> f, & self -> eof ); if ( rc == 0 ) { if ( self -> eof < idx2_eof ) rc = RC ( rcDB, rcIndex, rcConstructing, rcIndex, rcCorrupt ); else { self -> eof = idx2_eof; return 0; } } KFileRelease ( self -> f ); self -> f = NULL; return rc; }
/* ---------------------------------------------------------------------- * Destroy * */ static rc_t CC KCounterFileDestroy (KCounterFile *self) { rc_t rc = 0; uint64_t size; assert (self != NULL); assert (self->bytecounter != NULL); if (self->force || ! self->size_allowed) { size_t num_read = 0; uint8_t ignored[64*1024]; size = self->max_position; if (self->dad.read_enabled) do { rc = KFileRead (self->original, size, ignored, sizeof ignored, &num_read); size += num_read; DBGMSG(DBG_KFS,DBG_FLAG(DBG_KFS_COUNTER), ("%s: size '%lu' num_read '%lu'\n", __func__, size, num_read)); if (rc != 0) break; check_state (self, ignored, num_read); } while (num_read != 0); } else { rc = KFileSize (self->original, &size); DBGMSG(DBG_KFS,DBG_FLAG(DBG_KFS_COUNTER), ("%s: lazy way size '%lu'\n", __func__, size)); } *self->bytecounter = size; if (rc == 0) { rc = KFileRelease (self->original); free (self); } return rc; }
static rc_t LoadHeader(char const **rslt, char const path[], char const base[]) { KFile const *kf; rc_t rc = OpenFile(&kf, path, base); *rslt = NULL; if (rc == 0) { uint64_t fsize; rc = KFileSize(kf, &fsize); if (rc == 0) { char *fdata = malloc(fsize+1); if (fdata) { size_t nread; rc = KFileRead(kf, 0, fdata, fsize, &nread); if (rc == 0) { if (nread) { fdata[nread] = '\0'; *rslt = fdata; } else { free(fdata); rc = RC(rcApp, rcArgv, rcAccessing, rcFile, rcEmpty); (void)PLOGERR(klogErr, (klogErr, rc, "File '$(file)' is empty", "file=%s", path)); } } else { (void)PLOGERR(klogErr, (klogErr, rc, "Failed to read file '$(file)'", "file=%s", path)); } } else { rc = RC(rcApp, rcArgv, rcAccessing, rcMemory, rcExhausted); (void)PLOGERR(klogErr, (klogErr, rc, "Failed to read file '$(file)'", "file=%s", path)); } } KFileRelease(kf); } else { (void)PLOGERR(klogErr, (klogErr, rc, "Failed to open file '$(file)'", "file=%s", path)); } return rc; }
/* Init */ static rc_t KColumnDataInit ( KColumnData *self, uint64_t pos, size_t pgsize ) { rc_t rc = KFileSize ( self -> f, & self -> eof ); if ( rc == 0 ) { if ( self -> eof < pos || pgsize == 0 || ( pos % pgsize ) != 0 ) rc = RC ( rcDB, rcColumn, rcConstructing, rcData, rcCorrupt ); else { self -> eof = pos; self -> pgsize = pgsize; return 0; } } KFileRelease ( self -> f ); self -> f = NULL; return rc; }
/* ---------------------------------------------------------------------- * Size * returns size in bytes of file * * "size" [ OUT ] - return parameter for file size */ static rc_t CC KCounterFileSize (const KCounterFile *self, uint64_t *size) { rc_t rc; uint64_t fsize; assert (self != NULL); assert (self->original != NULL); assert (size != NULL); rc = KFileSize (self->original, &fsize); if (rc == 0) { /* success: refreshing the value */ *size = ((KCounterFile *)self)->max_position = fsize; } /* pass along RC value */ 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 { uint64_t fz; size_t z; rc_t irc; uint64_t ignored; rc = KFileSize (infile, &fz); /* ignore rc for now? yes hack */ z = string_size (leaf); /* vdb-decrypt and vdb-encrypt both ignore repository cache files. */ irc = GetCacheTruncatedSize (infile, &ignored, true); if (irc == 0) STSMSG (1, ("skipping cache download file %s", leaf)); else if ((fz == 0) && (string_cmp (leaf + (z - (sizeof (".lock")-1)), sizeof (".lock"), ".lock", sizeof (".lock") , sizeof (".lock")) == 0)) STSMSG (1, ("skipping cache lock download file %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 && do_this_file) 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 == 0) { 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; }
/* EncryptionKey * return any associated encryption key * * attempts to copy NUL-terminated key into provided buffer * * "buffer" [ OUT ] and "bsize" [ IN ] - encryption key output parameter * * "key_size" [ OUT, NULL OKAY ] - returns the key size in * bytes, excluding any NUL termination. */ LIB_EXPORT rc_t CC KRepositoryEncryptionKey ( const KRepository *self, char *buffer, size_t bsize, size_t *key_size ) { rc_t rc; if ( self == NULL ) rc = RC ( rcKFG, rcNode, rcAccessing, rcSelf, rcNull ); else { const KConfigNode *node; if ( key_size != NULL ) * key_size = 0; rc = KConfigNodeOpenNodeRead ( self -> node, & node, "encryption-key" ); if ( rc == 0 ) { size_t num_read, remaining; rc = KConfigNodeRead ( node, 0, buffer, bsize, & num_read, & remaining ); KConfigNodeRelease ( node ); if ( rc == 0 ) { if ( key_size != NULL ) * key_size = num_read + remaining; if ( remaining != 0 ) rc = RC ( rcKFG, rcNode, rcAccessing, rcBuffer, rcInsufficient ); else if ( num_read < bsize ) memset ( & buffer [ num_read ], 0, bsize - num_read ); } } else if ( GetRCState ( rc ) == rcNotFound ) { char path [ 4096 ]; rc_t rc2 = KRepositoryEncryptionKeyFile ( self, path, sizeof path, NULL ); if ( rc2 == 0 ) { KDirectory *wd; rc2 = KDirectoryNativeDir ( & wd ); if ( rc2 == 0 ) { const KFile *keyFile; rc2 = KDirectoryOpenFileRead ( wd, & keyFile, path ); KDirectoryRelease ( wd ); if ( rc2 == 0 ) { size_t num_read; rc = KFileReadAll ( keyFile, 0, buffer, bsize, & num_read ); if ( rc == 0 ) { if ( num_read == bsize ) { uint64_t eof; rc = KFileSize ( keyFile, & eof ); if ( rc == 0 ) num_read = ( size_t ) eof; else num_read = 0; rc = RC ( rcKFG, rcFile, rcReading, rcBuffer, rcInsufficient ); memset ( buffer, 0, bsize ); } else if ( num_read == 0 ) { rc = RC ( rcKFG, rcFile, rcReading, rcFile, rcEmpty ); memset ( buffer, 0, bsize ); } else { char *eoln = string_chr ( buffer, num_read, '\n' ); if ( eoln != NULL ) { if ( eoln == buffer ) num_read = 0; else if ( eoln [ -1 ] == '\r' ) num_read = eoln - buffer - 1; else num_read = eoln - buffer; } if ( key_size != NULL ) * key_size = num_read; memset ( & buffer [ num_read ], 0, bsize - num_read ); } } KFileRelease ( keyFile ); } } } } } return rc; }
static rc_t aws_find_nodes ( KConfigNode *aws_node, const char *aws_path ) { KDirectory *wd; rc_t rc = KDirectoryNativeDir ( &wd ); if ( rc == 0 ) { char *buffer; size_t num_read; uint64_t buf_size; const KFile *credentials, *config; rc = KDirectoryOpenFileRead ( wd, &credentials, "%s%s", aws_path, "/credentials" ); if ( rc == 0 ) { rc = KFileSize ( credentials, &buf_size ); if ( rc == 0 ) { buffer = malloc ( buf_size ); if ( buffer != NULL ) { rc = KFileReadAll ( credentials, 0, buffer, ( size_t ) buf_size, &num_read ); if ( rc == 0 ) aws_parse_file ( credentials, aws_node, buffer, num_read, true ); free ( buffer ); } } KFileRelease ( credentials ); } rc = KDirectoryOpenFileRead ( wd, &config, "%s%s", aws_path, "/config" ); if ( rc == 0 ) { rc = KFileSize ( config, &buf_size ); if ( rc == 0 ) { buffer = malloc ( buf_size ); if ( buffer != NULL ) { rc = KFileReadAll ( config, 0, buffer, ( size_t ) buf_size, &num_read ); if ( rc == 0 ) aws_parse_file ( config, aws_node, buffer, num_read, false ); free ( buffer ); } } KFileRelease ( config ); } KDirectoryRelease ( wd ); } return rc; }
/* ---------------------------------------------------------------------- * Size * returns size in bytes of file * * "size" [ OUT ] - return parameter for file size */ static rc_t CC CCFileSize (const CCFile *self, uint64_t *size) { return KFileSize (self->original, size); }
/* MakeWrite * make a queue file for writing-behind on background thread * * when the file is created, a background thread is started that * waits for buffers to appear in the cross-thread queue. as the producer * thread writes, data are accumulated into buffers which are pushed * into the queue as they fill, and written in turn on the bg thread. * * the producer thread is throttled by queue capacity - determined by * "queue_bytes" and "block_size", such that if the queue is full, * the thread will sleep. the background thread is also throttled by * the queue in that it will sleep if the queue is empty with pending * data. * * the background thread will exit upon a permanent error, or if the * queue is sealed by the producer thread. * * when the file is collected in response to a release message, * the queue will be sealed against further inserts, pending buffers * will be written, the background thread will be joined, and * the source file will be released. * * the intended usage is serial writing of the file. random writes * will be accepted, but may reduce the queue efficiency. * * "qf" [ OUT ] - return parameter for queue file * * "dst" [ IN ] - destination file for write-behind on background thread. * must have write permissions. * * "queue_bytes" [ IN ] - the write-behind limit of the producer * thread, in bytes. this is the amount of data that will be queued * for the background thread before the producer thread sleeps. * * "block_size" [ IN, DEFAULT ZERO ] - optional parameter giving * desired block size when writing to "dst". this may be used * to tune writing for source data, e.g. 64K blocks for gzip. */ LIB_EXPORT rc_t CC KQueueFileMakeWrite ( KFile **qfp, KFile *dst, size_t queue_bytes, size_t block_size, uint32_t timeout_ms ) { rc_t rc; if ( qfp == NULL ) rc = RC ( rcApp, rcFile, rcConstructing, rcParam, rcNull ); else { if ( dst == NULL ) rc = RC ( rcApp, rcFile, rcConstructing, rcFile, rcNull ); else if ( ! dst -> write_enabled ) { if ( dst -> read_enabled ) rc = RC ( rcApp, rcFile, rcConstructing, rcFile, rcReadonly ); else rc = RC ( rcApp, rcFile, rcConstructing, rcFile, rcNoPerm ); } else { KQueueFile *qf = malloc ( sizeof * qf ); if ( qf == NULL ) rc = RC ( rcApp, rcFile, rcConstructing, rcMemory, rcExhausted ); else { rc = KFileInit ( & qf -> dad, ( const KFile_vt* ) & KQueueFileWrite_vt_v1, "KQueueFile", "no-name", false, true ); if ( rc == 0 ) { qf -> f = dst; rc = KFileAddRef ( dst ); if ( rc == 0 ) { uint32_t capacity; /* zero block size means default */ if ( block_size == 0 ) block_size = DEFAULT_BLOCK_SIZE; /* queue capacity is expressed in bytes originally translate to buffer count */ capacity = ( queue_bytes + block_size - 1 ) / block_size; if ( capacity == 0 ) capacity = 1; /* actual capacity will be a power of 2 */ rc = KQueueMake ( & qf -> q, capacity ); if ( rc == 0 ) { /* capture current size if supported */ qf -> rc_from_size_on_open = KFileSize ( dst, & qf -> apparent_size ); /* starting position not used */ qf -> start_pos = 0; /* requested buffer size */ qf -> b = NULL; qf -> bsize = block_size; /* timeout */ qf -> timeout_ms = timeout_ms == 0 ? DEFAULT_TIMEOUT_MS : timeout_ms; /* finally, start the background thread */ rc = KThreadMake ( & qf -> t, KQueueFileRunWrite, qf ); if ( rc == 0 ) { * qfp = & qf -> dad; return 0; } KQueueRelease ( qf -> q ); } KFileRelease ( qf -> f ); } } free ( qf ); } } * qfp = NULL; } return rc; }
static rc_t CC KBufWriteFileSize ( const KBufWriteFile *self, uint64_t *size ) { return KFileSize ( self -> f, size ); }
static rc_t CC KHttpUndyingFileSize(const KHttpUndyingFile *self, uint64_t *size) { return KFileSize(GetUnderlyingFile(self), size); }
static rc_t KCounterFileMake (KCounterFile ** pself, KFile * original, uint64_t * bytecounter, uint64_t * linecounter, bool force) { uint64_t fsize; rc_t rc; KCounterFile * self; /* ----- * we can not accept any of the three pointer parameters as NULL */ assert (pself != NULL); assert (original != NULL); assert (bytecounter != NULL); /* ----- * get space for the object */ self = malloc (sizeof (KCounterFile)); if (self == NULL) /* allocation failed */ { /* fail */ rc = RC (rcFS, rcFile, rcConstructing, rcMemory, rcExhausted); } else { rc = KFileInit (&self->dad, /* initialize base class */ (const KFile_vt*)&vtKCounterFile,/* VTable for KCounterFile */ original->read_enabled, original->write_enabled); if (rc == 0) { for (;;) { if (force) /* all sizes come from actual reads */ { fsize = 0; self->force = true; self->size_allowed = false; } else { rc = KFileSize(original,&fsize); if (GetRCState(rc) == rcUnsupported) { force = true; continue; } else if (rc) break; self->force = false; self->size_allowed = true; } self->max_position = fsize; self->original = original; self->bytecounter = bytecounter; self->linecounter = linecounter; if (linecounter) { self->line_state = ENOTHING; *linecounter = 0; } else { self->line_state = EBINARY; } *bytecounter = fsize; *pself = self; return 0; } } /* fail */ free (self); } *pself = NULL; return rc; }
static rc_t LogFileSize ( const LogFile *self, uint64_t *size ) { rc_t rc = KFileSize ( self -> wrapped, size ); WriteToRecorder ( self -> rec, "S\t%lu\n", *size ); return rc; }
rc_t get_a_sequence (param_block * pb) { char * eol; rc_t rc = 0; if (pb->seq == NULL) /* first call */ { const void * annoying; uint64_t file_pos; size_t map_size; uint64_t file_size; rc = KFileSize (pb->file, &file_size); if (rc) return rc; rc = KMMapAddrRead (pb->mmap, &annoying); if (rc) return rc; pb->seq = annoying; if (pb->seq == NULL) return 0; rc = KMMapPosition (pb->mmap, &file_pos); if (rc) return rc; if (file_pos != 0) { rc = RC (rcExe, rcMemMap, rcAccessing, rcOffset, rcInvalid); return rc; } rc = KMMapSize (pb->mmap, &map_size); if (rc) return rc; if (map_size != file_size) { rc = RC (rcExe, rcMemMap, rcAccessing, rcFile, rcInvalid); return rc; } pb->eof = pb->seq + map_size; } else { pb->seq += pb->seq_size + 1; if (pb->seq >= pb->eof) { pb->seq = NULL; return 0; } } eol = string_chr (pb->seq, pb->eof - pb->seq, '\n'); if (eol == NULL) pb->seq_size = pb->eof - pb->seq; else pb->seq_size = eol - pb->seq; return rc; }