Lines Matching refs:file
551 static lfs_ssize_t lfs_file_flushedwrite(lfs_t *lfs, lfs_file_t *file,
553 static lfs_ssize_t lfs_file_rawwrite(lfs_t *lfs, lfs_file_t *file,
555 static int lfs_file_rawsync(lfs_t *lfs, lfs_file_t *file);
556 static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file);
557 static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file);
579 static lfs_ssize_t lfs_file_flushedread(lfs_t *lfs, lfs_file_t *file,
581 static lfs_ssize_t lfs_file_rawread(lfs_t *lfs, lfs_file_t *file,
583 static int lfs_file_rawclose(lfs_t *lfs, lfs_file_t *file);
584 static lfs_soff_t lfs_file_rawsize(lfs_t *lfs, lfs_file_t *file);
3006 /// Top level file operations ///
3007 static int lfs_file_rawopencfg(lfs_t *lfs, lfs_file_t *file,
3022 // setup simple file details
3024 file->cfg = cfg;
3025 file->flags = flags;
3026 file->pos = 0;
3027 file->off = 0;
3028 file->cache.buffer = NULL;
3030 // allocate entry for file if it doesn't exist
3031 lfs_stag_t tag = lfs_dir_find(lfs, &file->m, &path, &file->id);
3032 if (tag < 0 && !(tag == LFS_ERR_NOENT && file->id != 0x3ff)) {
3038 file->type = LFS_TYPE_REG;
3039 lfs_mlist_append(lfs, (struct lfs_mlist *)file);
3060 err = lfs_dir_commit(lfs, &file->m, LFS_MKATTRS(
3061 {LFS_MKTAG(LFS_TYPE_CREATE, file->id, 0), NULL},
3062 {LFS_MKTAG(LFS_TYPE_REG, file->id, nlen), path},
3063 {LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0), NULL}));
3065 // it may happen that the file name doesn't fit in the metadata blocks, e.g., a 256 byte file name will
3083 tag = LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0);
3084 file->flags |= LFS_F_DIRTY;
3088 tag = lfs_dir_get(lfs, &file->m, LFS_MKTAG(0x700, 0x3ff, 0),
3089 LFS_MKTAG(LFS_TYPE_STRUCT, file->id, 8), &file->ctz);
3094 lfs_ctz_fromle32(&file->ctz);
3098 for (unsigned i = 0; i < file->cfg->attr_count; i++) {
3100 if ((file->flags & LFS_O_RDONLY) == LFS_O_RDONLY) {
3101 lfs_stag_t res = lfs_dir_get(lfs, &file->m,
3103 LFS_MKTAG(LFS_TYPE_USERATTR + file->cfg->attrs[i].type,
3104 file->id, file->cfg->attrs[i].size),
3105 file->cfg->attrs[i].buffer);
3114 if ((file->flags & LFS_O_WRONLY) == LFS_O_WRONLY) {
3115 if (file->cfg->attrs[i].size > lfs->attr_max) {
3120 file->flags |= LFS_F_DIRTY;
3126 if (file->cfg->buffer) {
3127 file->cache.buffer = file->cfg->buffer;
3129 file->cache.buffer = lfs_malloc(lfs->cfg->cache_size);
3130 if (!file->cache.buffer) {
3137 lfs_cache_zero(lfs, &file->cache);
3141 file->ctz.head = LFS_BLOCK_INLINE;
3142 file->ctz.size = lfs_tag_size(tag);
3143 file->flags |= LFS_F_INLINE;
3144 file->cache.block = file->ctz.head;
3145 file->cache.off = 0;
3146 file->cache.size = lfs->cfg->cache_size;
3148 // don't always read (may be new/trunc file)
3149 if (file->ctz.size > 0) {
3150 lfs_stag_t res = lfs_dir_get(lfs, &file->m,
3152 LFS_MKTAG(LFS_TYPE_STRUCT, file->id,
3153 lfs_min(file->cache.size, 0x3fe)),
3154 file->cache.buffer);
3167 file->flags |= LFS_F_ERRED;
3169 lfs_file_rawclose(lfs, file);
3174 static int lfs_file_rawopen(lfs_t *lfs, lfs_file_t *file,
3177 int err = lfs_file_rawopencfg(lfs, file, path, flags, &defaults);
3182 static int lfs_file_rawclose(lfs_t *lfs, lfs_file_t *file) {
3184 int err = lfs_file_rawsync(lfs, file);
3190 lfs_mlist_remove(lfs, (struct lfs_mlist*)file);
3193 if (!file->cfg->buffer) {
3194 lfs_free(file->cache.buffer);
3202 static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) {
3220 for (lfs_off_t i = 0; i < file->off; i++) {
3222 if (file->flags & LFS_F_INLINE) {
3223 err = lfs_dir_getread(lfs, &file->m,
3225 NULL, &file->cache, file->off-i,
3227 LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0),
3234 &file->cache, &lfs->rcache, file->off-i,
3235 file->block, i, &data, 1);
3252 // copy over new state of file
3253 memcpy(file->cache.buffer, lfs->pcache.buffer, lfs->cfg->cache_size);
3254 file->cache.block = lfs->pcache.block;
3255 file->cache.off = lfs->pcache.off;
3256 file->cache.size = lfs->pcache.size;
3259 file->block = nblock;
3260 file->flags |= LFS_F_WRITING;
3273 static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file) {
3274 file->off = file->pos;
3276 int err = lfs_file_relocate(lfs, file);
3281 file->flags &= ~LFS_F_INLINE;
3286 static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
3287 if (file->flags & LFS_F_READING) {
3288 if (!(file->flags & LFS_F_INLINE)) {
3289 lfs_cache_drop(lfs, &file->cache);
3291 file->flags &= ~LFS_F_READING;
3295 if (file->flags & LFS_F_WRITING) {
3296 lfs_off_t pos = file->pos;
3298 if (!(file->flags & LFS_F_INLINE)) {
3301 .ctz.head = file->ctz.head,
3302 .ctz.size = file->ctz.size,
3304 .pos = file->pos,
3309 while (file->pos < file->ctz.size) {
3318 res = lfs_file_flushedwrite(lfs, file, &data, 1);
3332 int err = lfs_bd_flush(lfs, &file->cache, &lfs->rcache, true);
3343 LFS_DEBUG("Bad block at 0x%"PRIx32, file->block);
3344 err = lfs_file_relocate(lfs, file);
3350 file->pos = lfs_max(file->pos, file->ctz.size);
3353 // actual file updates
3354 file->ctz.head = file->block;
3355 file->ctz.size = file->pos;
3356 file->flags &= ~LFS_F_WRITING;
3357 file->flags |= LFS_F_DIRTY;
3359 file->pos = pos;
3367 static int lfs_file_rawsync(lfs_t *lfs, lfs_file_t *file) {
3368 if (file->flags & LFS_F_ERRED) {
3369 // it's not safe to do anything if our file errored
3373 int err = lfs_file_flush(lfs, file);
3375 file->flags |= LFS_F_ERRED;
3380 if ((file->flags & LFS_F_DIRTY) &&
3381 !lfs_pair_isnull(file->m.pair)) {
3387 if (file->flags & LFS_F_INLINE) {
3388 // inline the whole file
3390 buffer = file->cache.buffer;
3391 size = file->ctz.size;
3396 ctz = file->ctz;
3402 // commit file data and attributes
3403 err = lfs_dir_commit(lfs, &file->m, LFS_MKATTRS(
3404 {LFS_MKTAG(type, file->id, size), buffer},
3405 {LFS_MKTAG(LFS_FROM_USERATTRS, file->id,
3406 file->cfg->attr_count), file->cfg->attrs}));
3408 file->flags |= LFS_F_ERRED;
3412 file->flags &= ~LFS_F_DIRTY;
3419 static lfs_ssize_t lfs_file_flushedread(lfs_t *lfs, lfs_file_t *file,
3424 if (file->pos >= file->ctz.size) {
3429 size = lfs_min(size, file->ctz.size - file->pos);
3434 if (!(file->flags & LFS_F_READING) ||
3435 file->off == lfs->cfg->block_size) {
3436 if (!(file->flags & LFS_F_INLINE)) {
3437 int err = lfs_ctz_find(lfs, NULL, &file->cache,
3438 file->ctz.head, file->ctz.size,
3439 file->pos, &file->block, &file->off);
3444 file->block = LFS_BLOCK_INLINE;
3445 file->off = file->pos;
3448 file->flags |= LFS_F_READING;
3452 lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->off);
3453 if (file->flags & LFS_F_INLINE) {
3454 int err = lfs_dir_getread(lfs, &file->m,
3455 NULL, &file->cache, lfs->cfg->block_size,
3457 LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0),
3458 file->off, data, diff);
3464 NULL, &file->cache, lfs->cfg->block_size,
3465 file->block, file->off, data, diff);
3471 file->pos += diff;
3472 file->off += diff;
3480 static lfs_ssize_t lfs_file_rawread(lfs_t *lfs, lfs_file_t *file,
3482 LFS_ASSERT((file->flags & LFS_O_RDONLY) == LFS_O_RDONLY);
3485 if (file->flags & LFS_F_WRITING) {
3487 int err = lfs_file_flush(lfs, file);
3494 return lfs_file_flushedread(lfs, file, buffer, size);
3499 static lfs_ssize_t lfs_file_flushedwrite(lfs_t *lfs, lfs_file_t *file,
3504 if ((file->flags & LFS_F_INLINE) &&
3505 lfs_max(file->pos+nsize, file->ctz.size) >
3510 // inline file doesn't fit anymore
3511 int err = lfs_file_outline(lfs, file);
3513 file->flags |= LFS_F_ERRED;
3520 if (!(file->flags & LFS_F_WRITING) ||
3521 file->off == lfs->cfg->block_size) {
3522 if (!(file->flags & LFS_F_INLINE)) {
3523 if (!(file->flags & LFS_F_WRITING) && file->pos > 0) {
3525 int err = lfs_ctz_find(lfs, NULL, &file->cache,
3526 file->ctz.head, file->ctz.size,
3527 file->pos-1, &file->block, &(lfs_off_t){0});
3529 file->flags |= LFS_F_ERRED;
3534 lfs_cache_zero(lfs, &file->cache);
3537 // extend file with new blocks
3539 int err = lfs_ctz_extend(lfs, &file->cache, &lfs->rcache,
3540 file->block, file->pos,
3541 &file->block, &file->off);
3543 file->flags |= LFS_F_ERRED;
3547 file->block = LFS_BLOCK_INLINE;
3548 file->off = file->pos;
3551 file->flags |= LFS_F_WRITING;
3555 lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->off);
3557 int err = lfs_bd_prog(lfs, &file->cache, &lfs->rcache, true,
3558 file->block, file->off, data, diff);
3563 file->flags |= LFS_F_ERRED;
3569 err = lfs_file_relocate(lfs, file);
3571 file->flags |= LFS_F_ERRED;
3576 file->pos += diff;
3577 file->off += diff;
3587 static lfs_ssize_t lfs_file_rawwrite(lfs_t *lfs, lfs_file_t *file,
3589 LFS_ASSERT((file->flags & LFS_O_WRONLY) == LFS_O_WRONLY);
3591 if (file->flags & LFS_F_READING) {
3593 int err = lfs_file_flush(lfs, file);
3599 if ((file->flags & LFS_O_APPEND) && file->pos < file->ctz.size) {
3600 file->pos = file->ctz.size;
3603 if (file->pos + size > lfs->file_max) {
3604 // Larger than file limit?
3608 if (!(file->flags & LFS_F_WRITING) && file->pos > file->ctz.size) {
3610 lfs_off_t pos = file->pos;
3611 file->pos = file->ctz.size;
3613 while (file->pos < pos) {
3614 lfs_ssize_t res = lfs_file_flushedwrite(lfs, file, &(uint8_t){0}, 1);
3621 lfs_ssize_t nsize = lfs_file_flushedwrite(lfs, file, buffer, size);
3626 file->flags &= ~LFS_F_ERRED;
3631 static lfs_soff_t lfs_file_rawseek(lfs_t *lfs, lfs_file_t *file,
3634 lfs_off_t npos = file->pos;
3638 if ((lfs_soff_t)file->pos + off < 0) {
3641 npos = file->pos + off;
3644 lfs_soff_t res = lfs_file_rawsize(lfs, file) + off;
3653 // file position out of range
3657 if (file->pos == npos) {
3662 // if we're only reading and our new offset is still in the file's cache
3666 !(file->flags & LFS_F_WRITING)
3671 int oindex = lfs_ctz_index(lfs, &(lfs_off_t){file->pos});
3675 && noff >= file->cache.off
3676 && noff < file->cache.off + file->cache.size) {
3677 file->pos = npos;
3678 file->off = noff;
3684 int err = lfs_file_flush(lfs, file);
3690 file->pos = npos;
3695 static int lfs_file_rawtruncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
3696 LFS_ASSERT((file->flags & LFS_O_WRONLY) == LFS_O_WRONLY);
3702 lfs_off_t pos = file->pos;
3703 lfs_off_t oldsize = lfs_file_rawsize(lfs, file);
3705 // revert to inline file?
3711 lfs_soff_t res = lfs_file_rawseek(lfs, file, 0, LFS_SEEK_SET);
3718 res = lfs_file_flushedread(lfs, file,
3724 file->ctz.head = LFS_BLOCK_INLINE;
3725 file->ctz.size = size;
3726 file->flags |= LFS_F_DIRTY | LFS_F_READING | LFS_F_INLINE;
3727 file->cache.block = file->ctz.head;
3728 file->cache.off = 0;
3729 file->cache.size = lfs->cfg->cache_size;
3730 memcpy(file->cache.buffer, lfs->rcache.buffer, size);
3734 int err = lfs_file_flush(lfs, file);
3740 err = lfs_ctz_find(lfs, NULL, &file->cache,
3741 file->ctz.head, file->ctz.size,
3742 size-1, &file->block, &(lfs_off_t){0});
3749 file->pos = size;
3750 file->ctz.head = file->block;
3751 file->ctz.size = size;
3752 file->flags |= LFS_F_DIRTY | LFS_F_READING;
3756 lfs_soff_t res = lfs_file_rawseek(lfs, file, 0, LFS_SEEK_END);
3762 while (file->pos < size) {
3763 res = lfs_file_rawwrite(lfs, file, &(uint8_t){0}, 1);
3771 lfs_soff_t res = lfs_file_rawseek(lfs, file, pos, LFS_SEEK_SET);
3780 static lfs_soff_t lfs_file_rawtell(lfs_t *lfs, lfs_file_t *file) {
3782 return file->pos;
3785 static int lfs_file_rawrewind(lfs_t *lfs, lfs_file_t *file) {
3786 lfs_soff_t res = lfs_file_rawseek(lfs, file, 0, LFS_SEEK_SET);
3794 static lfs_soff_t lfs_file_rawsize(lfs_t *lfs, lfs_file_t *file) {
3798 if (file->flags & LFS_F_WRITING) {
3799 return lfs_max(file->pos, file->ctz.size);
3803 return file->ctz.size;
5132 } file;
5365 entry.d.u.file.head, entry.d.u.file.size, cb, data);
5923 int lfs_file_open(lfs_t *lfs, lfs_file_t *file, const char *path, int flags) {
5929 (void*)lfs, (void*)file, path, flags);
5930 LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
5932 err = lfs_file_rawopen(lfs, file, path, flags);
5940 int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
5949 (void*)lfs, (void*)file, path, flags,
5951 LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
5953 err = lfs_file_rawopencfg(lfs, file, path, flags, cfg);
5960 int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
5965 LFS_TRACE("lfs_file_close(%p, %p)", (void*)lfs, (void*)file);
5966 LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
5968 err = lfs_file_rawclose(lfs, file);
5976 int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
5981 LFS_TRACE("lfs_file_sync(%p, %p)", (void*)lfs, (void*)file);
5982 LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
5984 err = lfs_file_rawsync(lfs, file);
5992 lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
5999 (void*)lfs, (void*)file, buffer, size);
6000 LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
6002 lfs_ssize_t res = lfs_file_rawread(lfs, file, buffer, size);
6010 lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
6017 (void*)lfs, (void*)file, buffer, size);
6018 LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
6020 lfs_ssize_t res = lfs_file_rawwrite(lfs, file, buffer, size);
6028 lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
6035 (void*)lfs, (void*)file, off, whence);
6036 LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
6038 lfs_soff_t res = lfs_file_rawseek(lfs, file, off, whence);
6046 int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
6052 (void*)lfs, (void*)file, size);
6053 LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
6055 err = lfs_file_rawtruncate(lfs, file, size);
6063 lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file) {
6068 LFS_TRACE("lfs_file_tell(%p, %p)", (void*)lfs, (void*)file);
6069 LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
6071 lfs_soff_t res = lfs_file_rawtell(lfs, file);
6078 int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file) {
6083 LFS_TRACE("lfs_file_rewind(%p, %p)", (void*)lfs, (void*)file);
6085 err = lfs_file_rawrewind(lfs, file);
6092 lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) {
6097 LFS_TRACE("lfs_file_size(%p, %p)", (void*)lfs, (void*)file);
6098 LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
6100 lfs_soff_t res = lfs_file_rawsize(lfs, file);