コード例 #1
0
ファイル: ad_xfs_resize.c プロジェクト: ParaStation/psmpi2
void ADIOI_XFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code)
{
    int err;
    static char myname[] = "ADIOI_XFS_RESIZE";

    err = ftruncate64(fd->fd_sys, size);
    if (err == -1) {
        *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
                                           myname, __LINE__, MPI_ERR_IO, "**io",
                                           "**io %s", strerror(errno));
    } else
        *error_code = MPI_SUCCESS;
}
コード例 #2
0
ファイル: ARTfulkv4.c プロジェクト: achille/ARTful
ARTtrie *ARTnew (int fd)
{
int flag = PROT_READ | PROT_WRITE;
ARTnode256 *radix256, *root256;
ARTtrie *trie;
ulong offset;
uint i, j;

#ifdef PERSIST
	if( !(offset = lseek64 (fd, 0L, 2)) )
		ftruncate64 (fd, offset = ArenaInit);

	Arena = mmap (0, ArenaVM, flag, MAP_SHARED, fd, 0);
#else
	offset = ArenaVM;
	Arena = mmap(NULL, offset, flag, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
#endif

	ArenaFd = fd;

	trie = (ARTtrie *)Arena;
	trie->arena_size = offset;

	//	is this a new file?
	//	if so, fill out the first two levels
	//	of the trie with radix256 nodes.

	if( !trie->arena_next ) {
	  trie->arena_next = sizeof(ARTtrie);
	  root256 = (ARTnode256 *)(Arena + trie->arena_next);
	  trie->root->off = trie->arena_next >> 3;
	  trie->root->type = Array256;
	  trie->arena_next += sizeof(ARTnode256);

	  for( i = 0; i < 256; i++ ) {
		radix256 = (ARTnode256 *)(Arena + trie->arena_next);
		root256->radix[i].off = trie->arena_next >> 3;
		root256->radix[i].type = Array256;
		trie->arena_next += sizeof(ARTnode256);
//		for( j = 0; j < 256; j++ ) { // fill in 3rd level
//			radix256[i].radix[j].off = trie->arena_next >> 3;
//			radix256[i].radix[j].type = Array256;
//	  		trie->arena_next += sizeof(ARTnode256);
//		}
	  }

	  // round up to complete the first chunks

	  trie->arena_next |= ARENA_chunk - 1;
	  trie->arena_next++;
	}
コード例 #3
0
ファイル: pal_io.c プロジェクト: KrzysztofCwalina/corefx
int32_t SystemNative_FTruncate(intptr_t fd, int64_t length)
{
    int32_t result;
    while ((
        result =
#if HAVE_FTRUNCATE64
        ftruncate64(
#else
        ftruncate(
#endif
            ToFileDescriptor(fd),
            (off_t)length)) < 0 && errno == EINTR);
    return result;
}
コード例 #4
0
ファイル: file.c プロジェクト: CS461-CUDA-Benchmark/benchmark
exception_t* file_free(file_t* file) {
	char* function_name = "file_free()";
	exception_t* exception;

	// Validate parameters.
	if ( file == NULL ) {
		return exception_throw("file was NULL.", function_name);
	}

	// Write metadata or truncate file.
	// Note that file->flag reflects the file when it was opened,
	// and the file is now the _opposite_ of what the flag states.
	if ( file->flag == UNENCRYPTED ) {
		// Write padding to the end of the file.
		exception = file_write_metadata(file);
		if ( exception != NULL ) {
			return exception_append(exception, function_name);
		}
	}
	else if ( file->flag == ENCRYPTED ) {
		// Truncate the file padding.
		if ( ftruncate64(file->fd, (off64_t)(file->size - (off64_t)file->padding)) == -1 ) {
			return exception_throw("Unable to truncate file.", function_name);
		}
	}
	else {
		return exception_throw("Unexpected flag.", function_name);
	}

	// Free file name,
	free(file->name);

	// Close the file.
	if ( close(file->fd) == -1 ) {
		perror("Unable to close file.");
		return exception_throw("Unable to close file.", function_name);
	}

	// Set structure defaults.
	file->blocks = NULL;
	file->name = NULL;
	file->block_count = 0;
	file->size = 0;
	file->padding = 0;
	file->fd = 0;
	file->flag = 0;

	// Return success.
	return NULL;
}
コード例 #5
0
ファイル: pal_io.cpp プロジェクト: AArnott/corefx
extern "C" int32_t SystemNative_FTruncate(intptr_t fd, int64_t length)
{
    int32_t result;
    while (CheckInterrupted(
        result =
#if HAVE_FTRUNCATE64
        ftruncate64(
#else
        ftruncate(
#endif
            ToFileDescriptor(fd),
            length)));
    return result;
}
コード例 #6
0
ファイル: file_trunc.c プロジェクト: 64116278/zfs
static void
do_trunc(int fd)
{
	off_t   roffset = 0;

	roffset = random() % fsize;
	if (ftruncate64(fd, (offset + roffset))  < 0) {
		perror("truncate");
		exit(7);
	}

	if (vflag) {
		(void) fprintf(stderr, "Truncated at offset %" PRId64 "\n",
		    (offset + roffset));
	}
}
コード例 #7
0
ファイル: 15846_0.c プロジェクト: B-Rich/osf_db
int main(int argc, char **argv)
{
	int fd, fd1, ret;
	char *buf;
	char wbuf[8192];
	unsigned long long offset = 0xffffff000ULL;
	char *p=wbuf;

	fd = open(FILENAME, O_RDWR|O_CREAT|O_LARGEFILE/*|O_TRUNC*/, 0644);
	if (fd < 0) {
		perror(FILENAME);
		return -1;
	}

	ftruncate64(fd, offset + 4096*4);
	buf = mmap64(NULL, 4096*4, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
	if (buf == MAP_FAILED) {
		perror("mmap");
		return -1;
	}

	fd1 = open(FILENAME, O_RDWR|O_DIRECT|O_LARGEFILE, 0644);
	if (fd < 0) {
		perror(FILENAME);
		return -1;
	}

	p = (char *)((unsigned long) p | 4095)+1;


	if (fork()) {
		while(1) {
			/* map in the page */
			buf[10] = 1;
		}
	} else {
		ret = pwrite64(fd1, p, 4096, offset);
		if (ret < 4096) {
			printf("write: %d %p\n", ret, p);
			perror("write");
			return -1;
		}
	}

	return 0;
}
コード例 #8
0
ファイル: truncate.c プロジェクト: Claruarius/stblinux-2.6.37
static int
truncate_f(
	int		argc,
	char		**argv)
{
	off64_t		offset;
	size_t		blocksize, sectsize;

	init_cvtnum(&blocksize, &sectsize);
	offset = cvtnum(blocksize, sectsize, argv[1]);
	if (offset < 0) {
		printf(_("non-numeric truncate argument -- %s\n"), argv[1]);
		return 0;
	}

	if (ftruncate64(file->fd, offset) < 0) {
		perror("ftruncate");
		return 0;
	}
	return 0;
}
コード例 #9
0
ファイル: file.c プロジェクト: CS461-CUDA-Benchmark/benchmark
exception_t* file_read_metadata(file_t* file) {
	char* function_name = "file_read_metadata()";
	long long temp;

	// Validate parameters.
	if ( file == NULL ) {
		return exception_throw("file was NULL.", function_name);
	}

	// Seek to end of the file.
	temp = lseek64(file->fd, 0, SEEK_END);
	if ( temp == -1 ) {
		perror(NULL);
		return exception_throw("Unable to lseek to file end.", function_name);
	}

	// Move back by the size of the metadata.
	temp = lseek64(file->fd, (int)(-sizeof(file->padding)), SEEK_CUR);
	if ( temp == -1 ) {
		perror(NULL);
		return exception_throw("Unable to lseek to metadata.", function_name);
	}

	// Read in metadata.
	temp = read(file->fd, &file->padding, sizeof(file->padding));
	if ( temp == -1 ) {
		perror(NULL);
		return exception_throw("Unable to read in metadata.", function_name);
	}

	// Delete the metadata.
	file->size -= sizeof(file->padding);
	if ( ftruncate64(file->fd, (off64_t)(file->size)) == -1 ) {
		perror(NULL);
		return exception_throw("Unable to truncate metadata.", function_name);
	}

	// Return success.
	return NULL;
}
コード例 #10
0
ファイル: tclUnixChan.c プロジェクト: smh377/tcl
static int
FileTruncateProc(
    ClientData instanceData,
    Tcl_WideInt length)
{
    FileState *fsPtr = instanceData;
    int result;

#ifdef HAVE_TYPE_OFF64_T
    /*
     * We assume this goes with the type for now...
     */

    result = ftruncate64(fsPtr->fd, (off64_t) length);
#else
    result = ftruncate(fsPtr->fd, (off_t) length);
#endif
    if (result) {
	return errno;
    }
    return 0;
}
コード例 #11
0
void
xftruncate (int fd, long long length)
{
  if (ftruncate64 (fd, length) != 0)
    FAIL_EXIT1 ("ftruncate64 (%d, %lld): %m", fd, length);
}
コード例 #12
0
ファイル: wrappers.c プロジェクト: BhargavKola/xenomai-forge
int __real_ftruncate64(int fildes, long long length)
{
	return ftruncate64(fildes, length);
}
コード例 #13
0
ファイル: padding_encoding.c プロジェクト: graingert/6share
int padding_decoder(char *file_name, unsigned long long content_length) {

  int fp_in;
  unsigned long long f_size;

#ifdef _MSC_VER
  struct __stat64 file_stats;
#else  
  struct stat64 file_stats;
#endif

  char file_name_in[256] = "";
  char file_name_out[256] = "";
  char *ptr;
  int retval;

  strcpy(file_name_in, file_name);  
  ptr = strstr(file_name_in, PAD_SUFFIX);

  memcpy(file_name_out, file_name_in, (ptr - file_name_in));

#ifdef _MSC_VER
  fp_in = open((const char*)file_name_in, _O_RDWR | _O_CREAT | _O_BINARY, _S_IREAD | _S_IWRITE);
#else
  fp_in = open64(file_name_in, O_RDWR | O_CREAT, S_IRWXU);
#endif

  if(fp_in == -1) {
    printf("open error: %s\n", file_name_in);
    return -1;
  }

#ifdef _MSC_VER
  _fstat64(fp_in, &file_stats);
#else
  fstat64(fp_in, &file_stats);
#endif

  f_size = file_stats.st_size;

  if(f_size > content_length) {
#ifdef _MSC_VER
    retval = _chsize(fp_in, (long)content_length); /* TODO: 64 bits, how ??? */
#else
	  retval = ftruncate64(fp_in, content_length);
#endif

	  if(retval != 0) {
		  printf("Problem in padding decoding.\n" );
		  close(fp_in);
		  return -1;
	  }
  }

  close(fp_in);
	 
	if(rename(file_name_in, file_name_out) < 0) {

		if(errno == EEXIST) {
			retval = remove(file_name_out);
		
			if(retval == -1) {    
				printf("errno: %i\n", errno);
				fflush(stdout);
				close(fp_in);
				return -1;
			}
		
			if(rename(file_name_in, file_name_out) < 0) {
				printf("rename() error1: %s\n", file_name_in);
				fflush(stdout);
				close(fp_in);
				return -1;
			}
		}
		else {
			printf("rename() error2: %s\n", file_name_in);
			fflush(stdout);
			close(fp_in);
			return -1;
		}
	}

  return 0;
}
コード例 #14
0
ファイル: xfs_copy.c プロジェクト: Claruarius/stblinux-2.6.37
int
main(int argc, char **argv)
{
	int		i, j;
	int		howfar = 0;
	int		open_flags;
	xfs_off_t	pos, end_pos;
	size_t		length;
	int		c, first_residue, tmp_residue;
	__uint64_t	size, sizeb;
	__uint64_t	numblocks = 0;
	int		wblocks = 0;
	int		num_threads = 0;
	struct dioattr	d;
	int		wbuf_size;
	int		wbuf_align;
	int		wbuf_miniosize;
	int		source_is_file = 0;
	int		buffered_output = 0;
	int		duplicate = 0;
	uint		btree_levels, current_level;
	ag_header_t	ag_hdr;
	xfs_mount_t	*mp;
	xfs_mount_t	mbuf;
	xfs_buf_t	*sbp;
	xfs_sb_t	*sb;
	xfs_agnumber_t	num_ags, agno;
	xfs_agblock_t	bno;
	xfs_daddr_t	begin, next_begin, ag_begin, new_begin, ag_end;
	struct xfs_btree_block *block;
	xfs_alloc_ptr_t	*ptr;
	xfs_alloc_rec_t	*rec_ptr;
	extern char	*optarg;
	extern int	optind;
	libxfs_init_t	xargs;
	thread_args	*tcarg;
	struct stat64	statbuf;

	progname = basename(argv[0]);

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	while ((c = getopt(argc, argv, "bdL:V")) != EOF)  {
		switch (c) {
		case 'b':
			buffered_output = 1;
			break;
		case 'd':
			duplicate = 1;
			break;
		case 'L':
			logfile_name = optarg;
			break;
		case 'V':
			printf(_("%s version %s\n"), progname, VERSION);
			exit(0);
		case '?':
			usage();
		}
	}

	if (argc - optind < 2)
		usage();

	if (logfile_name)  {
		logfd = open(logfile_name, O_CREAT|O_WRONLY|O_EXCL, 0600);
	} else  {
		logfile_name = LOGFILE_NAME;
		logfd = mkstemp(logfile_name);
	}

	if (logfd < 0)  {
		fprintf(stderr, _("%s: couldn't open log file \"%s\"\n"),
			progname, logfile_name);
		perror(_("Aborting XFS copy - reason"));
		exit(1);
	}

	if ((logerr = fdopen(logfd, "w")) == NULL)  {
		fprintf(stderr, _("%s: couldn't set up logfile stream\n"),
			progname);
		perror(_("Aborting XFS copy - reason"));
		exit(1);
	}

	source_name = argv[optind];
	source_fd = -1;
	optind++;

	num_targets = argc - optind;
	if ((target = malloc(sizeof(target_control) * num_targets)) == NULL)  {
		do_log(_("Couldn't allocate target array\n"));
		die_perror();
	}
	for (i = 0; optind < argc; i++, optind++)  {
		target[i].name = argv[optind];
		target[i].fd = -1;
		target[i].position = -1;
		target[i].state = INACTIVE;
		target[i].error = 0;
		target[i].err_type = 0;
	}

	parent_pid = getpid();

	if (atexit(killall))  {
		do_log(_("%s: couldn't register atexit function.\n"), progname);
		die_perror();
	}

	/* open up source -- is it a file? */

	open_flags = O_RDONLY;

	if ((source_fd = open(source_name, open_flags)) < 0)  {
		do_log(_("%s:  couldn't open source \"%s\"\n"),
			progname, source_name);
		die_perror();
	}

	if (fstat64(source_fd, &statbuf) < 0)  {
		do_log(_("%s:  couldn't stat source \"%s\"\n"),
			progname, source_name);
		die_perror();
	}

	if (S_ISREG(statbuf.st_mode))
		source_is_file = 1;

	if (source_is_file && platform_test_xfs_fd(source_fd))  {
		if (fcntl(source_fd, F_SETFL, open_flags | O_DIRECT) < 0)  {
			do_log(_("%s: Cannot set direct I/O flag on \"%s\".\n"),
				progname, source_name);
			die_perror();
		}
		if (xfsctl(source_name, source_fd, XFS_IOC_DIOINFO, &d) < 0)  {
			do_log(_("%s: xfsctl on file \"%s\" failed.\n"),
				progname, source_name);
			die_perror();
		}

		wbuf_align = d.d_mem;
		wbuf_size = MIN(d.d_maxiosz, 1 * 1024 * 1024);
		wbuf_miniosize = d.d_miniosz;
	} else  {
		/* set arbitrary I/O params, miniosize at least 1 disk block */

		wbuf_align = getpagesize();
		wbuf_size = 1 * 1024 * 1024;
		wbuf_miniosize = -1;	/* set after mounting source fs */
	}

	if (!source_is_file)  {
		/*
		 * check to make sure a filesystem isn't mounted
		 * on the device
		 */
		if (platform_check_ismounted(source_name, NULL, &statbuf, 0))  {
			do_log(
	_("%s:  Warning -- a filesystem is mounted on the source device.\n"),
				progname);
			do_log(
	_("\t\tGenerated copies may be corrupt unless the source is\n"));
			do_log(
	_("\t\tunmounted or mounted read-only.  Copy proceeding...\n"));
		}
	}

	/* prepare the libxfs_init structure */

	memset(&xargs, 0, sizeof(xargs));
	xargs.isdirect = LIBXFS_DIRECT;
	xargs.isreadonly = LIBXFS_ISREADONLY;

	if (source_is_file)  {
		xargs.dname = source_name;
		xargs.disfile = 1;
	} else
		xargs.volname = source_name;

	if (!libxfs_init(&xargs))  {
		do_log(_("%s: couldn't initialize XFS library\n"
			"%s: Aborting.\n"), progname, progname);
		exit(1);
	}

	/* prepare the mount structure */

	sbp = libxfs_readbuf(xargs.ddev, XFS_SB_DADDR, 1, 0);
	memset(&mbuf, 0, sizeof(xfs_mount_t));
	sb = &mbuf.m_sb;
	libxfs_sb_from_disk(sb, XFS_BUF_TO_SBP(sbp));

	mp = libxfs_mount(&mbuf, sb, xargs.ddev, xargs.logdev, xargs.rtdev, 1);
	if (mp == NULL) {
		do_log(_("%s: %s filesystem failed to initialize\n"
			"%s: Aborting.\n"), progname, source_name, progname);
		exit(1);
	} else if (mp->m_sb.sb_inprogress)  {
		do_log(_("%s %s filesystem failed to initialize\n"
			"%s: Aborting.\n"), progname, source_name, progname);
		exit(1);
	} else if (mp->m_sb.sb_logstart == 0)  {
		do_log(_("%s: %s has an external log.\n%s: Aborting.\n"),
			progname, source_name, progname);
		exit(1);
	} else if (mp->m_sb.sb_rextents != 0)  {
		do_log(_("%s: %s has a real-time section.\n"
			"%s: Aborting.\n"), progname, source_name, progname);
		exit(1);
	}

	source_blocksize = mp->m_sb.sb_blocksize;
	source_sectorsize = mp->m_sb.sb_sectsize;

	if (wbuf_miniosize == -1)
		wbuf_miniosize = source_sectorsize;

	ASSERT(source_blocksize % source_sectorsize == 0);
	ASSERT(source_sectorsize % BBSIZE == 0);

	if (source_blocksize > source_sectorsize)  {
		/* get number of leftover sectors in last block of ag header */

		tmp_residue = ((XFS_AGFL_DADDR(mp) + 1) * source_sectorsize)
					% source_blocksize;
		first_residue = (tmp_residue == 0) ? 0 :
			source_blocksize - tmp_residue;
		ASSERT(first_residue % source_sectorsize == 0);
	} else if (source_blocksize == source_sectorsize)  {
		first_residue = 0;
	} else  {
		do_log(_("Error:  filesystem block size is smaller than the"
			" disk sectorsize.\nAborting XFS copy now.\n"));
		exit(1);
	}

	first_agbno = (((XFS_AGFL_DADDR(mp) + 1) * source_sectorsize)
				+ first_residue) / source_blocksize;
	ASSERT(first_agbno != 0);
	ASSERT( ((((XFS_AGFL_DADDR(mp) + 1) * source_sectorsize)
				+ first_residue) % source_blocksize) == 0);

	/* now open targets */

	open_flags = O_RDWR;

	for (i = 0; i < num_targets; i++)  {
		int	write_last_block = 0;

		if (stat64(target[i].name, &statbuf) < 0)  {
			/* ok, assume it's a file and create it */

			do_out(_("Creating file %s\n"), target[i].name);

			open_flags |= O_CREAT;
			if (!buffered_output)
				open_flags |= O_DIRECT;
			write_last_block = 1;
		} else if (S_ISREG(statbuf.st_mode))  {
			open_flags |= O_TRUNC;
			if (!buffered_output)
				open_flags |= O_DIRECT;
			write_last_block = 1;
		} else  {
			/*
			 * check to make sure a filesystem isn't mounted
			 * on the device
			 */
			if (platform_check_ismounted(target[i].name,
							NULL, &statbuf, 0))  {
				do_log(_("%s:  a filesystem is mounted "
					"on target device \"%s\".\n"
					"%s cannot copy to mounted filesystems."
					"  Aborting\n"),
					progname, target[i].name, progname);
				exit(1);
			}
		}

		target[i].fd = open(target[i].name, open_flags, 0644);
		if (target[i].fd < 0)  {
			do_log(_("%s:  couldn't open target \"%s\"\n"),
				progname, target[i].name);
			die_perror();
		}

		if (write_last_block)  {
			/* ensure regular files are correctly sized */

			if (ftruncate64(target[i].fd, mp->m_sb.sb_dblocks *
						source_blocksize))  {
				do_log(_("%s:  cannot grow data section.\n"),
					progname);
				die_perror();
			}
			if (platform_test_xfs_fd(target[i].fd))  {
				if (xfsctl(target[i].name, target[i].fd,
						XFS_IOC_DIOINFO, &d) < 0)  {
					do_log(
				_("%s:  xfsctl on \"%s\" failed.\n"),
						progname, target[i].name);
					die_perror();
				} else {
					wbuf_align = MAX(wbuf_align, d.d_mem);
					wbuf_size = MIN(d.d_maxiosz, wbuf_size);
					wbuf_miniosize = MAX(d.d_miniosz,
								wbuf_miniosize);
				}
			}
		} else  {
			char	*lb[XFS_MAX_SECTORSIZE] = { NULL };
			off64_t	off;

			/* ensure device files are sufficiently large */

			off = mp->m_sb.sb_dblocks * source_blocksize;
			off -= sizeof(lb);
			if (pwrite64(target[i].fd, lb, sizeof(lb), off) < 0)  {
				do_log(_("%s:  failed to write last block\n"),
					progname);
				do_log(_("\tIs target \"%s\" too small?\n"),
					target[i].name);
				die_perror();
			}
		}
	}

	/* initialize locks and bufs */

	if (pthread_mutex_init(&glob_masks.mutex, NULL) != 0)  {
		do_log(_("Couldn't initialize global thread mask\n"));
		die_perror();
	}
	glob_masks.num_working = 0;

	if (wbuf_init(&w_buf, wbuf_size, wbuf_align,
					wbuf_miniosize, 0) == NULL)  {
		do_log(_("Error initializing wbuf 0\n"));
		die_perror();
	}

	wblocks = wbuf_size / BBSIZE;

	if (wbuf_init(&btree_buf, MAX(source_blocksize, wbuf_miniosize),
				wbuf_align, wbuf_miniosize, 1) == NULL)  {
		do_log(_("Error initializing btree buf 1\n"));
		die_perror();
	}

	if (pthread_mutex_init(&mainwait,NULL) != 0)  {
		do_log(_("Error creating first semaphore.\n"));
		die_perror();
		exit(1);
	}
	/* need to start out blocking */
	pthread_mutex_lock(&mainwait);

	/* set up sigchild signal handler */

	signal(SIGCHLD, handler);
	signal_maskfunc(SIGCHLD, SIG_BLOCK);

	/* make children */

	if ((targ = malloc(num_targets * sizeof(thread_args))) == NULL)  {
		do_log(_("Couldn't malloc space for thread args\n"));
		die_perror();
		exit(1);
	}

	for (i = 0, tcarg = targ; i < num_targets; i++, tcarg++)  {
		if (!duplicate)
			platform_uuid_generate(&tcarg->uuid);
		else
			platform_uuid_copy(&tcarg->uuid, &mp->m_sb.sb_uuid);

		if (pthread_mutex_init(&tcarg->wait, NULL) != 0)  {
			do_log(_("Error creating thread mutex %d\n"), i);
			die_perror();
			exit(1);
		}
		/* need to start out blocking */
		pthread_mutex_lock(&tcarg->wait);
	}

	for (i = 0, tcarg = targ; i < num_targets; i++, tcarg++)  {
		tcarg->id = i;
		tcarg->fd = target[i].fd;

		target[i].state = ACTIVE;
		num_threads++;

		if (pthread_create(&target[i].pid, NULL,
					begin_reader, (void *)tcarg))  {
			do_log(_("Error creating thread for target %d\n"), i);
			die_perror();
		}
	}

	ASSERT(num_targets == num_threads);

	/* set up statistics */

	num_ags = mp->m_sb.sb_agcount;

	init_bar(mp->m_sb.sb_blocksize / BBSIZE
			* ((__uint64_t)mp->m_sb.sb_dblocks
			    - (__uint64_t)mp->m_sb.sb_fdblocks + 10 * num_ags));

	kids = num_targets;
	block = (struct xfs_btree_block *) btree_buf.data;

	for (agno = 0; agno < num_ags && kids > 0; agno++)  {
		/* read in first blocks of the ag */

		read_ag_header(source_fd, agno, &w_buf, &ag_hdr, mp,
			source_blocksize, source_sectorsize);

		/* set the in_progress bit for the first AG */

		if (agno == 0)
			ag_hdr.xfs_sb->sb_inprogress = 1;

		/* save what we need (agf) in the btree buffer */

		memmove(btree_buf.data, ag_hdr.xfs_agf, source_sectorsize);
		ag_hdr.xfs_agf = (xfs_agf_t *) btree_buf.data;
		btree_buf.length = source_blocksize;

		/* write the ag header out */

		write_wbuf();

		/* traverse btree until we get to the leftmost leaf node */

		bno = be32_to_cpu(ag_hdr.xfs_agf->agf_roots[XFS_BTNUM_BNOi]);
		current_level = 0;
		btree_levels = be32_to_cpu(ag_hdr.xfs_agf->
						agf_levels[XFS_BTNUM_BNOi]);

		ag_end = XFS_AGB_TO_DADDR(mp, agno,
				be32_to_cpu(ag_hdr.xfs_agf->agf_length) - 1)
				+ source_blocksize / BBSIZE;

		for (;;) {
			/* none of this touches the w_buf buffer */

			ASSERT(current_level < btree_levels);

			current_level++;

			btree_buf.position = pos = (xfs_off_t)
				XFS_AGB_TO_DADDR(mp,agno,bno) << BBSHIFT;
			btree_buf.length = source_blocksize;

			read_wbuf(source_fd, &btree_buf, mp);
			block = (struct xfs_btree_block *)
				 ((char *)btree_buf.data +
				  pos - btree_buf.position);

			ASSERT(be32_to_cpu(block->bb_magic) == XFS_ABTB_MAGIC);

			if (be16_to_cpu(block->bb_level) == 0)
				break;

			ptr = XFS_ALLOC_PTR_ADDR(mp, block, 1,
							mp->m_alloc_mxr[1]);
			bno = be32_to_cpu(ptr[0]);
		}

		/* align first data copy but don't overwrite ag header */

		pos = w_buf.position >> BBSHIFT;
		length = w_buf.length >> BBSHIFT;
		next_begin = pos + length;
		ag_begin = next_begin;

		ASSERT(w_buf.position % source_sectorsize == 0);

		/* handle the rest of the ag */

		for (;;) {
			if (be16_to_cpu(block->bb_level) != 0)  {
				do_log(
			_("WARNING:  source filesystem inconsistent.\n"));
				do_log(
			_("  A leaf btree rec isn't a leaf.  Aborting now.\n"));
				exit(1);
			}

			rec_ptr = XFS_ALLOC_REC_ADDR(mp, block, 1);
			for (i = 0; i < be16_to_cpu(block->bb_numrecs);
							i++, rec_ptr++)  {
				/* calculate in daddr's */

				begin = next_begin;

				/*
				 * protect against pathological case of a
				 * hole right after the ag header in a
				 * mis-aligned case
				 */

				if (begin < ag_begin)
					begin = ag_begin;

				/*
				 * round size up to ensure we copy a
				 * range bigger than required
				 */

				sizeb = XFS_AGB_TO_DADDR(mp, agno, 
					be32_to_cpu(rec_ptr->ar_startblock)) - 
						begin;
				size = roundup(sizeb <<BBSHIFT, wbuf_miniosize);
				if (size > 0)  {
					/* copy extent */

					w_buf.position = (xfs_off_t)
						begin << BBSHIFT;

					while (size > 0)  {
						/*
						 * let lower layer do alignment
						 */
						if (size > w_buf.size)  {
							w_buf.length = w_buf.size;
							size -= w_buf.size;
							sizeb -= wblocks;
							numblocks += wblocks;
						} else  {
							w_buf.length = size;
							numblocks += sizeb;
							size = 0;
						}

						read_wbuf(source_fd, &w_buf, mp);
						write_wbuf();

						w_buf.position += w_buf.length;

						howfar = bump_bar(
							howfar, numblocks);
					}
				}

				/* round next starting point down */

				new_begin = XFS_AGB_TO_DADDR(mp, agno,
						be32_to_cpu(rec_ptr->ar_startblock) +
					 	be32_to_cpu(rec_ptr->ar_blockcount));
				next_begin = rounddown(new_begin,
						w_buf.min_io_size >> BBSHIFT);
			}

			if (be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK)
				break;

			/* read in next btree record block */

			btree_buf.position = pos = (xfs_off_t)
				XFS_AGB_TO_DADDR(mp, agno, be32_to_cpu(
						block->bb_u.s.bb_rightsib)) << BBSHIFT;
			btree_buf.length = source_blocksize;

			/* let read_wbuf handle alignment */

			read_wbuf(source_fd, &btree_buf, mp);

			block = (struct xfs_btree_block *)
				 ((char *) btree_buf.data +
				  pos - btree_buf.position);

			ASSERT(be32_to_cpu(block->bb_magic) == XFS_ABTB_MAGIC);
		}

		/*
		 * write out range of used blocks after last range
		 * of free blocks in AG
		 */
		if (next_begin < ag_end)  {
			begin = next_begin;

			sizeb = ag_end - begin;
			size = roundup(sizeb << BBSHIFT, wbuf_miniosize);

			if (size > 0)  {
				/* copy extent */

				w_buf.position = (xfs_off_t) begin << BBSHIFT;

				while (size > 0)  {
					/*
					 * let lower layer do alignment
					 */
					if (size > w_buf.size)  {
						w_buf.length = w_buf.size;
						size -= w_buf.size;
						sizeb -= wblocks;
						numblocks += wblocks;
					} else  {
						w_buf.length = size;
						numblocks += sizeb;
						size = 0;
					}

					read_wbuf(source_fd, &w_buf, mp);
					write_wbuf();

					w_buf.position += w_buf.length;

					howfar = bump_bar(howfar, numblocks);
				}
			}
		}
	}

	if (kids > 0)  {
		if (!duplicate)  {

			/* write a clean log using the specified UUID */
			for (j = 0, tcarg = targ; j < num_targets; j++)  {
				w_buf.owner = tcarg;
				w_buf.length = rounddown(w_buf.size,
							 w_buf.min_io_size);
				pos = write_log_header(
							source_fd, &w_buf, mp);
				end_pos = write_log_trailer(
							source_fd, &w_buf, mp);
				w_buf.position = pos;
				memset(w_buf.data, 0, w_buf.length);

				while (w_buf.position < end_pos)  {
					do_write(tcarg);
					w_buf.position += w_buf.length;
				}
				tcarg++;
			}
		} else {
			num_ags = 1;
		}

		/* reread and rewrite superblocks (UUID and in-progress) */
		/* [backwards, so inprogress bit only updated when done] */

		for (i = num_ags - 1; i >= 0; i--)  {
			read_ag_header(source_fd, i, &w_buf, &ag_hdr, mp,
				source_blocksize, source_sectorsize);
			if (i == 0)
				ag_hdr.xfs_sb->sb_inprogress = 0;

			/* do each thread in turn, each has its own UUID */

			for (j = 0, tcarg = targ; j < num_targets; j++)  {
				platform_uuid_copy(&ag_hdr.xfs_sb->sb_uuid,
							&tcarg->uuid);
				do_write(tcarg);
				tcarg++;
			}
		}

		bump_bar(100, 0);
	}

	check_errors();
	killall();
	pthread_exit(NULL);
	/*NOTREACHED*/
	return 0;
}
コード例 #15
0
ファイル: node.c プロジェクト: ystk/debian-xfsdump
/* ARGSUSED */
bool_t
node_init( intgen_t fd,
           off64_t off,
           size_t usrnodesz,
           ix_t nodehkix,
           size_t nodealignsz,
           size64_t vmsz,
           size64_t dirs_nondirs_cnt )
{
    size64_t nodesz;
    size64_t winmap_mem;
    size64_t segsz;
    size64_t segtablesz;
    size64_t nodesperseg;
    size64_t minsegsz;
    size64_t winmapmax;
    intgen_t rval;

    /* sanity checks
     */
    ASSERT( sizeof( node_hdr_t ) <= NODE_HDRSZ );
    ASSERT( sizeof( nh_t ) < sizeof( off64_t ));
    ASSERT( nodehkix < usrnodesz );
    ASSERT( usrnodesz >= sizeof( char * ) + 1 );
    /* so node is at least big enough to hold
     * the free list linkage and the housekeeping byte
     */
    ASSERT( nodehkix > sizeof( char * ));
    /* since beginning of each node is used to
     * link it in the free list.
     */

    /* adjust the user's node size to meet user's alignment constraint
    */
    nodesz = ( usrnodesz + nodealignsz - 1 ) & ~( nodealignsz - 1 );

#define	WINMAP_MAX	20	/* maximum number of windows to use */
#define	WINMAP_MIN	4	/* minimum number of windows to use */
#define	HARDLINK_FUDGE	1.2	/* approx 1.2 hard links per file */

    /* Calculate the expected size of the segment table using the number
     * of dirs and non-dirs.  Since we don't know how many hard-links
     * there will be, scale the size upward using HARDLINK_FUDGE.
     */

    segtablesz = ( (size64_t)(HARDLINK_FUDGE * (double)dirs_nondirs_cnt) * nodesz);

    /* Figure out how much memory is available for use by winmaps, and
     * use that to pick an appropriate winmapmax, segsz, and nodesperseg,
     * the goal being that if at all possible we want the entire segment
     * table to be mapped so that we aren't constantly mapping and
     * unmapping winmaps.  There must be at least WINMAP_MIN winmaps
     * because references can be held on more than one winmap at the
     * same time.  More winmaps are generally better to reduce the
     * number of nodes that are unmapped if unmapping does occur.
     */

    minsegsz = pgsz * nodesz;	/* must be pgsz and nodesz multiple */
    winmap_mem = min(vmsz, segtablesz);
    segsz = (((winmap_mem / WINMAP_MAX) + minsegsz - 1) / minsegsz) * minsegsz;
    segsz = max(segsz, minsegsz);

    nodesperseg = segsz / nodesz;

    winmapmax = min(WINMAP_MAX, vmsz / segsz);
    winmapmax = max(winmapmax, WINMAP_MIN);

    /* map the abstraction header
     */
    ASSERT( ( NODE_HDRSZ & pgmask ) == 0 );
    ASSERT( ! ( NODE_HDRSZ % pgsz ));
    ASSERT( off <= OFF64MAX );
    ASSERT( ! ( off % ( off64_t )pgsz ));
    node_hdrp = ( node_hdr_t * )mmap_autogrow(
                    NODE_HDRSZ,
                    fd,
                    off );
    if ( node_hdrp == (node_hdr_t *)-1 ) {
        mlog( MLOG_NORMAL | MLOG_ERROR, _(
                  "unable to map node hdr of size %d: %s\n"),
              NODE_HDRSZ,
              strerror( errno ));
        return BOOL_FALSE;
    }

    /* initialize and save persistent context.
     */
    node_hdrp->nh_nodesz = nodesz;
    node_hdrp->nh_nodehkix = nodehkix;
    node_hdrp->nh_segsz = segsz;
    node_hdrp->nh_segtblsz = segtablesz;
    node_hdrp->nh_winmapmax = winmapmax;
    node_hdrp->nh_nodesperseg = nodesperseg;
    node_hdrp->nh_nodealignsz = nodealignsz;
    node_hdrp->nh_freenix = NIX_NULL;
    node_hdrp->nh_firstsegoff = off + ( off64_t )NODE_HDRSZ;
    node_hdrp->nh_virgsegreloff = 0;
    node_hdrp->nh_virgrelnix = 0;

    /* save transient context
     */
    node_fd = fd;

    /* autogrow the first segment
     */
    mlog( MLOG_DEBUG,
          "pre-growing new node array segment at %lld "
          "size %lld\n",
          node_hdrp->nh_firstsegoff,
          ( off64_t )node_hdrp->nh_segsz );
    rval = ftruncate64( node_fd,
                        node_hdrp->nh_firstsegoff
                        +
                        ( off64_t )node_hdrp->nh_segsz );
    if ( rval ) {
        mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_TREE, _(
                  "unable to autogrow first node segment: %s (%d)\n"),
              strerror( errno ),
              errno );
        return BOOL_FALSE;
    }

    /* initialize the window abstraction
     */
    win_init( fd,
              node_hdrp->nh_firstsegoff,
              segsz,
              segtablesz,
              winmapmax );

    /* announce the results
     */
    mlog( MLOG_DEBUG | MLOG_TREE,
          "node_init:"
          " vmsz = %llu (0x%llx)"
          " segsz = %u (0x%x)"
          " segtblsz = %llu (0x%llx)"
          " nodesperseg = %u (0x%x)"
          " winmapmax = %llu (0x%llx)"
          "\n",
          vmsz, vmsz,
          segsz, segsz,
          segtablesz, segtablesz,
          nodesperseg, nodesperseg,
          winmapmax, winmapmax );

    return BOOL_TRUE;
}
コード例 #16
0
int writePREHASHES(int file, HashList *hashes_list)
{
uint32_t i;
uint_least32_t qty = 0;
#ifndef _POSIX_MAPPED_FILES
int writecheck;
#else
struct stat st;
int64_t mmap_offset = 0, size;
char *address;
#endif

#ifdef _POSIX_MAPPED_FILES
	i = ftruncate64(file, (hashes_list->used * PREHASH_SIZE) +  PREHASH_COUNT_SIZE);
	fstat(file, &st);
	size = st.st_size;
	address = mmap(0, size, PROT_WRITE, MAP_SHARED, file, 0);
	if(address == MAP_FAILED)
	{
		ci_debug_printf(3, " writePREHASHES: Failed to mmap with error: %s\n", strerror(errno));
		return -1;
	}
#endif

	if(hashes_list->used) // check before we write
	{
		qty = hashes_list->used;

#ifdef _POSIX_MAPPED_FILES
		binary2char((char *) &qty, address, PREHASH_COUNT_SIZE);
		mmap_offset += PREHASH_COUNT_SIZE;
#else
		do {
			writecheck = write(file, &qty, PREHASH_COUNT_SIZE);
			if(writecheck < PREHASH_COUNT_SIZE) lseek64(file, -writecheck, SEEK_CUR);
		} while (writecheck >=0 && writecheck < PREHASH_COUNT_SIZE);
#endif

		for(i = 0; i < hashes_list->used; i++)
		{
#ifdef _POSIX_MAPPED_FILES
			binary2char((char *) &hashes_list->hashes[i], address + mmap_offset, PREHASH_SIZE);
			mmap_offset += PREHASH_SIZE;
#else
			do { // write hash
				writecheck = write(file, &hashes_list->hashes[i], PREHASH_SIZE);
		                if(writecheck < PREHASH_SIZE) lseek64(file, -writecheck, SEEK_CUR);
			} while (writecheck >=0 && writecheck < PREHASH_SIZE);
#endif
		}
#ifdef _POSIX_MAPPED_FILES
		// wrap up mmap
/*		if(msync(address, size, MS_SYNC) < 0) {
			ci_debug_printf(3, "writeFBCHashes: msync failed with error: %s\n", strerror(errno));
			strerror(errno);
		} */
		if(munmap(address, size) < 0) {
			ci_debug_printf(3, " writePREHASHES: munmap failed with error: %s\n", strerror(errno));

		}
		i = ftruncate64(file, (qty * PREHASH_SIZE) + PREHASH_COUNT_SIZE);
#else
		ftruncate(file, lseek64(file, 0, SEEK_CUR));
#endif
		/* Ok, have written hashes, now save new count */
//		ci_debug_printf(10, "%"PRIu32" hashes, wrote %"PRIu32" hashes\n", hashes_list->used, qty);
		return 0;
	}
	return -1;
}
コード例 #17
0
ファイル: tst-aio64.c プロジェクト: Dinesh-Ramakrishnan/glibc
int
do_test (int argc, char *argv[])
{
  struct aiocb64 cbs[10];
  struct aiocb64 cbs_fsync;
  struct aiocb64 *cbp[10];
  struct aiocb64 *cbp_fsync[1];
  char buf[1000];
  size_t cnt;
  int result = 0;

  /* Preparation.  */
  for (cnt = 0; cnt < 10; ++cnt)
    {
      cbs[cnt].aio_fildes = fd;
      cbs[cnt].aio_reqprio = 0;
      cbs[cnt].aio_buf = memset (&buf[cnt * 100], '0' + cnt, 100);
      cbs[cnt].aio_nbytes = 100;
      cbs[cnt].aio_offset = cnt * 100;
      cbs[cnt].aio_sigevent.sigev_notify = SIGEV_NONE;

      cbp[cnt] = &cbs[cnt];
    }

  /* First a simple test.  */
  for (cnt = 10; cnt > 0; )
    if (aio_write64 (cbp[--cnt]) < 0 && errno == ENOSYS)
      {
	error (0, 0, "no aio support in this configuration");
	return 0;
      }
  /* Wait 'til the results are there.  */
  result |= do_wait (cbp, 10, 0);
  /* Test this.  */
  result |= test_file (buf, sizeof (buf), fd, "aio_write");

  /* Read now as we've written it.  */
  memset (buf, '\0', sizeof (buf));
  /* Issue the commands.  */
  for (cnt = 10; cnt > 0; )
    {
      --cnt;
      cbp[cnt] = &cbs[cnt];
      aio_read64 (cbp[cnt]);
    }
  /* Wait 'til the results are there.  */
  result |= do_wait (cbp, 10, 0);
  /* Test this.  */
  for (cnt = 0; cnt < 1000; ++cnt)
    if (buf[cnt] != '0' + (cnt / 100))
      {
	result = 1;
	error (0, 0, "comparison failed for aio_read test");
	break;
      }

  if (cnt == 1000)
    puts ("aio_read test ok");

  /* Remove the test file contents.  */
  if (ftruncate64 (fd, 0) < 0)
    {
      error (0, errno, "ftruncate failed\n");
      result = 1;
    }

  /* Test lio_listio.  */
  for (cnt = 0; cnt < 10; ++cnt)
    {
      cbs[cnt].aio_lio_opcode = LIO_WRITE;
      cbp[cnt] = &cbs[cnt];
    }
  /* Issue the command.  */
  lio_listio64 (LIO_WAIT, cbp, 10, NULL);
  /* ...and immediately test it since we started it in wait mode.  */
  result |= test_file (buf, sizeof (buf), fd, "lio_listio (write)");

  /* Test aio_fsync.  */
  cbs_fsync.aio_fildes = fd;
  cbs_fsync.aio_sigevent.sigev_notify = SIGEV_NONE;
  cbp_fsync[0] = &cbs_fsync;

  /* Remove the test file contents first.  */
  if (ftruncate64 (fd, 0) < 0)
    {
      error (0, errno, "ftruncate failed\n");
      result = 1;
    }

  /* Write again.  */
  for (cnt = 10; cnt > 0; )
    aio_write64 (cbp[--cnt]);

  if (aio_fsync64 (O_SYNC, &cbs_fsync) < 0)
    {
      error (0, errno, "aio_fsync failed\n");
      result = 1;
    }
  result |= do_wait (cbp_fsync, 1, 0);

  /* ...and test since all data should be on disk now.  */
  result |= test_file (buf, sizeof (buf), fd, "aio_fsync (aio_write)");

  /* Test aio_cancel.  */
  /* Remove the test file contents first.  */
  if (ftruncate64 (fd, 0) < 0)
    {
      error (0, errno, "ftruncate failed\n");
      result = 1;
    }

  /* Write again.  */
  for (cnt = 10; cnt > 0; )
    aio_write64 (cbp[--cnt]);

  /* Cancel all requests.  */
  if (aio_cancel64 (fd, NULL) == -1)
    printf ("aio_cancel64 (fd, NULL) cannot cancel anything\n");

  result |= do_wait (cbp, 10, ECANCELED);

  /* Another test for aio_cancel.  */
  /* Remove the test file contents first.  */
  if (ftruncate64 (fd, 0) < 0)
    {
      error (0, errno, "ftruncate failed\n");
      result = 1;
    }

  /* Write again.  */
  for (cnt = 10; cnt > 0; )
    {
      --cnt;
      cbp[cnt] = &cbs[cnt];
      aio_write64 (cbp[cnt]);
    }
  puts ("finished3");

  /* Cancel all requests.  */
  for (cnt = 10; cnt > 0; )
    if (aio_cancel64 (fd, cbp[--cnt]) == -1)
      /* This is not an error.  The request can simply be finished.  */
      printf ("aio_cancel64 (fd, cbp[%Zd]) cannot be canceled\n", cnt);
  puts ("finished2");

  result |= do_wait (cbp, 10, ECANCELED);

  puts ("finished");

  return result;
}
コード例 #18
0
ファイル: capfs_ftruncate64.c プロジェクト: mnv104/capfs
int capfs_ftruncate64(int fd, int64_t length)
{
	int i;
	ireq req;

	memset(&req, 0, sizeof(req));
	/* check for badness */
	if (fd < 0 || fd >= CAPFS_NR_OPEN 
		 || (pfds[fd] && pfds[fd]->fs == FS_RESV)) 
	{
		errno = EBADF;
		return(-1);
	}  

	/* check for UNIX */
	if (!pfds[fd] || pfds[fd]->fs==FS_UNIX) {
#ifndef LARGE_FILE_SUPPORT
		if ((off_t) length == length) {
			return ftruncate(fd, (off_t) length);
		}
		else {
			errno = EINVAL;
			return(-1);
		}
#else
		return ftruncate64(fd, length);
#endif
	}

	if (pfds[fd]->fs == FS_PDIR) {
		errno = EISDIR;
		return(-1);
	}
	if (capfs_mode == 0)
	{
		req.majik_nr             = IOD_MAJIK_NR;
		req.release_nr           = CAPFS_RELEASE_NR;
		req.type                 = IOD_FTRUNCATE;
		req.dsize                = 0;
		req.req.ftruncate.f_ino  = FINO;
		req.req.ftruncate.cap    = pfds[fd]->fd.cap;
		req.req.ftruncate.length = length;

		/* build job to send reqs and recv acks */
		if (build_simple_jobs(pfds[fd], &req) < 0) {
			LOG(stderr, WARNING_MSG, SUBSYS_LIB,  "capfs_ftruncate: build_simple_jobs failed\n");
			return(-1);
		}

		/* call do_job */
		while (!jlist_empty(active_p)) {
			if (do_jobs(active_p, &socks, -1) < 0) {
				LOG(stderr, WARNING_MSG, SUBSYS_LIB,  "capfs_ftruncate: do_jobs failed\n");
				return(-1);
			}
		}

		/* check acks from iods */
		for (i=0; i < PCNT; i++) {
			if (pfds[fd]->fd.iod[i].ack.status) {
				LOG(stderr, WARNING_MSG, SUBSYS_LIB,  "capfs_ftruncate: non-zero status returned from iod %d\n", i);
				errno = pfds[fd]->fd.iod[i].ack.eno;
				return(-1);
			}
		}
	}
	return(0);
}
コード例 #19
0
ファイル: fstest.c プロジェクト: VRciF/springy
static unsigned int
call_syscall(struct syscall_desc *scall, char *argv[])
{
	struct stat64 sb;
	struct utimbuf ut;
	long long flags;
	unsigned int i;
	char *endp;
	int rval;
	int more;
	union {
		char *str;
		long long num;
	} args[MAX_ARGS];

	more = 0;
	/*
	 * Verify correctness of the arguments.
	 */
	for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) {
		if (scall->sd_args[i] == TYPE_NONE) {
			if (argv[i] == NULL || strcmp(argv[i], ":") == 0)
				break;
			fprintf(stderr, "too many arguments [%s]\n", argv[i]);
			exit(1);
		} else {
			if (argv[i] == NULL || strcmp(argv[i], ":") == 0) {
				if (scall->sd_args[i] & TYPE_OPTIONAL) {
					args[i].str = NULL;
					break;
				}
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) {
				if (strcmp(argv[i], "NULL") == 0)
					args[i].str = NULL;
				else if (strcmp(argv[i], "DEADCODE") == 0)
					args[i].str = (void *)0xdeadc0de;
				else
					args[i].str = argv[i];
			} else if ((scall->sd_args[i] & TYPE_MASK)
						== TYPE_NUMBER) {
				args[i].num = strtoll(argv[i], &endp, 0);
				if (*endp != '\0' && !isspace((unsigned char)*endp)) {
					fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp);
					exit(1);
				}
			} else if ((scall->sd_args[i] & TYPE_MASK) ==
			    TYPE_DESCRIPTOR) {
				if (strcmp(argv[i], "AT_FDCWD") == 0) {
					args[i].num = AT_FDCWD;
				} else if (strcmp(argv[i], "BADFD") == 0) {
					/* In case AT_FDCWD is -1 on some systems... */
					if (AT_FDCWD == -1)
						args[i].num = -2;
					else
						args[i].num = -1;
				} else {
					int pos;

					pos = strtoll(argv[i], &endp, 0);
					if (*endp != '\0' &&
					    !isspace((unsigned char)*endp)) {
						fprintf(stderr,
						    "invalid argument %u, number expected [%s]\n",
						    i, endp);
						exit(1);
					}
					args[i].num = descriptor_get(pos);
				}
			}
		}
	}
	/*
	 * Call the given syscall.
	 */
#define	NUM(n)	(args[(n)].num)
#define	STR(n)	(args[(n)].str)
	switch (scall->sd_action) {
	case ACTION_OPEN:
		flags = str2flags(open_flags, STR(1));
		if (flags & O_CREAT) {
			if (i == 2) {
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			rval = open(STR(0), flags, (mode_t)NUM(2));
		} else {
			if (i == 3) {
				fprintf(stderr, "too many arguments\n");
				exit(1);
			}
			rval = open(STR(0), flags);
		}
		if (rval >= 0) {
			more = argv[i] && !strcmp(argv[i], ":");
			descriptor_add(rval);
		}
		break;
	case ACTION_CREATE:
		rval = open(STR(0), O_CREAT | O_EXCL, NUM(1));
		if (rval >= 0) {
			more = argv[i] && !strcmp(argv[i], ":");
			descriptor_add(rval);
		}
		break;
	case ACTION_UNLINK:
		rval = unlink(STR(0));
		break;
	case ACTION_MKDIR:
		rval = mkdir(STR(0), NUM(1));
		break;
	case ACTION_RMDIR:
		rval = rmdir(STR(0));
		break;
	case ACTION_LINK:
		rval = link(STR(0), STR(1));
		break;
	case ACTION_SYMLINK:
		rval = symlink(STR(0), STR(1));
		break;
	case ACTION_RENAME:
		rval = rename(STR(0), STR(1));
		break;
	case ACTION_MKFIFO:
		rval = mkfifo(STR(0), NUM(1));
		break;
	case ACTION_CHMOD:
		rval = chmod(STR(0), NUM(1));
		break;
#ifdef HAS_LCHMOD
	case ACTION_LCHMOD:
		rval = lchmod(STR(0), NUM(1));
		break;
#endif
	case ACTION_CHOWN:
		rval = chown(STR(0), NUM(1), NUM(2));
		break;
	case ACTION_LCHOWN:
		rval = lchown(STR(0), NUM(1), NUM(2));
		break;
#ifdef HAS_CHFLAGS
	case ACTION_CHFLAGS:
		rval = chflags(STR(0), str2flags(chflags_flags, STR(1)));
		break;
#endif
#ifdef HAS_LCHFLAGS
	case ACTION_LCHFLAGS:
		rval = lchflags(STR(0), str2flags(chflags_flags, STR(1)));
		break;
#endif
	case ACTION_TRUNCATE:
		rval = truncate64(STR(0), NUM(1));
		break;
	case ACTION_FTRUNCATE:
		rval = ftruncate64(NUM(0), NUM(1));
		break;
	case ACTION_STAT:
		rval = stat64(STR(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_LSTAT:
		rval = lstat64(STR(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_UTIME :
		switch (i) {
		case 1 :
			rval = utime(STR(0), (struct utimbuf*)NULL);
			break;
		case 3:
			ut.actime = NUM(1);
			ut.modtime = NUM(2);
			rval = utime(STR(0), &ut);
			break;
		default :
			fprintf(stderr,"utime() requires 1 or 3 arguments\n");
			exit(1);
		}
		break;
	case ACTION_BIND:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx));
		break;
	    }
	case ACTION_MKNOD:
	case ACTION_MKNODAT:
	    {
		mode_t ntype;
		dev_t dev;
		int fa;

		switch (scall->sd_action) {
		case ACTION_MKNOD:
			fa = 0;
			break;
		case ACTION_MKNODAT:
			fa = 1;
			break;
		default:
			abort();
		}

		dev = makedev(NUM(fa + 3), NUM(fa + 4));
		if (strcmp(STR(fa + 1), "c") == 0)	/* character device */
			ntype = S_IFCHR;
		else if (strcmp(STR(fa + 1), "b") == 0)	/* block device */
			ntype = S_IFBLK;
		else if (strcmp(STR(fa + 1), "f") == 0)	/* fifo special */
			ntype = S_IFIFO;
		else if (strcmp(STR(fa + 1), "d") == 0)	/* directory */
			ntype = S_IFDIR;
		else if (strcmp(STR(fa + 1), "o") == 0)	/* regular file */
			ntype = S_IFREG;
		else {
			fprintf(stderr, "wrong argument 1\n");
			exit(1);
		}
		switch (scall->sd_action) {
		case ACTION_MKNOD:
			rval = mknod(STR(0), ntype | NUM(2), dev);
			break;
		case ACTION_MKNODAT:
			rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev);
			break;
		default:
			abort();
		}
		break;
	    }
#ifdef HAS_ACL
	case ACTION_GETFACL :
		rval = do_getfacl(STR(0), STR(1));
		if (rval == 0)
			return (i);
		break;
	case ACTION_SETFACL :
		rval = do_setfacl(STR(0), STR(1), STR(2));
		break;
#endif
	default:
		fprintf(stderr, "unsupported syscall\n");
		exit(1);
	}
#undef STR
#undef NUM
	if (rval < 0) {
		const char *serrno;

		serrno = err2str(errno);
		fprintf(stderr, "%s returned %d\n", scall->sd_name, rval);
		printf("%s\n", serrno);
		exit(1);
	}
		/* Do not output a "0" when more syscalls to come */
	if (!more)
		printf("0\n");
	return (i);
}
コード例 #20
0
ファイル: ad_xfs_fcntl.c プロジェクト: davidheryanto/sc14
void ADIOI_XFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int *error_code)
{
    MPI_Datatype copy_etype, copy_filetype;
    int combiner, i, j, k, filetype_is_contig, err;
    ADIOI_Flatlist_node *flat_file;
    struct flock64 fl;
#ifndef PRINT_ERR_MSG
    static char myname[] = "ADIOI_XFS_FCNTL";
#endif

    switch(flag) {
    case ADIO_FCNTL_SET_VIEW:
        /* free copies of old etypes and filetypes and delete flattened 
           version of filetype if necessary */

	MPI_Type_get_envelope(fd->etype, &i, &j, &k, &combiner);
	if (combiner != MPI_COMBINER_NAMED) MPI_Type_free(&(fd->etype));

	ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig);
	if (!filetype_is_contig) ADIOI_Delete_flattened(fd->filetype);

	MPI_Type_get_envelope(fd->filetype, &i, &j, &k, &combiner);
	if (combiner != MPI_COMBINER_NAMED) MPI_Type_free(&(fd->filetype));

	/* set new info */
	ADIO_SetInfo(fd, fcntl_struct->info, &err);

        /* set new etypes and filetypes */

	MPI_Type_get_envelope(fcntl_struct->etype, &i, &j, &k, &combiner);
	if (combiner == MPI_COMBINER_NAMED) fd->etype = fcntl_struct->etype;
	else {
	    MPI_Type_contiguous(1, fcntl_struct->etype, &copy_etype);
	    MPI_Type_commit(&copy_etype);
	    fd->etype = copy_etype;
	}
	MPI_Type_get_envelope(fcntl_struct->filetype, &i, &j, &k, &combiner);
	if (combiner == MPI_COMBINER_NAMED) 
	    fd->filetype = fcntl_struct->filetype;
	else {
	    MPI_Type_contiguous(1, fcntl_struct->filetype, &copy_filetype);
	    MPI_Type_commit(&copy_filetype);
	    fd->filetype = copy_filetype;
	    ADIOI_Flatten_datatype(fd->filetype);
            /* this function will not flatten the filetype if it turns out
               to be all contiguous. */
	}

	MPI_Type_size(fd->etype, &(fd->etype_size));
	fd->disp = fcntl_struct->disp;

        /* reset MPI-IO file pointer to point to the first byte that can
           be accessed in this view. */

        ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig);
	if (filetype_is_contig) fd->fp_ind = fcntl_struct->disp;
	else {
	    flat_file = ADIOI_Flatlist;
	    while (flat_file->type != fd->filetype) 
		flat_file = flat_file->next;
	    for (i=0; i<flat_file->count; i++) {
		if (flat_file->blocklens[i]) {
		    fd->fp_ind = fcntl_struct->disp + flat_file->indices[i];
		    break;
		}
	    }
	}
	*error_code = MPI_SUCCESS;
	break;

    case ADIO_FCNTL_GET_FSIZE:
	fcntl_struct->fsize = lseek64(fd->fd_sys, 0, SEEK_END);
#ifdef PRINT_ERR_MSG
	*error_code = (fcntl_struct->fsize == -1) ? MPI_ERR_UNKNOWN : MPI_SUCCESS;
#else
	if (fcntl_struct->fsize == -1) {
	    *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR,
			      myname, "I/O Error", "%s", strerror(errno));
	    ADIOI_Error(fd, *error_code, myname);	    
	}
	else *error_code = MPI_SUCCESS;
#endif
	break;

    case ADIO_FCNTL_SET_DISKSPACE:
	i = 0;
	fl.l_start = 0;
	fl.l_whence = SEEK_SET;
	fl.l_len = fcntl_struct->diskspace;
	err = fcntl(fd->fd_sys, F_RESVSP64, &fl);
	if (err) i = 1;
	if (fcntl_struct->diskspace > lseek64(fd->fd_sys, 0, SEEK_END)) {
	    /* also need to set the file size */
	    err = ftruncate64(fd->fd_sys, fcntl_struct->diskspace);
	    if (err) i = 1;
	}
#ifdef PRINT_ERR_MSG
	*error_code = (i == 0) ? MPI_SUCCESS : MPI_ERR_UNKNOWN;
#else
	if (i == 1) {
	    *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR,
			      myname, "I/O Error", "%s", strerror(errno));
	    ADIOI_Error(fd, *error_code, myname);	    
	}
	else *error_code = MPI_SUCCESS;
#endif
	break;

    case ADIO_FCNTL_SET_IOMODE:
        /* for implementing PFS I/O modes. will not occur in MPI-IO
           implementation.*/
	if (fd->iomode != fcntl_struct->iomode) {
	    fd->iomode = fcntl_struct->iomode;
	    MPI_Barrier(MPI_COMM_WORLD);
	}
	*error_code = MPI_SUCCESS;
	break;

    case ADIO_FCNTL_SET_ATOMICITY:
	fd->atomicity = (fcntl_struct->atomicity == 0) ? 0 : 1;
	*error_code = MPI_SUCCESS;
	break;

    default:
	FPRINTF(stderr, "Unknown flag passed to ADIOI_XFS_Fcntl\n");
	MPI_Abort(MPI_COMM_WORLD, 1);
    }
}
コード例 #21
0
ファイル: xfs_fsr.c プロジェクト: crossmeta/sgi
/*
 * Do the defragmentation of a single file.
 * We already are pretty sure we can and want to 
 * defragment the file.  Create the tmp file, copy
 * the data (maintaining holes) and call the kernel
 * extent swap routinte.
 */
static int
packfile(char *fname, char *tname, int fd, xfs_bstat_t *statp, int do_rt)
{
	int 		tfd;
	int		srval;
	int		nextents, extent, cur_nextents, new_nextents;
	unsigned	blksz_dio;
	unsigned	dio_min;
	struct dioattr	dio;
	static xfs_swapext_t   sx;
	struct xfs_flock64  space;
	off64_t 	cnt, pos;
	void 		*fbuf;
	int 		ct, wc, wc_b4;
	struct fsxattr  tfsx;
	char		ffname[SMBUFSZ];
	int		ffd = 0;

	/*
	 * Work out the extent map - nextents will be set to the
	 * minimum number of extents needed for the file (taking 
	 * into account holes), cur_nextents is the current number
	 * of extents.
	 */
	nextents = read_fd_bmap(fd, statp, &cur_nextents);

	if ( cur_nextents == 1 || cur_nextents <= nextents ) {
		if (vflag)
			fsrprintf("%s already fully defragmented.\n", fname);
		return 1; /* indicates no change/no error */
	}

	if (dflag)
		fsrprintf("%s extents=%d can_save=%d tmp=%s\n", 
		          fname, cur_nextents, (cur_nextents - nextents), 
		          tname);

	if ((tfd = open(tname, openopts, 0666)) < 0) {
		if (vflag)
			fsrprintf("could not open tmp as uid %d: %s: %s\n",
				   statp->bs_uid,tname, strerror(errno));
		return -1;
	}
	unlink(tname);

	/* Setup extended attributes */
	if( statp->bs_xflags & XFS_XFLAG_HASATTR ) {
		if (attr_setf(tfd, "X", "X", 1, ATTR_CREATE) != 0) {
			fsrprintf("could not set ATTR on tmp: %s:\n", tname);
			close(tfd);
			return -1;
		}
		if (dflag)
			fsrprintf("%s set temp attr\n", tname);
	}

	if ((ioctl(tfd, XFS_IOC_DIOINFO, &dio)) < 0 ) {
		fsrprintf("could not get I/O info on tmp: %s\n", tname);
		close(tfd);
		return -1;
	}

	if (do_rt) {
		int rt_textsize = fsgeom.rtextsize * fsgeom.blocksize;

		tfsx.fsx_xflags = XFS_XFLAG_REALTIME;

		if ((tfsx.fsx_extsize = rt_textsize) <= 0 ) {
			fsrprintf("realtime geom not avail for tmp: %s\n", fname);
			close(tfd);
			return -1;
		}

		if (ioctl( tfd,  XFS_IOC_FSSETXATTR, &tfsx) < 0) {
			fsrprintf("could not set rt on tmp: %s\n", tname);
			close(tfd);
			return -1;
		}
	}

	dio_min   = dio.d_miniosz;
	if (statp->bs_size <= dio_min)
		blksz_dio = dio_min;
	else {
		blksz_dio = min(dio.d_maxiosz, BUFFER_MAX - pagesize);
		if (argv_blksz_dio != 0)
			blksz_dio = min(argv_blksz_dio, blksz_dio);
		blksz_dio = (min(statp->bs_size, blksz_dio) / dio_min) * dio_min;
	}

	if (dflag) {
	    fsrprintf("DEBUG: fsize=%lld blsz_dio=%d d_min=%d d_max=%d pgsz=%d\n",
	    statp->bs_size, blksz_dio, dio.d_miniosz, dio.d_maxiosz, pagesize);
	}

	/* Malloc a buffer */
	if (! (fbuf = (char *)memalign(dio.d_mem, blksz_dio))) {
		fsrprintf("could not allocate buf: %s\n", tname);
		close(tfd);
		return -1;
	}

	if (nfrags) {
		/* Create new tmp file in same AG as first */
		sprintf(ffname, "%s.frag", tname);

		/* Open the new file for sync writes */
		if ((ffd = open(ffname, openopts, 0666)) 
		    < 0) {
			fsrprintf("could not open fragfile: %s : %s\n",
				   ffname, strerror(errno));
			return -1;
		}
		unlink(ffname);
	}

	/* Loop through block map copying the file. */
	for (extent = 0; extent < nextents; extent++) {
		pos = outmap[extent].bmv_offset;
		if (outmap[extent].bmv_block == -1) {
			space.l_whence = 0;
			space.l_start = pos;
			space.l_len = outmap[extent].bmv_length;
			if (ioctl(tfd, XFS_IOC_UNRESVSP64, &space) < 0) {
				fsrprintf("could not trunc tmp %s\n", 
					   tname);
			}
			lseek64(tfd, outmap[extent].bmv_length, SEEK_CUR);
			lseek64(fd, outmap[extent].bmv_length, SEEK_CUR);
			continue;
		} else if (outmap[extent].bmv_length == 0) {
			/* to catch holes at the beginning of the file */
			continue;
		}
		if (! nfrags) {
			space.l_whence = SEEK_CUR;
			space.l_start = 0;
			space.l_len = outmap[extent].bmv_length;

			if (ioctl(tfd, XFS_IOC_RESVSP64, &space) < 0) {
				fsrprintf("could not pre-alloc tmp space: %s\n",
					  tname);
				close(tfd);
				free(fbuf);
				return -1;
			}
		}
		for (cnt = outmap[extent].bmv_length; cnt > 0;
		     cnt -= ct, pos += ct) {
			if (nfrags && --nfrags) {
				ct = min(cnt, dio_min);
			} else if (cnt % dio_min == 0) {
				ct = min(cnt, blksz_dio);
			} else {
				ct = min(cnt + dio_min - (cnt % dio_min), 
					blksz_dio);
			}
			ct = read(fd, fbuf, ct);
			if (ct == 0) {
				/* EOF, stop trying to read */
				extent = nextents;
				break;
			}
			/* Ensure we do direct I/O to correct block
			 * boundaries.
			 */
			if (ct % dio_min != 0) {
				wc = ct + dio_min - (ct % dio_min);
			} else {
				wc = ct;
			}
			wc_b4 = wc;
			if (ct < 0 || ((wc = write(tfd, fbuf, wc)) != wc_b4)) {
				if (ct < 0)
				fsrprintf("bad read of %d bytes from %s:%s\n",
				           wc_b4, fname, strerror(errno));
				else if (wc < 0)
				fsrprintf("bad write of %d bytes to %s: %s\n",
					   wc_b4, tname, strerror(errno));
				else {
					/*
					 * Might be out of space
					 *
					 * Try to finish write
					 */
					int resid = ct-wc;

					if ((wc = write(tfd, ((char *)fbuf)+wc,
							resid)) == resid) {
						/* worked on second attempt? */
						continue;
					}
					else
					if (wc < 0) {
				fsrprintf("bad write2 of %d bytes to %s: %s\n",
				           resid, tname, strerror(errno));
					} else {
						fsrprintf("bad copy to %s\n",
					           tname);
					}
				}
				free(fbuf);
				return -1;
			}
			if (nfrags) {
				/* Do a matching write to the tmp file */
				wc = wc_b4;
				if (((wc = write(ffd, fbuf, wc)) != wc_b4)) {						fsrprintf("bad write of %d bytes "
						  "to %s: %s\n",
					   wc_b4, ffname, strerror(errno));
				}
			}
		}
	}
	ftruncate64(tfd, statp->bs_size);
	if (ffd) close(ffd);
	fsync(tfd);

	free(fbuf);

	sx.sx_stat     = *statp; /* struct copy */
	sx.sx_version  = XFS_SX_VERSION;
	sx.sx_fdtarget = fd;
	sx.sx_fdtmp    = tfd;
	sx.sx_offset   = 0;
	sx.sx_length   = statp->bs_size;

	/* Check if the extent count improved */
	new_nextents = getnextents(tfd);
	if (cur_nextents <= new_nextents) {
		if (vflag)
			fsrprintf("No improvement made: %s\n", fname);
		close(tfd);
		return 1; /* no change/no error */
	}

	/* Swap the extents */
	srval = xfs_swapext(fd, &sx);
	if (srval < 0) {
		if (errno == ENOTSUP) {
			if (vflag || dflag) 
			   fsrprintf("%s: file type not supported\n", fname);
		} else if (errno == EFAULT) {
			/* The file has changed since we started the copy */
			if (vflag || dflag)
			   fsrprintf("%s:file modified defrag aborted\n", 
				     fname);
		} else if (errno == EBUSY) {
			/* Timestamp has changed or mmap'ed file */
			if (vflag || dflag)
			   fsrprintf("%s: file busy \n", fname);
		} else {
			fsrprintf("XFS_IOC_SWAPEXT failed: %s: %s\n", 
				  fname, strerror(errno));
		}
		close(tfd);
		return -1;
	}

	/* Report progress */
	if (vflag)
		fsrprintf("extents before:%d after:%d %s %s\n",
			  cur_nextents, new_nextents, 
			  (new_nextents <= nextents ? "DONE" : "    " ),
		          fname);
	close(tfd);
	return 0;
}
コード例 #22
0
ファイル: fileset.c プロジェクト: alhazred/onarm
/*
 * given a fileset entry, determines if the associated file
 * needs to be allocated or not, and if so does the allocation.
 */
static int
fileset_alloc_file(filesetentry_t *entry)
{
	char path[MAXPATHLEN];
	char *buf;
	struct stat64 sb;
	char *pathtmp;
	off64_t seek;
	int fd;

	*path = 0;
	(void) strcpy(path, *entry->fse_fileset->fs_path);
	(void) strcat(path, "/");
	(void) strcat(path, entry->fse_fileset->fs_name);
	pathtmp = fileset_resolvepath(entry);
	(void) strcat(path, pathtmp);

	filebench_log(LOG_DEBUG_IMPL, "Populated %s", entry->fse_path);

	/* see if reusing and this file exists */
	if ((entry->fse_flags & FSE_REUSING) && (stat64(path, &sb) == 0)) {
		if ((fd = open64(path, O_RDWR)) < 0) {
			filebench_log(LOG_INFO,
			    "Attempted but failed to Re-use file %s",
			    path);
			return (-1);
		}

		if (sb.st_size == (off64_t)entry->fse_size) {
			filebench_log(LOG_INFO,
			    "Re-using file %s", path);

			if (!integer_isset(entry->fse_fileset->fs_cached))
				(void) fileset_freemem(fd,
				    entry->fse_size);

			entry->fse_flags |= FSE_EXISTS;
			(void) close(fd);
			return (0);

		} else if (sb.st_size > (off64_t)entry->fse_size) {
			/* reuse, but too large */
			filebench_log(LOG_INFO,
			    "Truncating & re-using file %s", path);

			(void) ftruncate64(fd,
			    (off64_t)entry->fse_size);

			if (!integer_isset(entry->fse_fileset->fs_cached))
				(void) fileset_freemem(fd,
				    entry->fse_size);

			entry->fse_flags |= FSE_EXISTS;
			(void) close(fd);
			return (0);
		}
	} else {

		/* No file or not reusing, so create */
		if ((fd = open64(path, O_RDWR | O_CREAT, 0644)) < 0) {
			filebench_log(LOG_ERROR,
			    "Failed to pre-allocate file %s: %s",
			    path, strerror(errno));

			return (-1);
		}
	}

	if ((buf = (char *)malloc(FILE_ALLOC_BLOCK)) == NULL)
		return (-1);

	entry->fse_flags |= FSE_EXISTS;

	for (seek = 0; seek < entry->fse_size; ) {
		off64_t wsize;
		int ret = 0;

		/*
		 * Write FILE_ALLOC_BLOCK's worth,
		 * except on last write
		 */
		wsize = MIN(entry->fse_size - seek, FILE_ALLOC_BLOCK);

		ret = write(fd, buf, wsize);
		if (ret != wsize) {
			filebench_log(LOG_ERROR,
			    "Failed to pre-allocate file %s: %s",
			    path, strerror(errno));
			(void) close(fd);
			free(buf);
			return (-1);
		}
		seek += wsize;
	}

	if (!integer_isset(entry->fse_fileset->fs_cached))
		(void) fileset_freemem(fd, entry->fse_size);

	(void) close(fd);

	free(buf);

	filebench_log(LOG_DEBUG_IMPL,
	    "Pre-allocated file %s size %lld", path, entry->fse_size);

	return (0);
}
コード例 #23
0
static void
enlarge_archive (struct locarhandle *ah, const struct locarhead *head)
{
  struct stat64 st;
  int fd;
  struct locarhead newhead;
  size_t total;
  void *p;
  unsigned int cnt, loccnt;
  struct namehashent *oldnamehashtab;
  struct locrecent *oldlocrectab;
  struct locarhandle new_ah;
  struct oldlocrecent *oldlocrecarray;
  size_t prefix_len = output_prefix ? strlen (output_prefix) : 0;
  char archivefname[prefix_len + sizeof (ARCHIVE_NAME)];
  char fname[prefix_len + sizeof (ARCHIVE_NAME) + sizeof (".XXXXXX") - 1];

  if (output_prefix)
    memcpy (archivefname, output_prefix, prefix_len);
  strcpy (archivefname + prefix_len, ARCHIVE_NAME);
  strcpy (stpcpy (fname, archivefname), ".XXXXXX");

  /* Not all of the old file has to be mapped.  Change this now this
     we will have to access the whole content.  */
  if (fstat64 (ah->fd, &st) != 0)
  enomap:
    error (EXIT_FAILURE, errno, _("cannot map locale archive file"));

  if (st.st_size < ah->reserved)
    ah->addr = mmap64 (ah->addr, st.st_size, PROT_READ | PROT_WRITE,
		       MAP_SHARED | MAP_FIXED, ah->fd, 0);
  else
    {
      munmap (ah->addr, ah->reserved);
      ah->addr = mmap64 (NULL, st.st_size, PROT_READ | PROT_WRITE,
			 MAP_SHARED, ah->fd, 0);
      ah->reserved = st.st_size;
      head = ah->addr;
    }
  if (ah->addr == MAP_FAILED)
    goto enomap;
  ah->mmaped = st.st_size;

  /* Create a temporary file in the correct directory.  */
  fd = mkstemp (fname);
  if (fd == -1)
    error (EXIT_FAILURE, errno, _("cannot create temporary file"));

  /* Copy the existing head information.  */
  newhead = *head;

  /* Create the new archive header.  The sizes of the various tables
     should be double from what is currently used.  */
  newhead.namehash_size = MAX (next_prime (2 * newhead.namehash_used),
			       newhead.namehash_size);
  if (verbose)
    printf ("name: size: %u, used: %d, new: size: %u\n",
	    head->namehash_size, head->namehash_used, newhead.namehash_size);

  newhead.string_offset = (newhead.namehash_offset
			   + (newhead.namehash_size
			      * sizeof (struct namehashent)));
  /* Keep the string table size aligned to 4 bytes, so that
     all the struct { uint32_t } types following are happy.  */
  newhead.string_size = MAX ((2 * newhead.string_used + 3) & -4,
			     newhead.string_size);

  newhead.locrectab_offset = newhead.string_offset + newhead.string_size;
  newhead.locrectab_size = MAX (2 * newhead.locrectab_used,
				newhead.locrectab_size);

  newhead.sumhash_offset = (newhead.locrectab_offset
			    + (newhead.locrectab_size
			       * sizeof (struct locrecent)));
  newhead.sumhash_size = MAX (next_prime (2 * newhead.sumhash_used),
			      newhead.sumhash_size);

  total = (newhead.sumhash_offset
	   + newhead.sumhash_size * sizeof (struct sumhashent));

  /* The new file is empty now.  */
  newhead.namehash_used = 0;
  newhead.string_used = 0;
  newhead.locrectab_used = 0;
  newhead.sumhash_used = 0;

  /* Write out the header and create room for the other data structures.  */
  if (TEMP_FAILURE_RETRY (write (fd, &newhead, sizeof (newhead)))
      != sizeof (newhead))
    {
      int errval = errno;
      unlink (fname);
      error (EXIT_FAILURE, errval, _("cannot initialize archive file"));
    }

  if (ftruncate64 (fd, total) != 0)
    {
      int errval = errno;
      unlink (fname);
      error (EXIT_FAILURE, errval, _("cannot resize archive file"));
    }

  /* To prepare for enlargements of the mmaped area reserve some
     address space.  */
  size_t reserved = RESERVE_MMAP_SIZE;
  int xflags = 0;
  if (total < reserved
      && ((p = mmap64 (NULL, reserved, PROT_NONE, MAP_PRIVATE | MAP_ANON,
		       -1, 0)) != MAP_FAILED))
    xflags = MAP_FIXED;
  else
    {
      p = NULL;
      reserved = total;
    }

  /* Map the header and all the administration data structures.  */
  p = mmap64 (p, total, PROT_READ | PROT_WRITE, MAP_SHARED | xflags, fd, 0);
  if (p == MAP_FAILED)
    {
      int errval = errno;
      unlink (fname);
      error (EXIT_FAILURE, errval, _("cannot map archive header"));
    }

  /* Lock the new file.  */
  if (lockf64 (fd, F_LOCK, total) != 0)
    {
      int errval = errno;
      unlink (fname);
      error (EXIT_FAILURE, errval, _("cannot lock new archive"));
    }

  new_ah.mmaped = total;
  new_ah.addr = p;
  new_ah.fd = fd;
  new_ah.reserved = reserved;

  /* Walk through the hash name hash table to find out what data is
     still referenced and transfer it into the new file.  */
  oldnamehashtab = (struct namehashent *) ((char *) ah->addr
					   + head->namehash_offset);
  oldlocrectab = (struct locrecent *) ((char *) ah->addr
				       + head->locrectab_offset);

  /* Sort the old locrec table in order of data position.  */
  oldlocrecarray = alloca (sizeof (*oldlocrecarray) * head->namehash_size);
  for (cnt = 0, loccnt = 0; cnt < head->namehash_size; ++cnt)
    if (oldnamehashtab[cnt].locrec_offset != 0)
      {
	oldlocrecarray[loccnt].cnt = cnt;
	oldlocrecarray[loccnt++].locrec
	  = (struct locrecent *) ((char *) ah->addr
				  + oldnamehashtab[cnt].locrec_offset);
      }
  qsort (oldlocrecarray, loccnt, sizeof (struct oldlocrecent),
	 oldlocrecentcmp);

  uint32_t last_locrec_offset = 0;
  for (cnt = 0; cnt < loccnt; ++cnt)
    {
      /* Insert this entry in the new hash table.  */
      locale_data_t old_data;
      unsigned int idx;
      struct locrecent *oldlocrec = oldlocrecarray[cnt].locrec;

      for (idx = 0; idx < __LC_LAST; ++idx)
	if (idx != LC_ALL)
	  {
	    old_data[idx].size = oldlocrec->record[idx].len;
	    old_data[idx].addr
	      = ((char *) ah->addr + oldlocrec->record[idx].offset);

	    __md5_buffer (old_data[idx].addr, old_data[idx].size,
			  old_data[idx].sum);
	  }

      if (cnt > 0 && oldlocrecarray[cnt - 1].locrec == oldlocrec)
	{
	  const char *oldname
	    = ((char *) ah->addr
	       + oldnamehashtab[oldlocrecarray[cnt - 1].cnt].name_offset);

	  add_alias (&new_ah,
		     ((char *) ah->addr
		      + oldnamehashtab[oldlocrecarray[cnt].cnt].name_offset),
		     0, oldname, &last_locrec_offset);
	  continue;
	}

      last_locrec_offset =
	add_locale (&new_ah,
		    ((char *) ah->addr
		     + oldnamehashtab[oldlocrecarray[cnt].cnt].name_offset),
		    old_data, 0);
      if (last_locrec_offset == 0)
	error (EXIT_FAILURE, 0, _("cannot extend locale archive file"));
    }

  /* Make the file globally readable.  */
  if (fchmod (fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1)
    {
      int errval = errno;
      unlink (fname);
      error (EXIT_FAILURE, errval,
	     _("cannot change mode of resized locale archive"));
    }

  /* Rename the new file.  */
  if (rename (fname, archivefname) != 0)
    {
      int errval = errno;
      unlink (fname);
      error (EXIT_FAILURE, errval, _("cannot rename new archive"));
    }

  /* Close the old file.  */
  close_archive (ah);

  /* Add the information for the new one.  */
  *ah = new_ah;
}
コード例 #24
0
ファイル: pjdfstest.c プロジェクト: ChaosJohn/freebsd
static unsigned int
call_syscall(struct syscall_desc *scall, char *argv[])
{
	struct stat64 sb;
	long long flags;
	unsigned int i;
	char *endp;
	int name, rval;
	union {
		char *str;
		long long num;
	} args[MAX_ARGS];
#ifdef HAS_FREEBSD_ACL
	int entry_id = ACL_FIRST_ENTRY;
	acl_t acl, newacl;
	acl_entry_t entry, newentry;
#endif

	/*
	 * Verify correctness of the arguments.
	 */
	for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) {
		if (scall->sd_args[i] == TYPE_NONE) {
			if (argv[i] == NULL || strcmp(argv[i], ":") == 0)
				break;
			fprintf(stderr, "too many arguments [%s]\n", argv[i]);
			exit(1);
		} else {
			if (argv[i] == NULL || strcmp(argv[i], ":") == 0) {
				if (scall->sd_args[i] & TYPE_OPTIONAL)
					break;
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) {
				if (strcmp(argv[i], "NULL") == 0)
					args[i].str = NULL;
				else if (strcmp(argv[i], "DEADCODE") == 0)
					args[i].str = (void *)0xdeadc0de;
				else
					args[i].str = argv[i];
			} else if ((scall->sd_args[i] & TYPE_MASK) ==
			    TYPE_NUMBER) {
				args[i].num = strtoll(argv[i], &endp, 0);
				if (*endp != '\0' &&
				    !isspace((unsigned char)*endp)) {
					fprintf(stderr,
					    "invalid argument %u, number expected [%s]\n",
					    i, endp);
					exit(1);
				}
			} else if ((scall->sd_args[i] & TYPE_MASK) ==
			    TYPE_DESCRIPTOR) {
				if (strcmp(argv[i], "AT_FDCWD") == 0) {
					args[i].num = AT_FDCWD;
				} else if (strcmp(argv[i], "BADFD") == 0) {
					/* In case AT_FDCWD is -1 on some systems... */
					if (AT_FDCWD == -1)
						args[i].num = -2;
					else
						args[i].num = -1;
				} else {
					int pos;

					pos = strtoll(argv[i], &endp, 0);
					if (*endp != '\0' &&
					    !isspace((unsigned char)*endp)) {
						fprintf(stderr,
						    "invalid argument %u, number expected [%s]\n",
						    i, endp);
						exit(1);
					}
					args[i].num = descriptor_get(pos);
				}
			}
		}
	}
	/*
	 * Call the given syscall.
	 */
#define	NUM(n)	(args[(n)].num)
#define	STR(n)	(args[(n)].str)
	switch (scall->sd_action) {
	case ACTION_OPEN:
		flags = str2flags(open_flags, STR(1));
		if (flags & O_CREAT) {
			if (i == 2) {
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			rval = open(STR(0), (int)flags, (mode_t)NUM(2));
		} else {
			if (i == 3) {
				fprintf(stderr, "too many arguments\n");
				exit(1);
			}
			rval = open(STR(0), (int)flags);
		}
		if (rval >= 0)
			descriptor_add(rval);
		break;
	case ACTION_OPENAT:
		flags = str2flags(open_flags, STR(2));
		if (flags & O_CREAT) {
			if (i == 3) {
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			rval = openat(NUM(0), STR(1), (int)flags,
			    (mode_t)NUM(3));
		} else {
			if (i == 4) {
				fprintf(stderr, "too many arguments\n");
				exit(1);
			}
			rval = openat(NUM(0), STR(1), (int)flags);
		}
		if (rval >= 0)
			descriptor_add(rval);
		break;
	case ACTION_CREATE:
		rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1));
		if (rval >= 0)
			close(rval);
		break;
	case ACTION_UNLINK:
		rval = unlink(STR(0));
		break;
	case ACTION_UNLINKAT:
		rval = unlinkat(NUM(0), STR(1),
		    (int)str2flags(unlinkat_flags, STR(2)));
		break;
	case ACTION_MKDIR:
		rval = mkdir(STR(0), (mode_t)NUM(1));
		break;
	case ACTION_MKDIRAT:
		rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2));
		break;
	case ACTION_RMDIR:
		rval = rmdir(STR(0));
		break;
	case ACTION_LINK:
		rval = link(STR(0), STR(1));
		break;
	case ACTION_LINKAT:
		rval = linkat(NUM(0), STR(1), NUM(2), STR(3),
		    (int)str2flags(linkat_flags, STR(4)));
		break;
	case ACTION_SYMLINK:
		rval = symlink(STR(0), STR(1));
		break;
	case ACTION_SYMLINKAT:
		rval = symlinkat(STR(0), NUM(1), STR(2));
		break;
	case ACTION_RENAME:
		rval = rename(STR(0), STR(1));
		break;
	case ACTION_RENAMEAT:
		rval = renameat(NUM(0), STR(1), NUM(2), STR(3));
		break;
	case ACTION_MKFIFO:
		rval = mkfifo(STR(0), (mode_t)NUM(1));
		break;
	case ACTION_MKFIFOAT:
		rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2));
		break;
	case ACTION_MKNOD:
	case ACTION_MKNODAT:
	    {
		mode_t ntype;
		dev_t dev;
		int fa;

		switch (scall->sd_action) {
		case ACTION_MKNOD:
			fa = 0;
			break;
		case ACTION_MKNODAT:
			fa = 1;
			break;
		default:
			abort();
		}

		dev = makedev(NUM(fa + 3), NUM(fa + 4));
		if (strcmp(STR(fa + 1), "c") == 0)	/* character device */
			ntype = S_IFCHR;
		else if (strcmp(STR(fa + 1), "b") == 0)	/* block device */
			ntype = S_IFBLK;
		else if (strcmp(STR(fa + 1), "f") == 0)	/* fifo special */
			ntype = S_IFIFO;
		else if (strcmp(STR(fa + 1), "d") == 0)	/* directory */
			ntype = S_IFDIR;
		else if (strcmp(STR(fa + 1), "o") == 0)	/* regular file */
			ntype = S_IFREG;
		else {
			fprintf(stderr, "wrong argument 1\n");
			exit(1);
		}
		switch (scall->sd_action) {
		case ACTION_MKNOD:
			rval = mknod(STR(0), ntype | NUM(2), dev);
			break;
		case ACTION_MKNODAT:
			rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev);
			break;
		default:
			abort();
		}
		break;
	    }
	case ACTION_BIND:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx));
		break;
	    }
#ifdef HAS_BINDAT
	case ACTION_BINDAT:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = bindat(NUM(0), rval, (struct sockaddr *)&sunx,
		    sizeof(sunx));
		break;
	    }
#endif
	case ACTION_CONNECT:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx));
		break;
	    }
#ifdef HAS_CONNECTAT
	case ACTION_CONNECTAT:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = connectat(NUM(0), rval, (struct sockaddr *)&sunx,
		    sizeof(sunx));
		break;
	    }
#endif
	case ACTION_CHMOD:
		rval = chmod(STR(0), (mode_t)NUM(1));
		break;
	case ACTION_FCHMOD:
		rval = fchmod(NUM(0), (mode_t)NUM(1));
		break;
#ifdef HAS_LCHMOD
	case ACTION_LCHMOD:
		rval = lchmod(STR(0), (mode_t)NUM(1));
		break;
#endif
	case ACTION_FCHMODAT:
		rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2),
		    str2flags(fchmodat_flags, STR(3)));
		break;
	case ACTION_CHOWN:
		rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
		break;
	case ACTION_FCHOWN:
		rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2));
		break;
	case ACTION_LCHOWN:
		rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
		break;
	case ACTION_FCHOWNAT:
		rval = fchownat(NUM(0), STR(1), (uid_t)NUM(2), (gid_t)NUM(3),
		    (int)str2flags(fchownat_flags, STR(4)));
		break;
#ifdef HAS_CHFLAGS
	case ACTION_CHFLAGS:
		rval = chflags(STR(0),
		    (unsigned long)str2flags(chflags_flags, STR(1)));
		break;
#endif
#ifdef HAS_FCHFLAGS
	case ACTION_FCHFLAGS:
		rval = fchflags(NUM(0),
		    (unsigned long)str2flags(chflags_flags, STR(1)));
		break;
#endif
#ifdef HAS_CHFLAGSAT
	case ACTION_CHFLAGSAT:
		rval = chflagsat(NUM(0), STR(1),
		    (unsigned long)str2flags(chflags_flags, STR(2)),
		    (int)str2flags(chflagsat_flags, STR(3)));
		break;
#endif
#ifdef HAS_LCHFLAGS
	case ACTION_LCHFLAGS:
		rval = lchflags(STR(0),
		    (unsigned long)str2flags(chflags_flags, STR(1)));
		break;
#endif
	case ACTION_TRUNCATE:
		rval = truncate64(STR(0), NUM(1));
		break;
	case ACTION_FTRUNCATE:
		rval = ftruncate64(NUM(0), NUM(1));
		break;
	case ACTION_STAT:
		rval = stat64(STR(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_FSTAT:
		rval = fstat64(NUM(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_LSTAT:
		rval = lstat64(STR(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_FSTATAT:
		rval = fstatat(NUM(0), STR(1), &sb,
		    (int)str2flags(fstatat_flags, STR(2)));
		if (rval == 0) {
			show_stats(&sb, STR(3));
			return (i);
		}
		break;
	case ACTION_PATHCONF:
	case ACTION_FPATHCONF:
	case ACTION_LPATHCONF:
	    {
		long lrval;

		name = str2name(pathconf_names, STR(1));
		if (name == -1) {
			fprintf(stderr, "unknown name %s", STR(1));
			exit(1);
		}
		errno = 0;
		switch (scall->sd_action) {
		case ACTION_PATHCONF:
			lrval = pathconf(STR(0), name);
			break;
		case ACTION_FPATHCONF:
			lrval = fpathconf(NUM(0), name);
			break;
		case ACTION_LPATHCONF:
			lrval = lpathconf(STR(0), name);
			break;
		default:
			abort();
		}
		if (lrval == -1 && errno == 0) {
			printf("unlimited\n");
			return (i);
		} else if (lrval >= 0) {
			printf("%ld\n", lrval);
			return (i);
		}
		rval = -1;
		break;
	    }
#ifdef HAS_FREEBSD_ACL
	case ACTION_PREPENDACL:
		rval = -1;

		acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
		if (acl == NULL)
			break;

		newacl = acl_from_text(STR(1));
		if (acl == NULL)
			break;

		while (acl_get_entry(newacl, entry_id, &newentry) == 1) {
			entry_id = ACL_NEXT_ENTRY;

			if (acl_create_entry_np(&acl, &entry, 0))
				break;

			if (acl_copy_entry(entry, newentry))
				break;
		}

		rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl);
		break;
	case ACTION_READACL:
		acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
		if (acl == NULL)
			rval = -1;
		else
			rval = 0;
		break;
#endif
	case ACTION_WRITE:
		rval = write(NUM(0), STR(1), strlen(STR(1)));
		break;
	default:
		fprintf(stderr, "unsupported syscall\n");
		exit(1);
	}
#undef STR
#undef NUM
	if (rval < 0) {
		const char *serrno;

		serrno = err2str(errno);
		fprintf(stderr, "%s returned %d\n", scall->sd_name, rval);
		printf("%s\n", serrno);
		exit(1);
	}
	printf("0\n");
	return (i);
}
コード例 #25
0
static void
create_archive (const char *archivefname, struct locarhandle *ah)
{
  int fd;
  char fname[strlen (archivefname) + sizeof (".XXXXXX")];
  struct locarhead head;
  void *p;
  size_t total;

  strcpy (stpcpy (fname, archivefname), ".XXXXXX");

  /* Create a temporary file in the correct directory.  */
  fd = mkstemp (fname);
  if (fd == -1)
    error (EXIT_FAILURE, errno, _("cannot create temporary file"));

  /* Create the initial content of the archive.  */
  head.magic = AR_MAGIC;
  head.serial = 0;
  head.namehash_offset = sizeof (struct locarhead);
  head.namehash_used = 0;
  head.namehash_size = next_prime (INITIAL_NUM_NAMES);

  head.string_offset = (head.namehash_offset
			+ head.namehash_size * sizeof (struct namehashent));
  head.string_used = 0;
  head.string_size = INITIAL_SIZE_STRINGS;

  head.locrectab_offset = head.string_offset + head.string_size;
  head.locrectab_used = 0;
  head.locrectab_size = INITIAL_NUM_LOCREC;

  head.sumhash_offset = (head.locrectab_offset
			 + head.locrectab_size * sizeof (struct locrecent));
  head.sumhash_used = 0;
  head.sumhash_size = next_prime (INITIAL_NUM_SUMS);

  total = head.sumhash_offset + head.sumhash_size * sizeof (struct sumhashent);

  /* Write out the header and create room for the other data structures.  */
  if (TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head))) != sizeof (head))
    {
      int errval = errno;
      unlink (fname);
      error (EXIT_FAILURE, errval, _("cannot initialize archive file"));
    }

  if (ftruncate64 (fd, total) != 0)
    {
      int errval = errno;
      unlink (fname);
      error (EXIT_FAILURE, errval, _("cannot resize archive file"));
    }

  /* To prepare for enlargements of the mmaped area reserve some
     address space.  */
  size_t reserved = RESERVE_MMAP_SIZE;
  int xflags = 0;
  if (total < reserved
      && ((p = mmap64 (NULL, reserved, PROT_NONE, MAP_PRIVATE | MAP_ANON,
		       -1, 0)) != MAP_FAILED))
    xflags = MAP_FIXED;
  else
    {
      p = NULL;
      reserved = total;
    }

  /* Map the header and all the administration data structures.  */
  p = mmap64 (p, total, PROT_READ | PROT_WRITE, MAP_SHARED | xflags, fd, 0);
  if (p == MAP_FAILED)
    {
      int errval = errno;
      unlink (fname);
      error (EXIT_FAILURE, errval, _("cannot map archive header"));
    }

  /* Now try to rename it.  We don't use the rename function since
     this would overwrite a file which has been created in
     parallel.  */
  if (link (fname, archivefname) == -1)
    {
      int errval = errno;

      /* We cannot use the just created file.  */
      close (fd);
      unlink (fname);

      if (errval == EEXIST)
	{
	  /* There is already an archive.  Must have been a localedef run
	     which happened in parallel.  Simply open this file then.  */
	  open_archive (ah, false);
	  return;
	}

      error (EXIT_FAILURE, errval, _("failed to create new locale archive"));
    }

  /* Remove the temporary name.  */
  unlink (fname);

  /* Make the file globally readable.  */
  if (fchmod (fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1)
    {
      int errval = errno;
      unlink (archivefname);
      error (EXIT_FAILURE, errval,
	     _("cannot change mode of new locale archive"));
    }

  ah->fd = fd;
  ah->addr = p;
  ah->mmaped = total;
  ah->reserved = reserved;
}
コード例 #26
0
ファイル: usd_file.c プロジェクト: sanchit-matta/openafs
static int
usd_FileIoctl(usd_handle_t usd, int req, void *arg)
{
    int fd = (intptr_t)(usd->handle);
#ifdef O_LARGEFILE
    struct stat64 info;
#else /* O_LARGEFILE */
    struct stat info;
#endif /* O_LARGEFILE */
#ifdef AFS_AIX_ENV
    struct statfs fsinfo;	/* AIX stat structure doesn't have st_blksize */
#endif /* AFS_AIX_ENV */
    afs_int64 size;
    int code = 0;

    switch (req) {
    case USD_IOCTL_GETBLKSIZE:
#ifdef AFS_AIX_ENV
	code = fstatfs(fd, &fsinfo);
	if (code) {
	    *((long *)arg) = (long)4096;
	    return 0;
	}
	break;
#endif /* AFS_AIX_ENV */
    case USD_IOCTL_GETTYPE:
    case USD_IOCTL_GETDEV:
    case USD_IOCTL_GETSIZE:
#ifdef O_LARGEFILE
	code = fstat64(fd, &info);
#else /* O_LARGEFILE */
	code = fstat(fd, &info);
#endif /* O_LARGEFILE */
	if (code)
	    return errno;
	break;
    }

    switch (req) {
    case USD_IOCTL_GETTYPE:
	*(int *)arg = info.st_mode & S_IFMT;
	break;
    case USD_IOCTL_GETDEV:
	if (!(S_ISCHR(info.st_mode) || S_ISBLK(info.st_mode)))
	    return ENODEV;	/* not a device */
	*(dev_t *) arg = info.st_rdev;
	break;
    case USD_IOCTL_GETSIZE:
	if (S_ISCHR(info.st_mode) || S_ISBLK(info.st_mode))
	    return ENOTTY;	/* shouldn't be a device */
	*(afs_int64 *)arg = info.st_size;
	break;
    case USD_IOCTL_GETFULLNAME:
	*(char **)arg = usd->fullPathName;
	break;

    case USD_IOCTL_SETSIZE:

	/* We could just use ftruncate in all cases.  (This even works on AIX;
	 * I tried it). -blake 931118 */

	/* However, I'm pretty sure this doesn't work on Ultrix so I am
	 * unsure about OSF/1 and HP/UX. 931118 */

	size = *(afs_int64 *) arg;
	if (!osi_hFitsInOff(size))
	    return EFBIG;
#ifdef O_LARGEFILE
	code = ftruncate64(fd, size);
#else /* O_LARGEFILE */
	code = ftruncate(fd, size);
#endif /* O_LARGEFILE */
	if (code == -1)
	    code = errno;
	return code;

    case USD_IOCTL_TAPEOPERATION:
	{
#ifdef AFS_DARWIN100_ENV
	    code = EOPNOTSUPP;
#else
	    usd_tapeop_t *tapeOpp = (usd_tapeop_t *) arg;
#if defined(AFS_AIX_ENV)
	    struct stop os_tapeop;

	    if (tapeOpp->tp_op == USDTAPE_WEOF) {
		os_tapeop.st_op = STWEOF;
	    } else if (tapeOpp->tp_op == USDTAPE_REW) {
		os_tapeop.st_op = STREW;
	    } else if (tapeOpp->tp_op == USDTAPE_FSF) {
		os_tapeop.st_op = STFSF;
	    } else if (tapeOpp->tp_op == USDTAPE_BSF) {
		os_tapeop.st_op = STRSF;
	    } else if (tapeOpp->tp_op == USDTAPE_PREPARE) {
		return 0;
	    } else if (tapeOpp->tp_op == USDTAPE_SHUTDOWN) {
		return 0;
	    } else {
		/* unsupported tape operation */
		return EINVAL;
	    }
	    os_tapeop.st_count = tapeOpp->tp_count;

	    code = ioctl(fd, STIOCTOP, &os_tapeop);
#else
	    struct mtop os_tapeop;

	    if (tapeOpp->tp_op == USDTAPE_WEOF) {
		os_tapeop.mt_op = MTWEOF;
	    } else if (tapeOpp->tp_op == USDTAPE_REW) {
		os_tapeop.mt_op = MTREW;
	    } else if (tapeOpp->tp_op == USDTAPE_FSF) {
		os_tapeop.mt_op = MTFSF;
	    } else if (tapeOpp->tp_op == USDTAPE_BSF) {
		os_tapeop.mt_op = MTBSF;
	    } else if (tapeOpp->tp_op == USDTAPE_PREPARE) {
		return 0;
	    } else if (tapeOpp->tp_op == USDTAPE_SHUTDOWN) {
		return 0;
	    } else {
		/* unsupported tape operation */
		return EINVAL;
	    }
	    os_tapeop.mt_count = tapeOpp->tp_count;

	    code = ioctl(fd, MTIOCTOP, &os_tapeop);
#endif /* AFS_AIX_ENV */
#endif
	    if (code == -1) {
		code = errno;
	    } else {
		code = 0;
	    }
	    return code;
	}

    case USD_IOCTL_GETBLKSIZE:
	if (S_ISCHR(info.st_mode) || S_ISBLK(info.st_mode)) {
	    *((long *)arg) = (long)4096;
	    return 0;
	}
#ifdef AFS_AIX_ENV
	*((long *)arg) = (long)fsinfo.f_bsize;
#else /* AFS_AIX_ENV */
	*((long *)arg) = (long)info.st_blksize;
#endif /* AFS_AIX_ENV */
	break;

    default:
	return EINVAL;
    }
    return code;
}
コード例 #27
0
int main (int argc, char ** argv)
{
	errcode_t	retval;
	ext2_filsys	fs;
	int		c;
	int		flags = 0;
	int		flush = 0;
	int		force = 0;
	int		io_flags = 0;
	int		force_min_size = 0;
	int		print_min_size = 0;
	int		fd, ret;
	blk64_t		new_size = 0;
	blk64_t		max_size = 0;
	blk64_t		min_size = 0;
	io_manager	io_ptr;
	char		*new_size_str = 0;
	int		use_stride = -1;
	ext2fs_struct_stat st_buf;
	__s64		new_file_size;
	unsigned int	sys_page_size = 4096;
	long		sysval;
	int		len, mount_flags;
	char		*mtpt;

#ifdef ENABLE_NLS
	setlocale(LC_MESSAGES, "");
	setlocale(LC_CTYPE, "");
	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
	textdomain(NLS_CAT_NAME);
	set_com_err_gettext(gettext);
#endif

	add_error_table(&et_ext2_error_table);

	fprintf (stderr, "resize2fs %s (%s)\n",
		 E2FSPROGS_VERSION, E2FSPROGS_DATE);
	if (argc && *argv)
		program_name = *argv;

	while ((c = getopt (argc, argv, "d:fFhMPpS:")) != EOF) {
		switch (c) {
		case 'h':
			usage(program_name);
			break;
		case 'f':
			force = 1;
			break;
		case 'F':
			flush = 1;
			break;
		case 'M':
			force_min_size = 1;
			break;
		case 'P':
			print_min_size = 1;
			break;
		case 'd':
			flags |= atoi(optarg);
			break;
		case 'p':
			flags |= RESIZE_PERCENT_COMPLETE;
			break;
		case 'S':
			use_stride = atoi(optarg);
			break;
		default:
			usage(program_name);
		}
	}
	if (optind == argc)
		usage(program_name);

	device_name = argv[optind++];
	if (optind < argc)
		new_size_str = argv[optind++];
	if (optind < argc)
		usage(program_name);

	io_options = strchr(device_name, '?');
	if (io_options)
		*io_options++ = 0;

	/*
	 * Figure out whether or not the device is mounted, and if it is
	 * where it is mounted.
	 */
	len=80;
	while (1) {
		mtpt = malloc(len);
		if (!mtpt)
			return ENOMEM;
		mtpt[len-1] = 0;
		retval = ext2fs_check_mount_point(device_name, &mount_flags,
						  mtpt, len);
		if (retval) {
			com_err("ext2fs_check_mount_point", retval,
				_("while determining whether %s is mounted."),
				device_name);
			exit(1);
		}
		if (!(mount_flags & EXT2_MF_MOUNTED) || (mtpt[len-1] == 0))
			break;
		free(mtpt);
		len = 2 * len;
	}

	fd = ext2fs_open_file(device_name, O_RDWR, 0);
	if (fd < 0) {
		com_err("open", errno, _("while opening %s"),
			device_name);
		exit(1);
	}

	ret = ext2fs_fstat(fd, &st_buf);
	if (ret < 0) {
		com_err("open", errno,
			_("while getting stat information for %s"),
			device_name);
		exit(1);
	}

	if (flush) {
		retval = ext2fs_sync_device(fd, 1);
		if (retval) {
			com_err(argv[0], retval,
				_("while trying to flush %s"),
				device_name);
			exit(1);
		}
	}

	if (!S_ISREG(st_buf.st_mode )) {
		close(fd);
		fd = -1;
	}

#ifdef CONFIG_TESTIO_DEBUG
	if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
		io_ptr = test_io_manager;
		test_io_backing_manager = unix_io_manager;
	} else
#endif
		io_ptr = unix_io_manager;

	if (!(mount_flags & EXT2_MF_MOUNTED))
		io_flags = EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE;

	io_flags |= EXT2_FLAG_64BITS;

	retval = ext2fs_open2(device_name, io_options, io_flags,
			      0, 0, io_ptr, &fs);
	if (retval) {
		com_err (program_name, retval, _("while trying to open %s"),
			 device_name);
		printf (_("Couldn't find valid filesystem superblock.\n"));
		exit (1);
	}

	/*
	 * Check for compatibility with the feature sets.  We need to
	 * be more stringent than ext2fs_open().
	 */
	if (fs->super->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) {
		com_err(program_name, EXT2_ET_UNSUPP_FEATURE,
			"(%s)", device_name);
		exit(1);
	}

	min_size = calculate_minimum_resize_size(fs);

	if (print_min_size) {
		if (!force && ((fs->super->s_state & EXT2_ERROR_FS) ||
			       ((fs->super->s_state & EXT2_VALID_FS) == 0))) {
			fprintf(stderr,
				_("Please run 'e2fsck -f %s' first.\n\n"),
				device_name);
			exit(1);
		}
		printf(_("Estimated minimum size of the filesystem: %llu\n"),
		       min_size);
		exit(0);
	}

	/* Determine the system page size if possible */
#ifdef HAVE_SYSCONF
#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
#define _SC_PAGESIZE _SC_PAGE_SIZE
#endif
#ifdef _SC_PAGESIZE
	sysval = sysconf(_SC_PAGESIZE);
	if (sysval > 0)
		sys_page_size = sysval;
#endif /* _SC_PAGESIZE */
#endif /* HAVE_SYSCONF */

	/*
	 * Get the size of the containing partition, and use this for
	 * defaults and for making sure the new filesystem doesn't
	 * exceed the partition size.
	 */
	retval = ext2fs_get_device_size2(device_name, fs->blocksize,
					 &max_size);
	if (retval) {
		com_err(program_name, retval,
			_("while trying to determine filesystem size"));
		exit(1);
	}
	if (force_min_size)
		new_size = min_size;
	else if (new_size_str) {
		new_size = parse_num_blocks2(new_size_str,
					     fs->super->s_log_block_size);
		if (new_size == 0) {
			com_err(program_name, 0,
				_("Invalid new size: %s\n"), new_size_str);
			exit(1);
		}
	} else {
		new_size = max_size;
		/* Round down to an even multiple of a pagesize */
		if (sys_page_size > fs->blocksize)
			new_size &= ~((sys_page_size / fs->blocksize)-1);
	}
	if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
				       EXT4_FEATURE_INCOMPAT_64BIT)) {
		/* Take 16T down to 2^32-1 blocks */
		if (new_size == (1ULL << 32))
			new_size--;
		else if (new_size > (1ULL << 32)) {
			com_err(program_name, 0,
				_("New size too large to be "
				  "expressed in 32 bits\n"));
			exit(1);
		}
	}

	if (!force && new_size < min_size) {
		com_err(program_name, 0,
			_("New size smaller than minimum (%llu)\n"), min_size);
		exit(1);
	}
	if (use_stride >= 0) {
		if (use_stride >= (int) fs->super->s_blocks_per_group) {
			com_err(program_name, 0,
				_("Invalid stride length"));
			exit(1);
		}
		fs->stride = fs->super->s_raid_stride = use_stride;
		ext2fs_mark_super_dirty(fs);
	} else
		  determine_fs_stride(fs);

	/*
	 * If we are resizing a plain file, and it's not big enough,
	 * automatically extend it in a sparse fashion by writing the
	 * last requested block.
	 */
	new_file_size = ((__u64) new_size) * fs->blocksize;
	if ((__u64) new_file_size >
	    (((__u64) 1) << (sizeof(st_buf.st_size)*8 - 1)) - 1)
		fd = -1;
	if ((new_file_size > st_buf.st_size) &&
	    (fd > 0)) {
		if ((ext2fs_llseek(fd, new_file_size-1, SEEK_SET) >= 0) &&
		    (write(fd, "0", 1) == 1))
			max_size = new_size;
	}
	if (!force && (new_size > max_size)) {
		fprintf(stderr, _("The containing partition (or device)"
			" is only %llu (%dk) blocks.\nYou requested a new size"
			" of %llu blocks.\n\n"), max_size,
			fs->blocksize / 1024, new_size);
		exit(1);
	}
	if (new_size == ext2fs_blocks_count(fs->super)) {
		fprintf(stderr, _("The filesystem is already %llu blocks "
			"long.  Nothing to do!\n\n"), new_size);
		exit(0);
	}
	if (mount_flags & EXT2_MF_MOUNTED) {
		retval = online_resize_fs(fs, mtpt, &new_size, flags);
	} else {
		if (!force && ((fs->super->s_lastcheck < fs->super->s_mtime) ||
			       (fs->super->s_state & EXT2_ERROR_FS) ||
			       ((fs->super->s_state & EXT2_VALID_FS) == 0))) {
			fprintf(stderr,
				_("Please run 'e2fsck -f %s' first.\n\n"),
				device_name);
			exit(1);
		}
		/*
		 * XXXX The combination of flex_bg and !resize_inode
		 * causes major problems for resize2fs, since when the
		 * group descriptors grow in size this can potentially
		 * require multiple inode tables to be moved aside to
		 * make room, and resize2fs chokes rather badly in
		 * this scenario.  It's a rare combination, except
		 * when a filesystem is expanded more than a certain
		 * size, so for now, we'll just prohibit that
		 * combination.  This is something we should fix
		 * eventually, though.
		 */
		if ((fs->super->s_feature_incompat &
		     EXT4_FEATURE_INCOMPAT_FLEX_BG) &&
		    !(fs->super->s_feature_compat &
		      EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
			com_err(program_name, 0, _("%s: The combination of "
				"flex_bg and\n\t!resize_inode features "
				"is not supported by resize2fs.\n"),
				device_name);
			exit(1);
		}
		printf(_("Resizing the filesystem on "
			 "%s to %llu (%dk) blocks.\n"),
		       device_name, new_size, fs->blocksize / 1024);
		retval = resize_fs(fs, &new_size, flags,
				   ((flags & RESIZE_PERCENT_COMPLETE) ?
				    resize_progress_func : 0));
	}
	free(mtpt);
	if (retval) {
		com_err(program_name, retval, _("while trying to resize %s"),
			device_name);
		fprintf(stderr,
			_("Please run 'e2fsck -fy %s' to fix the filesystem\n"
			  "after the aborted resize operation.\n"),
			device_name);
		ext2fs_close(fs);
		exit(1);
	}
	printf(_("The filesystem on %s is now %llu blocks long.\n\n"),
	       device_name, new_size);

	if ((st_buf.st_size > new_file_size) &&
	    (fd > 0)) {
#ifdef HAVE_FTRUNCATE64
		retval = ftruncate64(fd, new_file_size);
#else
		retval = 0;
		/* Only truncate if new_file_size doesn't overflow off_t */
		if (((off_t) new_file_size) == new_file_size)
			retval = ftruncate(fd, (off_t) new_file_size);
#endif
		if (retval)
			com_err(program_name, retval,
				_("while trying to truncate %s"),
				device_name);
	}
	if (fd > 0)
		close(fd);
	remove_error_table(&et_ext2_error_table);
	return (0);
}
コード例 #28
0
ファイル: node.c プロジェクト: ystk/debian-xfsdump
nh_t
node_alloc( void )
{
    nix_t nix;
    u_char_t *p;
    nh_t nh;
    register nix_t *linkagep;
#ifdef NODECHK
    register u_char_t *hkpp;
    register u_char_t gen;
    register u_char_t unq;
#endif /* NODECHK */

    /* if free list is depleted, map in a new window at the
     * end of backing store. put all nodes on free list.
     * initialize the gen count to the node index, and the unique
     * pattern to the free pattern.
     */
    if ( node_hdrp->nh_freenix == NIX_NULL ) {
        nix_t virgbegnix; /* abs. nix of first node in virg seg */
        nix_t virgendnix; /* abs. nix of next node after last */
        nix_t sacrcnt; /* how many virgins to put on free list */
        nix_t sacrnix;

        ASSERT( node_hdrp->nh_virgrelnix
                <
                ( nix_t )node_hdrp->nh_nodesperseg );
        virgbegnix = OFF2NIX( node_hdrp->nh_virgsegreloff )
                     +
                     node_hdrp->nh_virgrelnix;
        virgendnix =
            OFF2NIX( ( node_hdrp->nh_virgsegreloff
                       +
                       ( off64_t )node_hdrp->nh_segsz ) );
#ifdef TREE_DEBUG
        mlog(MLOG_DEBUG | MLOG_TREE,
             "node_alloc(): create freelist - "
             "virg_begin=%lld virg_end=%lld\n",
             virgbegnix, virgendnix);
#endif
        ASSERT( virgendnix > virgbegnix );
        sacrcnt = min( VIRGSACRMAX, virgendnix - virgbegnix );
        ASSERT( sacrcnt >= 1 );
        p = 0; /* keep lint happy */
        win_map( NIX2OFF( virgbegnix ), ( void ** )&p );
        if (p == NULL)
            return NH_NULL;
        node_hdrp->nh_freenix = virgbegnix;
        for ( sacrnix = virgbegnix
                        ;
                sacrnix < virgbegnix + sacrcnt - 1
                ;
                p += node_hdrp->nh_nodesz, sacrnix++ ) {
            linkagep = ( nix_t * )p;
            *linkagep = sacrnix + 1;
#ifdef NODECHK
            hkpp = p + node_hdrp->nh_nodehkix;
            gen = ( u_char_t )sacrnix;
            *hkpp = ( u_char_t )HKPMKHKP( ( size_t )gen,
                                          NODEUNQFREE );
#endif /* NODECHK */
        }
        linkagep = ( nix_t * )p;
        *linkagep = NIX_NULL;
#ifdef NODECHK
        hkpp = p + node_hdrp->nh_nodehkix;
        gen = ( u_char_t )sacrnix;
        *hkpp = HKPMKHKP( gen, NODEUNQFREE );
#endif /* NODECHK */
        node_hdrp->nh_virgrelnix += sacrcnt;
        win_unmap( node_hdrp->nh_virgsegreloff, ( void ** )&p );

        if ( node_hdrp->nh_virgrelnix
                >=
                ( nix_t )node_hdrp->nh_nodesperseg ) {
            intgen_t rval;
            ASSERT( node_hdrp->nh_virgrelnix
                    ==
                    ( nix_t )node_hdrp->nh_nodesperseg );
            ASSERT( node_hdrp->nh_virgsegreloff
                    <=
                    OFF64MAX - ( off64_t )node_hdrp->nh_segsz );
#ifdef TREE_DEBUG
            mlog(MLOG_DEBUG | MLOG_TREE,
                 "node_alloc(): runout of nodes for freelist in "
                 "this segment - nodes used = %lld\n",
                 node_hdrp->nh_virgrelnix);
#endif
            node_hdrp->nh_virgsegreloff +=
                ( off64_t )node_hdrp->nh_segsz;
            node_hdrp->nh_virgrelnix = 0;
            mlog( MLOG_DEBUG,
                  "pre-growing new node array segment at %lld "
                  "size %lld\n",
                  node_hdrp->nh_firstsegoff
                  +
                  node_hdrp->nh_virgsegreloff
                  +
                  ( off64_t )node_hdrp->nh_segsz,
                  ( off64_t )node_hdrp->nh_segsz );
            rval = ftruncate64( node_fd,
                                node_hdrp->nh_firstsegoff
                                +
                                node_hdrp->nh_virgsegreloff
                                +
                                ( off64_t )node_hdrp->nh_segsz );
            if ( rval ) {
                mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _(
                          "unable to autogrow node segment %llu: "
                          "%s (%d)\n"),
                      node_hdrp->nh_virgsegreloff
                      /
                      ( off64_t )node_hdrp->nh_segsz,
                      strerror( errno ),
                      errno );
            }
        }
    }

    /* map in window containing node at top of free list,
     * and adjust free list.
     */
    nix = node_hdrp->nh_freenix;
#ifdef TREE_DEBUG
    mlog(MLOG_DEBUG | MLOG_TREE,
         "node_alloc(): win_map(%llu) and get head from node freelist\n",
         NIX2OFF(nix));
#endif
    win_map( NIX2OFF( nix ), ( void ** )&p );
    if (p == NULL)
        return NH_NULL;
#ifdef NODECHK
    hkpp = p + node_hdrp->nh_nodehkix;
    unq = HKPGETUNQ( *hkpp );
    ASSERT( unq != NODEUNQALCD );
    ASSERT( unq == NODEUNQFREE );
#endif /* NODECHK */
    linkagep = ( nix_t * )p;
    node_hdrp->nh_freenix = *linkagep;

    /* clean the node
     */
    memset( ( void * )p, 0, node_hdrp->nh_nodesz );

    /* build a handle for node
     */
    ASSERT( nix <= NIX_MAX );
#ifdef NODECHK
    hkpp = p + ( int )node_hdrp->nh_nodehkix;
    gen = ( u_char_t )( HKPGETGEN( *p ) + ( u_char_t )1 );
    nh = HDLMKHDL( gen, nix );
    *hkpp = HKPMKHKP( gen, NODEUNQALCD );
#else /* NODECHK */
    nh = ( nh_t )nix;
#endif /* NODECHK */

    /* unmap window
     */
#ifdef TREE_DEBUG
    mlog(MLOG_DEBUG | MLOG_TREE,
         "node_alloc(): win_unmap(%llu)\n", NIX2OFF(nix));
#endif
    win_unmap( NIX2OFF( nix ), ( void ** )&p );

    return nh;
}
コード例 #29
0
ファイル: sem.c プロジェクト: NanXiao/illumos-joyent
sem_t *
sem_open(const char *path, int oflag, /* mode_t mode, int value */ ...)
{
	va_list	ap;
	mode_t	crmode = 0;
	sem_t	*sem = NULL;
	struct	stat64 statbuf;
	semaddr_t *next = NULL;
	int	fd = 0;
	int	error = 0;
	int	cr_flag = 0;
	uint_t	value = 0;

	if (__pos4obj_check(path) == -1)
		return (SEM_FAILED);

	/* acquire semaphore lock to have atomic operation */
	if (__pos4obj_lock(path, SEM_LOCK_TYPE) < 0)
		return (SEM_FAILED);

	/* modify oflag to have RDWR and filter CREATE mode only */
	oflag = (oflag & (O_CREAT|O_EXCL)) | (O_RDWR);
	if (oflag & O_CREAT) {
		if (semvaluemax == 0 &&
		    (semvaluemax = _sysconf(_SC_SEM_VALUE_MAX)) <= 0)
			semvaluemax = -1;
		va_start(ap, oflag);
		crmode = va_arg(ap, mode_t);
		value = va_arg(ap, uint_t);
		va_end(ap);
		/* check value < the max for a named semaphore */
		if (semvaluemax < 0 ||
		    (ulong_t)value > (ulong_t)semvaluemax) {
			errno = EINVAL;
			goto out;
		}
	}

	errno = 0;

	if ((fd = __pos4obj_open(path, SEM_DATA_TYPE,
	    oflag, crmode, &cr_flag)) < 0)
		goto out;

	if (cr_flag)
		cr_flag = DFILE_CREATE | DFILE_OPEN;
	else
		cr_flag = DFILE_OPEN;

	/* find out inode # for the opened file */
	if (fstat64(fd, &statbuf) < 0)
		goto out;

	/* if created, acquire total_size in the file */
	if ((cr_flag & DFILE_CREATE) != 0) {
		if (ftruncate64(fd, (off64_t)sizeof (sem_t)) < 0)
			goto out;
	} else {
		/*
		 * if this semaphore has already been opened, inode
		 * will indicate then return the same semaphore address
		 */
		lmutex_lock(&semlock);
		for (next = semheadp; next != NULL; next = next->sad_next) {
			if (statbuf.st_ino == next->sad_inode &&
			    strcmp(path, next->sad_name) == 0) {
				(void) __close_nc(fd);
				lmutex_unlock(&semlock);
				(void) __pos4obj_unlock(path, SEM_LOCK_TYPE);
				return (next->sad_addr);
			}
		}
		lmutex_unlock(&semlock);
	}


	/* new sem descriptor to be allocated and new address to be mapped */
	if ((next = malloc(sizeof (semaddr_t))) == NULL) {
		errno = ENOMEM;
		goto out;
	}
	cr_flag |= ALLOC_MEM;

	/* LINTED */
	sem = (sem_t *)mmap64(NULL, sizeof (sem_t), PROT_READ|PROT_WRITE,
	    MAP_SHARED, fd, (off64_t)0);
	(void) __close_nc(fd);
	cr_flag &= ~DFILE_OPEN;
	if (sem == MAP_FAILED)
		goto out;
	cr_flag |= DFILE_MMAP;

	/* if created, initialize */
	if (cr_flag & DFILE_CREATE) {
		error = sema_init((sema_t *)sem, value, USYNC_PROCESS, 0);
		if (error) {
			errno = error;
			goto out;
		}
	}

	if (__pos4obj_unlock(path, SEM_LOCK_TYPE) == 0) {
		/* add to the list pointed by semheadp */
		lmutex_lock(&semlock);
		next->sad_next = semheadp;
		semheadp = next;
		next->sad_addr = sem;
		next->sad_inode = statbuf.st_ino;
		(void) strcpy(next->sad_name, path);
		lmutex_unlock(&semlock);
		return (sem);
	}
	/* fall into the error case */
out:
	error = errno;
	if ((cr_flag & DFILE_OPEN) != 0)
		(void) __close_nc(fd);
	if ((cr_flag & DFILE_CREATE) != 0)
		(void) __pos4obj_unlink(path, SEM_DATA_TYPE);
	if ((cr_flag & ALLOC_MEM) != 0)
		free(next);
	if ((cr_flag & DFILE_MMAP) != 0)
		(void) munmap((caddr_t)sem, sizeof (sem_t));
	(void) __pos4obj_unlock(path, SEM_LOCK_TYPE);
	errno = error;
	return (SEM_FAILED);
}
コード例 #30
0
ファイル: main.c プロジェクト: bagana/e2fsprogs
int main (int argc, char ** argv)
{
	errcode_t	retval;
	ext2_filsys	fs;
	int		c;
	int		flags = 0;
	int		flush = 0;
	int		force = 0;
	int		io_flags = 0;
	int		force_min_size = 0;
	int		print_min_size = 0;
	int		fd, ret;
	blk64_t		new_size = 0;
	blk64_t		max_size = 0;
	blk64_t		min_size = 0;
	io_manager	io_ptr;
	char		*new_size_str = 0;
	int		use_stride = -1;
	ext2fs_struct_stat st_buf;
	__s64		new_file_size;
	unsigned int	sys_page_size = 4096;
	unsigned int	blocksize;
	long		sysval;
	int		len, mount_flags;
	char		*mtpt, *undo_file = NULL;

#ifdef ENABLE_NLS
	setlocale(LC_MESSAGES, "");
	setlocale(LC_CTYPE, "");
	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
	textdomain(NLS_CAT_NAME);
	set_com_err_gettext(gettext);
#endif

	add_error_table(&et_ext2_error_table);

	fprintf (stderr, "resize2fs %s (%s)\n",
		 E2FSPROGS_VERSION, E2FSPROGS_DATE);
	if (argc && *argv)
		program_name = *argv;

	while ((c = getopt(argc, argv, "d:fFhMPpS:bsz:")) != EOF) {
		switch (c) {
		case 'h':
			usage(program_name);
			break;
		case 'f':
			force = 1;
			break;
		case 'F':
			flush = 1;
			break;
		case 'M':
			force_min_size = 1;
			break;
		case 'P':
			print_min_size = 1;
			break;
		case 'd':
			flags |= atoi(optarg);
			break;
		case 'p':
			flags |= RESIZE_PERCENT_COMPLETE;
			break;
		case 'S':
			use_stride = atoi(optarg);
			break;
		case 'b':
			flags |= RESIZE_ENABLE_64BIT;
			break;
		case 's':
			flags |= RESIZE_DISABLE_64BIT;
			break;
		case 'z':
			undo_file = optarg;
			break;
		default:
			usage(program_name);
		}
	}
	if (optind == argc)
		usage(program_name);

	device_name = argv[optind++];
	if (optind < argc)
		new_size_str = argv[optind++];
	if (optind < argc)
		usage(program_name);

	io_options = strchr(device_name, '?');
	if (io_options)
		*io_options++ = 0;

	/*
	 * Figure out whether or not the device is mounted, and if it is
	 * where it is mounted.
	 */
	len=80;
	while (1) {
		mtpt = malloc(len);
		if (!mtpt)
			return ENOMEM;
		mtpt[len-1] = 0;
		retval = ext2fs_check_mount_point(device_name, &mount_flags,
						  mtpt, len);
		if (retval) {
			com_err("ext2fs_check_mount_point", retval,
				_("while determining whether %s is mounted."),
				device_name);
			exit(1);
		}
		if (!(mount_flags & EXT2_MF_MOUNTED) || (mtpt[len-1] == 0))
			break;
		free(mtpt);
		len = 2 * len;
	}

	fd = ext2fs_open_file(device_name, O_RDWR, 0);
	if (fd < 0) {
		com_err("open", errno, _("while opening %s"),
			device_name);
		exit(1);
	}

	ret = ext2fs_fstat(fd, &st_buf);
	if (ret < 0) {
		com_err("open", errno,
			_("while getting stat information for %s"),
			device_name);
		exit(1);
	}

	if (flush) {
		retval = ext2fs_sync_device(fd, 1);
		if (retval) {
			com_err(argv[0], retval,
				_("while trying to flush %s"),
				device_name);
			exit(1);
		}
	}

	if (!S_ISREG(st_buf.st_mode )) {
		close(fd);
		fd = -1;
	}

#ifdef CONFIG_TESTIO_DEBUG
	if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
		io_ptr = test_io_manager;
		test_io_backing_manager = unix_io_manager;
	} else
#endif
		io_ptr = unix_io_manager;

	if (!(mount_flags & EXT2_MF_MOUNTED))
		io_flags = EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE;

	io_flags |= EXT2_FLAG_64BITS;
	if (undo_file) {
		retval = resize2fs_setup_tdb(device_name, undo_file, &io_ptr);
		if (retval)
			exit(1);
	}
	retval = ext2fs_open2(device_name, io_options, io_flags,
			      0, 0, io_ptr, &fs);
	if (retval) {
		com_err(program_name, retval, _("while trying to open %s"),
			device_name);
		printf("%s", _("Couldn't find valid filesystem superblock.\n"));
		exit (1);
	}
	fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE;

	/*
	 * Before acting on an unmounted filesystem, make sure it's ok,
	 * unless the user is forcing it.
	 *
	 * We do ERROR and VALID checks even if we're only printing the
	 * minimimum size, because traversal of a badly damaged filesystem
	 * can cause issues as well.  We don't require it to be fscked after
	 * the last mount time in this case, though, as this is a bit less
	 * risky.
	 */
	if (!force && !(mount_flags & EXT2_MF_MOUNTED)) {
		int checkit = 0;

		if (fs->super->s_state & EXT2_ERROR_FS)
			checkit = 1;

		if ((fs->super->s_state & EXT2_VALID_FS) == 0)
			checkit = 1;

		if ((fs->super->s_lastcheck < fs->super->s_mtime) &&
		    !print_min_size)
			checkit = 1;

		if (checkit) {
			fprintf(stderr,
				_("Please run 'e2fsck -f %s' first.\n\n"),
				device_name);
			exit(1);
		}
	}

	/*
	 * Check for compatibility with the feature sets.  We need to
	 * be more stringent than ext2fs_open().
	 */
	if (fs->super->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) {
		com_err(program_name, EXT2_ET_UNSUPP_FEATURE,
			"(%s)", device_name);
		exit(1);
	}

	min_size = calculate_minimum_resize_size(fs, flags);

	if (print_min_size) {
		printf(_("Estimated minimum size of the filesystem: %llu\n"),
		       min_size);
		exit(0);
	}

	/* Determine the system page size if possible */
#ifdef HAVE_SYSCONF
#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
#define _SC_PAGESIZE _SC_PAGE_SIZE
#endif
#ifdef _SC_PAGESIZE
	sysval = sysconf(_SC_PAGESIZE);
	if (sysval > 0)
		sys_page_size = sysval;
#endif /* _SC_PAGESIZE */
#endif /* HAVE_SYSCONF */

	/*
	 * Get the size of the containing partition, and use this for
	 * defaults and for making sure the new filesystem doesn't
	 * exceed the partition size.
	 */
	blocksize = fs->blocksize;
	retval = ext2fs_get_device_size2(device_name, blocksize,
					 &max_size);
	if (retval) {
		com_err(program_name, retval, "%s",
			_("while trying to determine filesystem size"));
		exit(1);
	}
	if (force_min_size)
		new_size = min_size;
	else if (new_size_str) {
		new_size = parse_num_blocks2(new_size_str,
					     fs->super->s_log_block_size);
		if (new_size == 0) {
			com_err(program_name, 0,
				_("Invalid new size: %s\n"), new_size_str);
			exit(1);
		}
	} else {
		new_size = max_size;
		/* Round down to an even multiple of a pagesize */
		if (sys_page_size > blocksize)
			new_size &= ~((sys_page_size / blocksize)-1);
	}
	/* If changing 64bit, don't change the filesystem size. */
	if (flags & (RESIZE_DISABLE_64BIT | RESIZE_ENABLE_64BIT)) {
		new_size = ext2fs_blocks_count(fs->super);
	}
	if (!ext2fs_has_feature_64bit(fs->super)) {
		/* Take 16T down to 2^32-1 blocks */
		if (new_size == (1ULL << 32))
			new_size--;
		else if (new_size > (1ULL << 32)) {
			com_err(program_name, 0, "%s",
				_("New size too large to be "
				  "expressed in 32 bits\n"));
			exit(1);
		}
	}

	if (!force && new_size < min_size) {
		com_err(program_name, 0,
			_("New size smaller than minimum (%llu)\n"), min_size);
		exit(1);
	}
	if (use_stride >= 0) {
		if (use_stride >= (int) fs->super->s_blocks_per_group) {
			com_err(program_name, 0, "%s",
				_("Invalid stride length"));
			exit(1);
		}
		fs->stride = fs->super->s_raid_stride = use_stride;
		ext2fs_mark_super_dirty(fs);
	} else
		  determine_fs_stride(fs);

	/*
	 * If we are resizing a plain file, and it's not big enough,
	 * automatically extend it in a sparse fashion by writing the
	 * last requested block.
	 */
	new_file_size = ((__u64) new_size) * blocksize;
	if ((__u64) new_file_size >
	    (((__u64) 1) << (sizeof(st_buf.st_size)*8 - 1)) - 1)
		fd = -1;
	if ((new_file_size > st_buf.st_size) &&
	    (fd > 0)) {
		if ((ext2fs_llseek(fd, new_file_size-1, SEEK_SET) >= 0) &&
		    (write(fd, "0", 1) == 1))
			max_size = new_size;
	}
	if (!force && (new_size > max_size)) {
		fprintf(stderr, _("The containing partition (or device)"
			" is only %llu (%dk) blocks.\nYou requested a new size"
			" of %llu blocks.\n\n"), max_size,
			blocksize / 1024, new_size);
		exit(1);
	}
	if ((flags & RESIZE_DISABLE_64BIT) && (flags & RESIZE_ENABLE_64BIT)) {
		fprintf(stderr, _("Cannot set and unset 64bit feature.\n"));
		exit(1);
	} else if (flags & (RESIZE_DISABLE_64BIT | RESIZE_ENABLE_64BIT)) {
		if (new_size >= (1ULL << 32)) {
			fprintf(stderr, _("Cannot change the 64bit feature "
				"on a filesystem that is larger than "
				"2^32 blocks.\n"));
			exit(1);
		}
		if (mount_flags & EXT2_MF_MOUNTED) {
			fprintf(stderr, _("Cannot change the 64bit feature "
				"while the filesystem is mounted.\n"));
			exit(1);
		}
		if (flags & RESIZE_ENABLE_64BIT &&
		    !ext2fs_has_feature_extents(fs->super)) {
			fprintf(stderr, _("Please enable the extents feature "
				"with tune2fs before enabling the 64bit "
				"feature.\n"));
			exit(1);
		}
	} else if (new_size == ext2fs_blocks_count(fs->super)) {
		fprintf(stderr, _("The filesystem is already %llu (%dk) "
			"blocks long.  Nothing to do!\n\n"), new_size,
			blocksize / 1024);
		exit(0);
	}
	if ((flags & RESIZE_ENABLE_64BIT) &&
	    ext2fs_has_feature_64bit(fs->super)) {
		fprintf(stderr, _("The filesystem is already 64-bit.\n"));
		exit(0);
	}
	if ((flags & RESIZE_DISABLE_64BIT) &&
	    !ext2fs_has_feature_64bit(fs->super)) {
		fprintf(stderr, _("The filesystem is already 32-bit.\n"));
		exit(0);
	}
	if (mount_flags & EXT2_MF_MOUNTED) {
		bigalloc_check(fs, force);
		retval = online_resize_fs(fs, mtpt, &new_size, flags);
	} else {
		bigalloc_check(fs, force);
		if (flags & RESIZE_ENABLE_64BIT)
			printf(_("Converting the filesystem to 64-bit.\n"));
		else if (flags & RESIZE_DISABLE_64BIT)
			printf(_("Converting the filesystem to 32-bit.\n"));
		else
			printf(_("Resizing the filesystem on "
				 "%s to %llu (%dk) blocks.\n"),
			       device_name, new_size, blocksize / 1024);
		retval = resize_fs(fs, &new_size, flags,
				   ((flags & RESIZE_PERCENT_COMPLETE) ?
				    resize_progress_func : 0));
	}
	free(mtpt);
	if (retval) {
		com_err(program_name, retval, _("while trying to resize %s"),
			device_name);
		fprintf(stderr,
			_("Please run 'e2fsck -fy %s' to fix the filesystem\n"
			  "after the aborted resize operation.\n"),
			device_name);
		ext2fs_close_free(&fs);
		exit(1);
	}
	printf(_("The filesystem on %s is now %llu (%dk) blocks long.\n\n"),
	       device_name, new_size, blocksize / 1024);

	if ((st_buf.st_size > new_file_size) &&
	    (fd > 0)) {
#ifdef HAVE_FTRUNCATE64
		retval = ftruncate64(fd, new_file_size);
#else
		retval = 0;
		/* Only truncate if new_file_size doesn't overflow off_t */
		if (((off_t) new_file_size) == new_file_size)
			retval = ftruncate(fd, (off_t) new_file_size);
#endif
		if (retval)
			com_err(program_name, retval,
				_("while trying to truncate %s"),
				device_name);
	}
	if (fd > 0)
		close(fd);
	remove_error_table(&et_ext2_error_table);
	return (0);
}