📄 rdcf2.c
字号:
f->mode |= WRITTEN; f->file.first_cluster = EMPTY_CLUSTER; f->file.size = 0L; update_directory_entry (f, 0); flush_buffer (f); } } else if (!found) { // printf("!found, !O_CREAT\n"); // not found, not CREATE -> error error_exit (f, ~ENOENT); } // mark APPEND if (mode & O_APPEND) { f->mode |= APPEND; } // now file is created or we have signalled an error // decide the file mode switch (mode & 0x3) { case O_RDONLY: // printf("open for reading\n"); f->mode |= RDCF_READ; break; case O_RDWR: // printf("open for reading\n"); f->mode |= RDCF_READ; // fallthrough to write case O_WRONLY: // printf("open for writing\n"); check_write_access (f); f->mode |= RDCF_WRITE; break; } // do final setup f->last_cluster = EMPTY_CLUSTER; f->position = 0; f->cluster = f->file.first_cluster; // seek to end of file if O_WRONLY and O_APPEND if ((mode & O_APPEND) && ((mode & 0x3) == O_WRONLY)) { // printf("O_APPEND seeking now\n"); int result; if ((result = rdcf_seek (f, f->file.size)) != 0) return result; } 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){ uint32_t size = f->file.size; unsigned unread_bytes = count; uint32_t position = f->position; char *buffer = buf; if ((f->result = setjmp (f->error)) != 0) return f->result; 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, uint32_t offset){ unsigned i, cluster; if ((f->result = setjmp (f->error)) != 0) return f->result; if (offset > f->file.size) error_exit (f, ~EINVAL); 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 uint8_t * buf, int count){ uint32_t size = f->file.size; uint32_t position = f->position; unsigned unwritten_bytes = count; const uint8_t *buffer = buf; if ((f->result = setjmp (f->error)) != 0) return f->result; f->buffer_status = EMPTY; if ((f->mode & RDCF_WRITE) == 0) error_exit (f, ~EBADFD); if (f->mode & APPEND) { // printf("O_APPEND seeking now\n"); int result; if ((result = rdcf_seek (f, size)) != 0) return result; position = f->position; } 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); if (new_cluster == EMPTY_CLUSTER) break; DriveDesc.FirstPossiblyEmptyCluster = 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; 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){ /* uint8_t 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 = (uint32_t) 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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -