This repository has been archived on 2023-11-05. You can view files and clone it, but cannot push or open issues or pull requests.
wasm-micro-runtime/samples/file/wasm-app/main.c
Jämes Ménétrey 0435acdd43
SGX IPFS: Fix a segfault and support seeking beyond the end of files while using SEEK_CUR/SEEK_END (#1916)
The current implementation throws a segmentation fault when padding
files using a large range, because the writing operation overflows the
source buffer, which was a single char.

IPFS previously assumed that the offset for the seek operation was related
to the start of the file (SEEK_SET). It now correctly checks the parameter
'whence' and computes the offset for SEEK_CUR (middle of the file) and
SEEK_END (end of the file).
2023-01-30 08:24:12 +08:00

172 lines
6.2 KiB
C

/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#define PATH_TEST_FOLDER "./test"
#define PATH_TEST_FILE (PATH_TEST_FOLDER "/test.txt")
#define FILE_TEXT "Hello, world!"
#define WORLD_OFFSET 7
#define NAME_REPLACMENT "James"
#define NAME_REPLACMENT_LEN (sizeof(NAME_REPLACMENT) - 1)
#define ADDITIONAL_SPACE 1 * 1024 * 1024
int
main(int argc, char **argv)
{
FILE *file;
const char *text = FILE_TEXT;
char buffer[1000];
int ret;
long long stat_size;
// Test: Create a folder to store the file, if it does not exist yet
ret = mkdir(PATH_TEST_FOLDER, 777);
assert(ret == 0 || (ret == -1 && errno == EEXIST));
// Test: File opening (fopen)
printf("Opening a file..\n");
file = fopen(PATH_TEST_FILE, "w+");
if (file == NULL) {
printf("Error! errno: %d\n", errno);
}
assert(file != NULL);
printf("[Test] File opening passed.\n");
// Test: Writing to a file (fprintf)
printf("Writing to the file..\n");
ret = fprintf(file, "%s", text);
assert(ret == strlen(text));
printf("[Test] File writing passed.\n");
// Test: Reading from a file (fseek)
printf("Moving the cursor to the start of the file..\n");
ret = fseek(file, 0, SEEK_SET);
assert(ret == 0);
printf("Reading from the file, up to 1000 characters..\n");
fread(buffer, 1, sizeof(buffer), file);
printf("Text read: %s\n", buffer);
assert(strncmp(text, buffer, strlen(text)) == 0);
printf("[Test] File reading passed.\n");
// Test: end of file detection (feof)
printf("Determine whether we reach the end of the file..\n");
int is_end_of_file = feof(file);
printf("Is the end of file? %d\n", is_end_of_file);
assert(is_end_of_file == 1);
printf("[Test] End of file detection passed.\n");
// Test: retrieving file offset (ftell)
printf("Getting the plaintext size..\n");
long plaintext_size = ftell(file);
printf("The plaintext size is %ld.\n", plaintext_size);
assert(plaintext_size == 13);
printf("[Test] Retrieving file offset passed.\n");
// Test: persist changes on disk (fflush)
printf("Force actual write of all the cached data to the disk..\n");
ret = fflush(file);
assert(ret == 0);
printf("[Test] Retrieving file offset passed.\n");
// Test: writing at specified offset (pwrite)
printf("Writing 5 characters at offset %d..\n", WORLD_OFFSET);
ret = pwrite(fileno(file), NAME_REPLACMENT, NAME_REPLACMENT_LEN,
WORLD_OFFSET);
printf("File current offset: %ld\n", ftell(file));
assert(ret == NAME_REPLACMENT_LEN);
assert(ftell(file) == strlen(FILE_TEXT));
printf("[Test] Writing at specified offset passed.\n");
// Test: reading at specified offset (pread)
printf("Reading %ld characters at offset %d..\n", NAME_REPLACMENT_LEN,
WORLD_OFFSET);
buffer[NAME_REPLACMENT_LEN] = '\0';
pread(fileno(file), buffer, NAME_REPLACMENT_LEN, WORLD_OFFSET);
printf("Text read: %s\n", buffer);
printf("File current offset: %ld\n", ftell(file));
assert(strcmp(NAME_REPLACMENT, buffer) == 0);
assert(ftell(file) == strlen(FILE_TEXT));
printf("[Test] Reading at specified offset passed.\n");
// Test: allocate more space to the file (posix_fallocate)
printf("Allocate more space to the file (posix_fallocate)..\n");
posix_fallocate(fileno(file), ftell(file), ADDITIONAL_SPACE);
printf("File current offset: %ld\n", ftell(file));
printf("Moving to the end..\n");
fseek(file, 0, SEEK_END);
printf("File current offset: %ld\n", ftell(file));
assert(ftell(file) == strlen(text) + ADDITIONAL_SPACE);
printf("[Test] Allocation or more space passed.\n");
// Test: allocate more space to the file (ftruncate)
printf("Allocate more space to the file (ftruncate)..\n");
ftruncate(fileno(file), ftell(file) + ADDITIONAL_SPACE);
assert(ftell(file) == strlen(text) + ADDITIONAL_SPACE);
printf("File current offset: %ld\n", ftell(file));
printf("Moving to the end..\n");
fseek(file, 0, SEEK_END);
printf("File current offset: %ld\n", ftell(file));
assert(ftell(file) == strlen(text) + 2 * ADDITIONAL_SPACE);
printf("[Test] Extension of the file size passed.\n");
// Test: allocate more space to the file (fseek)
printf("Allocate more space to the file (fseek) from the start..\n");
printf("File current offset: %ld\n", ftell(file));
fseek(file, 3 * ADDITIONAL_SPACE, SEEK_SET);
printf("File current offset: %ld\n", ftell(file));
assert(ftell(file) == 3 * ADDITIONAL_SPACE);
printf("[Test] Extension of the file size passed.\n");
// Test: allocate more space to the file (fseek)
printf("Allocate more space to the file (fseek) from the end..\n");
printf("File current offset: %ld\n", ftell(file));
fseek(file, ADDITIONAL_SPACE, SEEK_END);
printf("File current offset: %ld\n", ftell(file));
assert(ftell(file) == 4 * ADDITIONAL_SPACE);
printf("[Test] Extension of the file size passed.\n");
// Test: allocate more space to the file (fseek)
printf("Allocate more space to the file (fseek) from the middle..\n");
fseek(file, 3 * ADDITIONAL_SPACE, SEEK_SET);
printf("File current offset: %ld\n", ftell(file));
fseek(file, 2 * ADDITIONAL_SPACE, SEEK_CUR);
printf("File current offset: %ld\n", ftell(file));
assert(ftell(file) == 5 * ADDITIONAL_SPACE);
printf("[Test] Extension of the file size passed.\n");
// Display some debug information
printf("Getting the size of the file on disk..\n");
struct stat st;
stat(PATH_TEST_FILE, &st);
stat_size = st.st_size;
assert(stat_size != 0);
// Compare with the size from fstat
fstat(fileno(file), &st);
printf("The file size is: %lld (stat), %lld (fstat).\n", stat_size,
st.st_size);
assert(stat_size != 0);
assert(stat_size == st.st_size);
// Test: closing the file (fclose)
printf("Closing from the file..\n");
ret = fclose(file);
assert(ret == 0);
printf("[Test] Closing file passed.\n");
printf("All the tests passed!\n");
return 0;
}