static void remove_test_files() { char filename[4096]; int count = 0; while (1) { mxf_snprintf(filename, sizeof(filename), g_testFile, count); if (remove(filename) != 0) { break; } count++; } }
int64_t mxf_page_file_get_size(const char *filenameTemplate) { int index = 0; char filename[4096]; struct stat statBuf; int64_t size = 0; for(;;) { mxf_snprintf(filename, sizeof(filename), filenameTemplate, index); if (stat(filename, &statBuf) != 0) break; size += statBuf.st_size; index++; } return size; }
int mxf_page_file_remove(const char *filenameTemplate) { int index = 0; char filename[4096]; for(;;) { mxf_snprintf(filename, sizeof(filename), filenameTemplate, index); if (remove(filename) != 0) { break; } index++; } if (index == 0) { /* first file couldn't be removed or does not exist */ return 0; } return 1; }
int mxf_page_file_forward_truncate(MXFPageFile *mxfPageFile) { MXFFileSysData *sysData = mxfPageFile->mxfFile->sysData; int page = (int)(sysData->position / sysData->pageSize); int i; char filename[4096]; #if defined(_WIN32) int fileid; #endif if (sysData->mode == READ_MODE) { mxf_log_error("Cannot forward truncate read-only mxf page file\n"); return 0; } /* close and truncate to zero length page files before the current one */ for (i = 0; i < page; i++) { if (sysData->pages[i].wasRemoved) { continue; } if (sysData->pages[i].fileDescriptor != NULL) { /* close the file */ disk_file_close(sysData->pages[i].fileDescriptor); /* remove the file descriptor from the list */ if (sysData->fileDescriptorHead == sysData->pages[i].fileDescriptor) { sysData->fileDescriptorHead = sysData->fileDescriptorHead->next; } else { sysData->pages[i].fileDescriptor->prev->next = sysData->pages[i].fileDescriptor->next; } if (sysData->fileDescriptorTail == sysData->pages[i].fileDescriptor) { sysData->fileDescriptorTail = sysData->fileDescriptorTail->prev; } else { sysData->pages[i].fileDescriptor->next->prev = sysData->pages[i].fileDescriptor->prev; } SAFE_FREE(sysData->pages[i].fileDescriptor); } /* truncate the file to zero length */ mxf_snprintf(filename, sizeof(filename), sysData->filenameTemplate, sysData->pages[i].index); #if defined(_WIN32) /* WIN32 does not have truncate() so open the file with _O_TRUNC then close it */ if ((fileid = _open(filename, _O_CREAT | _O_TRUNC, _S_IWRITE)) == -1 || _close(fileid) == -1) #else if (truncate(filename, 0) != 0) #endif { mxf_log_warn("Failed to truncate '%s' to zero length: %s\n", filename, strerror(errno)); } sysData->pages[i].wasRemoved = 1; } return 1; }
int mxf_page_file_open_modify(const char *filenameTemplate, int64_t pageSize, MXFPageFile **mxfPageFile) { MXFFile *newMXFFile = NULL; int pageCount; int allocatedPages; char filename[4096]; FILE *file; int64_t fileSize; if (strstr(filenameTemplate, "%d") == NULL) { mxf_log_error("Filename template '%s' doesn't contain %%d\n", filenameTemplate); return 0; } /* count number of page files */ pageCount = 0; for(;;) { mxf_snprintf(filename, sizeof(filename), filenameTemplate, pageCount); if ((file = fopen(filename, "rb")) == NULL) { break; } fclose(file); pageCount++; } if (pageCount == 0) { /* file not found */ return 0; } /* check the size of the first file equals the pageSize */ if (pageCount > 1) { mxf_snprintf(filename, sizeof(filename), filenameTemplate, 0); fileSize = disk_file_size(filename); if (fileSize < 0) { mxf_log_error("Failed to stat file '%s': %s\n", filename, strerror(errno)); return 0; } if (pageSize != fileSize) { mxf_log_error("Size of first file '%s' (%"PRId64" does not equal page size %"PRId64"\n", filename, fileSize, pageSize); return 0; } } CHK_MALLOC_ORET(newMXFFile, MXFFile); memset(newMXFFile, 0, sizeof(*newMXFFile)); newMXFFile->close = page_file_close; newMXFFile->read = page_file_read; newMXFFile->write = page_file_write; newMXFFile->get_char = page_file_getchar; newMXFFile->put_char = page_file_putchar; newMXFFile->eof = page_file_eof; newMXFFile->seek = page_file_seek; newMXFFile->tell = page_file_tell; newMXFFile->is_seekable = page_file_is_seekable; newMXFFile->size = page_file_size; newMXFFile->free_sys_data = free_page_file; CHK_MALLOC_OFAIL(newMXFFile->sysData, MXFFileSysData); memset(newMXFFile->sysData, 0, sizeof(*newMXFFile->sysData)); CHK_OFAIL((newMXFFile->sysData->filenameTemplate = strdup(filenameTemplate)) != NULL); newMXFFile->sysData->pageSize = pageSize; newMXFFile->sysData->mode = MODIFY_MODE; newMXFFile->sysData->mxfPageFile.mxfFile = newMXFFile; /* allocate pages */ allocatedPages = (pageCount < PAGE_ALLOC_INCR) ? PAGE_ALLOC_INCR : pageCount; CHK_MALLOC_ARRAY_ORET(newMXFFile->sysData->pages, Page, allocatedPages); memset(newMXFFile->sysData->pages, 0, allocatedPages * sizeof(Page)); newMXFFile->sysData->numPages = pageCount; newMXFFile->sysData->numPagesAllocated = allocatedPages; for (pageCount = 0; pageCount < newMXFFile->sysData->numPages; pageCount++) { newMXFFile->sysData->pages[pageCount].index = pageCount; newMXFFile->sysData->pages[pageCount].size = pageSize; } /* set the files size of the last file, which could have size < pageSize */ mxf_snprintf(filename, sizeof(filename), filenameTemplate, newMXFFile->sysData->numPages - 1); fileSize = disk_file_size(filename); if (fileSize < 0) { mxf_log_error("Failed to stat file '%s': %s\n", filename, strerror(errno)); goto fail; } newMXFFile->sysData->pages[newMXFFile->sysData->numPages - 1].size = fileSize; *mxfPageFile = &newMXFFile->sysData->mxfPageFile; return 1; fail: if (newMXFFile != NULL) { mxf_file_close(&newMXFFile); } return 0; }
static int open_file(MXFFileSysData *sysData, Page *page) { FILE *newFile = NULL; char filename[4096]; FileDescriptor *newFileDescriptor = NULL; if (page->wasRemoved) { mxf_log_warn("Failed to open mxf page file which was removed after truncation\n"); return 0; } /* move file descriptor to tail if already open, and return */ if (page->fileDescriptor != NULL) { if (page->fileDescriptor == sysData->fileDescriptorTail) { return 1; } /* extract file descriptor */ if (page->fileDescriptor->next != NULL) { page->fileDescriptor->next->prev = page->fileDescriptor->prev; } if (page->fileDescriptor->prev != NULL) { page->fileDescriptor->prev->next = page->fileDescriptor->next; } if (sysData->fileDescriptorHead == page->fileDescriptor) { sysData->fileDescriptorHead = page->fileDescriptor->next; } /* put file descriptor at tail */ page->fileDescriptor->next = NULL; page->fileDescriptor->prev = sysData->fileDescriptorTail; if (sysData->fileDescriptorTail != NULL) { sysData->fileDescriptorTail->next = page->fileDescriptor; } sysData->fileDescriptorTail = page->fileDescriptor; return 1; } /* close the least used file descriptor (the head) if too many file descriptors are open */ if (sysData->numFileDescriptors >= MAX_FILE_DESCRIPTORS) { if (sysData->fileDescriptorTail == sysData->fileDescriptorHead) { /* single file descriptor */ sysData->fileDescriptorHead->page->fileDescriptor = NULL; disk_file_close(sysData->fileDescriptorHead); SAFE_FREE(sysData->fileDescriptorHead); sysData->fileDescriptorHead = NULL; sysData->fileDescriptorTail = NULL; sysData->numFileDescriptors--; } else { /* multiple file descriptors */ FileDescriptor *newHead = sysData->fileDescriptorHead->next; sysData->fileDescriptorHead->page->fileDescriptor = NULL; disk_file_close(sysData->fileDescriptorHead); SAFE_FREE(sysData->fileDescriptorHead); sysData->fileDescriptorHead = newHead; newHead->prev = NULL; sysData->numFileDescriptors--; } } /* open the file */ mxf_snprintf(filename, sizeof(filename), sysData->filenameTemplate, page->index); switch (sysData->mode) { case READ_MODE: newFile = fopen(filename, "rb"); break; case WRITE_MODE: if (!page->wasOpenedBefore) { newFile = fopen(filename, "w+b"); } else { newFile = fopen(filename, "r+b"); } break; case MODIFY_MODE: newFile = fopen(filename, "r+b"); if (newFile == NULL) { newFile = fopen(filename, "w+b"); } break; } if (newFile == NULL) { mxf_log_error("Failed to open paged mxf file '%s': %s\n", filename, strerror(errno)); return 0; } /* create the new file descriptor */ CHK_MALLOC_OFAIL(newFileDescriptor, FileDescriptor); memset(newFileDescriptor, 0, sizeof(*newFileDescriptor)); newFileDescriptor->file = newFile; newFile = NULL; newFileDescriptor->page = page; page->fileDescriptor = newFileDescriptor; page->wasOpenedBefore = 1; page->offset = 0; if (sysData->fileDescriptorTail != NULL) { sysData->fileDescriptorTail->next = newFileDescriptor; } newFileDescriptor->prev = sysData->fileDescriptorTail; sysData->fileDescriptorTail = newFileDescriptor; if (sysData->fileDescriptorHead == NULL) { sysData->fileDescriptorHead = newFileDescriptor; } sysData->numFileDescriptors++; return 1; fail: if (newFile != NULL) { fclose(newFile); } return 0; }