/** * Given the full path to a file, calculate and return the number of the final chunk in the file. * The final chunk nunber is a function of the size of the file and the specified chunk size. It * is 0-based and is never negative. A file of size 0 has a final chunk number of 0. * * @param [in] filePath The full path to a file. * @param [in] chunkSize The size of the chunks to break the file in to. * * @return The number of the final chunk required to transfer the specified file. */ static u_int64_t _getFinalChunkNumberOfFile(const char *filePath, uint32_t chunkSize) { size_t fileSize = tutorialFileIO_GetFileSize(filePath); uint64_t totalNumberOfChunksInFile = _getNumberOfChunksRequired(fileSize, chunkSize); // If the file size == 0, the the final chunk number is 0. Else, it's one less // than the number of chunks in the file. return totalNumberOfChunksInFile > 0 ? (totalNumberOfChunksInFile - 1) : 0; }
PARCBuffer * tutorialFileIO_CreateDirectoryListing(const char *directoryName) { DIR *directory = opendir(directoryName); assertNotNull(directory, "Couldn't open directory '%s' for reading.", directoryName); PARCBufferComposer *directoryListing = parcBufferComposer_Create(); struct dirent *entry; while ((entry = readdir(directory)) != NULL) { switch (entry->d_type) { case DT_REG: { // a regular file // We need the full file path to check its size. PARCBufferComposer *fullFilePath = parcBufferComposer_Create(); parcBufferComposer_Format(fullFilePath, "%s/%s", directoryName, entry->d_name); PARCBuffer *fileNameBuffer = parcBufferComposer_ProduceBuffer(fullFilePath); char *fullFilePathString = parcBuffer_ToString(fileNameBuffer); parcBuffer_Release(&fileNameBuffer); if (tutorialFileIO_IsFileAvailable(fullFilePathString)) { parcBufferComposer_Format(directoryListing, " %s (%zu bytes)\n", entry->d_name, tutorialFileIO_GetFileSize(fullFilePathString)); } parcBufferComposer_Release(&fullFilePath); parcMemory_Deallocate((void **) &fullFilePathString); break; } case DT_LNK: case DT_DIR: default: // ignore everything but regular files break; } } closedir(directory); PARCBuffer *result = parcBufferComposer_ProduceBuffer(directoryListing); parcBufferComposer_Release(&directoryListing); return result; }