⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 integck.c

📁 mtd-utils 是一套更改linux mtd設備的工具
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (C) 2007 Nokia Corporation. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Author: Adrian Hunter */#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <stdint.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>#include <limits.h>#include <dirent.h>#include <sys/mman.h>#include "tests.h"/* Structures to store data written to the test file system,   so that we can check whether the file system is correct. */struct write_info /* Record of random data written into a file */{	struct write_info *next;	off_t offset; /* Where in the file the data was written */	size_t size; /* Number of bytes written */	unsigned random_seed; /* Seed for rand() to create random data */	off_t random_offset; /* Call rand() this number of times first */	int trunc; /* Records a truncation (raw_writes only) */};struct dir_entry_info;struct file_info /* Each file has one of these */{	char *name; /* Original name */	struct write_info *writes; /* Record accumulated writes to the file */	struct write_info *raw_writes;				/* Record in order all writes to the file */	struct fd_info *fds; /* All open file descriptors for this file */	struct dir_entry_info *links;	int link_count;	off_t length;	int deleted; /* File has been deleted but is still open */	int no_space_error; /* File has incurred a ENOSPC error */	uint64_t check_run_no; /* Run number used when checking */};struct symlink_info /* Each symlink has one of these */{	char *target_pathname;	struct dir_entry_info *entry; /* dir entry of this symlink */};struct dir_info /* Each directory has one of these */{	char *name;	struct dir_info *parent; /* Parent directory or null					for our top directory */	unsigned number_of_entries;	struct dir_entry_info *first;	struct dir_entry_info *entry; /* Dir entry of this dir */};struct dir_entry_info /* Each entry in a directory has one of these */{	struct dir_entry_info *next; /* List of entries in directory */	struct dir_entry_info *prev; /* List of entries in directory */	struct dir_entry_info *next_link; /* List of hard links for same file */	struct dir_entry_info *prev_link; /* List of hard links for same file */	char *name;	struct dir_info *parent; /* Parent directory */	char type; /* f => file, d => dir, s => symlink */	int checked; /* Temporary flag used when checking */	union entry_	{		struct file_info *file;		struct dir_info *dir;		struct symlink_info *symlink;		void *target;	} entry;};struct fd_info /* We keep a number of files open */{	struct fd_info *next;	struct file_info *file;	int fd;};struct open_file_info /* We keep a list of open files */{	struct open_file_info *next;	struct fd_info *fdi;};static struct dir_info *top_dir = NULL; /* Our top directory */static struct open_file_info *open_files = NULL; /* We keep a list of							open files */static size_t open_files_count = 0;static int grow   = 1; /* Should we try to grow files and directories */static int shrink = 0; /* Should we try to shrink files and directories */static int full   = 0; /* Flag that the file system is full */static uint64_t operation_count = 0; /* Number of operations used to fill                                        up the file system */static uint64_t initial_free_space = 0; /* Free space on file system when					   test starts */static unsigned log10_initial_free_space = 0; /* log10 of initial_free_space */static int check_nospc_files = 0; /* Also check data in files that incurred a				     "no space" error */static int can_mmap = 0; /* Can write via mmap */static long mem_page_size; /* Page size for mmap */static uint64_t check_run_no;static char *copy_string(const char *s){	char *str;	if (!s)		return NULL;	str = (char *) malloc(strlen(s) + 1);	CHECK(str != NULL);	strcpy(str, s);	return str;}static char *cat_strings(const char *a, const char *b){	char *str;	size_t sz;	if (a && !b)		return copy_string(a);	if (b && !a)		return copy_string(b);	if (!a && !b)		return NULL;	sz = strlen(a) + strlen(b) + 1;	str = (char *) malloc(sz);	CHECK(str != NULL);	strcpy(str, a);	strcat(str, b);	return str;}static char *cat_paths(const char *a, const char *b){	char *str;	size_t sz;	int as, bs;	size_t na, nb;	if (a && !b)		return copy_string(a);	if (b && !a)		return copy_string(b);	if (!a && !b)		return NULL;	as = 0;	bs = 0;	na = strlen(a);	nb = strlen(b);	if (na && a[na - 1] == '/')		as = 1;	if (nb && b[0] == '/')		bs = 1;	if ((as && !bs) || (!as && bs))		return cat_strings(a, b);	if (as && bs)		return cat_strings(a, b + 1);	sz = na + nb + 2;	str = (char *) malloc(sz);	CHECK(str != NULL);	strcpy(str, a);	strcat(str, "/");	strcat(str, b);	return str;}static char *dir_path(struct dir_info *parent, const char *name){	char *parent_path;	char *path;	if (!parent)		return cat_paths(tests_file_system_mount_dir, name);	parent_path = dir_path(parent->parent, parent->name);	path = cat_paths(parent_path, name);	free(parent_path);	return path;}static void open_file_add(struct fd_info *fdi){	struct open_file_info *ofi;	size_t sz;	sz = sizeof(struct open_file_info);	ofi = (struct open_file_info *) malloc(sz);	CHECK(ofi != NULL);	memset(ofi, 0, sz);	ofi->next = open_files;	ofi->fdi = fdi;	open_files = ofi;	open_files_count += 1;}static void open_file_remove(struct fd_info *fdi){	struct open_file_info *ofi;	struct open_file_info **prev;	prev = &open_files;	for (ofi = open_files; ofi; ofi = ofi->next) {		if (ofi->fdi == fdi) {			*prev = ofi->next;			free(ofi);			open_files_count -= 1;			return;		}		prev = &ofi->next;	}	CHECK(0); /* We are trying to remove something that is not there */}static struct fd_info *add_fd(struct file_info *file, int fd){	struct fd_info *fdi;	size_t sz;	sz = sizeof(struct fd_info);	fdi = (struct fd_info *) malloc(sz);	CHECK(fdi != NULL);	memset(fdi, 0, sz);	fdi->next = file->fds;	fdi->file = file;	fdi->fd = fd;	file->fds = fdi;	open_file_add(fdi);	return fdi;}static void add_dir_entry(struct dir_info *parent, char type, const char *name,			  void *target){	struct dir_entry_info *entry;	size_t sz;	sz = sizeof(struct dir_entry_info);	entry = (struct dir_entry_info *) malloc(sz);	CHECK(entry != NULL);	memset(entry, 0, sz);	entry->type = type;	entry->name = copy_string(name);	entry->parent = parent;	entry->next = parent->first;	if (parent->first)		parent->first->prev = entry;	parent->first = entry;	parent->number_of_entries += 1;	if (entry->type == 'f') {		struct file_info *file = target;		entry->entry.file = file;		entry->next_link = file->links;		if (file->links)			file->links->prev_link = entry;		file->links = entry;		file->link_count += 1;	} else if (entry->type == 'd') {		struct dir_info *dir = target;		entry->entry.dir = dir;		dir->entry = entry;		dir->name = copy_string(name);		dir->parent = parent;	} else if (entry->type == 's') {		struct symlink_info *symlink = target;		entry->entry.symlink = symlink;		symlink->entry = entry;	}}static void remove_dir_entry(struct dir_entry_info *entry){	entry->parent->number_of_entries -= 1;	if (entry->parent->first == entry)		entry->parent->first = entry->next;	if (entry->prev)		entry->prev->next = entry->next;	if (entry->next)		entry->next->prev = entry->prev;	if (entry->type == 'f') {		struct file_info *file = entry->entry.file;		if (entry->prev_link)			entry->prev_link->next_link = entry->next_link;		if (entry->next_link)			entry->next_link->prev_link = entry->prev_link;		if (file->links == entry)			file->links = entry->next_link;		file->link_count -= 1;		if (file->link_count == 0)			file->deleted = 1;	}	free(entry->name);	free(entry);}static struct dir_info *dir_new(struct dir_info *parent, const char *name){	struct dir_info *dir;	size_t sz;	char *path;	path = dir_path(parent, name);	if (mkdir(path, 0777) == -1) {		CHECK(errno == ENOSPC);		full = 1;		free(path);		return NULL;	}	free(path);	sz = sizeof(struct dir_info);	dir = (struct dir_info *) malloc(sz);	CHECK(dir != NULL);	memset(dir, 0, sz);	dir->name = copy_string(name);	dir->parent = parent;	if (parent)		add_dir_entry(parent, 'd', name, dir);	return dir;}static void file_delete(struct file_info *file);static void file_unlink(struct dir_entry_info *entry);static void symlink_remove(struct symlink_info *symlink);static void dir_remove(struct dir_info *dir){	char *path;	/* Remove directory contents */	while (dir->first) {		struct dir_entry_info *entry;		entry = dir->first;		if (entry->type == 'd')			dir_remove(entry->entry.dir);		else if (entry->type == 'f')			file_unlink(entry);		else if (entry->type == 's')			symlink_remove(entry->entry.symlink);		else			CHECK(0); /* Invalid struct dir_entry_info */	}	/* Remove entry from parent directory */	remove_dir_entry(dir->entry);	/* Remove directory itself */	path = dir_path(dir->parent, dir->name);	CHECK(rmdir(path) != -1);	free(dir);}static struct file_info *file_new(struct dir_info *parent, const char *name){	struct file_info *file = NULL;	char *path;	mode_t mode;	int fd;	size_t sz;	CHECK(parent != NULL);	path = dir_path(parent, name);	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;	fd = open(path, O_CREAT | O_EXCL | O_RDWR, mode);	if (fd == -1) {		CHECK(errno == ENOSPC);		free(path);		full = 1;		return NULL;	}	free(path);	sz = sizeof(struct file_info);	file = (struct file_info *) malloc(sz);	CHECK(file != NULL);	memset(file, 0, sz);	file->name = copy_string(name);	add_dir_entry(parent, 'f', name, file);	add_fd(file, fd);	return file;}static void link_new(struct dir_info *parent, const char *name,		     struct file_info *file){	struct dir_entry_info *entry;	char *path, *target;	int ret;	if (!file)		return;	entry = file->links;	if (!entry)		return;	path = dir_path(parent, name);	target = dir_path(entry->parent, entry->name);	ret = link(target, path);	if (ret == -1) {		CHECK(errno == ENOSPC);		free(target);		free(path);		full = 1;		return;	}	free(target);	free(path);	add_dir_entry(parent, 'f', name, file);}static void file_close(struct fd_info *fdi);static void file_close_all(struct file_info *file){	struct fd_info *fdi = file->fds;	while (fdi) {		struct fd_info *next = fdi->next;		file_close(fdi);		fdi = next;	}}static void file_unlink(struct dir_entry_info *entry){	struct file_info *file = entry->entry.file;	char *path;	path = dir_path(entry->parent, entry->name);	/* Remove file entry from parent directory */	remove_dir_entry(entry);	/* Unlink the file */	CHECK(unlink(path) != -1);	free(path);	/* Free struct file_info if file is not open and not linked */	if (!file->fds && !file->links) {		struct write_info *w, *next;		free(file->name);		w = file->writes;		while (w) {			next = w->next;			free(w);			w = next;		}		free(file);	} else if (!file->links)		file->deleted = 1;}static struct dir_entry_info *pick_entry(struct file_info *file){	struct dir_entry_info *entry;	size_t r;	if (!file->link_count)		return NULL;	r = tests_random_no(file->link_count);	entry = file->links;	while (entry && r--)		entry = entry->next_link;	return entry;}static void file_unlink_file(struct file_info *file)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -