📄 flashfs.c
字号:
** slot Details of file to be removed.**** Returns:** ESUCCESS File removed** <>ESUCCESS Error code.****----------------------------------------------------------------------*/static int flashfs_RemoveFile (OPENFILE *slot){ int rc; BOOL isDynamic; U32 prev; /* ** Look for the file, noting in which section it was found. */ if (flashfs_Find (slot, &prev, &isDynamic)) { /* ** Check that this filing system isn't actively in use (otherwise the ** writes will wreck any open reads). */ if (flashfs_HasFilesOpen (slot->partition)) { rc = EBUSY; TRACE3 ("File system in use\n"); } else { /* ** Action taken depends upon where the file to be removed is located. ** (Don't need to touch the other area). */ BYTE *copyBuffer; copyBuffer = (BYTE *) malloc (SCRATCH_BUFFER_SIZE); if (NULL != copyBuffer) { FLASHFS_DIRENT entry; U32 shift = 0; U32 link; rc = ESUCCESS; slot->datptr = slot->datptr - sizeof (entry) + sizeof (entry.data); flash_read_fs_data (slot->datptr, (BYTE *)&entry, sizeof entry); TRACE3 ("Remove file '%s' %x %d\n", slot->name, slot->datptr, slot->fmax); if (isDynamic) { if (prev != 0) { shift = prev - slot->datptr; } else { /* ** This is the first file in the list being removed. The distance shifted is simply the ** amount of space occupied by the file, ignoring the granularity. The code cannot assume ** that the current granularity is the same as that stored, and calculating the stored ** granularity is difficult in all circumstances. */ shift = flashfsSize - GRANULARITY - slot->datptr; /*REVIEW*/ } /* ** Reset previous link */ if (0 == prev) { /* ** The file being removed is the first file in the list so simply ** copy all other files "up", overwriting the previous file. */ if (entry.next != 0) { flashfsRoot.first.dynamic = entry.next + shift; } else { /* ** Special case: no more files */ flashfsRoot.first.dynamic = 0; } rc = flash_write_fs_data((BYTE *)&flashfsRoot, 0, sizeof flashfsRoot); } else { FLASHFS_DIRENT preventry; /* ** The file being removed is some way down the list; so rewrite the previous entry. */ flash_read_fs_data (prev, (BYTE *)&preventry, sizeof preventry); if (entry.next == 0) { preventry.next = 0; } else { preventry.next = entry.next + shift; } rc = flash_write_fs_data ((BYTE *)&preventry, prev, sizeof preventry); } /* ** Move any other files */ while ((ESUCCESS == rc) && (entry.next != 0)) { U32 addr = entry.next; flash_read_fs_data (addr, (BYTE *)&entry, sizeof (entry)); if (entry.next != 0) { link = entry.next + shift; } else { link = 0; } rc = move_flash_file (addr + shift, addr, entry.len + sizeof (entry), link, copyBuffer); } } else { /* ** Last entry: zap previous link */ if (entry.next == 0) { if (prev == 0) { /* ** First, and only, file being removed. */ flashfsRoot.first.fixed = 0; rc = flash_write_fs_data((BYTE *)&flashfsRoot, 0, sizeof flashfsRoot); } else { /* ** Last file in the chain... */ flash_read_fs_data (prev, (BYTE *)&entry, sizeof entry); entry.next = 0; rc = flash_write_fs_data ((BYTE *)&entry, prev, sizeof entry); } } else { prev = slot->datptr; shift = entry.next - prev; while ((ESUCCESS == rc) && (entry.next != 0)) { U32 addr = entry.next; flash_read_fs_data (addr, (BYTE *)&entry, sizeof entry); /* ** Adjust link provided that it is not the last one. */ if (entry.next != 0) { link = entry.next - shift; } else { link = 0; } rc = move_flash_file (prev, addr, entry.len + sizeof (entry), link, copyBuffer); prev = link; } } } /* ** Rewrite flash header if all was well (this will flush any trailing data). */ if (ESUCCESS == rc) { rc = flashfs_program_header (); } free (copyBuffer); } else { TRACE3 ("Can't allocate copy buffer\n"); rc = ENOMEM; } } } else { rc = ENOENT; } return rc;}/***----------------------------------------------------------------------**** flashfs_CreateFile:**** Create a file in flashfs.**** If the file already exists it will be removed. No other files can be** open (in the specified partition) as removal may move the files around** in flash memory.**** Arguments:** slot Details of file to be created**** Returns:** ESUCCESS File created** <>ESUCCESS Error code.****----------------------------------------------------------------------*/static int flashfs_CreateFile (OPENFILE *slot){ int rc; /* ** No other files open */ if (flashfs_HasFilesOpen (slot->partition)) { rc = EBUSY; } else { BOOL dummy; /* ** Delete any previous instance of the file. */ if (flashfs_Find (slot, NULL, &dummy)) { rc = flashfs_RemoveFile (slot); } else { rc = ESUCCESS; } /* ** If everything is still correct then set up the entry */ if (ESUCCESS == rc) { struct fsinfo fsinfobuf; /* ** Determine free space on device for use when writing. */ rc = flashfs_SysInfo (slot->partition, &fsinfobuf); if (ESUCCESS == rc) { FLASHFS_DIRENT entry; /* ** Calculate free space available for writing */ slot->limit = (fsinfobuf.blocks - fsinfobuf.used) * fsinfobuf.blocksize; if (slot->limit < ALIGN_UP (sizeof (FLASHFS_DIRENT))) { TRACE3 ("Create file '%s' failed - no more space\n", slot->name); rc = ENOSPC; } /* ** Now create flashfs entry, always create in 'fixed' area as it allows the ** the file to grow upwards. */ else if (flashfsRoot.first.fixed == 0) { slot->datptr = flashfsRoot.first.fixed = ALIGN_UP (sizeof (FLASHFS_ROOT)); rc = flash_write_fs_data((BYTE *)&flashfsRoot, 0, sizeof (FLASHFS_ROOT)); } else { U32 last; /* ** Chain down list of files, finding the last entry. */ entry.next = flashfsRoot.first.fixed; while (entry.next != 0) { last = entry.next; flash_read_fs_data (last, (BYTE *) &entry, sizeof (FLASHFS_DIRENT)); } assert (0 != CHECK_ADDR (last)); entry.next = slot->datptr = last + ALIGN_UP (sizeof (FLASHFS_DIRENT) + entry.len); rc = flash_write_fs_data ((BYTE *) &entry, last, sizeof (FLASHFS_DIRENT)); } if (ESUCCESS == rc) { /* ** Adjust available space by size of control block. */ slot->limit -= sizeof (FLASHFS_DIRENT); entry.next = 0; entry.len = 0; strncpy (entry.name, slot->name, FLASHFS_NAME_LENGTH); slot->fpos = 0; slot->fmax = 0; rc = flash_write_fs_data ((BYTE *) &entry, slot->datptr, sizeof (FLASHFS_DIRENT)); if (ESUCCESS == rc) { /* ** At this point the FLASHFS is, technically, corrupt and will only be valid again ** after the file has been closed. */ TRACE3 ("Create file '%s' @%x (limit %d)\n", slot->name, slot->datptr, slot->limit); /* ** Point to real data area. */ slot->datptr += sizeof (FLASHFS_DIRENT); /* ** Ensure header details are written out (maintains the file structure ** consistancy but not the checksum). This has to be done as the underlying ** flash drivers do a buffered write but the read routines don't go through ** the sector buffer. */ rc = program_sector (); } } } } } return rc;}/***----------------------------------------------------------------------**** flashfs_CloseFile:**** Close a file which was open for writing.**** Arguments:** slot Details of file to be closed**** Returns:** ESUCCESS File created** <>ESUCCESS Error code.****----------------------------------------------------------------------*/static int flashfs_CloseFile (OPENFILE *slot){ int rc; FLASHFS_DIRENT entry; assert (NULL != slot); assert (slot->inuse); TRACE3 ("Close file '%s' @%x\n", slot->name, slot->datptr - sizeof (FLASHFS_DIRENT)); /* ** Store file's correct length then update the checksum. */ flash_read_fs_data (slot->datptr - sizeof (FLASHFS_DIRENT), (BYTE *) &entry, sizeof (FLASHFS_DIRENT)); entry.len = slot->fmax; rc = flash_write_fs_data ((BYTE *) &entry, slot->datptr - sizeof (FLASHFS_DIRENT), sizeof (FLASHFS_DIRENT)); if (ESUCCESS == rc) { rc = flashfs_program_header (); } return rc;}static void flashfs_msgOpen(ATMOS_MESSAGE *m){ OPENFILE *slot; MSG_D_OPEN(o, m); assert (NULL != m); assert (m->code == MSG_N_OPEN); /* ** First see if there is a spare file slot. */ slot = flashfs_OpenslotFind (); if (NULL == slot) { TRACE1("%C: fopen failed, too many files open (%d)\n", FLASHFS_OPENS); m->errno = EMFILE; } else { char residue [256]; PTR values [MAX_FLASHFS_ATTRIBUTES]; FILE * fp = o->fp; /* ** Allow partition to be set by attribute selection (effective a write-once attribute). */ slot->partition = NO_PARTITION; flashfs_InitialiseAttributes (slot, &values [0]); /* Read and interpret open mode */ m->errno = open_decoder (fp, o->fname, o->mode, residue, MODE_WRITE | MODE_READ | _IOB_DIRECTORY, flashfsKeys, values, NULL); if (m->errno == ESUCCESS) { if (slot->partition == NO_PARTITION) { slot->partition = currentDefaultPartition; } if (flashfs_PartitionCheck (slot->partition, TRUE)) { /* ** Switch to new partition. */ flashfs_PartitionChange (slot->partition); if (fp->flags & _IOB_DIRECTORY) { /* ** Directory entry? Ignore filename since we only have a 'flat' FS to date. */ slot->inuse = 1; slot->datptr = flashfsRoot.first.dynamic; slot->fpos = DYNAMIC; /* dynamic files to start*/ slot->fmax = 0; /* set for completeness. */ slot->fp = fp; strcpy (slot->name, "."); fp->flags |= _IOB_OPEN; fp->devuse = (PTR) slot; TRACE3("%C: fopen for \"d\" OK\n"); } else { /* ** 'normal' file open ... so copy name into slot and search for that name ** but ensure that the name isn't overlong. */ strncpy (slot->name, residue, FLASHFS_NAME_LENGTH); slot->name [FLASHFS_NAME_LENGTH - 1] = '\0'; if ('\0' != slot->name [0]) { BOOL isDynamic; /* ** If opening for write then must create the file. */ if (fp->flags & _IOB_WRITE) { m->errno = flashfs_CreateFile (slot); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -