Beispiel #1
0
void integck(void)
{
	pid_t pid;
	int64_t rpt;
	uint64_t z;
	char dir_name[256];

	/* Make our top directory */
	pid = getpid();
	printf("pid is %u\n", (unsigned) pid);
	tests_cat_pid(dir_name, "integck_test_dir_", pid);
	if (chdir(dir_name) != -1) {
		/* Remove it if it is already there */
		tests_clear_dir(".");
		CHECK(chdir("..") != -1);
		CHECK(rmdir(dir_name) != -1);
	}
	initial_free_space = tests_get_free_space();
	log10_initial_free_space = 0;
	for (z = initial_free_space; z >= 10; z /= 10)
		++log10_initial_free_space;
	top_dir = dir_new(NULL, dir_name);

	if (!top_dir)
		return;

	srand(pid);

	create_test_data();

	if (!tests_fs_is_rootfs()) {
		close_open_files();
		tests_remount(); /* Requires root access */
	}

	/* Check everything */
	dir_check(top_dir);
	check_deleted_files();

	for (rpt = 0; tests_repeat_parameter == 0 ||
				rpt < tests_repeat_parameter; ++rpt) {
		update_test_data();

		if (!tests_fs_is_rootfs()) {
			close_open_files();
			tests_remount(); /* Requires root access */
		}

		/* Check everything */
		dir_check(top_dir);
		check_deleted_files();
	}

	/* Tidy up by removing everything */
	close_open_files();
	tests_clear_dir(dir_name);
	CHECK(rmdir(dir_name) != -1);
}
Beispiel #2
0
/**
 * @brief fatfs_cp copy a file
 * @param fc the current FAT session
 * @param from_name original filename
 * @param to_name the name of the copy filename
 * @return 0 on success
 */
int fatfs_cp(struct block_cache *output, off_t block_offset, const char *from_name, const char *to_name)
{
    close_open_files();
    MAYBE_MOUNT(output, block_offset);

    FIL fromfil;
    FIL tofil;
    CHECK("fatfs_cp can't open file", from_name, f_open(&fromfil, from_name, FA_READ));
    CHECK("fatfs_cp can't open file", to_name, f_open(&tofil, to_name, FA_CREATE_ALWAYS | FA_WRITE));

    for (;;) {
        char buffer[4096];
        UINT bw, br;

        CHECK("fatfs_cp can't read", from_name, f_read(&fromfil, buffer, sizeof(buffer), &br));
        if (br == 0)
            break;

        CHECK("fatfs_cp can't write", to_name, f_write(&tofil, buffer, br, &bw));
        if (br != bw)
            ERR_RETURN("Error copying file to FAT");

    }
    f_close(&fromfil);
    f_close(&tofil);
    return 0;
}
Beispiel #3
0
/**
 * @brief fatfs_setlabel Set the volume label
 * @param fc the current FAT session
 * @param label the name of the filesystem
 * @return 0 on success
 */
int fatfs_setlabel(struct block_cache *output, off_t block_offset, const char *label)
{
    close_open_files();
    MAYBE_MOUNT(output, block_offset);
    CHECK("fat_setlabel", label, f_setlabel(label));
    return 0;
}
Beispiel #4
0
void fatfs_closefs()
{
    if (output_) {
        close_open_files();

        // This unmounts. Don't check error.
        f_mount(NULL, "", 0);
        output_ = NULL;
    }
}
Beispiel #5
0
/**
 * @brief fatfs_exists check if the specified file exists
 * @param fc the current FAT session
 * @param filename the filename
 * @return 0 if it exists
 */
int fatfs_exists(struct block_cache *output, off_t block_offset, const char *filename)
{
    close_open_files();
    MAYBE_MOUNT(output, block_offset);

    FIL fil;
    CHECK("fatfs_exists", filename, f_open(&fil, filename, FA_OPEN_EXISTING));
    f_close(&fil);

    return 0;
}
Beispiel #6
0
/**
 * @brief fatfs_touch create an empty file if the file doesn't exist
 * @param fc the current FAT session
 * @param filename the file to touch
 * @return 0 on success
 */
int fatfs_touch(struct block_cache *output, off_t block_offset, const char *filename)
{
    close_open_files();
    MAYBE_MOUNT(output, block_offset);

    FIL fil;
    CHECK("fat_touch", filename, f_open(&fil, filename, FA_OPEN_ALWAYS));
    f_close(&fil);

    return 0;
}
Beispiel #7
0
void repl_driver(void)
{
    int k;
    k = setjmp(errjmp);
    if (k == 2) return;
    signal(SIGFPE,handle_sigfpe);
    signal(SIGINT,handle_sigint);
    close_open_files();
    errjmp_ok = 1;
    nointerrupt = 0;
    if (init_file && (k == 0)) vload(init_file);
    repl();
}
Beispiel #8
0
/**
 * @brief fatfs_mv rename a file
 * @param fc the current FAT session
 * @param cmd the command name for error messages
 * @param from_name original filename
 * @param to_name new filename
 * @param force set to true to rename the file even if to_name exists
 * @return 0 on success
 */
int fatfs_mv(struct block_cache *output, off_t block_offset, const char *cmd, const char *from_name, const char *to_name, bool force)
{
    close_open_files();
    MAYBE_MOUNT(output, block_offset);

    // If forcing, remove the file first.
    if (force && fatfs_rm(output, block_offset, cmd, to_name, false))
        return -1;

    CHECK(cmd, from_name, f_rename(from_name, to_name));

    return 0;
}
Beispiel #9
0
/**
 * @brief fatfs_file_matches check if the pattern can be found in filename
 * @param fc the current FAT session
 * @param filename the file to search through
 * @param pattern the pattern to patch
 * @return 0 if the file exists and the pattern is inside of it
 */
int fatfs_file_matches(struct block_cache *output, off_t block_offset, const char *filename, const char *pattern)
{
    close_open_files();
    MAYBE_MOUNT(output, block_offset);

    FIL fil;
    CHECK("fatfs_file_matches can't open file", filename, f_open(&fil, filename, FA_READ));

    char buffer[4096];
    int rc = -1;
    size_t pattern_len = strlen(pattern);
    if (pattern_len >= sizeof(buffer))
        goto cleanup;
    if (pattern_len == 0) {
        // 0-length patterns always match if the file exists.
        rc = 0;
        goto cleanup;
    }
    size_t offset = 0;
    for (;;) {
        UINT br;

        CHECK_CLEANUP("fatfs_file_matches", filename, f_read(&fil, buffer + offset, sizeof(buffer) - offset, &br));
        if (br == 0)
            break;

        if (memmem(buffer, br, pattern, pattern_len) != 0) {
            // Found it.
            rc = 0;
            break;
        }

        // Handle pattern matches between this buffer and the next one.
        if (br >= pattern_len) {
            // Copy the last (pattern_len - 1) bytes to the beginning and read
            // from there next time.
            offset = pattern_len - 1;
            memcpy(buffer, buffer + br - offset, offset);
        } else {
            // Read less than pattern_len, so read more from there next time
            // assuming that there is a next time.
            offset = br;
        }
    }
cleanup:
    f_close(&fil);

    return rc;
}
Beispiel #10
0
/**
 * @brief fatfs_mkdir Make a directory
 * @param fc the current FAT session
 * @param dir the name of the directory
 * @return 0 on success
 */
int fatfs_mkdir(struct block_cache *output, off_t block_offset, const char *dir)
{
    close_open_files();
    MAYBE_MOUNT(output, block_offset);

    // Check if the directory already exists and is a directory.
    FILINFO info;
    FRESULT rc = f_stat(dir, &info);
    if (rc == FR_OK && info.fattrib & AM_DIR)
        return 0;

    // Try to make it if not.
    CHECK("fat_mkdir", dir, f_mkdir(dir));
    return 0;
}
Beispiel #11
0
int fatfs_pwrite(struct block_cache *output, off_t block_offset, const char *filename, int offset, const char *buffer, off_t size)
{
    // Check if this is the same file as a previous pwrite call
    if (current_file_ && strcmp(current_file_, filename) != 0)
        close_open_files();

    MAYBE_MOUNT(output, block_offset);

    if (!current_file_) {
        CHECK("fat_write can't open file", filename, f_open(&fil_, filename, FA_OPEN_ALWAYS | FA_WRITE));

        // Assuming it opens ok, cache the filename for future writes.
        current_file_ = strdup(filename);
    }

    // Check if this pwrite requires a seek.
    DWORD desired_offset = offset;
    if (desired_offset != f_tell(&fil_)) {
        // Need to seek, but if we're seeking past the end, be sure to fill in with zeros.
        if (desired_offset > f_size(&fil_)) {
            // Seek to the end
            CHECK("fat_write can't seek to end of file", filename, f_lseek(&fil_, f_size(&fil_)));

            // Write zeros.
            DWORD zero_count = desired_offset - f_tell(&fil_);
            char zero_buffer[FWUP_BLOCK_SIZE];
            memset(zero_buffer, 0, sizeof(zero_buffer));
            while (zero_count) {
                DWORD btw = (zero_count < sizeof(zero_buffer) ? zero_count : sizeof(zero_buffer));
                UINT bw;
                CHECK("fat_write can't write", filename, f_write(&fil_, zero_buffer, btw, &bw));
                if (btw != bw)
                    ERR_RETURN("Error writing file to FAT: %s, expected %ld bytes written, got %d (maybe the disk is full?)", filename, size, bw);
                zero_count -= bw;
            }
        } else {
            CHECK("fat_write can't seek in file", filename, f_lseek(&fil_, desired_offset));
        }
    }

    UINT bw;
    CHECK("fat_write can't write", filename, f_write(&fil_, buffer, size, &bw));

    if (size != bw)
        ERR_RETURN("Error writing file to FAT: %s, expected %ld bytes written, got %d (maybe the disk is full?)", filename, size, bw);

    return 0;
}
Beispiel #12
0
/**
 * @brief fatfs_rm Delete a file
 * @param fc the current FAT session
 * @param cmd the command name for error messages
 * @param filename the name of the file
 * @param file_must_exist true if the file must exist
 * @return 0 on success
 */
int fatfs_rm(struct block_cache *output, off_t block_offset, const char *cmd, const char *filename, bool file_must_exist)
{
    close_open_files();
    MAYBE_MOUNT(output, block_offset);

    FRESULT rc = f_unlink(filename);
    switch (rc) {
    case FR_OK:
        return 0;

    case FR_NO_FILE:
        if (!file_must_exist)
            return 0;

        // fall through
    default:
        fatfs_error(cmd, filename, rc);
        return -1;
    }
}
Beispiel #13
0
int fatfs_truncate(struct block_cache *output, off_t block_offset, const char *filename)
{
    // Check if this is the same file as a previous pwrite call
    if (current_file_ && strcmp(current_file_, filename) != 0)
        close_open_files();

    MAYBE_MOUNT(output, block_offset);

    if (!current_file_) {
        // FA_CREATE_ALWAYS truncates if the file exists
        CHECK("Can't open file on FAT partition", filename, f_open(&fil_, filename, FA_CREATE_ALWAYS | FA_WRITE));

        // Assuming it opens ok, cache the filename for future writes.
        current_file_ = strdup(filename);
    } else {
        // Truncate an already open file
        CHECK("Can't seek to the beginning", filename, f_lseek(&fil_, 0));
        CHECK("Can't truncate file on FAT partition", filename, f_truncate(&fil_));
    }

    // Leave the file open since the main use case is to start writing to it afterwards.
    return 0;
}
Beispiel #14
0
/* Select an open file at random */
static void operate_on_an_open_file(void)
{
	size_t r;
	struct open_file_info *ofi;

	/* When shrinking, close all open files 1 time in 128 */
	if (shrink) {
		static int x = 0;

		x += 1;
		x &= 127;
		if (x == 0) {
			close_open_files();
			return;
		}
	}
	/* Close any open files that have errored */
	if (!check_nospc_files) {
		ofi = open_files;
		while (ofi) {
			if (ofi->fdi->file->no_space_error) {
				struct fd_info *fdi;

				fdi = ofi->fdi;
				ofi = ofi->next;
				file_close(fdi);
			} else
				ofi = ofi->next;
		}
	}
	r = tests_random_no(open_files_count);
	for (ofi = open_files; ofi; ofi = ofi->next, --r)
		if (!r) {
			operate_on_open_file(ofi->fdi);
			return;
		}
}