示例#1
0
int main(int argc, char *argv[])
{
    int ret,i;
    char* argv2[argc-1+2];  // File name removed, "-o nonempty,direct_io" added
    int our_arguments_count=5; /* argv[0], source file, storage file and mount point */

    block_size=8192;
    fd=0;
    fd_write=0;
    fd_write_map=0;
    mem_write_map=MAP_FAILED;
    fd_read=0;
    fd_read_map=0;
    mem_read_map=MAP_FAILED;
    read_only = 0;

    int block_size_overridden=0;

    if(argc<4){
	fprintf(stderr,"fusecoraw alpha version. Copy-on-read-and-write block device using FUSE and sparse files. Fusecow originally created by _Vi, altered to fusecoraw by EvdH.\n");
    fprintf(stderr,"Usage: %s read_file mountpoint_file write_file read_file [-RM read_file.map] [-WM write_file.map] [-B blocksize] [-RO (read-only, for remounting)] [FUSE_options]\n",argv[0]);
	fprintf(stderr,"Examples:\n");
	fprintf(stderr,"    fusecoraw source mountpoint copy-on-write-fle copy-on-read-file\n");
	fprintf(stderr,"Remember to \"touch\" your mountpoints, not \"mkdir\" them.\n");
	return 1;
    }

    {
    char write_mapfile_buff[4096];
    sprintf(write_mapfile_buff, "%s.map", argv[3]);
    const char *write_mapfile = write_mapfile_buff;
    char read_mapfile_buff[4096];
    sprintf(read_mapfile_buff, "%s.map", argv[4]);
    const char *read_mapfile = read_mapfile_buff;
    for(;argv[our_arguments_count];) {
        if(!strcmp(argv[our_arguments_count], "-B")) {
        ++our_arguments_count;
        sscanf(argv[our_arguments_count], "%i", &block_size);
        block_size_overridden = 1;
        ++our_arguments_count;
        } else
        if(!strcmp(argv[our_arguments_count], "-WM")) {
        ++our_arguments_count;
        write_mapfile = argv[our_arguments_count];
        ++our_arguments_count;
        } else
        if(!strcmp(argv[our_arguments_count], "-RM")) {
        ++our_arguments_count;
        read_mapfile = argv[our_arguments_count];
        ++our_arguments_count;
        } else
        if(!strcmp(argv[our_arguments_count], "-RO")) {
        ++our_arguments_count;
        read_only = 1;
        } else {
        break;
        }
    }

    fd=open64(argv[1],O_RDONLY);
    if(fd<0){
        fprintf(stderr, "Unable to open read file \"%s\"\n", argv[1]);
        perror("open");
        return 1;
    }
    fd_write=open64(argv[3], O_RDWR|O_CREAT, 0777);
    if(fd_write<0){
        fprintf(stderr, "Unable to open write file \"%s\"\n", argv[3]);
        perror("open");
        return 1;
    }
    fd_write_map=open(write_mapfile, O_RDWR|O_CREAT, 0777);
    if(fd_write_map<0){
        fprintf(stderr, "Unable to open map file \"%s\"\n", write_mapfile);
        perror("open");
        return 1;
    }

    if(read_only)
        fd_read=open64(argv[4], O_RDONLY, 0777);
    else
        fd_read=open64(argv[4], O_RDWR|O_CREAT, 0777);
    if(fd_read<0){
        fprintf(stderr, "Unable to open read file \"%s\"\n", argv[4]);
        perror("open");
        return 1;
    }


    if(read_only)
        fd_read_map=open(read_mapfile, O_RDONLY, 0777);
    else
        fd_read_map=open(read_mapfile, O_RDWR|O_CREAT, 0777);
    if(fd_read_map<0){
        fprintf(stderr, "Unable to open read map file \"%s\"\n", read_mapfile);
        perror("open");
        return 1;
    }


    char write_signature[8];
    write_signature[0]=0;
    pread64(fd_write_map, &write_signature, sizeof write_signature, 0);
    write_signature[7]=0;
    if (strcmp(write_signature, "fusecow")) {
        // No signature:
        struct stat stbuf;
        fstat(fd, &stbuf);
        stbuf.st_size = st_size = (off64_t)lseek64(fd, (off64_t)0, SEEK_END);
        pwrite64(fd_write_map, "fusecow\n", 8, 0);
        pwrite64(fd_write_map, &st_size, sizeof st_size, 8);
        pwrite64(fd_write_map, &block_size, sizeof block_size, 16);
        // Actual data begins at offset 32
    } else {
        pread64(fd_write_map, &st_size, sizeof st_size, 8);
        int blocksize;
        pread64(fd_write_map, &blocksize, sizeof block_size, 16);
        if(block_size_overridden && blocksize!=block_size) {
        fprintf(stderr, "Your block size %d and block size %d saved in \"%s\" is not the same\nI will use saved block size anyway\n",
            block_size, blocksize, write_mapfile);
        // return 1;
        }
        block_size = blocksize;
    }

    char read_signature[8];
    read_signature[0]=0;
    pread64(fd_read_map, &read_signature, sizeof read_signature, 0);
    read_signature[7]=0;
    if (strcmp(read_signature, "fusecow")) {
        // No signature:
        struct stat stbuf;
        fstat(fd, &stbuf);
        stbuf.st_size = st_size = (off64_t)lseek64(fd, (off64_t)0, SEEK_END);
        pwrite64(fd_read_map, "fusecow\n", 8, 0);
        pwrite64(fd_read_map, &st_size, sizeof st_size, 8);
        pwrite64(fd_read_map, &block_size, sizeof block_size, 16);
        // Actual data begins at offset 32
    } else {
        pread64(fd_read_map, &st_size, sizeof st_size, 8);
        int blocksize;
        pread64(fd_read_map, &blocksize, sizeof block_size, 16);
        if(block_size_overridden && blocksize!=block_size) {
        fprintf(stderr, "Your block size %d and block size %d saved in \"%s\" is not the same\nI will use saved block size anyway\n",
            block_size, blocksize, read_mapfile);
        // return 1;
        }
        block_size = blocksize;
    }

    mem_write_map_size = get_map_size();
    ftruncate(fd_write_map, mem_write_map_size);
    mem_write_map = mmap(NULL, mem_write_map_size , PROT_READ|PROT_WRITE, MAP_SHARED, fd_write_map, 0);
    if(mem_write_map==MAP_FAILED) {
        perror("mmap");
        fprintf(stderr, "Unable to open memory mapping. Using simplified mode.\n");
    }


    mem_read_map_size = get_map_size();
    ftruncate(fd_read_map, mem_read_map_size);
    if(!read_only){
        mem_read_map = mmap(NULL, mem_read_map_size , PROT_READ|PROT_WRITE, MAP_SHARED, fd_read_map, 0);
        if(mem_read_map==MAP_FAILED) {
            perror("mmap");
            fprintf(stderr, "Unable to open memory mapping. Using simplified mode.\n");
        }
        }
    }

    copyup_buffer = (char*) malloc(block_size);

    int argc2=0;
    argv2[argc2++]=argv[0];
    argv2[argc2++]=argv[2]; // mount point file
    for(i=our_arguments_count;i<argc;++i)argv2[argc2++]=argv[i];
    argv2[argc2++]="-o";
    argv2[argc2++]="nonempty,direct_io";
    argv2[argc2]=0;

    ret=fuse_main(argc2, argv2, &fusecow_oper, NULL);

    close(fd);
    close(fd_write);
    close(fd_write_map);
    close(fd_read);
    close(fd_read_map);
    munmap(mem_write_map, mem_write_map_size);
    munmap(mem_read_map, mem_read_map_size);
    free(copyup_buffer);

    return ret;
}
示例#2
0
int
main(int argc, char *argv[])
{
	char *progname;
	int fd;
	int c;
	extern char *optarg;
	unsigned nprocs = 0;
	unsigned procno;
	pid_t *pidarray=NULL;
	pid_t pid;
	pid_t wr_pid = 0;
	uchar_t *buf=NULL;
	unsigned int seed;
	int pagesize = sysconf(_SC_PAGE_SIZE);
	int alarmtime = 0;
	struct sigaction sa;
	unsigned i;
	int write_cnt;
	uchar_t data;
	int no_prob = 0;
	int wait_stat;
	time_t t;
#ifdef LARGE_FILE
	off64_t bytes_left;
#else /* LARGE_FILE */
	off_t bytes_left;
#endif /* LARGE_FILE */

	progname = *argv;
	tst_tmpdir();
	if (argc < 2) {
		(void)fprintf(stderr, "usage: %s %s\n", progname, usage);
		exit(1);
	}

	while ((c = getopt(argc, argv, "S:omdlrf:p:t:w:s:")) != -1) {
		switch (c) {
		case 'd':
			debug = 1;
			break;
		case 't':
			alarmtime = atoi(optarg) * 60;
			break;
		case 'p':
			nprocs = atoi(optarg);
			break;
		case 'l':
			leavefile = 1;
			break;
		case 's':
			sleeptime = atoi(optarg);
			if (sleeptime < 0) {
				(void)fprintf(stderr, "error: negative "
					"sleeptime\n");
                	        anyfail();
			}
			break;
		case 'w':
			growsize = atoi(optarg);
			if (growsize < 0) {
				(void)fprintf(stderr, "error: negative write "
					"size\n");
        	                anyfail();
			}
			break;
		case 'f':
#ifdef LARGE_FILE
			filesize = atoll(optarg);
#else /* LARGE_FILE */
			filesize = atoi(optarg);
#endif /* LARGE_FILE */
			if (filesize < 0) {
				(void)fprintf(stderr, "error: negative "
					"filesize\n");
                	        anyfail();
			}
			break;
		case 'r':
			randloops = 1;
			break;
		case 'm':
			dosync = 1;
			break;
		case 'o':
			do_offset = 1;
			break;
		case 'S':
#ifdef LARGE_FILE
			sparseoffset = atoll(optarg);
#else /* LARGE_FILE */
			sparseoffset = atoi(optarg);
#endif /* LARGE_FILE */
			if (sparseoffset % pagesize != 0) {
				fprintf(stderr, 
				   "sparseoffset must be pagesize multiple\n");
        	                anyfail();
			}
			break;
		default:
			(void)fprintf(stderr, "usage: %s %s\n", progname,
				usage);
			anyfail();
		}
	}

	if (nprocs > 255) {
		(void)fprintf(stderr, "invalid nprocs %d - (range 0-255)\n",
			nprocs);
                anyfail();
	}
	(void)time(&t);
	//(void)printf("%s: Started %s", argv[0], ctime(&t)); LTP Port

	(void)sprintf(filename, "%sout.%d", progname, getpid());
	seed = initrand();
	pattern = seed & 0xff;

	if (debug) {
#ifdef LARGE_FILE
		(void)printf("creating file <%s> with %Ld bytes, pattern %d\n", 
			filename, filesize, pattern);
#else /* LARGE_FILE */
		(void)printf("creating file <%s> with %ld bytes, pattern %d\n", 
			filename, filesize, pattern);
#endif /* LARGE_FILE */
		if (alarmtime)
			(void)printf("running for %d minutes\n", alarmtime/60);
		else
			(void)printf("running with no time limit\n");
	}

	/*
	 *  Plan for death by signal.  User may have specified
	 *  a time limit, in which case set an alarm and catch SIGALRM.
	 *  Also catch and cleanup with SIGINT, SIGQUIT, and SIGTERM.
	 */
	sa.sa_handler = finish;
	sa.sa_flags = 0;
	if (sigemptyset(&sa.sa_mask)) {
		perror("sigempty error");
		goto cleanup;
	}

	if (sigaction(SIGINT, &sa, 0) == -1) {
		perror("sigaction error SIGINT");
		goto cleanup;
	}
	if (alarmtime) {
		if (sigaction(SIGALRM, &sa, 0) == -1) {
			perror("sigaction error");
			goto cleanup;
		}
		(void)alarm(alarmtime);
	}
	/* If we get a SIGQUIT or SIGTERM, clean up and exit immediately. */
	sa.sa_handler = clean_up_file;
	if (sigaction(SIGQUIT, &sa, 0) == -1) {
		perror("sigaction error SIGQUIT");
		goto cleanup;
	}
	if (sigaction(SIGTERM, &sa, 0) == -1) {
		perror("sigaction error SIGTERM");
		goto cleanup;
	}

#ifdef LARGE_FILE
	if ((fd = open64(filename, O_CREAT|O_TRUNC|O_RDWR, 0664)) == -1) {
#else /* LARGE_FILE */
	if ((fd = open(filename, O_CREAT|O_TRUNC|O_RDWR, 0664)) == -1) {
#endif /* LARGE_FILE */
		perror("open error");
                anyfail();
	}

	if ((buf = (uchar_t *)malloc(pagesize+growsize)) == NULL
	    || (pidarray = (pid_t *)malloc(nprocs*sizeof(pid_t))) == NULL) {
		perror("malloc error");
                anyfail();
	}

	for (i = 0; i < nprocs; i++)
		*(pidarray+i) = 0;

	for (i = 0, data = 0; i < pagesize; i++) {
		*(buf+i) = (data + pattern) & 0xff;
		if (++data == nprocs)
			data = 0;
	}
	for (data = 0; i < pagesize+growsize; i++) {
		*(buf+i) = (data + pattern) & 0xff;
		if (++data == nprocs)
			data = 0;
	}

#ifdef LARGE_FILE
	if (lseek64(fd, sparseoffset, SEEK_SET) < 0) {
#else /* LARGE_FILE */
	if (lseek(fd, sparseoffset, SEEK_SET) < 0) {
#endif /* LARGE_FILE */
		perror("lseek");
               anyfail();
	}

	for (bytes_left = filesize; bytes_left; bytes_left -= c) {
		write_cnt = min(pagesize, bytes_left);
		if ((c = write(fd, (char *)buf, write_cnt)) != write_cnt) {
			if (c == -1) {
				perror("write error");
			} else {
				(void)fprintf(stderr, "write: wrote %d of %d "
					"bytes\n", c, write_cnt);
			}
			(void)close(fd);
			(void)unlink(filename);
			anyfail();
		}
	}

	(void)close(fd);

	/*
	 *  Fork off mmap children.
	 */
	for (procno = 0; procno < nprocs; procno++) {
		switch (pid = fork()) {

		case -1:
			perror("fork error");
			goto cleanup;

		case 0:
			child_mapper(filename, procno, nprocs);
			exit(0);

		default:
			pidarray[procno] = pid;
		}
	}

	/*
	 *  Now fork off an additional process to continually
	 *  write to (and grow) the file.
	 */
	if ((wr_pid = fork()) == -1) {
		perror("fork error");
		goto cleanup;
	} else if (wr_pid == 0) {	/* child */
		child_writer(filename, buf);
		exit(0);
	}

	/*
	 *  Now wait for children and refork them as needed.
	 */
	
	while (!finished) {
		pid = wait(&wait_stat);
		/*
		 *  Block signals while processing child exit.
		 */

		if (sighold(SIGALRM) || sighold(SIGINT)) {
			perror("sighold error");
			goto cleanup;
		}

		if (pid != -1) {
			/*
			 *  Check exit status, then refork with the
			 *  appropriate procno.
			 */
			if (!WIFEXITED(wait_stat) 
			    || WEXITSTATUS(wait_stat) != 0) {
				(void)fprintf(stderr, "child exit with err "
					"<x%x>\n", wait_stat);
				goto cleanup;
			}
			for (i = 0; i < nprocs; i++)
				if (pid == pidarray[i])
					break;
			if (i == nprocs) {
				if (pid == wr_pid) {
					(void)fprintf(stderr, 
					"writer child unexpected exit <x%x>\n",
						wait_stat);
					wr_pid = 0;
				} else
					(void)fprintf(stderr, "unknown child "
						"pid %d, <x%x>\n",
						pid, wait_stat);
				goto cleanup;
			}

			if ((pid = fork()) == -1) {
				perror("fork error");
				pidarray[i] = 0;
				goto cleanup;
			} else if (pid == 0) {		/* child */
				child_mapper(filename, i, nprocs);
				exit(0);
			} else
				pidarray[i] = pid;
		} else {
			/*
			 *  wait returned an error.  If EINTR, then
			 *  normal finish, else it's an unexpected
			 *  error...
			 */
			if (errno != EINTR || !finished) {
				perror("unexpected wait error");
				goto cleanup;
			}
		}
		if (sigrelse(SIGALRM) || sigrelse(SIGINT)) {
			perror("sigrelse error");
			goto cleanup;
		}
	}
	
	/*
	 *  Finished!  Check the file for sanity, then kill all
	 *  the children and done!.
	 */

	(void)alarm(0);
	no_prob = 1;

cleanup:
	for (i = 0; i < nprocs; i++)
		(void)kill(pidarray[i], SIGKILL);
	(void)kill(wr_pid, SIGKILL);

	while (wait(&wait_stat) != -1 || errno != ECHILD)
		continue;

	if (no_prob) {		/* only check file if no errors */
		if (!fileokay(filename, buf)) {
			(void)fprintf(stderr, "file data incorrect!\n");
			(void)printf("  leaving file <%s>\n", filename);
                        anyfail();

		} else {
			(void)printf("file data okay\n");
			if (!leavefile)
				(void)unlink(filename);
		}
	} else
		(void)printf("  leaving file <%s>\n", filename);
	
	(void)time(&t);
//	(void)printf("%s: Finished %s", argv[0], ctime(&t)); LTP Port
	ok_exit();
	return 0;
}


/*
 *  Child process that reads/writes map.  The child stats the file
 *  to determine the size, maps the size of the file, then reads/writes
 *  its own locations on random pages of the map (its locations being
 *  determined based on nprocs & procno).  After a specific number of
 *  iterations, it exits.
 */
void
child_mapper(char *file, unsigned procno, unsigned nprocs)
{
#ifdef LARGE_FILE
	struct stat64 statbuf;
	off64_t filesize;
	off64_t offset;
#else /* LARGE_FILE */
	struct stat statbuf;
	off_t filesize;
	off_t offset;
#endif /* LARGE_FILE */
	size_t validsize;
	size_t mapsize;
	caddr_t maddr, paddr;
	int fd;
	int pagesize = sysconf(_SC_PAGE_SIZE);
	unsigned randpage;
	unsigned int seed;
	unsigned loopcnt;
	unsigned nloops;
	unsigned mappages; 
	unsigned mapflags;
	unsigned i;

	mapflags = MAP_SHARED;

	seed = initrand();		/* initialize random seed */


#ifdef LARGE_FILE
	if ((fd = open64(file, O_RDWR)) == -1) {
#else /* LARGE_FILE */
	if ((fd = open(file, O_RDWR)) == -1) {
#endif /* LARGE_FILE */
		perror("open error");
                anyfail();
	}

#ifdef LARGE_FILE
	if (fstat64(fd, &statbuf) == -1) {
#else /* LARGE_FILE */
	if (fstat(fd, &statbuf) == -1) {
#endif /* LARGE_FILE */
		perror("stat error");
                anyfail();
	}
	filesize = statbuf.st_size;

	if (statbuf.st_size - sparseoffset > SIZE_MAX) {
		fprintf(stderr, "size_t overflow when setting up map\n");
                anyfail();
	}
	mapsize = (size_t)(statbuf.st_size - sparseoffset);
	mappages = roundup(mapsize, pagesize) / pagesize;
	offset = sparseoffset;
	if (do_offset) {
		int pageoffset = lrand48() % mappages;
		int byteoffset = pageoffset * pagesize;
		offset += byteoffset;
		mapsize -= byteoffset;
		mappages -= pageoffset;
	}

#ifdef LARGE_FILE
	if ((maddr = mmap64(0, mapsize, PROT_READ|PROT_WRITE, 
			mapflags, fd, offset)) == (caddr_t)-1) {
#else /* LARGE_FILE */
	if ((maddr = mmap(0, mapsize, PROT_READ|PROT_WRITE, 
			mapflags, fd, offset)) == (caddr_t)-1) {
#endif /* LARGE_FILE */
		perror("mmap error");
                anyfail();
	}

	(void)close(fd);

	nloops = (randloops) ? (lrand48() % MAXLOOPS) : MAXLOOPS;

	if (debug) {
#ifdef LARGE_FILE
		(void)printf("child %d (pid %ld): seed %d, fsize %Ld, "
			"mapsize %d, off %Ld, loop %d\n",
			procno, getpid(), seed, filesize, mapsize,
			offset/pagesize, nloops);
#else /* LARGE_FILE */
		(void)printf("child %d (pid %d): seed %d, fsize %ld, "
			"mapsize %ld, off %ld, loop %d\n",
			procno, getpid(), seed, filesize, (long)mapsize,
			offset/pagesize, nloops);
#endif /* LARGE_FILE */
	}

	/*
	 *  Now loop read/writing random pages.
	 */
	for (loopcnt = 0; loopcnt < nloops; loopcnt++) {
		randpage = lrand48() % mappages;
		paddr = maddr + (randpage * pagesize);	 /* page address */

		if (randpage < mappages - 1
		    || !(mapsize % pagesize))
			validsize = pagesize;
		else
			validsize = mapsize % pagesize;

		/*
		 * Because one child is mapping file in extend mode,
		 * it may be padded with zeros at end.  So we can't
		 * do an exact check -- accept known pattern OR zeros.
		 */
		for (i = procno; i < validsize; i += nprocs) {
			if (*((unsigned char *)(paddr+i)) 
			    != ((procno + pattern) & 0xff)
			    && *((unsigned char *)(paddr+i)) != 0) {
				(void)fprintf(stderr, "child %d: invalid data "
				"<x%x>", procno, *((unsigned char *)(paddr+i)));
				(void)fprintf(stderr, " at pg %d off %d, exp "
					"<x%x>\n", randpage, i,
					(procno+pattern)&0xff);
                        anyfail();
			}
			/*
			 *  Now write it.
			 */

			*(paddr+i) = (procno + pattern) & 0xff;
		}
	}
	if (dosync) {
		/*
		 * Exercise msync() as well!
		 */
		randpage = lrand48() % mappages;
		paddr = maddr + (randpage * pagesize);	 /* page address */
		if (msync(paddr, (mappages - randpage)*pagesize, 
		    MS_SYNC) == -1) {
			perror("msync error");
                        anyfail();
		}
	}

	exit(0);
}

/*
 *  child_writer
 * 	The child process that continually (and slowly!!) grows
 *	the file.  The purpose of this is to exercise the code
 *	supporting mapping of fragments.  The map children are 
 *	constantly reforking and will pick up the map changes, etc.
 *	This process executes until signalled (i.e. has no exit!)
 *	unless error.	
 */
void
child_writer(char *file, uchar_t *buf)	/* buf already set up in main */
{
	int fd;
#ifdef LARGE_FILE
	struct stat64 statbuf;
	off64_t off;
#else /* LARGE_FILE */
	struct stat statbuf;
	off_t off;
#endif /* LARGE_FILE */
	int pagesize = sysconf(_SC_PAGE_SIZE);
	uchar_t *p;
	int cnt;

#ifdef LARGE_FILE
	if ((fd = open64(file, O_RDWR)) == -1) {
#else /* LARGE_FILE */
	if ((fd = open(file, O_RDWR)) == -1) {
#endif /* LARGE_FILE */
		perror("open error");
                anyfail();
	}

#ifdef LARGE_FILE
	if ((off = lseek64(fd, 0, SEEK_END)) == -1) {
#else /* LARGE_FILE */
	if ((off = lseek(fd, 0, SEEK_END)) == -1) {
#endif /* LARGE_FILE */
		perror("lseek error");
                anyfail();
	}


	for (;;) {
#ifdef LARGE_FILE
		if (fstat64(fd, &statbuf) == -1) {
#else /* LARGE_FILE */
		if (fstat(fd, &statbuf) == -1) {
#endif /* LARGE_FILE */
			perror("fstat error");
                        anyfail();
		}
#ifdef LARGE_FILE
		if (debug)
			(void)printf("writer %d bytes at off %Ld, size %Ld\n", 
				growsize, off, statbuf.st_size); 
#else /* LARGE_FILE */
		if (debug)
			(void)printf("writer %d bytes at off %ld, size %ld\n", 
				growsize, off, statbuf.st_size); 
#endif /* LARGE_FILE */

		/*
		 *  Write some number of bytes, then sleep some
		 *  number of seconds...
		 *  Need to keep track of our offset so write the
		 *  right bytes.
		 */

		p = buf + (off % pagesize);

		if ((cnt = write(fd, p, growsize)) != growsize) {
			if (cnt == -1)
				perror("write error");
			else
				(void)fprintf(stderr, "wrote %d of %d bytes\n",
					cnt, growsize);
                        anyfail();
		}

		off += growsize;

		(void)sleep(sleeptime);
		if (dosync) {
			if (fsync(fd) == -1) {
				perror("fsync error");
                                anyfail();
			}
		}
	}
}


/*
 *  Make sure file has all the correct data.

 */
int
fileokay(char *file, uchar_t *expbuf)
{
#ifdef LARGE_FILE
	struct stat64 statbuf;
#else /* LARGE_FILE */
	struct stat statbuf;
#endif /* LARGE_FILE */
	size_t mapsize;
	uchar_t *readbuf;
	unsigned mappages;
	unsigned pagesize = sysconf(_SC_PAGE_SIZE);
	int fd;
	int cnt;
	unsigned i, j;

#ifdef LARGE_FILE
	if ((fd = open64(file, O_RDONLY)) == -1) {
#else /* LARGE_FILE */
	if ((fd = open(file, O_RDONLY)) == -1) {
#endif /* LARGE_FILE */
		perror("open error");
                anyfail();
	}
#ifdef LARGE_FILE
	if (fstat64(fd, &statbuf) == -1) {
#else /* LARGE_FILE */
	if (fstat(fd, &statbuf) == -1) {
#endif /* LARGE_FILE */
		perror("stat error");
                anyfail();
	}
#ifdef LARGE_FILE
	if (lseek64(fd, sparseoffset, SEEK_SET) < 0) {
#else /* LARGE_FILE */
	if (lseek(fd, sparseoffset, SEEK_SET) < 0) {
#endif /* LARGE_FILE */
		perror("lseek");
		exit(1);
	}

	readbuf = (uchar_t *)malloc(pagesize);

	if (statbuf.st_size - sparseoffset > SIZE_MAX) {
		fprintf(stderr, "size_t overflow when setting up map\n");
		exit(1);
	}
	mapsize = (size_t)(statbuf.st_size - sparseoffset);
	mappages = roundup(mapsize, pagesize) / pagesize;

	for (i = 0; i < mappages; i++) {
		cnt = read(fd, (char *)readbuf, pagesize);
		if (cnt == -1) {
			perror("read error");
			return(0);	
		} else if (cnt != pagesize) {
			/*
			 *  Okay if at last page in file... 
			 */
			if ((i * pagesize) + cnt != mapsize) {
				(void)fprintf(stderr, "read %d of %ld bytes\n",
					(i*pagesize)+cnt, (long)mapsize);
				return(0);
			}
		}
		/*
		 *  Compare read bytes of data.
		 *  May have zeros from map extend...
		 */
		for (j = 0; j < cnt; j++) {
			if (expbuf[j] != readbuf[j] && readbuf[j] != 0) {
				(void)fprintf(stderr, 
					"read bad data: exp %c got %c",
					expbuf[j], readbuf[j]);
#ifdef LARGE_FILE
				(void)fprintf(stderr, ", pg %d off %d, "
					"(fsize %Ld)\n", i, j, statbuf.st_size);
#else /* LARGE_FILE */
				(void)fprintf(stderr, ", pg %d off %d, "
					"(fsize %ld)\n", i, j, statbuf.st_size);
#endif /* LARGE_FILE */
				return(0);
			}
		}
	}
					
	return(1);
}

/*ARGSUSED*/
void
finish(int sig)
{
	finished++;
	/* finish nicely and check the file contents */
}

/*ARGSUSED*/
void
clean_up_file(int sig)
{
	if (!leavefile)
		(void)unlink(filename);
	exit(1);
}

unsigned int
initrand(void)
{
	unsigned int seed;

	/*
	 *  Initialize random seed...  Got this from a test written
	 *  by scooter:
	 *	Use srand/rand to diffuse the information from the
	 *	time and pid.  If you start several processes, then
	 *	the time and pid information don't provide much
	 *	variation.
	 */
	srand((unsigned int)getpid());
	seed = rand();
	srand((unsigned int)time((time_t *)0));
	seed = (seed ^ rand()) % 100000;
	srand48((long int)seed);
	return (seed);
}


/*****  LTP Port        *****/
void ok_exit()
{
        tst_resm(TPASS, "Test passed\n");
	tst_rmdir();
	tst_exit();
}


int anyfail()
{
  tst_resm(TFAIL, "Test failed\n");
  tst_rmdir();
  tst_exit();
  return(0);
}
示例#3
0
文件: directio.c 项目: prashants/c
int main(int argc, char *argv[])
{
	int fd = 0, disk = 0;
	int ret;
	int offset;
	unsigned long c = 0;
	int block_size, block_count, block_num;
	off64_t block_off, seek_ret;
	struct stat64 statinfo;
	struct timeval start_time, end_time;
	char *membuf = NULL;
	unsigned char *buf;

	//unsigned char buf[BLK_SIZE]  __attribute__ ((__aligned__ (BLK_SIZE)));
	//buf = (unsigned char *)memalign(BLK_SIZE, BLK_SIZE);
	//if (!buf) {
	//	fprintf(stderr, "failed to allocate memory\n");
	//	goto err;
	//}

	/* Allocate memory on page boundary */
	ret = posix_memalign((void **)&buf, BLK_SIZE, BLK_SIZE);
	if (ret != 0) {
		fprintf(stderr, "Failed to allocate memory\n");
		goto err;
	}

	if (argc != 3) {
		fprintf(stderr, "Invalid number of arguments\n"
				"Format  : $./directio <partition> <file>\n"
				"Example : $./directio /dev/sda1 ~/test.dump\n");
		goto err;
	}

	/* open partition */
	disk = open(argv[1], O_RDONLY | O_DIRECT | O_LARGEFILE);
	if (disk <= 0) {
		fprintf(stderr, "Cannot open partition %s\n", argv[1]);
		goto err;
	}

	/* open file */
	fd = open(argv[2], O_RDONLY | O_DIRECT | O_LARGEFILE);
	if (fd <= 0) {
		fprintf(stderr, "Cannot open file %s\n", argv[2]);
		goto err;
	}

	/* allocate buffer */
	membuf = malloc(BUF_SIZE);
	if (!membuf) {
		fprintf(stderr, "Failed to allocate memory\n");
		goto err;
	}

	/* get block size */
	if (ioctl(fd, FIGETBSZ, &block_size) < 0) {
		fprintf(stderr, "Failed to get block size\n");
		goto err;
	}

	/* get number of blocks of file */
	if (fstat64(fd, &statinfo) < 0) {
		fprintf(stderr, "Stat failed\n");
		goto err;
	}

	/* calculate number of blocks for the file */
	block_count = (statinfo.st_size + block_size - 1) / block_size;

	fprintf(stdout, "File : %s block_count = %d, block_size = %d\n",
			argv[2], block_count, block_size);

	offset = 0;
	gettimeofday(&start_time, 0);
	for (c = 0; c < block_count; c++) {
		/* get next block number allocated to file */
		block_num = c;
		if (ioctl(fd, FIBMAP, &block_num)) {
			fprintf(stderr, "IOCTL failed\n");
		}

		/* seek to the block directly on disk */
		block_off = (off64_t)block_num * (off64_t)block_size;
		seek_ret = lseek64(disk, block_off, SEEK_SET);
		if (seek_ret < 0) {
			fprintf(stderr, "Seek error at %lu - %lu\n",
					(unsigned long)block_off, (unsigned long)seek_ret);
			goto err;
		}

		/* read the block directly from disk */
		if (read(disk, buf, BLK_SIZE) != BLK_SIZE) {
			fprintf(stderr, "Read error at %lu\n",
					(long)block_off);
			goto err;
		}

		/* copy data to memory buffer of 10 MB */
		memcpy(membuf + offset, buf, BLK_SIZE);
		offset += 4096;
		if (offset >= BUF_SIZE) {
			printf("block_count = %lu / %d\n", c, block_count);
			offset = 0; /* reset buffer when end reached */
		}
	}
	gettimeofday(&end_time, 0);
	fprintf(stdout, "Time taken : %lu\n", end_time.tv_sec - start_time.tv_sec);

	return 0;

err:
	if (membuf)
		free(membuf);
	if (fd > 0)
		close(fd);
	if (disk > 0)
		close(disk);
	if (buf)
		free(buf);

	return -1;
}
bool ObbFile::writeTo(int fd)
{
    if (fd < 0) {
        return false;
    }

    lseek64(fd, 0, SEEK_END);

    if (mPackageName.size() == 0 || mVersion == -1) {
        ALOGW("tried to write uninitialized ObbFile data\n");
        return false;
    }

    unsigned char intBuf[sizeof(uint32_t)+1];
    memset(&intBuf, 0, sizeof(intBuf));

    put4LE(intBuf, kSigVersion);
    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
        ALOGW("couldn't write signature version: %s\n", strerror(errno));
        return false;
    }

    put4LE(intBuf, mVersion);
    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
        ALOGW("couldn't write package version\n");
        return false;
    }

    put4LE(intBuf, mFlags);
    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
        ALOGW("couldn't write package version\n");
        return false;
    }

    if (write(fd, mSalt, sizeof(mSalt)) != (ssize_t)sizeof(mSalt)) {
        ALOGW("couldn't write salt: %s\n", strerror(errno));
        return false;
    }

    size_t packageNameLen = mPackageName.size();
    put4LE(intBuf, packageNameLen);
    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
        ALOGW("couldn't write package name length: %s\n", strerror(errno));
        return false;
    }

    if (write(fd, mPackageName.string(), packageNameLen) != (ssize_t)packageNameLen) {
        ALOGW("couldn't write package name: %s\n", strerror(errno));
        return false;
    }

    put4LE(intBuf, kPackageNameOffset + packageNameLen);
    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
        ALOGW("couldn't write footer size: %s\n", strerror(errno));
        return false;
    }

    put4LE(intBuf, kSignature);
    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
        ALOGW("couldn't write footer magic signature: %s\n", strerror(errno));
        return false;
    }

    return true;
}
示例#5
0
int get_data_from_block (int fp, int fd, unsigned long data_block)
{
  int i = 0;
  unsigned long device_block_number;
/*
static int lg;
char *disp1="\ngiis.........Smile or Sad face?";
char *disp2="                 ";
char disp3[]="|\\-/|\\-/"; 
char disp4[]="               :-";
char disp5[]=")(";
*/



  /* just for fun */

  /* Some graphics output commented because it's affects speedy recovery 
     Removing following comments is not a risky opertions at all. */

/*		system("clear");
		write(0,disp1,strlen(disp1));
		write(0,disp2,strlen(disp2));
		write(0,&disp3[lg],1);
		write(0,disp4,strlen(disp4));
		write(0,&disp5[lg%2],1);
		lg++;
		if(lg==strlen(disp3))
		lg=0;
*/

  fs.block_number = data_block; /* blocks */

  if (fs.block_number != 0)
  {

    /* 
       First thought some big file are unable to recover since they might be using
       fragment blocks.So i let go.Just in final hours i found something you can
       call its as a bug  but for me it's big breakthough.

       Here we just can't go and get blocks sometimes blocks might be scattered around
       the disk.So make sure that you access  data from all groups.
       So Always keep a close eye on block number and it's Group Descriptor

     */

    if (gd == 0)
      i = eye_on_gd ();
    if (i == -1)
    {
      printf ("\n\tAbnormal : Group Descriptor not found ");
      return 0;
    }

    /* Calling eye_on_gd() affect performance so call when it's needed absoultely */

    if (fs.block_number > (fs.block_bitmap + fs.blocks_per_group) ||
        fs.block_number < (fs.block_bitmap))
      i = eye_on_gd ();
    if (i == -1)
    {
      printf ("\n\tAbnormal : Group Descriptor not found %lu", fs.block_number);
      return 0;
    }

    device_block_number =
      ((fs.block_number - 1) % fs.blocks_per_group) +
      fs.group_number * fs.blocks_per_group;
    device_block_number += fs.first_data_block;
    fs.content_offset =
      (unsigned long long) device_block_number *(unsigned long long) fs.block_size;
    fs.content_offset += fs.block_size;
    //set devicefile to appropriate address
    lseek64 (fd, fs.content_offset, 0);

    read_show_file (fd, fp);

    if (fileoverwritten == 444)
    {                           //Check for fileoverwritten ???
      return 0;
    }

    if (size == 0 || fs.block_number == giis_f.info.last_data_block)
    {


      if ((size == 0) && (fs.block_number == giis_f.info.last_data_block)
          && (err_size == giis_f.info.file_size))
      {
        return 0;               /* fine */
      }

      else
      {
        printf ("\n\n\tWarning : %s size differs\n\t", giis_f.info.name);
        printf ("Actual Size(Approx):%lu MB", ((giis_f.info.file_size / 1024) / 1024));
        printf ("\n\tRecovered Only(Approx):%lu MB ", ((err_size / 1024) / 1024));
        return 0;
      }
    }
    return 444;                 /*... nothing special. my lucky number */

  }

  return JSJ_NO_RETURN;
}
static int dump_bml_partition(const MtdPartition* pSrcPart, const MtdPartition* pReservoirPart,
		const unsigned short* blockMapping, const char* filename)
{
	int fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
	if (fd < 0)
	{
		fprintf(stderr, "error opening %s", filename);
		return -1;
	}
	BmlOverMtdReadContext* pSrcRead = bml_over_mtd_read_partition(pSrcPart);
	if (pSrcRead == NULL)
	{
		close(fd);
		fprintf(stderr, "dump_bml_partition: Error opening src part for reading.\n");
		return -1;
	}

	BmlOverMtdReadContext* pResRead = bml_over_mtd_read_partition(pReservoirPart);
	if (pResRead == NULL)
	{
		close(fd);
		bml_over_mtd_read_close(pSrcRead);
		fprintf(stderr, "dump_bml_partition: Error opening reservoir part for reading.\n");
		return -1;
	}


	int numBlocks = pSrcPart->size / pSrcPart->erase_size;
	int currblock = 0;
	for (;currblock < numBlocks; ++currblock)
	{
		int srcFd = -1;
		if (blockMapping[currblock] == 0xffff)
		{
			//Good block, use src partition
			srcFd = pSrcRead->fd;
			if (lseek64(pSrcRead->fd, currblock*pSrcPart->erase_size, SEEK_SET)==-1)
			{
				close(fd);
				bml_over_mtd_read_close(pSrcRead);
				bml_over_mtd_read_close(pResRead);
				fprintf(stderr, "dump_bml_partition: lseek in src partition failed\n");
				return -1;
			}
		} else
		{
			//Bad block, use mapped block in reservoir partition
			srcFd = pResRead->fd;
			if (lseek64(pResRead->fd, blockMapping[currblock]*pSrcPart->erase_size, SEEK_SET)==-1)
			{
				close(fd);
				bml_over_mtd_read_close(pSrcRead);
				bml_over_mtd_read_close(pResRead);
				fprintf(stderr, "dump_bml_partition: lseek in reservoir partition failed\n");
				return -1;
			}
		}
		size_t blockBytesRead = 0;
		while (blockBytesRead < pSrcPart->erase_size)
		{
			ssize_t len = read(srcFd, pSrcRead->buffer + blockBytesRead,
					pSrcPart->erase_size - blockBytesRead);
			if (len <= 0)
			{
				close(fd);
				bml_over_mtd_read_close(pSrcRead);
				bml_over_mtd_read_close(pResRead);
				fprintf(stderr, "dump_bml_partition: reading partition failed\n");
				return -1;
			}
			blockBytesRead += len;
		}

		size_t blockBytesWritten = 0;
		while (blockBytesWritten < pSrcPart->erase_size)
		{
			ssize_t len = write(fd, pSrcRead->buffer + blockBytesWritten,
					pSrcPart->erase_size - blockBytesWritten);
			if (len <= 0)
			{
				close(fd);
				bml_over_mtd_read_close(pSrcRead);
				bml_over_mtd_read_close(pResRead);
				fprintf(stderr, "dump_bml_partition: writing partition dump file failed\n");
				return -1;
			}
			blockBytesWritten += len;
		}

	}

	bml_over_mtd_read_close(pSrcRead);
	bml_over_mtd_read_close(pResRead);

	if (close(fd)) {
		unlink(filename);
		printf("error closing %s", filename);
		return -1;
	}

	return 0;
}
//-------------------------------------------------------------------------
int find_start_point_dr2(int tape_fd, int beam, int pol) {
//-------------------------------------------------------------------------
  char buf[1024];

  // In early tapes there was a bug where the first N blocks would be duplicates
  // of data from previous files.  So we do a preemptive fast forward until we see a
  // frame sequence number of 1.
  int i,readbytes=HeaderSize;
  dataheader_t header;
  header.frameseq=100000;

  while ((readbytes==HeaderSize) && (header.frameseq>10)) {
    char buffer[HeaderSize];
    int nread;
    readbytes=0;
    while ((readbytes!=HeaderSize) && (nread = read(tape_fd,buffer,HeaderSize-readbytes))) { 
	    readbytes+=nread;
    }
    if (nread < 0) {
	log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"File error %d.\n", errno);
	exit(1);
    }
    if (readbytes == HeaderSize) {
      header.populate_from_data(buffer);
      if (header.frameseq>10) {
        lseek64(tape_fd,DataSize,SEEK_CUR);
      } else {
        lseek64(tape_fd,-1*(off64_t)HeaderSize,SEEK_CUR);
      }
    }
  }

  if (readbytes != HeaderSize) {
    // we fast forwarded through the entire tape without finding the first frame
    // maybe this is one of the really early tapes that was split into chunks.
    lseek64(tape_fd,0,SEEK_SET);
    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Warning: First block not found\n");
  }
  // End preemptive fast forward

  // Optionally fast forward to the point of resumption
  if (resumetape) {
    tape thistape;
    thistape.id=0; 
    readbytes=HeaderSize;
    sprintf(buf,"%d",rcvr.s4_id-AO_ALFA_0_0);
    if (thistape.fetch(std::string("where name=\'")+header.name+"\' and beam="+buf)) {
      log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG,"Resuming tape %s beam %d pol %d\n",thistape.name,beam,pol );
      while ((readbytes==HeaderSize) && (header.dataseq!=thistape.last_block_done)) {
        int nread=0;
        char buffer[HeaderSize];
        readbytes=0;
        while ((readbytes!=HeaderSize) &&
	      ((nread = read(tape_fd,buffer,HeaderSize-readbytes)) > 0 )) {
	    readbytes+=nread;
        }
        if (readbytes == HeaderSize) {
          header.populate_from_data(buffer);
          if (header.dataseq!=thistape.last_block_done) {
            lseek64(tape_fd,(off64_t)(DataSize+HeaderSize)*(thistape.last_block_done-header.dataseq)-HeaderSize,SEEK_CUR);
          } else {
            lseek64(tape_fd,-1*(off_t)HeaderSize,SEEK_CUR);
            log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Found starting point");
          }
	}
	if (nread == 0) {
	  log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"End of file.\n");
	  exit(0);
        }
        if (nread < 0) {
	  log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"File error %d.\n",errno);
	  exit(1);
	}
      }
    }
  }
  // End fast forward to the point of resumption
 
  return 0;
}
示例#8
0
void
do_sync_io(th_arg_t *th_arg, int *fd_list)
{
    struct timeval       start_tv;
    struct timeval       timer;
    meter_t             *meter;
    struct drand48_data  rand;
    int64_t              addr;
    void                *buf;
    int                  i;

    int file_idx;
    int64_t *ofst_list;
    int64_t *ofst_min_list;
    int64_t *ofst_max_list;

    meter = th_arg->meter;
    srand48_r(th_arg->common_seed ^ th_arg->tid, &rand);

    register double iowait_time = 0;
    register int64_t io_count = 0;

    buf = memalign(option.blk_sz, option.blk_sz);

    // offset handling
    ofst_list = malloc(sizeof(int64_t) * option.nr_files);
    ofst_min_list = malloc(sizeof(int64_t) * option.nr_files);
    ofst_max_list = malloc(sizeof(int64_t) * option.nr_files);

    for (i = 0; i < option.nr_files; i++) {
        if (option.ofst_start >= 0) {
            ofst_min_list[i] = option.ofst_start;
        } else {
            ofst_min_list[i] = 0;
        }

        if (option.ofst_end >= 0) {
            ofst_max_list[i] = option.ofst_end;
        } else {
            ofst_max_list[i] = option.file_size_list[i] / option.blk_sz;
        }

        if (option.seq) {
            ofst_list[i] = ofst_min_list[i]
                + (ofst_max_list[i] - ofst_min_list[i]) * th_arg->id / option.multi;
        } else {
            ofst_list[i] = ofst_min_list[i];
        }
    }

    file_idx = 0;

    GETTIMEOFDAY(&start_tv);
    if (option.rand){
        while (mb_elapsed_time_from(&start_tv) < option.timeout) {
            for(i = 0;i < 100; i++){
                // select file
                long ret;
                lrand48_r(&rand, &ret);
                file_idx = ret % option.nr_files;

                ofst_list[file_idx] = (int64_t) mb_rand_range_long(&rand,
                                                                   ofst_min_list[file_idx],
                                                                   ofst_max_list[file_idx]);

                addr = ofst_list[file_idx] * option.blk_sz + option.misalign;

                GETTIMEOFDAY(&timer);
                if (mb_read_or_write() == MB_DO_READ) {
                    mb_preadall(fd_list[file_idx], buf, option.blk_sz, addr, option.continue_on_error);
                } else {
                    mb_pwriteall(fd_list[file_idx], buf, option.blk_sz, addr, option.continue_on_error);
                }
                iowait_time += mb_elapsed_time_from(&timer);
                io_count ++;

                long idx;
                volatile double dummy = 0.0;
                for(idx = 0; idx < option.bogus_comp; idx++){
                    dummy += idx;
                }
            }
        }
    } else if (option.seq) {
        while (mb_elapsed_time_from(&start_tv) < option.timeout) {
            for(i = 0;i < 100; i++){
                // select file
                file_idx++;
                file_idx %= option.nr_files;

                // incr offset
                ofst_list[file_idx]++;
                if (ofst_list[file_idx] >= ofst_max_list[file_idx]) {
                    ofst_list[file_idx] = ofst_min_list[file_idx];
                }
                addr = ofst_list[file_idx] * option.blk_sz + option.misalign;
                if (lseek64(fd_list[file_idx], addr, SEEK_SET) == -1){
                    perror("do_sync_io:lseek64");
                    exit(EXIT_FAILURE);
                }

                GETTIMEOFDAY(&timer);
                if (option.read) {
                    mb_readall(fd_list[file_idx], buf, option.blk_sz, option.continue_on_error);
                } else if (option.write) {
                    mb_writeall(fd_list[file_idx], buf, option.blk_sz, option.continue_on_error);
                } else {
                    fprintf(stderr, "Only read or write can be specified in seq.");
                    exit(EXIT_FAILURE);
                }
                iowait_time += mb_elapsed_time_from(&timer);
                io_count ++;

                long idx;
                volatile double dummy = 0.0;
                for(idx = 0; idx < option.bogus_comp; idx++){
                    dummy += idx;
                }
            }
        }
    }

    meter->iowait_time = iowait_time;
    meter->count = io_count;

    free(buf);
}
示例#9
0
//called from the frame queue controller to get frame data for display
VideoData* YUVReader::pullFrame(int frameNumber)
{
  if (DEBUG)
    printf("Getting frame number %d\n", frameNumber);

  //deal with frame number wrapping
  if (frameNumber < 0)
  {
    frameNumber *= -1;
    frameNumber %= (lastFrameNum + 1);
    frameNumber = lastFrameNum - frameNumber;
  }

  if (frameNumber > lastFrameNum)
    frameNumber %= (lastFrameNum + 1);

  /* allocate new storage:
   *  1) work out dimensions for the planes
   *  2) create contiguous storage (we already know the frame_size)
   *  3) create aliases for any other planes
   */
  VideoData* frame = new VideoData();
  frame->data.packing_format = packing_format;
  frame->data.chroma_format = chroma_format;
  setPlaneDimensions(*(PictureData<void>*) &frame->data, packing_format,
      chroma_format, videoWidth, videoHeight);

  frame->data.plane[0].data = std::shared_ptr<DataPtr>(
      new DataPtr_valloc(frame_size));
  void* const data = frame->data.plane[0].data->ptr;
  uint8_t* ptr = (uint8_t*) data;
  for (unsigned i = 1; i < frame->data.plane.size(); i++)
  {
    ptr += frame->data.plane[i - 1].length;
    frame->data.plane[i].data = std::shared_ptr<DataPtr>(new DataPtr_alias(ptr));
  }
  /* xxx: fixup plane numbering if required (eg YV12 vs I420) */

  //set frame number and first/last flags
  frame->frame_number = frameNumber;
  frame->is_first_frame = (frameNumber == firstFrameNum);
  frame->is_last_frame = (frameNumber == lastFrameNum);
  frame->is_interlaced = interlacedSource;

  frame->sample_aspect_ratio_numerator = sample_aspect_ratio_numerator;
  frame->sample_aspect_ratio_denominator = sample_aspect_ratio_denominator;
  frame->data.sar = (float) sample_aspect_ratio_numerator
      / (float) sample_aspect_ratio_denominator;

  //seek to requested frame
  off64_t offset = (off64_t) frame_size * (off64_t) frameNumber;
  off64_t sret = lseek64(fd, offset, SEEK_SET);
  if (!sret && offset != 0)
    perror("LSEEK");

  QTime timer;
  timer.restart();

  for (unsigned done = 0; done < frame_size;)
  {
    int len = read(fd, (uint8_t*) data + done, frame_size - done);
    if (len <= 0)
    {
      std::stringstream ss;
      ss << "read() @ frame" << frameNumber << "(" << offset << "+" << done
          << " of " << frame_size << ")";
      perror(ss.str().c_str());
      break;
    }
    done += len;
  }

  if (bit_shift > 0)
  {
    shiftPlanar16PixelData(frame->data, bit_shift);
  }

  Stats::Section& stats = Stats::getSection("YUV Reader");
  addStat(stats, "Read", timer.elapsed(), "ms");
  addStat(stats, "VideoWidth", videoWidth);
  addStat(stats, "VideoHeight", videoHeight);
  addStat(stats, "FirstFrame", firstFrameNum);
  addStat(stats, "LastFrame", lastFrameNum);
  addStat(stats, "VideoFormat", fileType.toLatin1().data());

  return frame;
}
示例#10
0
int test_stripes(int *source, unsigned long long *offsets,
		 int raid_disks, int chunk_size, int level, int layout,
		 unsigned long long start, unsigned long long length)
{
	/* ready the data and p (and q) blocks, and check we got them right */
	char *stripe_buf = xmalloc(raid_disks * chunk_size);
	char **stripes = xmalloc(raid_disks * sizeof(char*));
	char **blocks = xmalloc(raid_disks * sizeof(char*));
	char *p = xmalloc(chunk_size);
	char *q = xmalloc(chunk_size);

	int i;
	int diskP, diskQ;
	int data_disks = raid_disks - (level == 5 ? 1: 2);

	if (!tables_ready)
		make_tables();

	for ( i = 0 ; i < raid_disks ; i++)
		stripes[i] = stripe_buf + i * chunk_size;

	while (length > 0) {
		int disk;

		for (i = 0 ; i < raid_disks ; i++) {
			lseek64(source[i], offsets[i]+start, 0);
			read(source[i], stripes[i], chunk_size);
		}
		for (i = 0 ; i < data_disks ; i++) {
			int disk = geo_map(i, start/chunk_size, raid_disks,
					   level, layout);
			blocks[i] = stripes[disk];
			printf("%d->%d\n", i, disk);
		}
		switch(level) {
		case 6:
			qsyndrome(p, q, (uint8_t**)blocks, data_disks, chunk_size);
			diskP = geo_map(-1, start/chunk_size, raid_disks,
				       level, layout);
			if (memcmp(p, stripes[diskP], chunk_size) != 0) {
				printf("P(%d) wrong at %llu\n", diskP,
				       start / chunk_size);
			}
			diskQ = geo_map(-2, start/chunk_size, raid_disks,
				       level, layout);
			if (memcmp(q, stripes[diskQ], chunk_size) != 0) {
				printf("Q(%d) wrong at %llu\n", diskQ,
				       start / chunk_size);
			}
			disk = raid6_check_disks(data_disks, start, chunk_size,
						 level, layout, diskP, diskQ,
						 p, q, stripes);
			if(disk >= 0) {
			  printf("Possible failed disk: %d\n", disk);
			}
			if(disk == -2) {
			  printf("Failure detected, but disk unknown\n");
			}
			break;
		}
		length -= chunk_size;
		start += chunk_size;
	}
	return 0;
}
示例#11
0
long long FileRingBuffer::Seek(long long pos, int whence, bool has_lock)
{
    LOG(VB_FILE, LOG_INFO, LOC + QString("Seek(%1,%2,%3)")
            .arg(pos).arg((SEEK_SET==whence)?"SEEK_SET":
                          ((SEEK_CUR==whence)?"SEEK_CUR":"SEEK_END"))
            .arg(has_lock?"locked":"unlocked"));

    long long ret = -1;

    StopReads();

    // lockForWrite takes priority over lockForRead, so this will
    // take priority over the lockForRead in the read ahead thread.
    if (!has_lock)
        rwlock.lockForWrite();

    StartReads();

    if (writemode)
    {
        ret = WriterSeek(pos, whence, true);
        if (!has_lock)
            rwlock.unlock();
        return ret;
    }

    poslock.lockForWrite();

    // Optimize no-op seeks
    if (readaheadrunning &&
        ((whence == SEEK_SET && pos == readpos) ||
         (whence == SEEK_CUR && pos == 0)))
    {
        ret = readpos;

        poslock.unlock();
        if (!has_lock)
            rwlock.unlock();

        return ret;
    }

    // only valid for SEEK_SET & SEEK_CUR
    long long new_pos = (SEEK_SET==whence) ? pos : readpos + pos;

#if 1
    // Optimize short seeks where the data for
    // them is in our ringbuffer already.
    if (readaheadrunning &&
        (SEEK_SET==whence || SEEK_CUR==whence))
    {
        rbrlock.lockForWrite();
        rbwlock.lockForRead();
        LOG(VB_FILE, LOG_INFO, LOC +
            QString("Seek(): rbrpos: %1 rbwpos: %2"
                    "\n\t\t\treadpos: %3 internalreadpos: %4")
                .arg(rbrpos).arg(rbwpos)
                .arg(readpos).arg(internalreadpos));
        bool used_opt = false;
        if ((new_pos < readpos))
        {
            int min_safety = max(fill_min, readblocksize);
            int free = ((rbwpos >= rbrpos) ?
                        rbrpos + bufferSize : rbrpos) - rbwpos;
            int internal_backbuf =
                (rbwpos >= rbrpos) ? rbrpos : rbrpos - rbwpos;
            internal_backbuf = min(internal_backbuf, free - min_safety);
            long long sba = readpos - new_pos;
            LOG(VB_FILE, LOG_INFO, LOC +
                QString("Seek(): internal_backbuf: %1 sba: %2")
                    .arg(internal_backbuf).arg(sba));
            if (internal_backbuf >= sba)
            {
                rbrpos = (rbrpos>=sba) ? rbrpos - sba :
                    bufferSize + rbrpos - sba;
                used_opt = true;
                LOG(VB_FILE, LOG_INFO, LOC +
                    QString("Seek(): OPT1 rbrpos: %1 rbwpos: %2"
                                "\n\t\t\treadpos: %3 internalreadpos: %4")
                        .arg(rbrpos).arg(rbwpos)
                        .arg(new_pos).arg(internalreadpos));
            }
        }
        else if ((new_pos >= readpos) && (new_pos <= internalreadpos))
        {
            rbrpos = (rbrpos + (new_pos - readpos)) % bufferSize;
            used_opt = true;
            LOG(VB_FILE, LOG_INFO, LOC +
                QString("Seek(): OPT2 rbrpos: %1 sba: %2")
                    .arg(rbrpos).arg(readpos - new_pos));
        }
        rbwlock.unlock();
        rbrlock.unlock();

        if (used_opt)
        {
            if (ignorereadpos >= 0)
            {
                // seek should always succeed since we were at this position
                int ret;
                if (remotefile)
                    ret = remotefile->Seek(internalreadpos, SEEK_SET);
                else
                {
                    ret = lseek64(fd2, internalreadpos, SEEK_SET);
                    posix_fadvise(fd2, internalreadpos,
                                  128*1024, POSIX_FADV_WILLNEED);
                }
                LOG(VB_FILE, LOG_INFO, LOC +
                    QString("Seek to %1 from ignore pos %2 returned %3")
                        .arg(internalreadpos).arg(ignorereadpos).arg(ret));
                ignorereadpos = -1;
            }
            readpos = new_pos;
            poslock.unlock();
            generalWait.wakeAll();
            ateof = false;
            readsallowed = false;
            if (!has_lock)
                rwlock.unlock();
            return new_pos;
        }
    }
#endif

#if 1
    // This optimizes the seek end-250000, read, seek 0, read portion 
    // of the pattern ffmpeg performs at the start of playback to
    // determine the pts.
    // If the seek is a SEEK_END or is a seek where the position
    // changes over 100 MB we check the file size and if the
    // destination point is within 300000 bytes of the end of
    // the file we enter a special mode where the read ahead
    // buffer stops reading data and all reads are made directly
    // until another seek is performed. The point of all this is
    // to avoid flushing out the buffer that still contains all
    // the data the final seek 0, read will need just to read the
    // last 250000 bytes. A further optimization would be to buffer
    // the 250000 byte read, which is currently performed in 32KB
    // blocks (inefficient with RemoteFile).
    if ((remotefile || fd2 >= 0) && (ignorereadpos < 0))
    {
        long long off_end = 0xDEADBEEF;
        if (SEEK_END == whence)
        {
            off_end = pos;
            if (remotefile)
            {
                new_pos = remotefile->GetFileSize() - off_end;
            }
            else
            {
                QFileInfo fi(filename);
                new_pos = fi.size() - off_end;
            }
        }
        else
        {
            if (remotefile)
            {
                off_end = remotefile->GetFileSize() - new_pos;
            }
            else
            {
                QFileInfo fi(filename);
                off_end = fi.size() - new_pos;
            }
        }

        if (off_end != 0xDEADBEEF)
        {
            LOG(VB_FILE, LOG_INFO, LOC +
                QString("Seek(): Offset from end: %1").arg(off_end));
        }

        if (off_end == 250000)
        {
            LOG(VB_FILE, LOG_INFO, LOC +
                QString("Seek(): offset from end: %1").arg(off_end) +
                "\n\t\t\t -- ignoring read ahead thread until next seek.");

            ignorereadpos = new_pos;
            errno = EINVAL;
            long long ret;
            if (remotefile)
                ret = remotefile->Seek(ignorereadpos, SEEK_SET);
            else
                ret = lseek64(fd2, ignorereadpos, SEEK_SET);

            if (ret < 0)
            {
                int tmp_eno = errno;
                QString cmd = QString("Seek(%1, SEEK_SET) ign ")
                    .arg(ignorereadpos);

                ignorereadpos = -1;

                LOG(VB_GENERAL, LOG_ERR, LOC + cmd + " Failed" + ENO);

                // try to return to former position..
                if (remotefile)
                    ret = remotefile->Seek(internalreadpos, SEEK_SET);
                else
                    ret = lseek64(fd2, internalreadpos, SEEK_SET);
                if (ret < 0)
                {
                    QString cmd = QString("Seek(%1, SEEK_SET) int ")
                        .arg(internalreadpos);
                    LOG(VB_GENERAL, LOG_ERR, LOC + cmd + " Failed" + ENO);
                }
                else
                {
                    QString cmd = QString("Seek(%1, %2) int ")
                        .arg(internalreadpos)
                        .arg((SEEK_SET == whence) ? "SEEK_SET" :
                             ((SEEK_CUR == whence) ?"SEEK_CUR" : "SEEK_END"));
                    LOG(VB_GENERAL, LOG_ERR, LOC + cmd + " succeeded");
                }
                ret = -1;
                errno = tmp_eno;
            }
            else
            {
                ateof = false;
                readsallowed = false;
            }

            poslock.unlock();

            generalWait.wakeAll();

            if (!has_lock)
                rwlock.unlock();

            return ret;
        }
    }
#endif

    // Here we perform a normal seek. When successful we
    // need to call ResetReadAhead(). A reset means we will
    // need to refill the buffer, which takes some time.
    if (remotefile)
    {
        ret = remotefile->Seek(pos, whence, readpos);
        if (ret<0)
            errno = EINVAL;
    }
    else
    {
        ret = lseek64(fd2, pos, whence);
    }

    if (ret >= 0)
    {
        readpos = ret;
        
        ignorereadpos = -1;

        if (readaheadrunning)
            ResetReadAhead(readpos);

        readAdjust = 0;
    }
    else
    {
        QString cmd = QString("Seek(%1, %2)").arg(pos)
            .arg((whence == SEEK_SET) ? "SEEK_SET" :
                 ((whence == SEEK_CUR) ? "SEEK_CUR" : "SEEK_END"));
        LOG(VB_GENERAL, LOG_ERR, LOC + cmd + " Failed" + ENO);
    }

    poslock.unlock();

    generalWait.wakeAll();

    if (!has_lock)
        rwlock.unlock();

    return ret;
}
示例#12
0
/* Restore data:
 * We are given:
 *  A list of 'fds' of the active disks. Some may be '-1' for not-available.
 *  A geometry: raid_disks, chunk_size, level, layout
 *  An 'fd' to read from.  It is already seeked to the right (Read) location.
 *  A start and length.
 * The length must be a multiple of the stripe size.
 *
 * We build a full stripe in memory and then write it out.
 * We assume that there are enough working devices.
 */
int restore_stripes(int *dest, unsigned long long *offsets,
		    int raid_disks, int chunk_size, int level, int layout,
		    int source, unsigned long long read_offset,
		    unsigned long long start, unsigned long long length,
		    char *src_buf)
{
	char *stripe_buf;
	char **stripes = xmalloc(raid_disks * sizeof(char*));
	char **blocks = xmalloc(raid_disks * sizeof(char*));
	int i;
	int rv;

	int data_disks = raid_disks - (level == 0 ? 0 : level <= 5 ? 1 : 2);

	if (posix_memalign((void**)&stripe_buf, 4096, raid_disks * chunk_size))
		stripe_buf = NULL;

	if (zero == NULL || chunk_size > zero_size) {
		if (zero)
			free(zero);
		zero = xcalloc(1, chunk_size);
		zero_size = chunk_size;
	}

	if (stripe_buf == NULL || stripes == NULL || blocks == NULL
	    || zero == NULL) {
		rv = -2;
		goto abort;
	}
	for (i = 0; i < raid_disks; i++)
		stripes[i] = stripe_buf + i * chunk_size;
	while (length > 0) {
		unsigned int len = data_disks * chunk_size;
		unsigned long long offset;
		int disk, qdisk;
		int syndrome_disks;
		if (length < len) {
			rv = -3;
			goto abort;
		}
		for (i = 0; i < data_disks; i++) {
			int disk = geo_map(i, start/chunk_size/data_disks,
					   raid_disks, level, layout);
			if (src_buf == NULL) {
				/* read from file */
				if (lseek64(source, read_offset, 0) !=
					 (off64_t)read_offset) {
					rv = -1;
					goto abort;
				}
				if (read(source,
					 stripes[disk],
					 chunk_size) != chunk_size) {
					rv = -1;
					goto abort;
				}
			} else {
				/* read from input buffer */
				memcpy(stripes[disk],
				       src_buf + read_offset,
				       chunk_size);
			}
			read_offset += chunk_size;
		}
		/* We have the data, now do the parity */
		offset = (start/chunk_size/data_disks) * chunk_size;
		switch (level) {
		case 4:
		case 5:
			disk = geo_map(-1, start/chunk_size/data_disks,
					   raid_disks, level, layout);
			for (i = 0; i < data_disks; i++)
				blocks[i] = stripes[(disk+1+i) % raid_disks];
			xor_blocks(stripes[disk], blocks, data_disks, chunk_size);
			break;
		case 6:
			disk = geo_map(-1, start/chunk_size/data_disks,
				       raid_disks, level, layout);
			qdisk = geo_map(-2, start/chunk_size/data_disks,
				       raid_disks, level, layout);
			if (is_ddf(layout)) {
				/* q over 'raid_disks' blocks, in device order.
				 * 'p' and 'q' get to be all zero
				 */
				for (i = 0; i < raid_disks; i++)
					if (i == disk || i == qdisk)
						blocks[i] = (char*)zero;
					else
						blocks[i] = stripes[i];
				syndrome_disks = raid_disks;
			} else {
				/* for md, q is over 'data_disks' blocks,
				 * starting immediately after 'q'
				 */
				for (i = 0; i < data_disks; i++)
					blocks[i] = stripes[(qdisk+1+i) % raid_disks];

				syndrome_disks = data_disks;
			}
			qsyndrome((uint8_t*)stripes[disk],
				  (uint8_t*)stripes[qdisk],
				  (uint8_t**)blocks,
				  syndrome_disks, chunk_size);
			break;
		}
		for (i=0; i < raid_disks ; i++)
			if (dest[i] >= 0) {
				if (lseek64(dest[i],
					 offsets[i]+offset, 0) < 0) {
					rv = -1;
					goto abort;
				}
				if (write(dest[i], stripes[i],
					 chunk_size) != chunk_size) {
					rv = -1;
					goto abort;
				}
			}
		length -= len;
		start += len;
	}
	rv = 0;

abort:
	free(stripe_buf);
	free(stripes);
	free(blocks);
	return rv;
}
示例#13
0
/*******************************************************************************
 * Function:	save_stripes
 * Description:
 *	Function reads data (only data without P and Q) from array and writes
 * it to buf and opcjonaly to backup files
 * Parameters:
 *	source		: A list of 'fds' of the active disks.
 *			  Some may be absent
 *	offsets		: A list of offsets on disk belonging
 *			 to the array [bytes]
 *	raid_disks	: geometry: number of disks in the array
 *	chunk_size	: geometry: chunk size [bytes]
 *	level		: geometry: RAID level
 *	layout		: geometry: layout
 *	nwrites		: number of backup files
 *	dest		: A list of 'fds' for mirrored targets
 *			  (e.g. backup files). They are already seeked to right
 *			  (write) location. If NULL, data will be wrote
 *			  to the buf only
 *	start		: start address of data to read (must be stripe-aligned)
 *			  [bytes]
 *	length	-	: length of data to read (must be stripe-aligned)
 *			  [bytes]
 *	buf		: buffer for data. It is large enough to hold
 *			  one stripe. It is stripe aligned
 * Returns:
 *	 0 : success
 *	-1 : fail
 ******************************************************************************/
int save_stripes(int *source, unsigned long long *offsets,
		 int raid_disks, int chunk_size, int level, int layout,
		 int nwrites, int *dest,
		 unsigned long long start, unsigned long long length,
		 char *buf)
{
	int len;
	int data_disks = raid_disks - (level == 0 ? 0 : level <=5 ? 1 : 2);
	int disk;
	int i;
	unsigned long long length_test;

	if (!tables_ready)
		make_tables();
	ensure_zero_has_size(chunk_size);

	len = data_disks * chunk_size;
	length_test = length / len;
	length_test *= len;

	if (length != length_test) {
		dprintf("Error: save_stripes(): Data are not alligned. EXIT\n");
		dprintf("\tArea for saving stripes (length) = %llu\n", length);
		dprintf("\tWork step (len)                  = %i\n", len);
		dprintf("\tExpected save area (length_test) = %llu\n",
			length_test);
		abort();
	}

	while (length > 0) {
		int failed = 0;
		int fdisk[3], fblock[3];
		for (disk = 0; disk < raid_disks ; disk++) {
			unsigned long long offset;
			int dnum;

			offset = (start/chunk_size/data_disks)*chunk_size;
			dnum = geo_map(disk < data_disks ? disk : data_disks - disk - 1,
				       start/chunk_size/data_disks,
				       raid_disks, level, layout);
			if (dnum < 0) abort();
			if (source[dnum] < 0 ||
			    lseek64(source[dnum], offsets[dnum]+offset, 0) < 0 ||
			    read(source[dnum], buf+disk * chunk_size, chunk_size)
			    != chunk_size)
				if (failed <= 2) {
					fdisk[failed] = dnum;
					fblock[failed] = disk;
					failed++;
				}
		}
		if (failed == 0 || fblock[0] >= data_disks)
			/* all data disks are good */
			;
		else if (failed == 1 || fblock[1] >= data_disks+1) {
			/* one failed data disk and good parity */
			char *bufs[data_disks];
			for (i=0; i < data_disks; i++)
				if (fblock[0] == i)
					bufs[i] = buf + data_disks*chunk_size;
				else
					bufs[i] = buf + i*chunk_size;

			xor_blocks(buf + fblock[0]*chunk_size,
				   bufs, data_disks, chunk_size);
		} else if (failed > 2 || level != 6)
			/* too much failure */
			return -1;
		else {
			/* RAID6 computations needed. */
			uint8_t *bufs[data_disks+4];
			int qdisk;
			int syndrome_disks;
			disk = geo_map(-1, start/chunk_size/data_disks,
				       raid_disks, level, layout);
			qdisk = geo_map(-2, start/chunk_size/data_disks,
				       raid_disks, level, layout);
			if (is_ddf(layout)) {
				/* q over 'raid_disks' blocks, in device order.
				 * 'p' and 'q' get to be all zero
				 */
				for (i = 0; i < raid_disks; i++)
					bufs[i] = zero;
				for (i = 0; i < data_disks; i++) {
					int dnum = geo_map(i,
							   start/chunk_size/data_disks,
							   raid_disks, level, layout);
					int snum;
					/* i is the logical block number, so is index to 'buf'.
					 * dnum is physical disk number
					 * and thus the syndrome number.
					 */
					snum = dnum;
					bufs[snum] = (uint8_t*)buf + chunk_size * i;
				}
				syndrome_disks = raid_disks;
			} else {
				/* for md, q is over 'data_disks' blocks,
				 * starting immediately after 'q'
				 * Note that for the '_6' variety, the p block
				 * makes a hole that we need to be careful of.
				 */
				int j;
				int snum = 0;
				for (j = 0; j < raid_disks; j++) {
					int dnum = (qdisk + 1 + j) % raid_disks;
					if (dnum == disk || dnum == qdisk)
						continue;
					for (i = 0; i < data_disks; i++)
						if (geo_map(i,
							    start/chunk_size/data_disks,
							    raid_disks, level, layout) == dnum)
							break;
					/* i is the logical block number, so is index to 'buf'.
					 * dnum is physical disk number
					 * snum is syndrome disk for which 0 is immediately after Q
					 */
					bufs[snum] = (uint8_t*)buf + chunk_size * i;

					if (fblock[0] == i)
						fdisk[0] = snum;
					if (fblock[1] == i)
						fdisk[1] = snum;
					snum++;
				}

				syndrome_disks = data_disks;
			}

			/* Place P and Q blocks at end of bufs */
			bufs[syndrome_disks] = (uint8_t*)buf + chunk_size * data_disks;
			bufs[syndrome_disks+1] = (uint8_t*)buf + chunk_size * (data_disks+1);

			if (fblock[1] == data_disks)
				/* One data failed, and parity failed */
				raid6_datap_recov(syndrome_disks+2, chunk_size,
						  fdisk[0], bufs);
			else {
				if (fdisk[0] > fdisk[1]) {
					int t = fdisk[0];
					fdisk[0] = fdisk[1];
					fdisk[1] = t;
				}
				/* Two data blocks failed, P,Q OK */
				raid6_2data_recov(syndrome_disks+2, chunk_size,
						  fdisk[0], fdisk[1], bufs);
			}
		}
		if (dest) {
			for (i = 0; i < nwrites; i++)
				if (write(dest[i], buf, len) != len)
					return -1;
		} else {
			/* build next stripe in buffer */
			buf += len;
		}
		length -= len;
		start += len;
	}
	return 0;
}
示例#14
0
int nandread_main(int argc, char **argv)
{
    char *devname = NULL;
    char *filename = NULL;
    char *statusfilename = NULL;
    char *statusext = ".stat";
    int fd;
    int outfd = -1;
    FILE *statusfile = NULL;
    int ret;
    int verbose = 0;
    void *buffer;
    loff_t pos, opos, end, bpos;
    loff_t start = 0, len = 0;
    int c;
    int i;
    int empty_pages = 0;
    int page_count = 0;
    int bad_block;
    int rawmode = 0;
    uint32_t *oob_data;
    uint8_t *oob_fixed;
    size_t spare_size = 64;
    struct mtd_info_user mtdinfo;
    struct mtd_ecc_stats initial_ecc, last_ecc, ecc;
    struct mtd_oob_buf oobbuf;
    struct nand_ecclayout ecclayout;

    do {
        c = getopt(argc, argv, "d:f:s:S:L:Rhv");
        if (c == EOF)
            break;
        switch (c) {
        case 'd':
            devname = optarg;
            break;
        case 'f':
            filename = optarg;
            break;
        case 's':
            spare_size = atoi(optarg);
            break;
        case 'S':
            start = strtoll(optarg, NULL, 0);
            break;
        case 'L':
            len = strtoll(optarg, NULL, 0);
            break;
        case 'R':
            rawmode = 1;
            break;
        case 'v':
            verbose++;
            break;
        case 'h':
            fprintf(stderr, "%s [-d <dev>] [-f file] [-s sparesize] [-vh]\n"
                    "  -d <dev>   Read from <dev>\n"
                    "  -f <file>  Write to <file>\n"
                    "  -s <size>  Number of spare bytes in file (default 64)\n"
                    "  -R         Raw mode\n"
                    "  -S <start> Start offset (default 0)\n"
                    "  -L <len>   Length (default 0)\n"
                    "  -v         Print info\n"
                    "  -h         Print help\n", argv[0]);
            return -1;
        case '?':
            fprintf(stderr, "%s: invalid option -%c\n",
                argv[0], optopt);
            exit(1);
        }
    } while (1);

    if (optind < argc) {
        fprintf(stderr, "%s: extra arguments\n", argv[0]);
        return 1;
    }
    if (!devname) {
        fprintf(stderr, "%s: specify device name\n", argv[0]);
        return 1;
    }

    fd = open(devname, O_RDONLY);
    if (fd < 0) {
        fprintf(stderr, "cannot open %s, %s\n", devname, strerror(errno));
        return 1;
    }

    if (filename) {
        outfd = creat(filename, 0666);
        if (outfd < 0) {
            fprintf(stderr, "cannot open %s, %s\n", filename, strerror(errno));
            return 1;
        }
        statusfilename = malloc(strlen(filename) + strlen(statusext) + 1);
        strcpy(statusfilename, filename);
        strcat(statusfilename, statusext);
        statusfile = fopen(statusfilename, "w+");
        if (!statusfile) {
            fprintf(stderr, "cannot open %s, %s\n", statusfilename, strerror(errno));
            return 1;
        }
    }

    ret = ioctl(fd, MEMGETINFO, &mtdinfo);
    if (ret) {
        fprintf(stderr, "failed get mtd info for %s, %s\n",
                devname, strerror(errno));
        return 1;
    }

    if (verbose) {
        printf("size: %u\n", mtdinfo.size);
        printf("erase size: %u\n", mtdinfo.erasesize);
        printf("write size: %u\n", mtdinfo.writesize);
        printf("oob size: %u\n", mtdinfo.oobsize);
    }

    buffer = malloc(mtdinfo.writesize + mtdinfo.oobsize + spare_size);
    if (!buffer) {
        fprintf(stderr, "failed allocate readbuffer size %u\n",
                mtdinfo.writesize + mtdinfo.oobsize);
        return 1;
    }

    oobbuf.length = mtdinfo.oobsize;
    oob_data = (uint32_t *)((uint8_t *)buffer + mtdinfo.writesize);
    memset(oob_data, 0xff, mtdinfo.oobsize + spare_size);
    oobbuf.ptr = (uint8_t *)oob_data + spare_size;

    ret = ioctl(fd, ECCGETLAYOUT, &ecclayout);
    if (ret) {
        fprintf(stderr, "failed get ecc layout for %s, %s\n",
                devname, strerror(errno));
        return 1;
    }
    if (verbose) {
        printf("ecc bytes: %u\n", ecclayout.eccbytes);
        printf("oobavail: %u\n", ecclayout.oobavail);
    }
    if (ecclayout.oobavail > spare_size)
        printf("oobavail, %d > image spare size, %d\n", ecclayout.oobavail, spare_size);

    ret = ioctl(fd, ECCGETSTATS, &initial_ecc);
    if (ret) {
        fprintf(stderr, "failed get ecc stats for %s, %s\n",
                devname, strerror(errno));
        return 1;
    }
    last_ecc = initial_ecc;

    if (verbose) {
        printf("initial ecc corrected: %u\n", initial_ecc.corrected);
        printf("initial ecc failed: %u\n", initial_ecc.failed);
        printf("initial ecc badblocks: %u\n", initial_ecc.badblocks);
        printf("initial ecc bbtblocks: %u\n", initial_ecc.bbtblocks);
    }

    if (rawmode) {
        rawmode = mtdinfo.oobsize;
        ret = ioctl(fd, MTDFILEMODE, MTD_MODE_RAW);
        if (ret) {
            fprintf(stderr, "failed set raw mode for %s, %s\n",
                    devname, strerror(errno));
            return 1;
        }
    }

    end = len ? (start + len) : mtdinfo.size;
    for (pos = start, opos = 0; pos < end; pos += mtdinfo.writesize) {
        bad_block = 0;
        if (verbose > 3)
            printf("reading at %llx\n", pos);
        lseek64(fd, pos, SEEK_SET);
        ret = read(fd, buffer, mtdinfo.writesize + rawmode);
        if (ret < (int)mtdinfo.writesize) {
            fprintf(stderr, "short read at %llx, %d\n", pos, ret);
            bad_block = 2;
        }
        if (!rawmode) {
            oobbuf.start = pos;
            ret = ioctl(fd, MEMREADOOB, &oobbuf);
            if (ret) {
                fprintf(stderr, "failed to read oob data at %llx, %d\n", pos, ret);
                bad_block = 2;
            }
        }
        ret = ioctl(fd, ECCGETSTATS, &ecc);
        if (ret) {
            fprintf(stderr, "failed get ecc stats for %s, %s\n",
                    devname, strerror(errno));
            return 1;
        }
        bpos = pos / mtdinfo.erasesize * mtdinfo.erasesize;
        ret = ioctl(fd, MEMGETBADBLOCK, &bpos);
        if (ret && errno != EOPNOTSUPP) {
            printf("badblock at %llx\n", pos);
            bad_block = 1;
        }
        if (ecc.corrected != last_ecc.corrected)
            printf("ecc corrected, %u, at %llx\n", ecc.corrected - last_ecc.corrected, pos);
        if (ecc.failed != last_ecc.failed)
            printf("ecc failed, %u, at %llx\n", ecc.failed - last_ecc.failed, pos);
        if (ecc.badblocks != last_ecc.badblocks)
            printf("ecc badblocks, %u, at %llx\n", ecc.badblocks - last_ecc.badblocks, pos);
        if (ecc.bbtblocks != last_ecc.bbtblocks)
            printf("ecc bbtblocks, %u, at %llx\n", ecc.bbtblocks - last_ecc.bbtblocks, pos);

        if (!rawmode) {
            oob_fixed = (uint8_t *)oob_data;
            for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) {
                int len = ecclayout.oobfree[i].length;
                if (oob_fixed + len > oobbuf.ptr)
                    len = oobbuf.ptr - oob_fixed;
                if (len) {
                    memcpy(oob_fixed, oobbuf.ptr + ecclayout.oobfree[i].offset, len);
                    oob_fixed += len;
                }
            }
        }

        if (outfd >= 0) {
            ret = write(outfd, buffer, mtdinfo.writesize + spare_size);
            if (ret < (int)(mtdinfo.writesize + spare_size)) {
                fprintf(stderr, "short write at %llx, %d\n", pos, ret);
                close(outfd);
                outfd = -1;
            }
            if (ecc.corrected != last_ecc.corrected)
                fprintf(statusfile, "%08llx: ecc corrected\n", opos);
            if (ecc.failed != last_ecc.failed)
                fprintf(statusfile, "%08llx: ecc failed\n", opos);
            if (bad_block == 1)
                fprintf(statusfile, "%08llx: badblock\n", opos);
            if (bad_block == 2)
                fprintf(statusfile, "%08llx: read error\n", opos);
            opos += mtdinfo.writesize + spare_size;
        }

        last_ecc = ecc;
        page_count++;
        if (test_empty(buffer, mtdinfo.writesize + mtdinfo.oobsize + spare_size))
            empty_pages++;
        else if (verbose > 2 || (verbose > 1 && !(pos & (mtdinfo.erasesize - 1))))
            printf("page at %llx (%d oobbytes): %08x %08x %08x %08x "
                   "%08x %08x %08x %08x\n", pos, oobbuf.start,
                   oob_data[0], oob_data[1], oob_data[2], oob_data[3],
                   oob_data[4], oob_data[5], oob_data[6], oob_data[7]);
    }

    if (outfd >= 0) {
        fprintf(statusfile, "read %d pages, %d empty\n", page_count, empty_pages);
        fprintf(statusfile, "total ecc corrected, %u\n", ecc.corrected - initial_ecc.corrected);
        fprintf(statusfile, "total ecc failed, %u\n", ecc.failed - initial_ecc.failed);
        fprintf(statusfile, "total ecc badblocks, %u\n", ecc.badblocks - initial_ecc.badblocks);
        fprintf(statusfile, "total ecc bbtblocks, %u\n", ecc.bbtblocks - initial_ecc.bbtblocks);
    }
    if (verbose) {
        printf("total ecc corrected, %u\n", ecc.corrected - initial_ecc.corrected);
        printf("total ecc failed, %u\n", ecc.failed - initial_ecc.failed);
        printf("total ecc badblocks, %u\n", ecc.badblocks - initial_ecc.badblocks);
        printf("total ecc bbtblocks, %u\n", ecc.bbtblocks - initial_ecc.bbtblocks);
    }
    printf("read %d pages, %d empty\n", page_count, empty_pages);

    return 0;
}
示例#15
0
static int
readblks(int fd, size_t alignment)
{
	__uint64_t offset;
	char *buffer, *tmp;
	unsigned int xfer, block, i;
        int err=0;

	if (alloconly)
		return 0;
	xfer = READ_XFER*blocksize;
	if (posix_memalign((void **) &buffer, alignment, xfer)) {
		perror("malloc");
		exit(1);
	}
	memset(buffer, 0, xfer);
	if (verbose)
		printf("\n");

	if (lseek64(fd, fileoffset, SEEK_SET) < 0) {
		perror("lseek");
		exit(1);
	}
	block = 0;
	offset = 0;
	while (offset < filesize) {
		if ((i = read(fd, buffer, xfer) < xfer)) {
			if (i < 2)
				break;
			perror("read");
			exit(1);
		}
		tmp = buffer;
		for (i = 0; i < READ_XFER; i++) {
			__uint64_t want;
			__uint64_t first;
			__uint64_t second;

			if (verbose && ((block % 100) == 0)) {
				printf("+");
				fflush(stdout);
			}

			want = BITVAL(valid, block) ? offset : 0;
			first = *(__uint64_t *) tmp;
			second = *(__uint64_t *) (tmp + 256);
			if (first != want || second != want) {
				printf("mismatched data at offset=0x%" PRIx64
					", expected 0x%" PRIx64
					", got 0x%" PRIx64
					" and 0x%" PRIx64 "\n",
					 fileoffset + offset, want,
					 first, second);
				err++;
			}
			if (verbose > 2) {
				printf("block %d blocksize %d\n", block,
				       blocksize);
				dumpblock((int *)tmp, fileoffset + offset,
					  blocksize);
			}

			block++;
			offset += blocksize;
			tmp += blocksize;
		}
	}
	if (verbose)
		printf("\n");

	free(buffer);
        return err;
}
示例#16
0
文件: ftest07.c 项目: rocklee104/ltp
static void dotest(int testers, int me, int fd)
{
	char *bits, *hold_bits;
	char val;
	int count, collide, chunk, whenmisc, xfr, i;

	/* Stuff for the readv call */
	struct iovec r_iovec[MAXIOVCNT];
	int r_ioveclen;

	/* Stuff for the writev call */
	struct iovec val_iovec[MAXIOVCNT];

	struct iovec zero_iovec[MAXIOVCNT];
	int w_ioveclen;
	struct stat stat;

	nchunks = max_size / csize;
	whenmisc = 0;

	if ((bits = malloc((nchunks + 7) / 8)) == NULL) {
		tst_brkm(TBROK, NULL, "\tmalloc failed(bits)");
	}
	if ((hold_bits = malloc((nchunks + 7) / 8)) == NULL) {
		tst_brkm(TBROK, NULL, "\tmalloc failed(hlod_bits)");
	}

	/*Allocate memory for the iovec buffers and init the iovec arrays
	 */
	r_ioveclen = w_ioveclen = csize / MAXIOVCNT;

	/* Please note that the above statement implies that csize
	 * be evenly divisible by MAXIOVCNT.
	 */

	for (i = 0; i < MAXIOVCNT; i++) {
		if ((r_iovec[i].iov_base = calloc(r_ioveclen, 1)) == NULL) {
			tst_brkm(TFAIL, NULL,
				 "\tmalloc failed(r_iovec[i].iov_base)");
		}
		r_iovec[i].iov_len = r_ioveclen;

		/* Allocate unused memory areas between all the buffers to
		 * make things more diffult for the OS.
		 */

		if (malloc((i + 1) * 8) == NULL) {
			tst_brkm(TBROK, NULL, "\tmalloc failed((i+1)*8)");
		}
		if ((val_iovec[i].iov_base = calloc(w_ioveclen, 1)) == NULL) {
			tst_resm(TBROK, "\tmalloc failed(val_iovec[i]");
			exit(1);
		}
		val_iovec[i].iov_len = w_ioveclen;

		if (malloc((i + 1) * 8) == NULL) {
			tst_brkm(TBROK, NULL, "\tmalloc failed((i+1)*8)");
		}
		if ((zero_iovec[i].iov_base = calloc(w_ioveclen, 1)) == NULL) {
			tst_brkm(TBROK, NULL, "\tmalloc failed(zero_iover)");
		}
		zero_iovec[i].iov_len = w_ioveclen;

		if (malloc((i + 1) * 8) == NULL) {
			tst_brkm(TBROK, NULL, "\tmalloc failed((i+1)*8)");
		}
	}
	/*
	 * No init sectors; allow file to be sparse.
	 */
	val = (64 / testers) * me + 1;

	/*
	 * For each iteration:
	 *      zap bits array
	 *      loop
	 *              pick random chunk, read it.
	 *              if corresponding bit off {
	 *                      verify = 0. (sparse file)
	 *                      ++count;
	 *              } else
	 *                      verify = val.
	 *              write "val" on it.
	 *              repeat unitl count = nchunks.
	 *      ++val.
	 */

	srand(getpid());
	if (misc_intvl)
		whenmisc = NEXTMISC;

	while (iterations-- > 0) {
		for (i = 0; i < NMISC; i++)
			misc_cnt[i] = 0;
		ftruncate(fd, 0);
		file_max = 0;
		memset(bits, 0, (nchunks + 7) / 8);
		memset(hold_bits, 0, (nchunks + 7) / 8);

		/* Have to fill the val and zero iov buffers in a different manner
		 */
		for (i = 0; i < MAXIOVCNT; i++) {
			memset(val_iovec[i].iov_base, val,
			       val_iovec[i].iov_len);
			memset(zero_iovec[i].iov_base, 0,
			       zero_iovec[i].iov_len);

		}
		count = 0;
		collide = 0;
		while (count < nchunks) {
			chunk = rand() % nchunks;
			/*
			 * Read it.
			 */
			if (lseek64(fd, CHUNK(chunk), 0) < 0) {
				tst_brkm(TFAIL,
					 NULL,
					 "\tTest[%d]: lseek64(0) fail at %Lx, errno = %d.",
					 me, CHUNK(chunk), errno);
			}
			if ((xfr = readv(fd, &r_iovec[0], MAXIOVCNT)) < 0) {
				tst_brkm(TFAIL,
					 NULL,
					 "\tTest[%d]: readv fail at %Lx, errno = %d.",
					 me, CHUNK(chunk), errno);
			}
			/*
			 * If chunk beyond EOF just write on it.
			 * Else if bit off, haven't seen it yet.
			 * Else, have.  Verify values.
			 */
			if (CHUNK(chunk) >= file_max) {
				bits[chunk / 8] |= (1 << (chunk % 8));
				++count;
			} else if ((bits[chunk / 8] & (1 << (chunk % 8))) == 0) {
				if (xfr != csize) {
					tst_brkm(TFAIL,
						 NULL,
						 "\tTest[%d]: xfr=%d != %d, zero read.",
						 me, xfr, csize);
				}
				for (i = 0; i < MAXIOVCNT; i++) {
					if (memcmp
					    (r_iovec[i].iov_base,
					     zero_iovec[i].iov_base,
					     r_iovec[i].iov_len)) {
						tst_resm(TFAIL,
							 "\tTest[%d] bad verify @ 0x%Lx for val %d count %d xfr %d file_max 0x%x, should be 0.",
							 me, CHUNK(chunk), val,
							 count, xfr, file_max);
						tst_resm(TINFO,
							 "\tTest[%d]: last_trunc = 0x%x",
							 me, last_trunc);
						fstat(fd, &stat);
						tst_resm(TINFO,
							 "\tStat: size=%llx, ino=%x",
							 stat.st_size, (unsigned)stat.st_ino);
						sync();
						ft_dumpiov(&r_iovec[i]);
						ft_dumpbits(bits,
							    (nchunks + 7) / 8);
						ft_orbits(hold_bits, bits,
							  (nchunks + 7) / 8);
						tst_resm(TINFO, "\tHold ");
						ft_dumpbits(hold_bits,
							    (nchunks + 7) / 8);
						tst_exit();
					}
				}
				bits[chunk / 8] |= (1 << (chunk % 8));
				++count;
			} else {
				if (xfr != csize) {
					tst_brkm(TFAIL,
						 NULL,
						 "\tTest[%d]: xfr=%d != %d, val read.",
						 me, xfr, csize);
				}
				++collide;
				for (i = 0; i < MAXIOVCNT; i++) {
					if (memcmp
					    (r_iovec[i].iov_base,
					     val_iovec[i].iov_base,
					     r_iovec[i].iov_len)) {
						tst_resm(TFAIL,
							 "\tTest[%d] bad verify @ 0x%Lx for val %d count %d xfr %d file_max 0x%x.",
							 me, CHUNK(chunk), val,
							 count, xfr, file_max);
						tst_resm(TINFO,
							 "\tTest[%d]: last_trunc = 0x%x",
							 me, last_trunc);
						fstat(fd, &stat);
						tst_resm(TINFO,
							 "\tStat: size=%llx, ino=%x",
							 stat.st_size, (unsigned)stat.st_ino);
						sync();
						ft_dumpiov(&r_iovec[i]);
						ft_dumpbits(bits,
							    (nchunks + 7) / 8);
						ft_orbits(hold_bits, bits,
							  (nchunks + 7) / 8);
						tst_resm(TINFO, "\tHold ");
						ft_dumpbits(hold_bits,
							    (nchunks + 7) / 8);
						tst_exit();
					}
				}
			}
			/*
			 * Writev it.
			 */
			if (lseek64(fd, -((off64_t) xfr), 1) < 0) {
				tst_brkm(TFAIL,
					 NULL,
					 "\tTest[%d]: lseek64(1) fail at %Lx, errno = %d.",
					 me, CHUNK(chunk), errno);
			}
			if ((xfr =
			     writev(fd, &val_iovec[0], MAXIOVCNT)) < csize) {
				if (errno == ENOSPC) {
					tst_resm(TFAIL,
						 "\tTest[%d]: no space, exiting.",
						 me);
					fsync(fd);
					tst_exit();
				}
				tst_brkm(TFAIL,
					 NULL,
					 "\tTest[%d]: writev fail at %Lx xfr %d, errno = %d.",
					 me, CHUNK(chunk), xfr, errno);
			}
			if (CHUNK(chunk) + csize > file_max)
				file_max = CHUNK(chunk) + csize;
			/*
			 * If hit "misc" interval, do it.
			 */
			if (misc_intvl && --whenmisc <= 0) {
				ft_orbits(hold_bits, bits, (nchunks + 7) / 8);
				domisc(me, fd, bits);
				whenmisc = NEXTMISC;
			}
			if (count + collide > 2 * nchunks)
				break;
		}

		/*
		 * End of iteration, maybe before doing all chunks.
		 */
		fsync(fd);
		++misc_cnt[m_fsync];
		//tst_resm(TINFO, "\tTest{%d} val %d done, count = %d, collide = {%d}",
		//              me, val, count, collide);
		//for (i = 0; i < NMISC; i++)
		//      tst_resm(TINFO, "\t\tTest{%d}: {%d} %s's.", me, misc_cnt[i], m_str[i]);
		++val;
	}
}
static const unsigned short* CreateBlockMapping(const MtdPartition* pSrcPart, int srcPartStartBlock,
		const MtdPartition *pReservoirPart, int reservoirPartStartBlock)
{
	size_t srcTotal, srcErase, srcWrite;
	if (mtd_partition_info(pSrcPart, &srcTotal, &srcErase, &srcWrite) != 0)
	{
		fprintf(stderr, "Failed to access partition.\n");
		return NULL;
	}

	int numSrcBlocks = srcTotal/srcErase;

	unsigned short* pMapping = malloc(numSrcBlocks * sizeof(unsigned short));
	if (pMapping == NULL)
	{
		fprintf(stderr, "Failed to allocate block mapping memory.\n");
		return NULL;
	}
	memset(pMapping, 0xFF, numSrcBlocks * sizeof(unsigned short));

	size_t total, erase, write;
	if (mtd_partition_info(pReservoirPart, &total, &erase, &write) != 0)
	{
		fprintf(stderr, "Failed to access reservoir partition.\n");
		free(pMapping);
		return NULL;
	}

	if (erase != srcErase || write != srcWrite)
	{
		fprintf(stderr, "Source partition and reservoir partition differ in size properties.\n");
		free(pMapping);
		return NULL;
	}

	printf("Partition info: Total %d, Erase %d, write %d\n", total, erase, write);

	BmlOverMtdReadContext *readctx = bml_over_mtd_read_partition(pReservoirPart);
	if (readctx == NULL)
	{
		fprintf(stderr, "Failed to open reservoir partition for reading.\n");
		free(pMapping);
		return NULL;
	}

	if (total < erase || total > INT_MAX)
	{
		fprintf(stderr, "Unsuitable reservoir partition properties.\n");
		free(pMapping);
		bml_over_mtd_read_close(readctx);
		return NULL;
	}

	int foundMappingTable = 0;

	int currOffset = total; //Offset *behind* the last byte
	while (currOffset > 0)
	{
		currOffset -= erase;
		loff_t pos = lseek64(readctx->fd, currOffset, SEEK_SET);
		int mgbb = ioctl(readctx->fd, MEMGETBADBLOCK, &pos);
		if (mgbb != 0)
		{
			printf("Bad block %d in reservoir area, skipping.\n", currOffset/erase);
			continue;
		}
		ssize_t readBytes = read(readctx->fd, readctx->buffer, erase);
		if (readBytes != (ssize_t)erase)
		{
			fprintf(stderr, "Failed to read good block in reservoir area (%s).\n",
					strerror(errno));
			free(pMapping);
			bml_over_mtd_read_close(readctx);
			return NULL;
		}
		if (readBytes >= 0x2000)
		{
			char* buf = readctx->buffer;
			if (buf[0]=='U' && buf[1]=='P' && buf[2]=='C' && buf[3]=='H')
			{
				printf ("Found mapping block mark at 0x%x (block %d).\n", currOffset, currOffset/erase);

				unsigned short* mappings = (unsigned short*) &buf[0x1000];
				if (mappings[0]==0 && mappings[1]==0xffff)
				{
					printf("Found start of mapping table.\n");
					foundMappingTable = 1;
					//Skip first entry (dummy)
					unsigned short* mappingEntry = mappings + 2;
					while (mappingEntry - mappings < 100
							&& mappingEntry[0] != 0xffff)
					{
						unsigned short rawSrcBlk = mappingEntry[0];
						unsigned short rawDstBlk = mappingEntry[1];

						printf("Found raw block mapping %d -> %d\n", rawSrcBlk,
								rawDstBlk);

						unsigned int srcAbsoluteStartAddress = srcPartStartBlock * erase;
						unsigned int resAbsoluteStartAddress = reservoirPartStartBlock * erase;

						int reservoirLastBlock = reservoirPartStartBlock + numSrcBlocks - 1;
						if (rawDstBlk < reservoirPartStartBlock
								|| rawDstBlk*erase >= resAbsoluteStartAddress+currOffset)
						{
							fprintf(stderr, "Mapped block not within reasonable reservoir area.\n");
							foundMappingTable = 0;
							break;
						}

						int srcLastBlock = srcPartStartBlock + numSrcBlocks - 1;
						if (rawSrcBlk >= srcPartStartBlock && rawSrcBlk <= srcLastBlock)
						{

							unsigned short relSrcBlk = rawSrcBlk - srcPartStartBlock;
							unsigned short relDstBlk = rawDstBlk - reservoirPartStartBlock;
							printf("Partition relative block mapping %d -> %d\n",relSrcBlk, relDstBlk);

							printf("Absolute mapped start addresses 0x%x -> 0x%x\n",
									srcAbsoluteStartAddress+relSrcBlk*erase,
									resAbsoluteStartAddress+relDstBlk*erase);
							printf("Partition relative mapped start addresses 0x%x -> 0x%x\n",
									relSrcBlk*erase, relDstBlk*erase);

							//Set mapping entry. For duplicate entries, later entries replace former ones.
							//*Assumption*: Bad blocks in reservoir area will not be mapped themselves in
							//the mapping table. User partition blocks will not be mapped to bad blocks
							//(only) in the reservoir area. This has to be confirmed on a wider range of
							//devices.
							pMapping[relSrcBlk] = relDstBlk;

						}
						mappingEntry+=2;
					}
					break; //We found the mapping table, no need to search further
				}


			}
		}

	}
	bml_over_mtd_read_close(readctx);

	if (foundMappingTable == 0)
	{
		fprintf(stderr, "Cannot find mapping table in reservoir partition.\n");
		free(pMapping);
		return NULL;
	}

	//Consistency and validity check
	int mappingValid = 1;
	readctx = bml_over_mtd_read_partition(pSrcPart);
	if (readctx == NULL)
	{
		fprintf(stderr, "Cannot open source partition for reading.\n");
		free(pMapping);
		return NULL;
	}
	int currBlock = 0;
	for (;currBlock < numSrcBlocks; ++currBlock)
	{
		loff_t pos = lseek64(readctx->fd, currBlock*erase, SEEK_SET);
		int mgbb = ioctl(readctx->fd, MEMGETBADBLOCK, &pos);
		if (mgbb == 0)
		{
			if (pMapping[currBlock]!=0xffff)
			{
				fprintf(stderr, "Consistency error: Good block has mapping entry %d -> %d\n", currBlock, pMapping[currBlock]);
				mappingValid = 0;
			}
		} else
		{
			//Bad block!
			if (pMapping[currBlock]==0xffff)
			{
				fprintf(stderr, "Consistency error: Bad block has no mapping entry \n");
				mappingValid = 0;
			} else
			{
				BmlOverMtdReadContext* reservoirReadCtx = bml_over_mtd_read_partition(pReservoirPart);
				if (reservoirReadCtx == 0)
				{
					fprintf(stderr, "Reservoir partition cannot be opened for reading in consistency check.\n");
					mappingValid = 0;
				} else
				{
					pos = lseek64(reservoirReadCtx->fd, pMapping[currBlock]*erase, SEEK_SET);
					mgbb = ioctl(reservoirReadCtx->fd, MEMGETBADBLOCK, &pos);
					if (mgbb == 0)
					{
						printf("Bad block has properly mapped reservoir block %d -> %d\n",currBlock, pMapping[currBlock]);
					}
					else
					{
						fprintf(stderr, "Consistency error: Mapped block is bad, too. (%d -> %d)\n",currBlock, pMapping[currBlock]);
						mappingValid = 0;
					}

				}
				bml_over_mtd_read_close(reservoirReadCtx);
			}

		}

	}
	bml_over_mtd_read_close(readctx);


	if (!mappingValid)
	{
		free(pMapping);
		return NULL;
	}

	return pMapping;
}
示例#18
0
文件: test-lfs.c 项目: hwoarang/glibc
int
do_test (int argc, char *argv[])
{
  int ret, fd2;
  struct stat64 statbuf;

  ret = lseek64 (fd, TWO_GB+100, SEEK_SET);
  if (ret == -1 && errno == ENOSYS)
    {
      error (0, 0, "lseek64 is not supported.");
      exit (EXIT_SUCCESS);
    }
  if (ret == -1 && errno == EINVAL)
    {
      error (0, 0, "LFS seems not to be supported.");
      exit (EXIT_SUCCESS);
    }
  if (ret == -1)
    {
      error (0, errno, "lseek64 failed with error");
      exit (EXIT_FAILURE);
    }

  ret = write (fd, "Hello", 5);
  if (ret == -1 && errno == EFBIG)
    {
      error (0, 0, "LFS seems not to be supported.");
      exit (EXIT_SUCCESS);
    }

  if (ret == -1 && errno == ENOSPC)
    {
      error (0, 0, "Not enough space to write file.");
      exit (EXIT_SUCCESS);
    }

  if (ret != 5)
    error (EXIT_FAILURE, errno, "cannot write test string to large file");

  ret = close (fd);

  if (ret == -1)
    error (EXIT_FAILURE, errno, "error closing file");

  ret = stat64 (name, &statbuf);

  if (ret == -1 && (errno == ENOSYS || errno == EOVERFLOW))
    error (0, 0, "stat64 is not supported.");
  else if (ret == -1)
    error (EXIT_FAILURE, errno, "cannot stat file `%s'", name);
  else if (statbuf.st_size != (TWO_GB + 100 + 5))
    error (EXIT_FAILURE, 0, "stat reported size %lld instead of %lld.",
	   (long long int) statbuf.st_size, (TWO_GB + 100 + 5));

  fd2 = openat64 (AT_FDCWD, name, O_RDWR);
  if (fd2 == -1)
    {
      if (errno == ENOSYS)
	{
	  /* Silently ignore this test.  */
	  error (0, 0, "openat64 is not supported");
	}
      else
	error (EXIT_FAILURE, errno, "openat64 failed to open big file");
    }
  else
    {
      ret = close (fd2);

      if (ret == -1)
	error (EXIT_FAILURE, errno, "error closing file");
    }

  test_ftello ();

  return 0;
}
static int flash_bml_partition(const MtdPartition* pSrcPart, const MtdPartition* pReservoirPart,
		const unsigned short* blockMapping, const char* filename)
{
	int fd = open(filename, O_RDONLY);
	if (fd < 0)
	{
		fprintf(stderr, "error opening %s", filename);
		return -1;
	}
	BmlOverMtdWriteContext* pSrcWrite = bml_over_mtd_write_partition(pSrcPart);
	if (pSrcWrite == NULL)
	{
		close(fd);
		fprintf(stderr, "flash_bml_partition: Error opening src part for writing.\n");
		return -1;
	}

#ifdef DUMMY_WRITING
	close(pSrcWrite->fd);
	pSrcWrite->fd = open("/sdcard/srcPartWriteDummy.bin", O_WRONLY|O_CREAT|O_TRUNC, 0666);
#endif

	BmlOverMtdWriteContext* pResWrite = bml_over_mtd_write_partition(pReservoirPart);
	if (pResWrite == NULL)
	{
		close(fd);
		bml_over_mtd_write_close(pSrcWrite);
		fprintf(stderr, "flash_bml_partition: Error opening reservoir part for writing.\n");
		return -1;
	}
#ifdef DUMMY_WRITING
	close(pResWrite->fd);
	pResWrite->fd = open("/sdcard/resPartWriteDummy.bin", O_WRONLY|O_CREAT|O_TRUNC, 0666);
#endif

	struct stat fileStat;
	if (fstat(fd, &fileStat) != 0)
	{
		close(fd);
		bml_over_mtd_write_close(pSrcWrite);
		bml_over_mtd_write_close(pResWrite);
		fprintf(stderr, "flash_bml_partition: Failed to stat source file.\n");
		return -1;

	}
	if (fileStat.st_size > pSrcPart->size)
	{
		close(fd);
		bml_over_mtd_write_close(pSrcWrite);
		bml_over_mtd_write_close(pResWrite);
		fprintf(stderr, "flash_bml_partition: Source file too large for target partition.\n");
		return -1;
	}

	int numBlocks = (fileStat.st_size +  pSrcPart->erase_size - 1) / pSrcPart->erase_size;
	int currblock;
	for (currblock = 0 ;currblock < numBlocks; ++currblock)
	{
		memset(pSrcWrite->buffer, 0xFF, pSrcPart->erase_size);
		size_t blockBytesRead = 0;
		while (blockBytesRead < pSrcPart->erase_size)
		{
			ssize_t len = read(fd, pSrcWrite->buffer + blockBytesRead,
					pSrcPart->erase_size - blockBytesRead);
			if (len < 0)
			{
				close(fd);
				bml_over_mtd_write_close(pSrcWrite);
				bml_over_mtd_write_close(pResWrite);
				fprintf(stderr, "flash_bml_partition: read source file failed\n");
				return -1;
			}
			if (len == 0)
			{
				//End of file
				break;
			}

			blockBytesRead += len;
		}



		int srcFd = -1;
		if (blockMapping[currblock] == 0xffff)
		{
			//Good block, use src partition
			srcFd = pSrcWrite->fd;
			if (lseek64(pSrcWrite->fd, currblock*pSrcPart->erase_size, SEEK_SET)==-1)
			{
				close(fd);
				bml_over_mtd_write_close(pSrcWrite);
				bml_over_mtd_write_close(pResWrite);
				fprintf(stderr, "flash_bml_partition: lseek in src partition failed\n");
				return -1;
			}
		} else
		{
			//Bad block, use mapped block in reservoir partition
			srcFd = pResWrite->fd;
			if (lseek64(pResWrite->fd, blockMapping[currblock]*pSrcPart->erase_size, SEEK_SET)==-1)
			{
				close(fd);
				bml_over_mtd_write_close(pSrcWrite);
				bml_over_mtd_write_close(pResWrite);
				fprintf(stderr, "flash_bml_partition: lseek in reservoir partition failed\n");
				return -1;
			}
		}
		size_t blockBytesWritten = 0;
		while (blockBytesWritten < pSrcPart->erase_size)
		{
#ifdef DUMMY_WRITING
			ssize_t len = write(srcFd, pSrcWrite->buffer + blockBytesWritten,
					pSrcPart->erase_size - blockBytesWritten);
#else
			ssize_t len = bml_over_mtd_write_block(srcFd, pSrcPart->erase_size, pSrcWrite->buffer);
#endif
			if (len <= 0)
			{
				close(fd);
				bml_over_mtd_write_close(pSrcWrite);
				bml_over_mtd_write_close(pResWrite);
				fprintf(stderr, "flash_bml_partition: writing to partition failed\n");
				return -1;
			}
			blockBytesWritten += len;
		}


	}

	bml_over_mtd_write_close(pSrcWrite);
	bml_over_mtd_write_close(pResWrite);

	if (close(fd)) {
		printf("error closing %s", filename);
		return -1;
	}

	return 0;
}
示例#20
0
static inline off64_t
vhd_journal_position(vhd_journal_t *j)
{
	return lseek64(j->jfd, 0, SEEK_CUR);
}
示例#21
0
bool ObbFile::parseObbFile(int fd)
{
    off64_t fileLength = lseek64(fd, 0, SEEK_END);

    if (fileLength < kFooterMinSize) {
        if (fileLength < 0) {
            ALOGW("error seeking in ObbFile: %s\n", strerror(errno));
        } else {
            ALOGW("file is only %lld (less than %d minimum)\n", fileLength, kFooterMinSize);
        }
        return false;
    }

    ssize_t actual;
    size_t footerSize;

    {
        lseek64(fd, fileLength - kFooterTagSize, SEEK_SET);

        char *footer = new char[kFooterTagSize];
        actual = TEMP_FAILURE_RETRY(read(fd, footer, kFooterTagSize));
        if (actual != kFooterTagSize) {
            ALOGW("couldn't read footer signature: %s\n", strerror(errno));
            return false;
        }

        unsigned int fileSig = get4LE((unsigned char*)footer + sizeof(int32_t));
        if (fileSig != kSignature) {
            ALOGW("footer didn't match magic string (expected 0x%08x; got 0x%08x)\n",
                    kSignature, fileSig);
            return false;
        }

        footerSize = get4LE((unsigned char*)footer);
        if (footerSize > (size_t)fileLength - kFooterTagSize
                || footerSize > kMaxBufSize) {
            ALOGW("claimed footer size is too large (0x%08zx; file size is 0x%08llx)\n",
                    footerSize, fileLength);
            return false;
        }

        if (footerSize < (kFooterMinSize - kFooterTagSize)) {
            ALOGW("claimed footer size is too small (0x%zx; minimum size is 0x%x)\n",
                    footerSize, kFooterMinSize - kFooterTagSize);
            return false;
        }
    }

    off64_t fileOffset = fileLength - footerSize - kFooterTagSize;
    if (lseek64(fd, fileOffset, SEEK_SET) != fileOffset) {
        ALOGW("seek %lld failed: %s\n", fileOffset, strerror(errno));
        return false;
    }

    mFooterStart = fileOffset;

    char* scanBuf = (char*)malloc(footerSize);
    if (scanBuf == NULL) {
        ALOGW("couldn't allocate scanBuf: %s\n", strerror(errno));
        return false;
    }

    actual = TEMP_FAILURE_RETRY(read(fd, scanBuf, footerSize));
    // readAmount is guaranteed to be less than kMaxBufSize
    if (actual != (ssize_t)footerSize) {
        ALOGI("couldn't read ObbFile footer: %s\n", strerror(errno));
        free(scanBuf);
        return false;
    }

#ifdef DEBUG
    for (int i = 0; i < footerSize; ++i) {
        ALOGI("char: 0x%02x\n", scanBuf[i]);
    }
#endif

    uint32_t sigVersion = get4LE((unsigned char*)scanBuf);
    if (sigVersion != kSigVersion) {
        ALOGW("Unsupported ObbFile version %d\n", sigVersion);
        free(scanBuf);
        return false;
    }

    mVersion = (int32_t) get4LE((unsigned char*)scanBuf + kPackageVersionOffset);
    mFlags = (int32_t) get4LE((unsigned char*)scanBuf + kFlagsOffset);

    memcpy(&mSalt, (unsigned char*)scanBuf + kSaltOffset, sizeof(mSalt));

    size_t packageNameLen = get4LE((unsigned char*)scanBuf + kPackageNameLenOffset);
    if (packageNameLen == 0
            || packageNameLen > (footerSize - kPackageNameOffset)) {
        ALOGW("bad ObbFile package name length (0x%04zx; 0x%04zx possible)\n",
                packageNameLen, footerSize - kPackageNameOffset);
        free(scanBuf);
        return false;
    }

    char* packageName = reinterpret_cast<char*>(scanBuf + kPackageNameOffset);
    mPackageName = String8(const_cast<char*>(packageName), packageNameLen);

    free(scanBuf);

#ifdef DEBUG
    ALOGI("Obb scan succeeded: packageName=%s, version=%d\n", mPackageName.string(), mVersion);
#endif

    return true;
}
示例#22
0
文件: mpq.cpp 项目: AdharRuafo/mangos
/*
 *  This function reads a file and verify if it is a legit MPQ archive
 *  or not. Then it fills the mpq_header structure and reads the hash
 *  table.
 */
int libmpq_archive_open(mpq_archive *mpq_a, unsigned char *mpq_filename) {
	int fd = 0;
	int rb = 0;
	int ncnt = FALSE;
	struct stat fileinfo;

	/* allocate memory */
	mpq_a->mpq_l = (mpq_list *)malloc(sizeof(mpq_list));
	memset(mpq_a->mpq_l, 0, sizeof(mpq_list));
	mpq_a->header = (mpq_header *)malloc(sizeof(mpq_header));
	memset(mpq_a->header, 0, sizeof(mpq_header));

	/* Check if file exists and is readable */
	fd = _open((char *)mpq_filename, MPQ_FILE_OPEN_FLAGS);
	if (fd == LIBMPQ_EFILE) {
		return LIBMPQ_EFILE;
	}

	/* fill the structures with informations */
	strcpy((char *)mpq_a->filename, (char *)mpq_filename);
	libmpq_init_buffer(mpq_a);
	mpq_a->fd               = fd;
	mpq_a->header->id       = 0;
	mpq_a->maxblockindex    = 0;
	mpq_a->mpq_l->mpq_files = NULL;

    mpq_a->mpqpos = 0; //k

	while (!ncnt) {
		mpq_a->header->id = 0;
		#ifdef WIN32
			_lseeki64(mpq_a->fd, mpq_a->mpqpos, SEEK_SET);
		#else
			lseek64(mpq_a->fd, mpq_a->mpqpos, SEEK_SET);
		#endif
		rb = _read(mpq_a->fd, mpq_a->header, sizeof(mpq_header));

		/* if different number of bytes read, break the loop */
		if (rb != sizeof(mpq_header)) {
			return LIBMPQ_EFILE_FORMAT;
		}

		/* special offset for protected MPQs */
		if (mpq_a->header->offset == LIBMPQ_HEADER_W3M) {
			mpq_a->flags |= LIBMPQ_FLAG_PROTECTED;
			mpq_a->header->offset = sizeof(mpq_header);
		}

		/* if valid signature has been found, break the loop */
        if (mpq_a->header->id == LIBMPQ_ID_MPQ) {
            ncnt = true;
        }
        /*if (mpq_a->header->id == LIBMPQ_ID_MPQ &&
		    mpq_a->header->offset == sizeof(mpq_header) &&
		    mpq_a->header->hashtablepos < mpq_a->header->archivesize &&
		    mpq_a->header->blocktablepos < mpq_a->header->archivesize) {
			ncnt = TRUE;
		}*/

		/* move to the next possible offset */
		if (!ncnt) {
			mpq_a->mpqpos += 0x200;
		}
	}

	/* get the right positions of the hash table and the block table. */
	mpq_a->blocksize = (0x200 << mpq_a->header->blocksize);
	fstat(mpq_a->fd, &fileinfo);

	/* Normal MPQs must have position of */
	/*if (mpq_a->header->hashtablepos + mpq_a->mpqpos < fileinfo.st_size &&
	    mpq_a->header->blocktablepos + mpq_a->mpqpos < fileinfo.st_size) {
		mpq_a->header->hashtablepos  += mpq_a->mpqpos;
		mpq_a->header->blocktablepos += mpq_a->mpqpos;
	} else {
		return LIBMPQ_EFILE_FORMAT;
	}*/

	/* Try to read and decrypt the hashtable */
	if (libmpq_read_hashtable(mpq_a) != 0) {
		return LIBMPQ_EHASHTABLE;
	}

	/* Try to read and decrypt the blocktable */
	if (libmpq_read_blocktable(mpq_a) != 0) {
		return LIBMPQ_EBLOCKTABLE;
	}

	return LIBMPQ_TOOLS_SUCCESS;
}
示例#23
0
文件: img2simg.c 项目: Crixec/libmif
int img2simg_main(int argc, char *argv[])
{
  int in;
  int out;
  int ret;
  struct sparse_file *s;
  unsigned int block_size = 4096;
  off64_t len;

  if (argc < 3 || argc > 4) {
    img2simg_usage();
    return(-1);
  }

  if (argc == 4) {
    block_size = atoi(argv[3]);
  }

  if (block_size < 1024 || block_size % 4 != 0) {
    img2simg_usage();
    return(-1);
  }

  if (strcmp(argv[1], "-") == 0) {
    in = STDIN_FILENO;
  } else {
    in = open(argv[1], O_RDONLY | O_BINARY);
    if (in < 0) {
      fprintf(stderr, "Cannot open input file %s\n", argv[1]);
      return(-1);
    }
  }

  if (strcmp(argv[2], "-") == 0) {
    out = STDOUT_FILENO;
  } else {
    out = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0664);
    if (out < 0) {
      fprintf(stderr, "Cannot open output file %s\n", argv[2]);
      return(-1);
    }
  }

  len = lseek64(in, 0, SEEK_END);
  lseek64(in, 0, SEEK_SET);

  s = sparse_file_new(block_size, len);
  if (!s) {
    fprintf(stderr, "Failed to create sparse file\n");
    return(-1);
  }

  sparse_file_verbose(s);
  ret = sparse_file_read(s, in, false, false);
  if (ret) {
    fprintf(stderr, "Failed to read file\n");
    return(-1);
  }

  ret = sparse_file_write(s, out, false, true, false);
  if (ret) {
    fprintf(stderr, "Failed to write sparse file\n");
    return(-1);
  }

  close(in);
  close(out);

  return(0);
}
示例#24
0
static void
S_run_tests(void) {
    FILE *fh;
    off64_t offset;
    int check_val;
    char check_char;
    int fd;

    /* A little over 4 GB, and a little over 2 GB. */
    off64_t gb4_plus = ((off64_t)0x7FFFFFFF << 1) + 100;
    off64_t gb2_plus = (off64_t)0x7FFFFFFF + 200;

    LONG_EQ(sizeof(off64_t), 8, "off64_t type has 8 bytes");

#ifndef HAS_64BIT_STDIO
    SKIP_REMAINING("No stdio large file support");
    return;
#endif
#ifndef STAT_TESTS_ENABLED
    SKIP_REMAINING("Need stat with st_size and st_blocks");
    return;
#else
    /* Check for sparse files. */
    if (!S_check_sparse_files()) {
        SKIP_REMAINING("Can't verify large file support "
                       "without sparse files");
        return;
    }
    if (!S_can_create_big_files()) {
        SKIP_REMAINING("Unsafe to create 5GB sparse files on this system");
        return;
    }

    fh = fopen64("_charm_large_file_test", "w+");
    if (fh == NULL) {
        SKIP_REMAINING("Failed to open file");
        return;
    }

    check_val = fseeko64(fh, gb4_plus, SEEK_SET);
    LONG_EQ(check_val, 0, "fseeko64 above 4 GB");

    offset = ftello64(fh);
    OK((offset == gb4_plus), "ftello64 above 4 GB");

    check_val = fprintf(fh, "X");
    LONG_EQ(check_val, 1, "print above 4 GB");

    check_val = fseeko64(fh, gb2_plus, SEEK_SET);
    LONG_EQ(check_val, 0, "fseeko64 above 2 GB");

    offset = ftello64(fh);
    OK((offset == gb2_plus), "ftello64 above 2 GB");

    check_val = fseeko64(fh, -1, SEEK_END);
    LONG_EQ(check_val, 0, "seek to near end");

    check_char = fgetc(fh);
    LONG_EQ(check_char, 'X', "read value after multiple seeks");

    check_val = fclose(fh);
    LONG_EQ(check_val, 0, "fclose succeeds after all that");

    /* Truncate, just in case the call to remove fails. */
    fh = fopen64("_charm_large_file_test", "w+");
    if (fh != NULL) {
        fclose(fh);
    }
    remove("_charm_large_file_test");

#ifndef HAS_64BIT_LSEEK
    SKIP_REMAINING("No 64-bit lseek");
    return;
#else
    fd = open("_charm_large_file_test",
              O_RDWR | O_CREAT | LARGEFILE_OPEN_FLAG, 0666);
    if (fd == -1) {
        FAIL("open failed");
        SKIP_REMAINING("open failed");
        return;
    }

    offset = lseek64(fd, gb4_plus, SEEK_SET);
    OK(offset == gb4_plus, "lseek64 above 4 GB");

    offset = lseek64(fd, 0, SEEK_CUR);
    OK(offset == gb4_plus, "lseek64 in place above 4 GB");

    check_val = write(fd, "X", 1);
    LONG_EQ(check_val, 1, "write() above 4 GB");

    offset = lseek64(fd, gb2_plus, SEEK_SET);
    OK(offset == gb2_plus, "lseek64 above 2 GB");

    offset = lseek64(fd, 0, SEEK_CUR);
    OK((offset == gb2_plus), "lseek64 in place above 2 GB");

    offset = lseek64(fd, -1, SEEK_END);
    OK(offset == gb4_plus, "seek to near end");

    check_val = read(fd, &check_char, 1);
    LONG_EQ(check_val, 1, "read() after multiple lseek64 calls");
    LONG_EQ(check_char, 'X',
            "read() correct data after multiple lseek64 calls");
#ifdef HAS_64BIT_PREAD
    check_char = 0;
    check_val = pread64(fd, &check_char, 1, gb4_plus);
    LONG_EQ(check_val, 1, "pread64");
    LONG_EQ(check_char, 'X', "pread64() correct data");
#else
    SKIP("no pread64");
    SKIP("no pread64");
#endif

    check_val = close(fd);
    LONG_EQ(check_val, 0, "close succeeds after all that");
#endif

    /* Truncate, just in case the call to remove fails. */
    fh = fopen64("_charm_large_file_test", "w+");
    if (fh != NULL) {
        fclose(fh);
    }
    remove("_charm_large_file_test");
#endif /* STAT_TESTS_ENABLED */
}
示例#25
0
void Device::SetPos(hddsize pos) {
	// set position
	if(lseek64(fd, pos, SEEK_SET) < 0) {
		ReportError();
	}
}
示例#26
0
文件: file.c 项目: forostm/libecw
NCSError NCSRemoveDir( const char *pDirName)
{
#ifdef LINUX
	if(rmdir(pDirName) == 0) {
#elif defined(_WIN32_WCE)
	if(RemoveDirectory(OS_STRING(pDirName)) != 0) {
#else
	if(rmdir(pDirName) == 0) {
#endif
		return(NCS_SUCCESS);
	} else {
		return(NCS_FILEIO_ERROR);
	}
}

/* 
** Seek to given position
*/
INT64 NCSFileSeekNative(NCS_FILE_HANDLE hFile,
				  INT64 nOffset,
				  NCS_FILE_ORIGIN origin)
{
#if defined WIN32
	LARGE_INTEGER li;

	li.QuadPart = nOffset;

	li.LowPart = SetFilePointer(hFile,						// file handle
						li.LowPart,							// low 32 bits
						&li.HighPart,						// high 32 bits
						origin);						// relative to start of file

	if( li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR )
		return( -1 );
	else
		return( li.QuadPart );
#elif defined PALM
	switch(origin) {
		case NCS_FILE_SEEK_START:
				hFile->iOffset = nOffset;
			break;
		case NCS_FILE_SEEK_CURRENT:
				hFile->iOffset += nOffset;
			break;
		case NCS_FILE_SEEK_END:
				hFile->iOffset = hFile->nDBSize + nOffset - 1;
	}
	return(hFile->iOffset);
#elif defined MACINTOSH
	UINT32	myOffset;
	int		result; 
			
	myOffset = U32SetU(nOffset);
			
	if(!myOffset) result = 0;
			
	result = SetFPos((short)hFile, fsFromStart, myOffset);
			
	if(!result) return myOffset;
	else return (0);
#elif defined SOLARIS
	return (INT64) llseek(hFile, (offset_t)nOffset, origin);
#elif defined LINUX
	return (INT64) lseek64(hFile, (__off64_t)nOffset, origin);
#elif defined HPUX
	return (INT64) lseek64(hFile, (off64_t)nOffset, origin);
#elif defined IRIX
	return (INT64) lseek64(hFile, (off64_t)nOffset, origin);
#elif defined MACOSX
    return (INT64) lseek(hFile, nOffset, origin);
#endif
}

/*
** Get current file position
*/
INT64 NCSFileTellNative(NCS_FILE_HANDLE hFile)
{
#if defined WIN32
	LARGE_INTEGER li;

	li.QuadPart = 0;

	li.LowPart = SetFilePointer(hFile,						// file handle
						li.LowPart,							// low 32 bits
						&li.HighPart,						// high 32 bits
						FILE_CURRENT);						// relative to present position

	if( li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR )
		return(-1);
	else
		return(li.QuadPart);

#elif defined MACINTOSH

	long  myOffset;
	OSErr	result;
		
	result = GetFPos((short)hFile, &myOffset);
			
	if (result==noErr)
		return ((INT64)myOffset);
	else
		return ((INT64)-1);

#elif defined PALM
	return(hFile->iOffset);
#elif defined SOLARIS
	INT64 nOffset = llseek(hFile, (offset_t)0, SEEK_CUR);
	return(nOffset);
#elif defined IRIX
	return((INT64)telli64(hFile));
#elif defined LINUX
	return (INT64) lseek64(hFile, (__off64_t)0, SEEK_CUR);
#elif defined HPUX
	return (INT64) lseek64(hFile, (off64_t)0, SEEK_CUR);
#elif defined MACOSX
	return (INT64) lseek(hFile, (long)0, SEEK_CUR);
#else
#error ERROR: EcwFileGetPos() routine is not defined for this platform
#endif
}
示例#27
0
int get_devinfo(struct s_devinfo *outdev, char *indevname, int min, int maj)
{
    char sysblkdevname[512];
    blkid_tag_iterate iter;
    char sysblkinfo[PATH_MAX];
    const char *type, *value;
    struct stat64 statbuf;
    struct dirent *dir;
    char temp[PATH_MAX];
    blkid_dev dev;
    DIR *dirdesc;
    FILE *finfo;
    int found;
    int fd;
    int i;
    
    // init
    memset(outdev, 0, sizeof(struct s_devinfo));
    
    // defaults values
    outdev->devtype=BLKDEV_INVALID;
    snprintf(outdev->label, sizeof(outdev->label), "<unknown>");
    snprintf(outdev->uuid, sizeof(outdev->uuid), "<unknown>");
    snprintf(outdev->fsname, sizeof(outdev->fsname), "<unknown>");
    
    // check the name starts with "/dev/"
    if ((strlen(indevname) < 5) || (memcmp(indevname, "/dev/", 5)!=0))
        return -1;
    
    // get short name ("/dev/sda1" -> "sda1")
    snprintf(outdev->devname, sizeof(outdev->devname), "%s", indevname+5); // skip "/dev/"
    
    // get long name if there is one (eg: LVM / devmapper)
    snprintf(outdev->longname, sizeof(outdev->longname), "%s", indevname);
    if ((dirdesc=opendir("/dev/mapper"))!=NULL)
    {
        found=false;
        while (((dir=readdir(dirdesc)) != NULL) && found==false)
        {
            snprintf(temp, sizeof(temp), "/dev/mapper/%s", dir->d_name);
            if ((stat64(temp, &statbuf)==0) && S_ISBLK(statbuf.st_mode) && 
                (major(statbuf.st_rdev)==maj) && (minor(statbuf.st_rdev)==min))
            {
                snprintf(outdev->longname, sizeof(outdev->longname), "%s", temp);
                found=true;
            }
        }
        closedir(dirdesc);
    }
    
    // get device basic info (size, major, minor)
    if (((fd=open64(outdev->longname, O_RDONLY|O_LARGEFILE))<0) || 
        ((outdev->devsize=lseek64(fd, 0, SEEK_END))<0) ||
        (fstat64(fd, &statbuf)!=0) ||
        (!S_ISBLK(statbuf.st_mode)) ||
        (close(fd)<0))
        return -1;
    outdev->rdev=statbuf.st_rdev;
    outdev->major=major(statbuf.st_rdev);
    outdev->minor=minor(statbuf.st_rdev);
    format_size(outdev->devsize, outdev->txtsize, sizeof(outdev->txtsize), 'h');
    if (outdev->devsize==1024) // ignore extended partitions
        return -1;
    
    // devname shown in /sys/block (eg for HP-cciss: "cciss/c0d0" -> "cciss!c0d0")
    snprintf(sysblkdevname, sizeof(sysblkdevname), "%s", outdev->devname);
    for (i=0; (sysblkdevname[i]!=0) && (i<sizeof(sysblkdevname)); i++)
        if (sysblkdevname[i]=='/')
            sysblkdevname[i]='!';
    
    // check if it's a physical disk (there is a "/sys/block/${devname}/device")
    snprintf(sysblkinfo, sizeof(sysblkinfo), "/sys/block/%s/device", sysblkdevname);
    if (stat64(sysblkinfo, &statbuf)==0)
    {
        outdev->devtype=BLKDEV_PHYSDISK;
        snprintf(sysblkinfo, sizeof(sysblkinfo), "/sys/block/%s/device/model", sysblkdevname);
        if ( ((finfo=fopen(sysblkinfo, "rb")) != NULL) && (fread(temp, 1, sizeof(temp), finfo)>0) && fclose(finfo)==0 )
            for (i=0; (temp[i]!=0) && (temp[i]!='\r') && (temp[i]!='\n'); i++)
                outdev->name[i]=temp[i];
    }
    else
    {
        outdev->devtype=BLKDEV_FILESYSDEV;
    }
    
    // get blkid infos about the device (label, uuid)
    blkid_cache cache = NULL;
    if (blkid_get_cache(&cache, NULL) < 0)
        return -1;
    if ((dev=blkid_get_dev(cache, outdev->longname, BLKID_DEV_NORMAL))!=NULL)
    {
        iter = blkid_tag_iterate_begin(dev);
        while (blkid_tag_next(iter, &type, &value)==0)
        {
            if (strcmp(type, "LABEL")==0)
                snprintf(outdev->label, sizeof(outdev->label), "%s", value);
            else if (strcmp(type, "UUID")==0)
                snprintf(outdev->uuid, sizeof(outdev->uuid), "%s", value);
            else if (strcmp(type, "TYPE")==0)
                snprintf(outdev->fsname, sizeof(outdev->fsname), "%s", value);
        }
        blkid_tag_iterate_end(iter);
        
        // workaround: blkid < 1.41 don't know ext4 and say it is ext3 instead
        if (strcmp(outdev->fsname, "ext3")==0)
        {
            if (ext3_test(outdev->longname)==true)
                snprintf(outdev->fsname, sizeof(outdev->fsname), "ext3");
            else // cannot run ext4_test(): it would fail on an ext4 when e2fsprogs < 1.41
                snprintf(outdev->fsname, sizeof(outdev->fsname), "ext4");
        }
    }
    blkid_put_cache(cache); // free memory allocated by blkid_get_cache
    
    return 0;
}
示例#28
0
static void
writeblks(char *fname, int fd, size_t alignment)
{
	__uint64_t offset;
	char *buffer = NULL;
	int block;
	struct flock64 fl;

	if (!test) {
		if (posix_memalign((void **) &buffer, alignment, blocksize)) {
			perror("malloc");
			exit(1);
		}
		memset(buffer, 0, blocksize);
	}

	/*
	 * Avoid allocation patterns being perturbed by different speculative
	 * preallocation beyond EOF configurations by first truncating the file
	 * to the expected maximum file size.
	 */
	if (ftruncate(fd, filesize) < 0) {
		perror("ftruncate");
		exit(EXIT_FAILURE);
	}

	do {
		if (verbose && ((count % 100) == 0)) {
			printf(".");
			fflush(stdout);
		}
		block = findblock();
		if (block < 0) {
		    perror("findblock");
		    exit(1);
		}

		offset = (__uint64_t) block * blocksize;
		if (alloconly) {
                        if (test) continue;
                        
			fl.l_start = fileoffset + offset;
			fl.l_len = blocksize;
			fl.l_whence = 0;

			if (xfscntl(fname, fd, RESVSP64, &fl) < 0) {
				perror("xfsnctl(RESVSP64)");
				exit(1);
			}
			continue;
		}
		SETBIT(valid, block);
                if (!test) {
		        if (lseek64(fd, fileoffset + offset, SEEK_SET) < 0) {
			        perror("lseek");
			        exit(1);
		        }
			/*
			 * Before writing, record offset at the base
			 * of the buffer and at offset 256 bytes
			 * into it.  We'll verify this when we read
			 * it back in again.
			 */
			*(__uint64_t *) buffer = fileoffset + offset;
			*(__uint64_t *) (buffer + 256) = fileoffset + offset;

		        if (write(fd, buffer, blocksize) < blocksize) {
			        perror("write");
			        exit(1);
		        }
                }
		if (verbose > 1) {
			printf("%swriting data at offset=%llx\n",
				test ? "NOT " : "",
				(unsigned long long) (fileoffset + offset));
		}
	} while (--count);

	free(buffer);
}
示例#29
0
// Seeks to a location in the partition.  Don't mix with reads of
// anything other than whole blocks; unpredictable things will result.
void mtd_read_skip_to(const MtdReadContext* ctx, size_t offset) {
    lseek64(ctx->fd, offset, SEEK_SET);
}
示例#30
0
void blk_request(void *_vq)
{
	struct virtio_vq *vq = _vq;

	assert(vq != NULL);

	struct virtio_mmio_dev *dev = vq->vqdev->transport_dev;
	struct iovec *iov;
	uint32_t head;
	uint32_t olen, ilen;
	struct virtio_blk_outhdr *out;
	uint64_t offset;
	int64_t ret;
	size_t wlen;
	uint8_t *status;
	struct virtio_blk_config *cfg = vq->vqdev->cfg;

	if (vq->qready != 0x1)
		VIRTIO_DEV_ERRX(vq->vqdev,
		                "The service function for queue '%s' was launched before the driver set QueueReady to 0x1.",
		                 vq->name);

	if (!dev->poke_guest)
		VIRTIO_DEV_ERRX(vq->vqdev,
		                "The 'poke_guest' function pointer was not set.");

	iov = malloc(vq->qnum_max * sizeof(struct iovec));
	if (iov == NULL)
		VIRTIO_DEV_ERRX(vq->vqdev,
		                "malloc returned null trying to allocate iov.\n");

	for (;;) {
		head = virtio_next_avail_vq_desc(vq, iov, &olen, &ilen);
		/* There are always three iovecs.
		 * The first is the header.
		 * The second is the actual data.
		 * The third contains just the status byte.
		 */

		status = iov[2].iov_base;
		if (!status)
			VIRTIO_DEV_ERRX(vq->vqdev, "no room for status\n");

		out = iov[0].iov_base;
		if (out->type & VIRTIO_BLK_T_FLUSH)
			VIRTIO_DEV_ERRX(vq->vqdev, "Flush not supported.\n");

		offset = out->sector * 512;
		if (lseek64(diskfd, offset, SEEK_SET) != offset)
			VIRTIO_DEV_ERRX(vq->vqdev, "Bad seek at sector %llu\n",
			                out->sector);

		if (out->type & VIRTIO_BLK_T_OUT) {

			if ((offset + iov[1].iov_len) > (cfg->capacity * 512))
				VIRTIO_DEV_ERRX(vq->vqdev, "write past end of file!\n");

			ret = writev(diskfd, &iov[1], 1);

			if (ret >= 0 && ret == iov[1].iov_len)
				*status = VIRTIO_BLK_S_OK;
			else
				*status = VIRTIO_BLK_S_IOERR;
			wlen = sizeof(*status);
		} else {
			ret = readv(diskfd, &iov[1], 1);
			if (ret >= 0) {
				wlen = sizeof(*status) + ret;
				*status = VIRTIO_BLK_S_OK;
			} else {
				wlen = sizeof(*status);
				*status = VIRTIO_BLK_S_IOERR;
			}

			// Hexdump for debugging.
			if (debug_virtio_blk && ret >= 0) {
				char *pf = "";

				for (int i = 0; i < iov[olen].iov_len; i += 2) {
					uint8_t *p = (uint8_t *)iov[olen].iov_base + i;

					fprintf(stderr, "%s%02x", pf, *(p + 1));
					fprintf(stderr, "%02x", *p);
					fprintf(stderr, " ");
					pf = ((i + 2) % 16) ? " " : "\n";
				}
			}
		}

		virtio_add_used_desc(vq, head, wlen);
		virtio_mmio_set_vring_irq(dev);
		dev->poke_guest(dev->vec);
	}
}