FRESULT TM_FATFS_TruncateBeginning(FIL* fil, uint32_t index) { uint8_t Buffer[FATFS_TRUNCATE_BUFFER_SIZE]; /* Buffer for temporary data */ uint32_t FileSize = f_size(fil); /* Size of file */ uint32_t ReadIndex = index; /* Starting read index */ uint32_t WriteIndex = 0; /* We have to write at beginning */ uint32_t TotalSize = FileSize - ReadIndex; /* New file size after truncate */ uint32_t NewSize = TotalSize; /* Save new file size */ uint32_t BlockSize; /* Block size for read operation */ uint32_t Read; /* Read bytes */ uint32_t Written; /* Written bytes */ FRESULT fr; /* Result typedef */ /* Index is 0 or file is empty, nothing to do */ if (index == 0 || FileSize == 0) { return FR_OK; } /* Check if index is more than file size, truncate all */ if (index > FileSize) { fr = f_lseek(fil, 0); /* Go to beginning */ if (fr) return fr; /* Check for success */ return f_truncate(fil); /* Truncate file from new end to actual end */ } /* Until we have available data in file after user specific index */ while (TotalSize > 0) { /* Calculate new block size for new read operation */ BlockSize = (TotalSize > FATFS_TRUNCATE_BUFFER_SIZE) ? (FATFS_TRUNCATE_BUFFER_SIZE) : (TotalSize); fr = f_lseek(fil, ReadIndex); /* Go to the read index */ if (fr) return fr; /* Check for success */ fr = f_read(fil, &Buffer, BlockSize, &Read); /* Read data */ if (fr) return fr; /* Check for success */ fr = f_lseek(fil, WriteIndex); /* Go back to the write index */ if (fr) return fr; /* Check for success */ fr = f_write(fil, &Buffer, BlockSize, &Written);/* Write data */ if (fr) return fr; /* Check for success */ TotalSize -= BlockSize; /* Calculate new total size we have more to move everything */ ReadIndex += Read; /* Calculate new read pointer */ WriteIndex += Written; /* Calculate new write pointer */ } fr = f_lseek(fil, NewSize); /* Move pointer to the "end" of new file */ if (fr) return fr; /* Check for success */ fr = f_truncate(fil); /* Truncate file from new end to actual end */ return f_lseek(fil, 0); /* Move pointer to the beginning */ }
/** Функция обратного вызова при очистке */ static void EraseCallBack(char *path, char *fname) { FIL file; FRESULT res; char fullName[259] = {'\0'}; size_t len = strlen(path) + strlen(fname); if (len > ( sizeof(fullName) / sizeof(fullName[0])) ) return; sprintf(fullName, "%s/%s", path, fname); res = f_open(&file, fullName, FA_OPEN_EXISTING | FA_WRITE); f_sync(&file); if (res) { printf("Error open file: %s, res: %d\n\r", fullName, res); return; } res = f_truncate(&file); if (res != FR_OK) { printf("Error truncate file: %s, res: %d\n\r", fullName, res); } f_sync(&file); f_close(&file); }
bool fileWrite(const void *buffer, const char *path, u32 size) { FIL file; FRESULT result; switch(f_open(&file, path, FA_WRITE | FA_OPEN_ALWAYS)) { case FR_OK: { unsigned int written; result = f_write(&file, buffer, size, &written); if(result == FR_OK) result = f_truncate(&file); result |= f_close(&file); return result == FR_OK && (u32)written == size; } case FR_NO_PATH: for(u32 i = 1; path[i] != 0; i++) if(path[i] == '/') { char folder[i + 1]; memcpy(folder, path, i); folder[i] = 0; result = f_mkdir(folder); } return result == FR_OK && fileWrite(buffer, path, size); default: return false; } }
void ini_stripfile(FIL *file, unsigned int pos, unsigned int len) { FRESULT res; unsigned int rd; unsigned char c; if((pos+len) >= file->fsize) { f_lseek(file, pos); } else { for(; (pos+len)<file->fsize; pos++) { f_lseek(file, pos+len); res = f_read(file, &c, 1, &rd); if((res != FR_OK) || (rd != 1)) { break; } f_lseek(file, pos); f_putc(c, file); } } f_truncate(file); return; }
void shutdown_filesystem() { char c[]="\r\nLogger turned off\r\n"; uint8_t a; f_write(&FATFS_logfile,c,sizeof(c),&a); //Write the error to the file f_sync(&FATFS_logfile); //Flush buffers f_truncate(&FATFS_logfile); //Truncate the lenght - fix pre allocation f_close(&FATFS_logfile); //Close any opened file }
void OnTruncateFile(nwazetMessageContext_t* nmc){ uint8_t res = (uint8_t) FR_OK; fileObjectMap_t* fileObj = GetFileObjectById(nmc); if(fileObj){ res = (uint8_t) f_truncate(fileObj->file); fsCheckSuccess(__func__, "f_truncate", res, 0); StartResponse(nmc, res, true); } }
DWORD allocate_contiguous_clusters ( /* Returns the first sector in LBA (0:error or not contiguous) */ FIL* fp, /* Pointer to the open file object */ DWORD len /* Number of bytes to allocate */ ) { DWORD csz, tcl, ncl, ccl, cl; if (f_lseek(fp, 0) || !len) /* Check if the given parameters are valid */ return 0; csz = 512UL * fp->fs->csize; /* Cluster size in unit of byte (assuming 512 bytes/sector) */ tcl = (len + csz - 1) / csz; /* Total number of clusters required */ len = tcl * csz; /* Round-up file size to the cluster boundary */ /* Check if the existing cluster chain is contiguous */ if (len == fp->fsize) { ncl = 0; ccl = fp->sclust; do { cl = get_fat(fp->fs, ccl); /* Get the cluster status */ if (cl + 1 < 3) return 0; /* Hard error? */ if (cl != ccl + 1 && cl < fp->fs->n_fatent) break; /* Not contiguous? */ ccl = cl; } while (++ncl < tcl); if (ncl == tcl) /* Is the file contiguous? */ return clust2sect(fp->fs, fp->sclust); /* File is contiguous. Return the start sector */ } /* File is not contiguous */ #if _FS_READONLY return 0; /* Exit if in read-only cfg. */ #else if (!(fp->flag & FA_WRITE)) return 0; /* Exit if the file object is for read-only */ if (f_truncate(fp)) return 0; /* Remove the non-contiguous chain */ /* Find a free contiguous area */ ccl = cl = 2; ncl = 0; do { if (cl >= fp->fs->n_fatent) return 0; /* No contiguous area is found. */ if (get_fat(fp->fs, cl)) { /* Encounterd a cluster in use */ do { /* Skip the block of used clusters */ cl++; if (cl >= fp->fs->n_fatent) return 0; /* No contiguous area is found. */ } while (get_fat(fp->fs, cl)); ccl = cl; ncl = 0; } cl++; ncl++; } while (ncl < tcl); /* Create a contiguous cluster chain */ fp->fs->last_clust = ccl - 1; if (f_lseek(fp, len)) return 0; return clust2sect(fp->fs, fp->sclust); /* Return file start sector */ #endif }
int sc_ftruncate(thread_t *t, syscall_result_t *r, ftruncate_args_t *args) { file_t *f = f_get(t->thr_proc->p_fd, args->fd); if(!f) return -EBADF; f_truncate(f, args->length); frele(f); return -EOK; }
void record_init() { uint16_t num=0; int8_t i; NVIC_InitTypeDef NVIC_InitStructure; /* Configure the NVIC Preemption Priority Bits */ // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); NVIC_InitStructure.NVIC_IRQChannel = SDIO_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = SD_SDIO_DMA_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_Init(&NVIC_InitStructure); disk_initialize(0); res=f_mount(0, &fs[0]); res=f_open(&fsrc, "0:/num.txt",FA_OPEN_EXISTING | FA_READ | FA_WRITE); // 以读方式打开,如果文件不存在则打开失败 if ( res == FR_OK ) { res=f_read(&fsrc, read_Buff, sizeof(read_Buff), &br); for (i=0;i<br;i++) { num=num*10+(read_Buff[i]-0x30); } if (num>=99) num=0; sprintf(record_num,"%d",num+1); f_lseek(&fsrc,0); f_puts (record_num,&fsrc); f_truncate(&fsrc); f_close(&fsrc); sprintf(record_file_name,"0:/N%d.txt",num+1); f_open(&file, record_file_name,FA_CREATE_NEW| FA_WRITE); // 以读方式打开,如果文件不存在则打开失败 f_close(&file); } else f_close(&fsrc); /* 关闭打开的文件 */ }
int mon_log(int argc, char **argv){ FIL fil; int line_buf_size = MD_BUF_SIZE; char *line_buf; FRESULT fr; if(argc!=2){ printf("specify [read] or [erase]\n"); return -1; } if(strcmp(argv[1],"read")==0){ //allocate the line buffer line_buf = core_malloc(line_buf_size); //print the log out to STDOUT fr = f_open(&fil, LOG_FILE, FA_READ); if(fr){ printf("error reading log: %d\n",(int)fr); core_free(line_buf); return -1; } while(f_gets(line_buf, line_buf_size, &fil)){ printf("%s",line_buf); } f_close(&fil); core_free(line_buf); return 0; } else if(strcmp(argv[1],"erase")==0){ fr = f_open(&fil, LOG_FILE, FA_WRITE); if(fr){ printf("error erasing log: %d\n", (int)fr); return -1; } f_lseek(&fil,0); f_truncate(&fil); f_close(&fil); if(wemo_config.echo) printf("erased log\n"); return 0; } else{ printf("specify [read] or [erase]\n"); return -1; } //shouldn't get here return 0; }
/** * @brief This function handles ADC1-2 interrupt requests.- Should only be from the analog watchdog * @param None * @retval None */ __attribute__((externally_visible)) void ADC1_2_IRQHandler(void) { if(ADC_GetITStatus(ADC2, ADC_IT_AWD)) { //Analogue watchdog was triggered if(file_opened) { char c[]="\r\nLow Battery\r\n"; uint8_t a; f_write(&FATFS_logfile,c,sizeof(c),&a); //Write the error to the file f_sync(&FATFS_logfile); //Flush buffers f_truncate(&FATFS_logfile); //Truncate the lenght - fix pre allocation f_close(&FATFS_logfile); //Close any opened file } red_flash(); //Flash red led shutdown(); //Shutdown to save battery } ADC_ClearITPendingBit(ADC2, ADC_IT_EOC); ADC_ClearITPendingBit(ADC2, ADC_IT_JEOC); ADC_ClearITPendingBit(ADC1, ADC_IT_EOC); ADC_ClearITPendingBit(ADC1, ADC_IT_JEOC); //None of these should ever happen, but best to be safe ADC_ClearITPendingBit(ADC1, ADC_IT_AWD); //make sure flags are clear }
// Truncate file at current file pointer bool FileStore::Truncate() { switch (usageMode) { case FileUseMode::free: case FileUseMode::readOnly: INTERNAL_ERROR; return false; case FileUseMode::readWrite: if (!Flush()) { return false; } return f_truncate(&file) == FR_OK; case FileUseMode::invalidated: default: return false; } }
//delete spaces/line breaks at end of file void ini_delspace(FIL *file) { FRESULT res; unsigned int i, rd; unsigned char c; if(file->fsize) { for(i=file->fsize-1, c=0; ((c == 0) || (c == '\r') || (c == '\n'));) { f_lseek(file, i--); res = f_read(file, &c, 1, &rd); if((res != FR_OK) || (rd != 1)) { break; } } f_truncate(file); } return; }
static int fat_truncate(struct device_d *dev, FILE *f, ulong size) { FIL *f_file = f->inode; unsigned long lastofs; int ret; lastofs = f_file->fptr; ret = f_lseek(f_file, size); if (ret) return ret; ret = f_truncate(f_file); if (ret) return ret; ret = f_lseek(f_file, lastofs); if (ret) return ret; return 0; }
int fatfs_truncate(struct block_cache *output, off_t block_offset, const char *filename) { // Check if this is the same file as a previous pwrite call if (current_file_ && strcmp(current_file_, filename) != 0) close_open_files(); MAYBE_MOUNT(output, block_offset); if (!current_file_) { // FA_CREATE_ALWAYS truncates if the file exists CHECK("Can't open file on FAT partition", filename, f_open(&fil_, filename, FA_CREATE_ALWAYS | FA_WRITE)); // Assuming it opens ok, cache the filename for future writes. current_file_ = strdup(filename); } else { // Truncate an already open file CHECK("Can't seek to the beginning", filename, f_lseek(&fil_, 0)); CHECK("Can't truncate file on FAT partition", filename, f_truncate(&fil_)); } // Leave the file open since the main use case is to start writing to it afterwards. return 0; }
static int fatfs_ftruncate(mount_point_t *point, file_t *file, off_t len) { privinfo_t *priv = file->ctx; FRESULT res; if (priv == NULL) { seterrno(EINVAL); return -1; } res = f_lseek(&priv->file, len); if (res != FR_OK) { fatfs_result_to_errno(res); return -1; } res = f_truncate(&priv->file); if (res == FR_OK) { return 0; } else { fatfs_result_to_errno(res); return -1; } }
/** * @brief write a profile string to a ini file * @param section [in] name of the section,can't be NULL and empty string * @param key [in] name of the key pairs to value, can't be NULL and empty string * @param value [in] profile string value * @param file [in] path of ini file * @return 1 : success\n 0 : failure */ int write_profile_string(const char *section, const char *key, const char *value, const char *file) { char *buf; char *w_buf; int sec_s,sec_e,key_s,key_e, value_s, value_e; int value_len = (int)strlen(value); int file_size; unsigned int new_file_size; //check parameters assert(section != NULL && strlen(section)); assert(key != NULL && strlen(key)); assert(value != NULL); assert(file !=NULL &&strlen(key)); buf = (char *)sys_malloc(MAX_FILE_SIZE); w_buf = (char *)sys_malloc(MAX_FILE_SIZE); memset(buf,0,MAX_FILE_SIZE); memset(w_buf,0,MAX_FILE_SIZE); if(!load_ini_file(file,buf,&file_size)) { sec_s = -1; } else { parse_file(section,key,buf,&sec_s,&sec_e,&key_s,&key_e,&value_s,&value_e); } if( -1 == sec_s) { if(0==file_size) { sprintf(w_buf,"[%s]\r\n%s=%s\r\n",section,key,value); new_file_size = strlen(section) + strlen(key) + strlen(value) + 5; } else { //not find the section, then add the new section at end of the file memcpy(w_buf,buf,file_size); sprintf(w_buf+file_size,"\r\n[%s]\r\n%s=%s\r\n",section,key,value); new_file_size = file_size + strlen(section) + strlen(key) + value_len + 7; } } else if(-1 == key_s) { //not find the key, then add the new key=value at end of the section memcpy(w_buf, buf, sec_e); sprintf(w_buf + sec_e, "%s=%s\r\n", key, value); memcpy(w_buf + sec_e + strlen(key) + value_len + 3,buf + sec_e, file_size - sec_e); new_file_size = file_size + strlen(key) + value_len + 3; } else { //update value with new value memcpy(w_buf, buf, value_s); memcpy(w_buf + value_s, value, value_len); memcpy(w_buf+value_s+value_len, buf+value_e, file_size - value_e); new_file_size = file_size - value_e + value_len + value_s; } FIL file_obj; unsigned int br; if (f_open(&file_obj, file, FA_WRITE)) { sys_free(buf); sys_free(w_buf); return 0; } if (f_write(&file_obj, w_buf, new_file_size, &br)) { sys_free(buf); sys_free(w_buf); return 0; } if (f_truncate(&file_obj)) { /* Truncate unused area */ sys_free(buf); sys_free(w_buf); return 0; } f_close(&file_obj); sys_free(buf); sys_free(w_buf); return 1; }
static VALUE nurat_rem(VALUE self, VALUE other) { VALUE val = f_truncate(f_div(self, other)); return f_sub(self, f_mul(other, val)); }
void CFile::truncate() { f_truncate(&mFileDescriptor); }
/* :nodoc: */ static VALUE nurat_quot(VALUE self, VALUE other) { return f_truncate(f_div(self, other)); }
/* :nodoc: */ static VALUE nurat_quotrem(VALUE self, VALUE other) { VALUE val = f_truncate(f_div(self, other)); return rb_assoc_new(val, f_sub(self, f_mul(other, val))); }
void file_truncate(FIL *fp) { FRESULT res = f_truncate(fp); if (res != FR_OK) ff_fail(fp, res); }
FRESULT DFILE::fstruncate (void) { return(f_truncate (&_file)); }
static msg_t ThreadFatFSWorker(void *arg) { (void)arg; Thread* p; chRegSetThreadName("fatfsWorker"); while (!chThdShouldTerminate()) { /* Wait for msg with work to do. */ p = chMsgWait(); struct wrapper_msg_base* msg = (struct wrapper_msg_base*) chMsgGet(p); msg->result = FR_INVALID_PARAMETER; switch(msg->action) { case eTERMINATE: { break; } #if HAS_MOUNT case eFMOUNT: { const struct wrapper_msg_vBYTEpFATFS* exmsg = \ (const struct wrapper_msg_vBYTEpFATFS*) msg; msg->result = f_mount(exmsg->byte, exmsg->fatfsp); break; } #endif /* HAS_MOUNT */ #if HAS_OPEN case eFOPEN: { const struct wrapper_msg_pFILpTCHARvBYTE* exmsg = \ (const struct wrapper_msg_pFILpTCHARvBYTE*) msg; msg->result = f_open(exmsg->filep, exmsg->string, exmsg->byte); break; } #endif /* HAS_OPEN */ #if HAS_READ case eFREAD: { const struct wrapper_msg_pFILpVOIDvUINTpUINT* exmsg = \ (const struct wrapper_msg_pFILpVOIDvUINTpUINT*) msg; msg->result = f_read(exmsg->filep, exmsg->voidp, exmsg->uint, exmsg->uintp); break; } #endif /* HAS_READ */ #if HAS_WRITE case eFWRITE: { const struct wrapper_msg_pFILpVOIDvUINTpUINT* exmsg = \ (const struct wrapper_msg_pFILpVOIDvUINTpUINT*) msg; msg->result = f_write(exmsg->filep, exmsg->voidp, exmsg->uint, exmsg->uintp); break; } #endif /* HAD_WRITE */ #if HAS_SYNC case eFSYNC: { const struct wrapper_msg_pFIL* exmsg = \ (const struct wrapper_msg_pFIL*) msg; msg->result = f_sync(exmsg->filep); break; } #endif /* HAS_SYNC */ #if HAS_CHDRIVE case eFCHDRIVE: { const struct wrapper_msg_vBYTE* exmsg = \ (const struct wrapper_msg_vBYTE*) msg; msg->result = f_chdrive(exmsg->byte); break; } #endif #if HAS_CHDIR case eFCHDIR: { const struct wrapper_msg_pTCHAR* exmsg = \ (const struct wrapper_msg_pTCHAR*) msg; msg->result = f_chdir(exmsg->string); break; } #endif /* HAS_CHDIR */ #if HAS_GETCWD case eFGETCWD: { const struct wrapper_msg_pTCHARvUINT* exmsg = \ (const struct wrapper_msg_pTCHARvUINT*) msg; msg->result = f_getcwd(exmsg->string, exmsg->uint); break; } #endif #if HAS_LSEEK case eFLSEEK: { const struct wrapper_msg_pFILvDWORD* exmsg = \ (const struct wrapper_msg_pFILvDWORD*) msg; msg->result = f_lseek(exmsg->filep, exmsg->dword); break; } #endif /* HAS_LSEEK */ #if HAS_CLOSE case eFCLOSE: { const struct wrapper_msg_pFIL* exmsg = \ (const struct wrapper_msg_pFIL*) msg; msg->result = f_close(exmsg->filep); break; } #endif /* HAS_CLOSE */ #if HAS_OPENDIR case eFOPENDIR: { const struct wrapper_msg_pDIRpTCHAR* exmsg = \ (const struct wrapper_msg_pDIRpTCHAR*) msg; msg->result = f_opendir(exmsg->dirp, exmsg->string); break; } #endif /* HAD_OPENDIR */ #if HAS_READDIR case eFREADDIR: { const struct wrapper_msg_pDIRpFILINFO* exmsg = \ (const struct wrapper_msg_pDIRpFILINFO*) msg; msg->result = f_readdir(exmsg->dirp, exmsg->filinfop); break; } #endif /* HAS_READDIR */ #if HAS_STAT case eFSTAT: { const struct wrapper_msg_pTCHARpFILINFO* exmsg = \ (const struct wrapper_msg_pTCHARpFILINFO*) msg; msg->result = f_stat(exmsg->string, exmsg->filinfop); break; } #endif /* HAS_STAT */ #if HAS_GETFREE case eFGETFREE: { const struct wrapper_msg_pTCHARpDWORDppFATFS* exmsg = \ (const struct wrapper_msg_pTCHARpDWORDppFATFS*) msg; msg->result = f_getfree(exmsg->string, exmsg->dwordp, exmsg->fatfspp); break; } #endif /* HAS_GETFREE */ #if HAS_TRUNCATE case eFTRUNCATE: { const struct wrapper_msg_pFIL* exmsg = \ (const struct wrapper_msg_pFIL*) msg; msg->result = f_truncate(exmsg->filep); break; } #endif /* HAS_TRUNCATE */ #if HAS_UNLINK case eFUNLINK: { const struct wrapper_msg_pTCHAR* exmsg = \ (const struct wrapper_msg_pTCHAR*) msg; msg->result = f_unlink(exmsg->string); break; } #endif /* HAS_UNLINK */ #if HAS_MKDIR case eFMKDIR: { const struct wrapper_msg_pTCHAR* exmsg = \ (const struct wrapper_msg_pTCHAR*) msg; msg->result = f_mkdir(exmsg->string); break; } #endif /* HAS_MKDIR */ #if HAS_CHMOD case eFCHMOD: { const struct wrapper_msg_pTCHARvBYTEvBYTE* exmsg = \ (const struct wrapper_msg_pTCHARvBYTEvBYTE*) msg; msg->result = f_chmod(exmsg->string, exmsg->byte1, exmsg->byte2); break; } #endif /* HAS_CHMOD */ #if HAS_UTIME case eFUTIME: { const struct wrapper_msg_pTCHARpFILINFO* exmsg = \ (const struct wrapper_msg_pTCHARpFILINFO*) msg; msg->result = f_utime(exmsg->string, exmsg->filinfop); break; } #endif /* HAD_UTIME */ #if HAS_RENAME case eFRENAME: { const struct wrapper_msg_pTCHARpTCHAR* exmsg = \ (const struct wrapper_msg_pTCHARpTCHAR*) msg; msg->result = f_rename(exmsg->string1, exmsg->string2); break; } #endif /* HAS_RENAME */ #if HAS_MKFS case eFMKFS: { const struct wrapper_msg_vBYTEvBYTEvUINT* exmsg = \ (const struct wrapper_msg_vBYTEvBYTEvUINT*) msg; msg->result = f_mkfs(exmsg->byte1, exmsg->byte2, exmsg->uint); break; } #endif /* HAS_MKFS */ #if HAS_FDISK case eFFDISK: { const struct wrapper_msg_vBYTEpDWORDpVOID* exmsg = \ (const struct wrapper_msg_vBYTEpDWORDpVOID*) msg; msg->result = f_fdisk(exmsg->byte, exmsg->dwordp, exmsg->voidp); break; } #endif /* HAS_FDISK */ #if HAS_GETS case eFGETS: { struct wrapper_msg_pTCHARvINTpFILpTCHAR* exmsg = \ (struct wrapper_msg_pTCHARvINTpFILpTCHAR*) msg; exmsg->string2 = f_gets(exmsg->string, exmsg->n, exmsg->filep); break; } #endif /* HAS_GETS */ #if HAS_PUTC case eFPUTC: { const struct wrapper_msg_vTCHARpFIL* exmsg = \ (const struct wrapper_msg_vTCHARpFIL*) msg; msg->result = f_putc(exmsg->tchar, exmsg->filep); break; } #endif /* HAS_PUTC */ #if HAS_PUTS case eFPUTS: { const struct wrapper_msg_pTCHARpFIL* exmsg = \ (const struct wrapper_msg_pTCHARpFIL*) msg; msg->result = f_puts(exmsg->string, exmsg->filep); break; } #endif /* HAS_PUTS */ } /* Done, release msg again. */ chMsgRelease(p, 0); } return 0; }
FRESULT FatFs::File::truncate() { return f_truncate(&file); }