📄 rdcf2.c
字号:
// simply empty the file of clusters. if (found) { check_write_access(f); release_FAT_entries(f); flush_buffer(f); } else lengthen_directory_if_necessary(f); f->file.first_cluster = EMPTY_CLUSTER; f->file.size = 0L; } // create new dir entry if mode is not purely read: "r" if (!found && (mode & 0x3)) { f->file.attribute = RDCF_ARCHIVE; rdcf_get_date_and_time(&f->file.date_and_time); f->mode |= WRITTEN; f->file.first_cluster = EMPTY_CLUSTER; f->file.size = 0L; update_directory_entry(f, 0); flush_buffer(f); } if ((mode & 0x3) == 0) { // open for reading. f->mode |= RDCF_READ; if (!found) error_exit(f, ~ENOENT); } else { // open for writing or f->mode |= RDCF_WRITE; // open for read write. if ((mode & 0x3) == 2) f->mode |= RDCF_READ; check_write_access(f); } f->last_cluster = EMPTY_CLUSTER; f->BufferInUse = True; f->position = 0; f->cluster = f->file.first_cluster; if (mode & _FAPPEND) { // seek to end of file. if ((found = rdcf_seek(f, f->file.size)) != 0) return found; } return 0;}/*************************************************************** * rdcf_read * * fill buf with data from opened file. * returns positive number on succes of bytes read. ****************************************************************/int rdcf_read(struct rdcf *f, void *buf, int count){ ulong size = f->file.size; unsigned unread_bytes = count; ulong position = f->position; char *buffer = buf; if ((f->result=setjmp(f->error)) != 0) return f->result; if (f->BufferInUse == False) error_exit(f, ~EBADF); if ((f->mode & RDCF_READ) == 0) error_exit(f, ~EBADFD); f->buffer_status = EMPTY; while (unread_bytes>0) { unsigned n = unread_bytes; unsigned rest_of_sector = SECTOR_SIZE - position%SECTOR_SIZE; unsigned sector; if (size<position+n) n = size-position; if (n==0) break; sector = first_sector_in_cluster(f, f->cluster) + (position/SECTOR_SIZE)%f->sectors_per_cluster; if (n>rest_of_sector) n = rest_of_sector; if (position%SECTOR_SIZE==0 && n==SECTOR_SIZE) read_sector(f, sector, buffer); else /* read a partial sector */ { read_buffer(f, sector); memcpy(buffer, &f->buffer.buf[position%SECTOR_SIZE], n); } buffer += n; position += n; unread_bytes -= n; if (position%(f->sectors_per_cluster*SECTOR_SIZE)==0 && position<size) { unsigned next_cluster = FAT_entry(f, f->cluster); if (next_cluster >= f->last_cluster_mark) f->last_cluster = f->cluster; f->cluster = next_cluster; } } f->position = position; return f->result = count - unread_bytes;}int rdcf_seek(struct rdcf *f, ulong offset){ unsigned i, cluster; if ((f->result=setjmp(f->error)) != 0) return f->result; if (offset>f->file.size) error_exit(f, ~ESPIPE); f->buffer_status = EMPTY; cluster = f->file.first_cluster; for (i=offset/(f->sectors_per_cluster*SECTOR_SIZE); i>0; i--) { unsigned new_cluster = FAT_entry(f, cluster); if (new_cluster >= f->last_cluster_mark) f->last_cluster = cluster; cluster = new_cluster; } f->cluster = cluster; f->position = offset; return 0;}static int real_rdcf_write(struct rdcf *f, const uchar *buf, int count){ ulong size = f->file.size; ulong position = f->position; unsigned unwritten_bytes = count; unsigned first_possibly_empty_cluster = 2; const char *buffer = buf; if ((f->result=setjmp(f->error)) != 0) return f->result; if (f->BufferInUse == False) error_exit(f, ~EBADF); f->buffer_status = EMPTY; if ((f->mode & RDCF_WRITE) == 0) error_exit(f, ~EBADFD); while (unwritten_bytes>0) { unsigned sector; unsigned n = unwritten_bytes; unsigned rest_of_sector = SECTOR_SIZE - position%SECTOR_SIZE; if (n>rest_of_sector) n = rest_of_sector; if (f->cluster == EMPTY_CLUSTER || f->cluster >= f->last_cluster_mark) { unsigned new_cluster = add_new_cluster(f, f->last_cluster, first_possibly_empty_cluster); if (new_cluster == EMPTY_CLUSTER) break; first_possibly_empty_cluster = new_cluster+1; f->cluster = f->last_cluster = new_cluster; if (f->file.first_cluster==EMPTY_CLUSTER) f->file.first_cluster = new_cluster; } sector = first_sector_in_cluster(f, f->cluster) + (position/SECTOR_SIZE)%f->sectors_per_cluster; if (position%SECTOR_SIZE==0 && (n==SECTOR_SIZE || position+n>=size)) { write_sector(f, sector, buffer); } else /* write a partial sector */ { read_buffer(f, sector); memcpy(&f->buffer.buf[position%SECTOR_SIZE], buffer, n); f->buffer_status = DIRTY; } buffer += n; position += n; unwritten_bytes -= n; if (position>size) size = position; if (position%(f->sectors_per_cluster*SECTOR_SIZE)==0) { unsigned next_cluster = FAT_entry(f, f->cluster); if (next_cluster >= f->last_cluster_mark) f->last_cluster = f->cluster; f->cluster = next_cluster; } } flush_buffer(f); f->position = position; f->file.size = size; f->mode |= WRITTEN;#ifdef RDCF_FLUSH_DIR_AFTER_WRITE rdcf_get_date_and_time(&f->file.date_and_time); // do not allow empty files. update_directory_entry(f, (f->file.size) ? 0 : 1); flush_buffer(f);#endif return f->result = count-unwritten_bytes;}int rdcf_write(struct rdcf *f, const void *buf, int count){// traps write() and ensures no dangling FAT chains.int result; result = real_rdcf_write(f, buf, count); // uhoh, something really bad happened! // flush buffer and close the handle. if (result <= 0) { rdcf_close(f); } return result;}int rdcf_flush_directory(struct rdcf *f){ if ((f->result=setjmp(f->error)) != 0) return f->result; if (f->BufferInUse == False) return 0; rdcf_get_date_and_time(&f->file.date_and_time); // do not allow empty files. update_directory_entry(f, (f->file.size) ? 0 : 1); flush_buffer(f); return 0;}#if 0int rdcf_attribute(struct rdcf *f, const char *spec, unsigned attribute){ if ((f->result=setjmp(f->error)) != 0) return f->result; if (!find_file(f, initialize_fcb(f, spec)) || f->file.attribute & RDCF_DIRECTORY) { error_exit(f, ~ENOENT); } f->file.attribute = (f->file.attribute & ~CHANGEABLE_ATTRIBUTES) | (attribute & CHANGEABLE_ATTRIBUTES); update_directory_entry(f, 0); flush_buffer(f); return 0;}int rdcf_date_and_time(struct rdcf *f, const char *spec, struct rdcf_date_and_time *p){ if ((f->result=setjmp(f->error)) != 0) return f->result; spec = initialize_fcb(f, spec); if (*spec == 0) { f->directory_cluster = 0; if (!find_file_in_directory_or_find_volume(f, NULL)) error_exit(f, ~ENOENT); } else { if (!find_file(f, spec)) error_exit(f, ~ENOENT); } f->file.date_and_time = *p; if ((f->file.attribute & (RDCF_DIRECTORY+RDCF_VOLUME)) == 0) { check_write_access(f); f->file.attribute |= RDCF_ARCHIVE; } update_directory_entry(f, 0); if (f->file.attribute & RDCF_DIRECTORY) update_dot_and_dot_dot(f); flush_buffer(f); return 0;}int rdcf_directory(struct rdcf *f, const char *spec){ /* uchar name_extension[NAME_SIZE+EXTENSION_SIZE]; ??? */ if ((f->result=setjmp(f->error)) != 0) return f->result; if (find_file(f, initialize_fcb(f, spec))) error_exit(f, ~EISDIR); /* spec_to_name_extension(f, name_extension, f->file.spec); ??? */ /* name_extension_to_spec(f->file.spec, name_extension); ??? */ /* determine whether there is enough free space for directory */ { unsigned cluster = 2; unsigned required_clusters = f->directory_index == NO_DIRECTORY_INDEX ? 2 : 1; for (cluster = 2; required_clusters != 0; cluster++) { if (cluster > f->maximum_cluster_number) error_exit(f, ~ENOSPC); if (FAT_entry(f, cluster)==EMPTY_CLUSTER) required_clusters--; } } lengthen_directory_if_necessary(f); f->file.attribute = RDCF_DIRECTORY; f->file.first_cluster = add_new_cluster(f, EMPTY_CLUSTER, 2); clear_cluster(f, f->file.first_cluster); f->file.size = 0L; rdcf_get_date_and_time(&f->file.date_and_time); update_directory_entry(f, 0); update_dot_and_dot_dot(f); flush_buffer(f); return 0;}long int rdcf_free_space(struct rdcf *f#ifdef RDCF_MULTIPLE_DRIVE , char *spec#endif){ unsigned cluster; unsigned number_of_empty_clusters = 0; if ((f->result=setjmp(f->error)) != 0) return (long)(f->result);#ifndef RDCF_MULTIPLE_DRIVE initialize_fcb(f, NULL);#else if (*initialize_fcb(f, spec) != 0) error_exit(f, ~EINVAL);#endif for (cluster = 2; cluster <= f->maximum_cluster_number; cluster++) { if (FAT_entry(f, cluster) == EMPTY_CLUSTER) number_of_empty_clusters++; } f->file.size = (ulong) number_of_empty_clusters * (f->sectors_per_cluster * SECTOR_SIZE); return (long)(f->file.size);}int rdcf_get_file_information(struct rdcf *f, const char *spec, unsigned idx){ if ((f->result=setjmp(f->error)) != 0) return f->result; find_entry(f, spec, idx); read_directory_entry(f); return f->result = f->file.spec[0] == DELETED_FILE ? ENOENT : f->file.spec[0] == 0 ? ENOSPC : 0;}int rdcf_next_file_information(struct rdcf *f){ if ((f->result=setjmp(f->error)) != 0) return f->result; f->directory_index++; if (f->directory_cluster == 0) { if (f->directory_index >= (f->first_data_sector - f->first_directory_sector)*ENTRIES_PER_SECTOR) { error_exit(f, ~ENOSPC); } } else { if (f->directory_index >= ENTRIES_PER_SECTOR*f->sectors_per_cluster) { f->directory_cluster = FAT_entry(f, f->directory_cluster); if (f->directory_cluster >= f->last_cluster_mark) error_exit(f, ~ENOSPC); f->directory_index = 0; } } read_directory_entry(f); return f->result = f->file.spec[0] == DELETED_FILE ? ENOENT : f->file.spec[0] == 0 ? ENOSPC : 0;}/*-----------------------------------------------------------------------------When f represents a subdirectory, this function updates the . and .. entries atthe beginning of its first cluster.-----------------------------------------------------------------------------*/static void update_dot_and_dot_dot(struct rdcf *f){ f->directory_cluster = f->file.first_cluster; f->directory_index = 0; memset(f->file.spec, ' ', NAME_SIZE+EXTENSION_SIZE); f->file.spec[0] = '.'; update_directory_entry(f, 0); f->file.first_cluster = f->directory_first_cluster; f->directory_index = 1; f->file.spec[1] = '.'; update_directory_entry(f, 0);}/*-----------------------------------------------------------------------------This function contains the common code from rdcf_get_file_information() andrdcf_set_file_information(). It finds the directory entry specified by thespec and index, and puts its cluster and index into f->directory_cluster andf->directory_index.-----------------------------------------------------------------------------*/static void find_entry(struct rdcf *f, const char *spec, unsigned idx){ spec = initialize_fcb(f, spec); if (*spec == 0) { if (idx >= (f->first_data_sector - f->first_directory_sector)*ENTRIES_PER_SECTOR) { error_exit(f, ~ENOSPC); } f->directory_first_cluster = f->directory_cluster = 0; } else { if (!find_file(f, spec) || (f->file.attribute&RDCF_DIRECTORY) == 0) error_exit(f, ~ENOENT); f->directory_first_cluster = f->directory_cluster = f->file.first_cluster; while (idx >= ENTRIES_PER_SECTOR*f->sectors_per_cluster) { f->directory_cluster = FAT_entry(f, f->directory_cluster); if (f->directory_cluster >= f->last_cluster_mark) error_exit(f, ~ENOSPC); idx -= ENTRIES_PER_SECTOR*f->sectors_per_cluster; } } f->directory_index = idx;}#endif// vi:nowrap:#endif // HAS_MMC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -