Beispiel #1
0
static const entry_t *
get_pri_dirs(void)
{
	int fd, state;
	size_t sz;
	ssize_t size;
	struct stat64 sb;
	char *buf, *ebuf;
	entry_t *vec;

	/*
	 * if no /etc/ttysrch, use defaults
	 */
	if ((fd = open(TTYSRCH, 0)) < 0)
		return (def_srch_dirs);

	if (fstat64(fd, &sb) < 0) {
		(void) close(fd);
		return (def_srch_dirs);
	}

	sz = (size_t)sb.st_size;
	if (dir_vec != NULL && sz == dir_size &&
	    sb.st_mtim.tv_sec == dir_mtim.tv_sec &&
	    sb.st_mtim.tv_nsec == dir_mtim.tv_nsec) {
		/*
		 * size & modification time match
		 * no need to reread TTYSRCH
		 * just return old pointer
		 */
		(void) close(fd);
		return (dir_vec);
	}
	buf = realloc(dir_buf, sz + 1);
	if (buf != NULL) {
		dir_buf = buf;
		size = read(fd, dir_buf, sz);
	}
	(void) close(fd);

	if (buf == NULL || size < 0) {
		if (dir_vec != NULL) {
			free(dir_vec);
			dir_vec = NULL;
		}
		return ((entry_t *)def_srch_dirs);
	}
	dir_size = sz;
	dir_mtim = sb.st_mtim;

	/*
	 * ensure newline termination for buffer.  Add an extra
	 * entry to dir_vec for null terminator
	 */
	ebuf = &dir_buf[size];
	*ebuf++ = '\n';
	for (sz = 1, buf = dir_buf; buf < ebuf; ++buf)
		if (*buf == '\n')
			++sz;

	sz *= sizeof (*dir_vec);
	vec = realloc(dir_vec, sz);
	if (vec == NULL) {
		if (dir_vec != NULL) {
			free(dir_vec);
			dir_vec = NULL;
		}
		return (def_srch_dirs);
	}
	dir_vec = vec;
	state = START_STATE;
	for (buf = dir_buf; buf < ebuf; ++buf) {
		switch (state) {

		case START_STATE:
			if (*buf == COMMENT_CHAR) {
				state = COMMENT_STATE;
				break;
			}
			if (!isspace(*buf))	/* skip leading white space */
				state = DIRNAME_STATE;
				vec->name = buf;
				vec->flags = 0;
			break;

		case COMMENT_STATE:
			if (*buf == EOLN_CHAR)
				state = START_STATE;
			break;

		case DIRNAME_STATE:
			if (*buf == EOLN_CHAR) {
				state = CHECK_STATE;
				*buf = '\0';
			} else if (isspace(*buf)) {
				/* skip trailing white space */
				state = FLAG_STATE;
				*buf = '\0';
			}
			break;

		case FLAG_STATE:
			switch (*buf) {
				case 'M':
					vec->flags |= MATCH_MM;
					break;
				case 'F':
					vec->flags |= MATCH_FS;
					break;
				case 'I':
					vec->flags |= MATCH_INO;
					break;
				case EOLN_CHAR:
					state = CHECK_STATE;
					break;
			}
			break;

		case CHECK_STATE:
			if (strncmp(vec->name, DEV, strlen(DEV)) != 0) {
				int tfd = open("/dev/console", O_WRONLY);
				if (tfd >= 0) {
					char buf[256];
					/* LINTED variable format specifier */
					(void) snprintf(buf, sizeof (buf),
						_libc_gettext(
"ERROR: Entry '%s' in /etc/ttysrch ignored.\n"),
						vec->name);
					(void) write(tfd, buf, strlen(buf));
					(void) close(tfd);
				}
			} else {
				char *slash;
				slash = vec->name + strlen(vec->name) - 1;
				while (*slash == '/')
					*slash-- = '\0';
				if (vec->flags == 0)
					vec->flags = MATCH_ALL;
				vec++;
			}
			state = START_STATE;
			/*
			 * This state does not consume a character, so
			 * reposition the pointer.
			 */
			buf--;
			break;

		}
	}
	vec->name = NULL;
	return (dir_vec);
}
Beispiel #2
0
int
__part_load_locale(const char *name,
		int *using_locale,
		char *locale_buf,
		const char *category_filename,
		int locale_buf_size_max,
		int locale_buf_size_min,
		const char **dst_localebuf) {

	static char		locale_buf_C[] = "C";
	static int		num_lines;



	int			 fd;
	char			*lbuf;
	char			*p;
	const char 		*plim;
	char                     filename[PATH_MAX];
#ifdef __USE_INTERNAL_STAT64
	struct stat64		 st;
#else
	struct stat		 st;
#endif
	size_t			 namesize;
	size_t			 bufsize;
	int                      save_using_locale;
        char *nptr;

	save_using_locale = *using_locale;
	*using_locale = 0;

	if (name == NULL)
		goto no_locale;

	if (!strcmp(name, "C") || !strcmp(name, "POSIX"))
		return 0;

	/* XXX: when adding cxx support the function failed to compile, so
	 *      the missing functions below were commented out.
	 *      adding this message here to abort and warn the user */
    printf("__part_load_locale not implemented!\n");
    abort();

	/*
	 * If the locale name is the same as our cache, use the cache.
	 */
	lbuf = locale_buf;
	if (lbuf != NULL && strcmp(name, lbuf) == 0) {
		set_from_buf(lbuf, num_lines, dst_localebuf);
		*using_locale = 1;
		return 0;
	}

	/*
	 * Slurp the locale file into the cache.
	 */
	namesize = strlen(name) + 1;

	if (!_PathLocale)
		goto no_locale;
	/* Range checking not needed, 'name' size is limited */
	strcpy(filename, _PathLocale);
	strcat(filename, "/");
	strcat(filename, name);
	strcat(filename, "/");
	strcat(filename, category_filename);
	//fd = open(filename, O_RDONLY);
	if (fd < 0)
		goto no_locale;
#ifdef __USE_INTERNAL_STAT64
	if (fstat64(fd, &st) != 0)
#else
	//if (fstat(fd, &st) != 0)
#endif
	//	goto bad_locale;
	if (st.st_size <= 0)
		goto bad_locale;
	bufsize = namesize + st.st_size + 1;
	locale_buf = NULL;

        if (lbuf == NULL || lbuf == locale_buf_C)
          {
            lbuf = malloc(bufsize);
          }
        else
          {
            nptr = realloc(lbuf, bufsize);
            if (!nptr && lbuf)
              free (lbuf);
            lbuf = nptr;
          }

	if (lbuf == NULL)
		goto bad_locale;
	(void) strcpy(lbuf, name);
	p = lbuf + namesize;
	plim = p + st.st_size;
	//if (read(fd, p, (size_t) st.st_size) != st.st_size)
	//	goto bad_lbuf;
	//if (close(fd) != 0)
	//	goto bad_lbuf;
	/*
	 * Parse the locale file into localebuf.
	 */
	p[st.st_size] = '\0';
	if (plim[-1] != '\n')
		goto bad_lbuf;
	num_lines = split_lines(p, plim);
	if (num_lines >= locale_buf_size_max)
		num_lines = locale_buf_size_max;
	else if (num_lines >= locale_buf_size_min)
		num_lines = locale_buf_size_min;
	else
		goto reset_locale;
	set_from_buf(lbuf, num_lines, dst_localebuf);
	/*
	 * Record the successful parse in the cache.
	 */
	locale_buf = lbuf;

	*using_locale = 1;
	return 0;

reset_locale:
	locale_buf = locale_buf_C;
	save_using_locale = 0;
bad_lbuf:
	free(lbuf);
bad_locale:
	//(void)close(fd);
no_locale:
	*using_locale = save_using_locale;
	return -1;
}
Beispiel #3
0
/*
 * Name:	compute_checksum
 * Description:	generate checksum for specified file
 * Arguments:	r_cksumerr (int *) [RO, *RW]
 *			- pointer to integer that is set on return to:
 *				== 0 - no error occurred
 *				!= 0 - error occurred
 *		a_path (char *) [RO, *RO]
 *			- pointer to string representing path to file to
 *			  generate checksum of
 * Returns:	unsigned long - results:
 *			- If *r_cksumerr == 0, checksum of specified file
 *			- If *r_cksumerr != 0, undefined
 */
unsigned long
compute_checksum(int *r_cksumerr, char *a_path)
{
	CHECKSUM_T	suma;	/* to split four-bytes into 2 two-byte values */
	CHECKSUM_T	tempa;
	int		fd;
	uint32_t	lg;	/* running checksum value */
	uint32_t	buf[CHUNK/4]; /* to read CHUNK bytes */
	uint32_t	lsavhi;	/* high order two-bytes of four-byte checksum */
	uint32_t	lsavlo;	/* low order two-bytes of four-byte checksum */
	int		leap = sizeof (uint32_t);
	int		notyet = 0;
	int		nread;
	struct stat64	sbuf;

	/* reset error flag */
	*r_cksumerr = 0;

	/* open file and obtain -> where file is mapped/read */
	if ((fd = open(a_path, O_RDONLY)) < 0) {
		*r_cksumerr = 1;
		reperr(pkg_gt(ERR_NO_CKSUM));
		perror(ERR_NO_CKSUM);
		return (0);
	}

	if (fstat64(fd, &sbuf) != 0) {
		*r_cksumerr = 1;
		reperr(pkg_gt(ERR_NO_CKSUM));
		perror(ERR_NO_CKSUM);
		return (0);
	}

	/* initialize checksum value */
	lg = 0;

	/*
	 * Read CHUNK bytes off the file at a time; Read size of long bytes
	 * from memory at a time and process them.
	 * If last read, then read remnant bytes and process individually.
	 */
	errno = 0;
	while ((nread = read(fd, (void*)buf,
		    (sbuf.st_size < CHUNK) ? sbuf.st_size : CHUNK)) > 0) {
		uchar_t *s;
		uint32_t *p = buf;

		notyet = nread % leap;
		nread -= notyet;

		for (; nread > 0; nread -= leap) {
			lg += ((((*p)>>24)&0xFF) & WDMSK);
			lg += ((((*p)>>16)&0xFF) & WDMSK);
			lg += ((((*p)>>8)&0xFF) & WDMSK);
			lg += (((*p)&0xFF) & WDMSK);
			p++;
		}
		s = (uchar_t *)p;
		/* leftover bytes less than four in number */
		while (notyet--)
			lg += (((uint32_t)(*s++)) & WDMSK);
	}

	/* wind up */
	(void) close(fd);

	/* compute checksum components */
	suma.lg = lg;
	tempa.lg = (suma.hl.lo & WDMSK) + (suma.hl.hi & WDMSK);
	lsavhi = (uint32_t)tempa.hl.hi;
	lsavlo = (uint32_t)tempa.hl.lo;

	/* return final checksum value */
	return (lsavhi+lsavlo);
}
Beispiel #4
0
int main(int argc, char *argv[])
{
	int fd = 0, disk = 0;
	int ret;
	int offset;
	unsigned long c = 0;
	int block_size, block_count, block_num;
	off64_t block_off, seek_ret;
	struct stat64 statinfo;
	struct timeval start_time, end_time;
	char *membuf = NULL;
	unsigned char *buf;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return 0;

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

	return -1;
}
Beispiel #5
0
char *
gettxt(const char *msg_id, const char *dflt_str)
{
	struct db_cache	*dbc;
	struct db_list	*dbl;
	char 	msgfile[DB_NAME_LEN];	/* name of static shared library */
	int	msgnum;			/* message number */
	char	pathname[PATH_MAX];	/* full pathname to message file */
	int	fd;
	struct stat64	sb;
	void	*addr;
	char	*tokp;
	size_t	name_len;
	char	*curloc;

	if ((msg_id == NULL) || (*msg_id == '\0')) {
		return (handle_return(dflt_str));
	}

	/* parse msg_id */
	if (((tokp = strchr(msg_id, ':')) == NULL) || *(tokp+1) == '\0')
		return (handle_return(dflt_str));
	if ((name_len = (tokp - msg_id)) >= DB_NAME_LEN)
		return (handle_return(dflt_str));
	if (name_len > 0) {
		(void) strncpy(msgfile, msg_id, name_len);
		msgfile[name_len] = '\0';
	} else {
		lrw_rdlock(&_rw_cur_cat);
		if (cur_cat == NULL || *cur_cat == '\0') {
			lrw_unlock(&_rw_cur_cat);
			return (handle_return(dflt_str));
		}
		/*
		 * We know the following strcpy is safe.
		 */
		(void) strcpy(msgfile, cur_cat);
		lrw_unlock(&_rw_cur_cat);
	}
	while (*++tokp) {
		if (!isdigit((unsigned char)*tokp))
			return (handle_return(dflt_str));
	}
	msgnum = atoi(msg_id + name_len + 1);
	curloc = setlocale(LC_MESSAGES, NULL);

	lmutex_lock(&gettxt_lock);

try_C:
	dbc = db_cache;
	while (dbc) {
		if (strcmp(curloc, dbc->loc) == 0) {
			dbl = dbc->info;
			while (dbl) {
				if (strcmp(msgfile, dbl->db_name) == 0) {
					/* msgfile found */
					lmutex_unlock(&gettxt_lock);
					goto msgfile_found;
				}
				dbl = dbl->next;
			}
			/* not found */
			break;
		}
		dbc = dbc->next;
	}
	if (dbc == NULL) {
		/* new locale */
		if ((dbc = lmalloc(sizeof (struct db_cache))) == NULL) {
			lmutex_unlock(&gettxt_lock);
			return (handle_return(dflt_str));
		}
		if ((dbc->loc = lmalloc(strlen(curloc) + 1)) == NULL) {
			lfree(dbc, sizeof (struct db_cache));
			lmutex_unlock(&gettxt_lock);
			return (handle_return(dflt_str));
		}
		dbc->info = NULL;
		(void) strcpy(dbc->loc, curloc);
		/* connect dbc to the dbc list */
		dbc->next = db_cache;
		db_cache = dbc;
	}
	if ((dbl = lmalloc(sizeof (struct db_list))) == NULL) {
		lmutex_unlock(&gettxt_lock);
		return (handle_return(dflt_str));
	}

	if (snprintf(pathname, sizeof (pathname),
	    _DFLT_LOC_PATH "%s" MESSAGES "%s", dbc->loc, msgfile) >=
	    sizeof (pathname)) {
		lfree(dbl, sizeof (struct db_list));
		lmutex_unlock(&gettxt_lock);
		return (handle_return(dflt_str));
	}
	if ((fd = open(pathname, O_RDONLY)) == -1 ||
	    fstat64(fd, &sb) == -1 ||
	    (addr = mmap(NULL, (size_t)sb.st_size, PROT_READ, MAP_SHARED,
	    fd, 0L)) == MAP_FAILED) {
		if (fd != -1)
			(void) close(fd);
		lfree(dbl, sizeof (struct db_list));

		if (strcmp(dbc->loc, "C") == 0) {
			lmutex_unlock(&gettxt_lock);
			return (handle_return(dflt_str));
		}
		/* Change locale to C */
		curloc = (char *)loc_C;
		goto try_C;
	}
	(void) close(fd);

	/* save file name, memory address, fd and size */
	(void) strcpy(dbl->db_name, msgfile);
	dbl->addr = (uintptr_t)addr;

	/* connect dbl to the dbc->info list */
	dbl->next = dbc->info;
	dbc->info = dbl;

	lmutex_unlock(&gettxt_lock);

msgfile_found:
	/* check if msgnum out of domain */
	if (msgnum <= 0 || msgnum > *(int *)dbl->addr)
		return (handle_return(dflt_str));
	/* return pointer to message */
	return ((char *)(dbl->addr +
	    *(int *)(dbl->addr + msgnum * sizeof (int))));
}
Beispiel #6
0
static int
undo_one (void **p, void *info)
{
  struct prelink_entry *ent = * (struct prelink_entry **) p;
  DSO *dso;
  struct stat64 st;
  struct prelink_link *hardlink;
  char *move = NULL;
  size_t movelen = 0;

  if (ent->done != 2)
    return 1;

  if (ent->type != ET_DYN
      && (ent->type != ET_EXEC || libs_only))
    return 1;

  dso = open_dso (ent->canon_filename);
  if (dso == NULL)
    goto error_out;

  if (fstat64 (dso->fd, &st) < 0)
    {
      error (0, errno, "%s changed during prelinking", ent->filename);
      goto error_out;
    }

  if (st.st_dev != ent->dev || st.st_ino != ent->ino)
    {
      error (0, 0, "%s changed during prelinking", ent->filename);
      goto error_out;
    }

  if (verbose)
    {
      if (dry_run)
	printf ("Would undo %s\n", ent->canon_filename);
      else
	printf ("Undoing %s\n", ent->canon_filename);
    }

  if (prelink_undo (dso))
    goto error_out;

  if (dry_run)
    close_dso (dso);
  else
    {
      if (update_dso (dso, NULL))
	{
	  dso = NULL;
	  goto error_out;
	}
    }

  dso = NULL;

  /* Redo hardlinks.  */
  for (hardlink = ent->hardlink; hardlink; hardlink = hardlink->next)
    {
      size_t len;

      if (lstat64 (hardlink->canon_filename, &st) < 0)
	{
	  error (0, 0, "Could not stat %s (former hardlink to %s)",
		 hardlink->canon_filename, ent->canon_filename);
	  continue;
	}

      if (st.st_dev != ent->dev || st.st_ino != ent->ino)
	{
	  error (0, 0, "%s is no longer hardlink to %s",
		 hardlink->canon_filename, ent->canon_filename);
	  continue;
	}

      if (verbose)
	{
	  if (dry_run)
	    printf ("Would link %s to %s\n", hardlink->canon_filename,
		    ent->canon_filename);
	  else
	    printf ("Linking %s to %s\n", hardlink->canon_filename,
		    ent->canon_filename);
	}

      len = strlen (hardlink->canon_filename);
      if (len + sizeof (".#prelink#") > movelen)
	{
	  movelen = len + sizeof (".#prelink#");
	  move = realloc (move, movelen);
	  if (move == NULL)
	    {
	      error (0, ENOMEM, "Could not hardlink %s to %s",
		     hardlink->canon_filename, ent->canon_filename);
	      movelen = 0;
	      continue;
	    }
	}

      memcpy (mempcpy (move, hardlink->canon_filename, len), ".#prelink#",
	      sizeof (".#prelink#"));
      if (rename (hardlink->canon_filename, move) < 0)
	{
	  error (0, errno, "Could not hardlink %s to %s",
		 hardlink->canon_filename, ent->canon_filename);
	  continue;
	}

      if (link (ent->canon_filename, hardlink->canon_filename) < 0)
	{
	  error (0, errno, "Could not hardlink %s to %s",
		 hardlink->canon_filename, ent->canon_filename);

	  if (rename (move, hardlink->canon_filename) < 0)
	    {
	      error (0, errno, "Could not rename %s back to %s",
		     move, hardlink->canon_filename);
	    }
	  continue;
	}

      if (unlink (move) < 0)
	{
	  error (0, errno, "Could not unlink %s", move);
	  continue;
	}
    }
  free (move);
  return 1;

error_out:
  if (dso)
    close_dso (dso);
  (*(int *)info)++;
  return 1;
}
Beispiel #7
0
int vn_fromfd(int fd, char *path, int flags, struct vnode **vpp, boolean_t fromfd)
{
    int save_errno;
    vnode_t *vp;

    *vpp = vp = kmem_cache_alloc(vnode_cache, KM_SLEEP);
    memset(vp, 0, sizeof(vnode_t));

    if (fstat64(fd, &vp->v_stat) == -1) {
        save_errno = errno;
        close(fd);
        return (save_errno);
    }

    (void) fcntl(fd, F_SETFD, FD_CLOEXEC);

    vp->v_fd = fd;
    if(S_ISBLK(vp->v_stat.st_mode)) {
        /* LINUX */
        if(ioctl(fd, BLKGETSIZE64, &vp->v_size) != 0) {
            save_errno = errno;
            close(fd);
            return (save_errno);
        }
    } else
        vp->v_size = vp->v_stat.st_size;
    vp->v_path = strdup(path);

    vp->v_type = VNON;

    if(fromfd)
        vn_setops(vp, fd_fvnodeops);
    else
        vn_setops(vp, root_fvnodeops);

    if(S_ISREG(vp->v_stat.st_mode)) {
        vp->v_type = VREG;
        if (flags & FREAD)
            atomic_add_32(&((*vpp)->v_rdcnt), 1);
        if (flags & FWRITE)
            atomic_add_32(&((*vpp)->v_wrcnt), 1);
    } else if(S_ISDIR(vp->v_stat.st_mode))
        vp->v_type = VDIR;
    else if(S_ISCHR(vp->v_stat.st_mode))
        vp->v_type = VCHR;
    else if(S_ISBLK(vp->v_stat.st_mode))
        vp->v_type = VBLK;
    else if(S_ISFIFO(vp->v_stat.st_mode))
        vp->v_type = VFIFO;
    else if(S_ISLNK(vp->v_stat.st_mode))
        vp->v_type = VLNK;
    else if(S_ISSOCK(vp->v_stat.st_mode))
        vp->v_type = VSOCK;

    VERIFY(vp->v_type != VNON);

    zmutex_init(&vp->v_lock);
    rwst_init(&vp->v_vfsmhlock.ve_lock, NULL, RW_DEFAULT, NULL);

    vp->v_count = 1;
    vp->v_vfsp = rootvfs;

    /*fprintf(stderr, "VNode %p created at vn_open (%s)\n", *vpp, path);*/
    return (0);
}
Beispiel #8
0
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;
}
Beispiel #9
0
/*
 * Given a cache file, return the contents as a list of importable pools.
 * poolname or guid (but not both) are provided by the caller when trying
 * to import a specific pool.
 */
nvlist_t *
zpool_find_import_cached(libzfs_handle_t *hdl, const char *cachefile,
    char *poolname, uint64_t guid)
{
	char *buf;
	int fd;
	struct stat64 statbuf;
	nvlist_t *raw, *src, *dst;
	nvlist_t *pools;
	nvpair_t *elem;
	char *name;
	uint64_t this_guid;
	boolean_t active;

	verify(poolname == NULL || guid == 0);

	if ((fd = open(cachefile, O_RDONLY)) < 0) {
		zfs_error_aux(hdl, "%s", strerror(errno));
		(void) zfs_error(hdl, EZFS_BADCACHE,
		    dgettext(TEXT_DOMAIN, "failed to open cache file"));
		return (NULL);
	}

	if (fstat64(fd, &statbuf) != 0) {
		zfs_error_aux(hdl, "%s", strerror(errno));
		(void) close(fd);
		(void) zfs_error(hdl, EZFS_BADCACHE,
		    dgettext(TEXT_DOMAIN, "failed to get size of cache file"));
		return (NULL);
	}

	if ((buf = zfs_alloc(hdl, statbuf.st_size)) == NULL) {
		(void) close(fd);
		return (NULL);
	}

	if (read(fd, buf, statbuf.st_size) != statbuf.st_size) {
		(void) close(fd);
		free(buf);
		(void) zfs_error(hdl, EZFS_BADCACHE,
		    dgettext(TEXT_DOMAIN,
		    "failed to read cache file contents"));
		return (NULL);
	}

	(void) close(fd);

	if (nvlist_unpack(buf, statbuf.st_size, &raw, 0) != 0) {
		free(buf);
		(void) zfs_error(hdl, EZFS_BADCACHE,
		    dgettext(TEXT_DOMAIN,
		    "invalid or corrupt cache file contents"));
		return (NULL);
	}

	free(buf);

	/*
	 * Go through and get the current state of the pools and refresh their
	 * state.
	 */
	if (nvlist_alloc(&pools, 0, 0) != 0) {
		(void) no_memory(hdl);
		nvlist_free(raw);
		return (NULL);
	}

	elem = NULL;
	while ((elem = nvlist_next_nvpair(raw, elem)) != NULL) {
		verify(nvpair_value_nvlist(elem, &src) == 0);

		verify(nvlist_lookup_string(src, ZPOOL_CONFIG_POOL_NAME,
		    &name) == 0);
		if (poolname != NULL && strcmp(poolname, name) != 0)
			continue;

		verify(nvlist_lookup_uint64(src, ZPOOL_CONFIG_POOL_GUID,
		    &this_guid) == 0);
		if (guid != 0) {
			verify(nvlist_lookup_uint64(src, ZPOOL_CONFIG_POOL_GUID,
			    &this_guid) == 0);
			if (guid != this_guid)
				continue;
		}

		if (pool_active(hdl, name, this_guid, &active) != 0) {
			nvlist_free(raw);
			nvlist_free(pools);
			return (NULL);
		}

		if (active)
			continue;

		if ((dst = refresh_config(hdl, src)) == NULL) {
			nvlist_free(raw);
			nvlist_free(pools);
			return (NULL);
		}

		if (nvlist_add_nvlist(pools, nvpair_name(elem), dst) != 0) {
			(void) no_memory(hdl);
			nvlist_free(dst);
			nvlist_free(raw);
			nvlist_free(pools);
			return (NULL);
		}
		nvlist_free(dst);
	}

	nvlist_free(raw);
	return (pools);
}
Beispiel #10
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;
#ifdef HAVE_FSTAT64
	struct stat64	st_buf;
#else
	struct stat	st_buf;
#endif
	__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);
	}

#ifdef HAVE_FSTAT64
	ret = fstat64(fd, &st_buf);
#else
	ret = fstat(fd, &st_buf);
#endif
	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;
	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);
	}

	/*
	 * 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);
	}

	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 {
		/* Take down devices exactly 16T to 2^32-1 blocks */
		if (max_size == (1ULL << 32))
			max_size--;
		else if (max_size > (1ULL << 32)) {
			com_err(program_name, 0, _("New size too large to be "
				"expressed in 32 bits\n"));
			exit(1);
		}
		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 (!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);
		}
		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);
}
Beispiel #11
0
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);
}
Beispiel #12
0
/*
 * Try to work out the total size of all data by adding up the sizes of all
 * input files. If any of the input files are of indeterminate size (i.e.
 * they are a pipe), the total size is set to zero.
 *
 * Any files that cannot be stat()ed or that access() says we can't read
 * will cause a warning to be output and will be removed from the list.
 *
 * In line mode, any files that pass the above checks will then be read to
 * determine how many lines they contain, and the total size will be set to
 * the total line count. Only regular files will be read.
 */
void pv_calc_total_size(opts_t opts)
{
	struct stat64 sb;
	int rc, i, j, fd;

	opts->size = 0;
	rc = 0;

	if (opts->argc < 1) {
		if (fstat64(STDIN_FILENO, &sb) == 0)
			opts->size = sb.st_size;
		return;
	}

	for (i = 0; i < opts->argc; i++) {
		if (strcmp(opts->argv[i], "-") == 0) {
			rc = fstat64(STDIN_FILENO, &sb);
			if (rc != 0) {
				opts->size = 0;
				return;
			}
		} else {
			rc = stat64(opts->argv[i], &sb);
			if (rc == 0)
				rc = access(opts->argv[i], R_OK);
		}

		if (rc != 0) {
			fprintf(stderr, "%s: %s: %s\n", opts->program_name,
				opts->argv[i], strerror(errno));
			for (j = i; j < opts->argc - 1; j++) {
				opts->argv[j] = opts->argv[j + 1];
			}
			opts->argc--;
			i--;
			opts->exit_status |= 2;
			continue;
		}

		if (S_ISBLK(sb.st_mode)) {
			/*
			 * Get the size of block devices by opening
			 * them and seeking to the end.
			 */
			if (strcmp(opts->argv[i], "-") == 0) {
				fd = open64("/dev/stdin", O_RDONLY);
			} else {
				fd = open64(opts->argv[i], O_RDONLY);
			}
			if (fd >= 0) {
				opts->size += lseek64(fd, 0, SEEK_END);
				close(fd);
			} else {
				fprintf(stderr, "%s: %s: %s\n",
					opts->program_name, opts->argv[i],
					strerror(errno));
				opts->exit_status |= 2;
			}
		} else if (S_ISREG(sb.st_mode)) {
			opts->size += sb.st_size;
		} else {
			opts->size = 0;
		}
	}

	if (!opts->linemode)
		return;

	opts->size = 0;

	for (i = 0; i < opts->argc; i++) {
		fd = -1;

		if (strcmp(opts->argv[i], "-") == 0) {
			rc = fstat64(STDIN_FILENO, &sb);
			if ((rc != 0) || (!S_ISREG(sb.st_mode))) {
				opts->size = 0;
				return;
			}
			fd = dup(STDIN_FILENO);
		} else {
			rc = stat64(opts->argv[i], &sb);
			if ((rc != 0) || (!S_ISREG(sb.st_mode))) {
				opts->size = 0;
				return;
			}
			fd = open64(opts->argv[i], O_RDONLY);
		}

		if (fd < 0) {
			fprintf(stderr, "%s: %s: %s\n", opts->program_name,
				opts->argv[i], strerror(errno));
			opts->size = 0;
			opts->exit_status |= 2;
			return;
		}

		while (1) {
			unsigned char scanbuf[1024];	/* RATS: ignore (OK) */
			int numread, i;

			numread = read(fd, /* RATS: ignore (OK) */ scanbuf,
				       sizeof(scanbuf));
			if (numread < 0) {
				fprintf(stderr, "%s: %s: %s\n",
					opts->program_name, opts->argv[i],
					strerror(errno));
				opts->exit_status |= 2;
				break;
			} else if (numread == 0) {
				break;
			}
			for (i = 0; i < numread; i++) {
				if (scanbuf[i] == '\n')
					opts->size++;
			}
		}

		lseek64(fd, 0, SEEK_SET);
		close(fd);
	}
}
Beispiel #13
0
/*
 * Close the given file descriptor and open the next one, whose number in
 * the list is "filenum", returning the new file descriptor (or negative on
 * error). It is an error if the next input file is the same as the file
 * stdout is pointing to.
 */
int pv_next_file(opts_t opts, int filenum, int oldfd)
{
	struct stat64 isb;
	struct stat64 osb;
	int fd;

	if (oldfd > 0) {
		if (close(oldfd)) {
			fprintf(stderr, "%s: %s: %s\n",
				opts->program_name,
				_("failed to close file"),
				strerror(errno));
			opts->exit_status |= 8;
			return -1;
		}
	}

	if (filenum >= opts->argc) {
		opts->exit_status |= 8;
		return -1;
	}

	if (filenum < 0) {
		opts->exit_status |= 8;
		return -1;
	}

	if (strcmp(opts->argv[filenum], "-") == 0) {
		fd = STDIN_FILENO;
	} else {
		fd = open64(opts->argv[filenum], O_RDONLY);
		if (fd < 0) {
			fprintf(stderr, "%s: %s: %s: %s\n",
				opts->program_name,
				_("failed to read file"),
				opts->argv[filenum], strerror(errno));
			opts->exit_status |= 2;
			return -1;
		}
	}

	if (fstat64(fd, &isb)) {
		fprintf(stderr, "%s: %s: %s: %s\n",
			opts->program_name,
			_("failed to stat file"),
			opts->argv[filenum], strerror(errno));
		close(fd);
		opts->exit_status |= 2;
		return -1;
	}

	if (fstat64(STDOUT_FILENO, &osb)) {
		fprintf(stderr, "%s: %s: %s\n",
			opts->program_name,
			_("failed to stat output file"), strerror(errno));
		close(fd);
		opts->exit_status |= 2;
		return -1;
	}

	/*
	 * Check that this new input file is not the same as stdout's
	 * destination. This restriction is ignored for anything other
	 * than a regular file or block device.
	 */
	if (isb.st_dev != osb.st_dev)
		return fd;
	if (isb.st_ino != osb.st_ino)
		return fd;
	if (isatty(fd))
		return fd;
	if ((!S_ISREG(isb.st_mode)) && (!S_ISBLK(isb.st_mode)))
		return fd;

	fprintf(stderr, "%s: %s: %s\n",
		opts->program_name,
		_("input file is output file"), opts->argv[filenum]);
	close(fd);
	opts->exit_status |= 4;
	return -1;
}
Beispiel #14
0
int
main (void)
{
  const char *tmpdir;
  char *fname;
  int fd;
  FILE *fp;
  const char outstr[] = "hello world!\n";
  char strbuf[sizeof outstr];
  char buf[200];
  struct stat64 st1;
  struct stat64 st2;
  int result = 0;

  tmpdir = getenv ("TMPDIR");
  if (tmpdir == NULL || tmpdir[0] == '\0')
    tmpdir = "/tmp";

  asprintf (&fname, "%s/tst-fseek.XXXXXX", tmpdir);
  if (fname == NULL)
    error (EXIT_FAILURE, errno, "cannot generate name for temporary file");

  /* Create a temporary file.   */
  fd = mkstemp (fname);
  if (fd == -1)
    error (EXIT_FAILURE, errno, "cannot open temporary file");

  fp = fdopen (fd, "w+");
  if (fp == NULL)
    error (EXIT_FAILURE, errno, "cannot get FILE for temporary file");

  setbuffer (fp, strbuf, sizeof (outstr) -1);

  if (fwrite (outstr, sizeof (outstr) - 1, 1, fp) != 1)
    {
      printf ("%d: write error\n", __LINE__);
      result = 1;
      goto out;
    }

  /* The EOF flag must be reset.  */
  if (fgetc (fp) != EOF)
    {
      printf ("%d: managed to read at end of file\n", __LINE__);
      result = 1;
    }
  else if (! feof (fp))
    {
      printf ("%d: EOF flag not set\n", __LINE__);
      result = 1;
    }
  if (fseek (fp, 0, SEEK_CUR) != 0)
    {
      printf ("%d: fseek(fp, 0, SEEK_CUR) failed\n", __LINE__);
      result = 1;
    }
  else if (feof (fp))
    {
      printf ("%d: fseek() didn't reset EOF flag\n", __LINE__);
      result = 1;
    }

  /* Do the same for fseeko().  */
    if (fgetc (fp) != EOF)
    {
      printf ("%d: managed to read at end of file\n", __LINE__);
      result = 1;
    }
  else if (! feof (fp))
    {
      printf ("%d: EOF flag not set\n", __LINE__);
      result = 1;
    }
  if (fseeko (fp, 0, SEEK_CUR) != 0)
    {
      printf ("%d: fseek(fp, 0, SEEK_CUR) failed\n", __LINE__);
      result = 1;
    }
  else if (feof (fp))
    {
      printf ("%d: fseek() didn't reset EOF flag\n", __LINE__);
      result = 1;
    }

  /* Go back to the beginning of the file: absolute.  */
  if (fseek (fp, 0, SEEK_SET) != 0)
    {
      printf ("%d: fseek(fp, 0, SEEK_SET) failed\n", __LINE__);
      result = 1;
    }
  else if (fflush (fp) != 0)
    {
      printf ("%d: fflush() failed\n", __LINE__);
      result = 1;
    }
  else if (lseek (fd, 0, SEEK_CUR) != 0)
    {
      printf ("%d: lseek() returned different position\n", __LINE__);
      result = 1;
    }
  else if (fread (buf, sizeof (outstr) - 1, 1, fp) != 1)
    {
      printf ("%d: fread() failed\n", __LINE__);
      result = 1;
    }
  else if (memcmp (buf, outstr, sizeof (outstr) - 1) != 0)
    {
      printf ("%d: content after fseek(,,SEEK_SET) wrong\n", __LINE__);
      result = 1;
    }

  /* Now with fseeko.  */
  if (fseeko (fp, 0, SEEK_SET) != 0)
    {
      printf ("%d: fseeko(fp, 0, SEEK_SET) failed\n", __LINE__);
      result = 1;
    }
  else if (fflush (fp) != 0)
    {
      printf ("%d: fflush() failed\n", __LINE__);
      result = 1;
    }
  else if (lseek (fd, 0, SEEK_CUR) != 0)
    {
      printf ("%d: lseek() returned different position\n", __LINE__);
      result = 1;
    }
  else if (fread (buf, sizeof (outstr) - 1, 1, fp) != 1)
    {
      printf ("%d: fread() failed\n", __LINE__);
      result = 1;
    }
  else if (memcmp (buf, outstr, sizeof (outstr) - 1) != 0)
    {
      printf ("%d: content after fseeko(,,SEEK_SET) wrong\n", __LINE__);
      result = 1;
    }

  /* Go back to the beginning of the file: relative.  */
  if (fseek (fp, -((int) sizeof (outstr) - 1), SEEK_CUR) != 0)
    {
      printf ("%d: fseek(fp, 0, SEEK_SET) failed\n", __LINE__);
      result = 1;
    }
  else if (fflush (fp) != 0)
    {
      printf ("%d: fflush() failed\n", __LINE__);
      result = 1;
    }
  else if (lseek (fd, 0, SEEK_CUR) != 0)
    {
      printf ("%d: lseek() returned different position\n", __LINE__);
      result = 1;
    }
  else if (fread (buf, sizeof (outstr) - 1, 1, fp) != 1)
    {
      printf ("%d: fread() failed\n", __LINE__);
      result = 1;
    }
  else if (memcmp (buf, outstr, sizeof (outstr) - 1) != 0)
    {
      printf ("%d: content after fseek(,,SEEK_SET) wrong\n", __LINE__);
      result = 1;
    }

  /* Now with fseeko.  */
  if (fseeko (fp, -((int) sizeof (outstr) - 1), SEEK_CUR) != 0)
    {
      printf ("%d: fseeko(fp, 0, SEEK_SET) failed\n", __LINE__);
      result = 1;
    }
  else if (fflush (fp) != 0)
    {
      printf ("%d: fflush() failed\n", __LINE__);
      result = 1;
    }
  else if (lseek (fd, 0, SEEK_CUR) != 0)
    {
      printf ("%d: lseek() returned different position\n", __LINE__);
      result = 1;
    }
  else if (fread (buf, sizeof (outstr) - 1, 1, fp) != 1)
    {
      printf ("%d: fread() failed\n", __LINE__);
      result = 1;
    }
  else if (memcmp (buf, outstr, sizeof (outstr) - 1) != 0)
    {
      printf ("%d: content after fseeko(,,SEEK_SET) wrong\n", __LINE__);
      result = 1;
    }

  /* Go back to the beginning of the file: from the end.  */
  if (fseek (fp, -((int) sizeof (outstr) - 1), SEEK_END) != 0)
    {
      printf ("%d: fseek(fp, 0, SEEK_SET) failed\n", __LINE__);
      result = 1;
    }
  else if (fflush (fp) != 0)
    {
      printf ("%d: fflush() failed\n", __LINE__);
      result = 1;
    }
  else if (lseek (fd, 0, SEEK_CUR) != 0)
    {
      printf ("%d: lseek() returned different position\n", __LINE__);
      result = 1;
    }
  else if (fread (buf, sizeof (outstr) - 1, 1, fp) != 1)
    {
      printf ("%d: fread() failed\n", __LINE__);
      result = 1;
    }
  else if (memcmp (buf, outstr, sizeof (outstr) - 1) != 0)
    {
      printf ("%d: content after fseek(,,SEEK_SET) wrong\n", __LINE__);
      result = 1;
    }

  /* Now with fseeko.  */
  if (fseeko (fp, -((int) sizeof (outstr) - 1), SEEK_END) != 0)
    {
      printf ("%d: fseeko(fp, 0, SEEK_SET) failed\n", __LINE__);
      result = 1;
    }
  else if (fflush (fp) != 0)
    {
      printf ("%d: fflush() failed\n", __LINE__);
      result = 1;
    }
  else if (lseek (fd, 0, SEEK_CUR) != 0)
    {
      printf ("%d: lseek() returned different position\n", __LINE__);
      result = 1;
    }
  else if (fread (buf, sizeof (outstr) - 1, 1, fp) != 1)
    {
      printf ("%d: fread() failed\n", __LINE__);
      result = 1;
    }
  else if (memcmp (buf, outstr, sizeof (outstr) - 1) != 0)
    {
      printf ("%d: content after fseeko(,,SEEK_SET) wrong\n", __LINE__);
      result = 1;
    }

  if (fwrite (outstr, sizeof (outstr) - 1, 1, fp) != 1)
    {
      printf ("%d: write error 2\n", __LINE__);
      result = 1;
      goto out;
    }

  if (fwrite (outstr, sizeof (outstr) - 1, 1, fp) != 1)
    {
      printf ("%d: write error 3\n", __LINE__);
      result = 1;
      goto out;
    }

  if (fwrite (outstr, sizeof (outstr) - 1, 1, fp) != 1)
    {
      printf ("%d: write error 4\n", __LINE__);
      result = 1;
      goto out;
    }

  if (fwrite (outstr, sizeof (outstr) - 1, 1, fp) != 1)
    {
      printf ("%d: write error 5\n", __LINE__);
      result = 1;
      goto out;
    }

  if (fputc ('1', fp) == EOF || fputc ('2', fp) == EOF)
    {
      printf ("%d: cannot add characters at the end\n", __LINE__);
      result = 1;
      goto out;
    }

  /* Check the access time.  */
  if (fstat64 (fd, &st1) < 0)
    {
      printf ("%d: fstat64() before fseeko() failed\n\n", __LINE__);
      result = 1;
    }
  else
    {
      sleep (1);

      if (fseek (fp, -(2 + 2 * (sizeof (outstr) - 1)), SEEK_CUR) != 0)
	{
	  printf ("%d: fseek() after write characters failed\n", __LINE__);
	  result = 1;
	  goto out;
	}
      else
	{

	  time_t t;
	  /* Make sure the timestamp actually can be different.  */
	  sleep (1);
	  t = time (NULL);

	  if (fstat64 (fd, &st2) < 0)
	    {
	      printf ("%d: fstat64() after fseeko() failed\n\n", __LINE__);
	      result = 1;
	    }
	  if (st1.st_ctime >= t)
	    {
	      printf ("%d: st_ctime not updated\n", __LINE__);
	      result = 1;
	    }
	  if (st1.st_mtime >= t)
	    {
	      printf ("%d: st_mtime not updated\n", __LINE__);
	      result = 1;
	    }
	  if (st1.st_ctime >= st2.st_ctime)
	    {
	      printf ("%d: st_ctime not changed\n", __LINE__);
	      result = 1;
	    }
	  if (st1.st_mtime >= st2.st_mtime)
	    {
	      printf ("%d: st_mtime not changed\n", __LINE__);
	      result = 1;
	    }
	}
    }

  if (fread (buf, 1, 2 + 2 * (sizeof (outstr) - 1), fp)
      != 2 + 2 * (sizeof (outstr) - 1))
    {
      printf ("%d: reading 2 records plus bits failed\n", __LINE__);
      result = 1;
    }
  else if (memcmp (buf, outstr, sizeof (outstr) - 1) != 0
	   || memcmp (&buf[sizeof (outstr) - 1], outstr,
		      sizeof (outstr) - 1) != 0
	   || buf[2 * (sizeof (outstr) - 1)] != '1'
	   || buf[2 * (sizeof (outstr) - 1) + 1] != '2')
    {
      printf ("%d: reading records failed\n", __LINE__);
      result = 1;
    }
  else if (ungetc ('9', fp) == EOF)
    {
      printf ("%d: ungetc() failed\n", __LINE__);
      result = 1;
    }
  else if (fseek (fp, -(2 + 2 * (sizeof (outstr) - 1)), SEEK_END) != 0)
    {
      printf ("%d: fseek after ungetc failed\n", __LINE__);
      result = 1;
    }
  else if (fread (buf, 1, 2 + 2 * (sizeof (outstr) - 1), fp)
      != 2 + 2 * (sizeof (outstr) - 1))
    {
      printf ("%d: reading 2 records plus bits failed\n", __LINE__);
      result = 1;
    }
  else if (memcmp (buf, outstr, sizeof (outstr) - 1) != 0
	   || memcmp (&buf[sizeof (outstr) - 1], outstr,
		      sizeof (outstr) - 1) != 0
	   || buf[2 * (sizeof (outstr) - 1)] != '1')
    {
      printf ("%d: reading records for the second time failed\n", __LINE__);
      result = 1;
    }
  else if (buf[2 * (sizeof (outstr) - 1) + 1] == '9')
    {
      printf ("%d: unget character not ignored\n", __LINE__);
      result = 1;
    }
  else if (buf[2 * (sizeof (outstr) - 1) + 1] != '2')
    {
      printf ("%d: unget somehow changed character\n", __LINE__);
      result = 1;
    }

  fclose (fp);

  fp = fopen (fname, "r");
  if (fp == NULL)
    {
      printf ("%d: fopen() failed\n\n", __LINE__);
      result = 1;
    }
  else if (fstat64 (fileno (fp), &st1) < 0)
    {
      printf ("%d: fstat64() before fseeko() failed\n\n", __LINE__);
      result = 1;
    }
  else if (fseeko (fp, 0, SEEK_END) != 0)
    {
      printf ("%d: fseeko(fp, 0, SEEK_END) failed\n", __LINE__);
      result = 1;
    }
  else if (ftello (fp) != st1.st_size)
    {
      printf ("%d: fstat64 st_size %zd ftello %zd\n", __LINE__,
	      (size_t) st1.st_size, (size_t) ftello (fp));
      result = 1;
    }
  else
    printf ("%d: SEEK_END works\n", __LINE__);
  if (fp != NULL)
    fclose (fp);

  fp = fopen (fname, "r");
  if (fp == NULL)
    {
      printf ("%d: fopen() failed\n\n", __LINE__);
      result = 1;
    }
  else if (fstat64 (fileno (fp), &st1) < 0)
    {
      printf ("%d: fstat64() before fgetc() failed\n\n", __LINE__);
      result = 1;
    }
  else if (fgetc (fp) == EOF)
    {
      printf ("%d: fgetc() before fseeko() failed\n\n", __LINE__);
      result = 1;
    }
  else if (fseeko (fp, 0, SEEK_END) != 0)
    {
      printf ("%d: fseeko(fp, 0, SEEK_END) failed\n", __LINE__);
      result = 1;
    }
  else if (ftello (fp) != st1.st_size)
    {
      printf ("%d: fstat64 st_size %zd ftello %zd\n", __LINE__,
	      (size_t) st1.st_size, (size_t) ftello (fp));
      result = 1;
    }
  else
    printf ("%d: SEEK_END works\n", __LINE__);
  if (fp != NULL)
    fclose (fp);

 out:
  unlink (fname);

  return result;
}
Beispiel #15
0
static int
do_test (void)
{
  /* fdopendir takes over the descriptor, make a copy.  */
  int dupfd = dup (dir_fd);
  if (dupfd == -1)
    {
      puts ("dup failed");
      return 1;
    }
  if (lseek (dupfd, 0, SEEK_SET) != 0)
    {
      puts ("1st lseek failed");
      return 1;
    }

  /* The directory should be empty safe the . and .. files.  */
  DIR *dir = fdopendir (dupfd);
  if (dir == NULL)
    {
      puts ("fdopendir failed");
      return 1;
    }
  struct dirent64 *d;
  while ((d = readdir64 (dir)) != NULL)
    if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
      {
	printf ("temp directory contains file \"%s\"\n", d->d_name);
	return 1;
      }
  closedir (dir);

  /* Try to create a file.  */
  int fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
  if (fd == -1)
    {
      if (errno == ENOSYS)
	{
	  puts ("*at functions not supported");
	  return 0;
	}

      puts ("file creation failed");
      return 1;
    }
  write (fd, "hello", 5);
  puts ("file created");

  struct stat64 st1;
  if (fstat64 (fd, &st1) != 0)
    {
      puts ("fstat64 failed");
      return 1;
    }

  close (fd);

  if (linkat (dir_fd, "some-file", dir_fd, "another-file", 0) != 0)
    {
      puts ("symlinkat failed");
      return 1;
    }

  struct stat64 st2;
  if (fstatat64 (dir_fd, "some-file", &st2, 0) != 0)
    {
      puts ("fstatat64 failed");
      return 1;
    }
  if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
    {
      puts ("file changed after symlinkat");
      return 1;
    }

  if (fstatat64 (dir_fd, "another-file", &st2, AT_SYMLINK_NOFOLLOW) != 0)
    {
      puts ("2nd fstatat64 failed");
      return 1;
    }
  if (S_ISLNK (st2.st_mode))
    {
      puts ("2nd fstatat64 shows file is a symlink");
      return 1;
    }
  if (st1.st_dev != st2.st_dev
      || st1.st_ino != st2.st_ino
      || st1.st_size != st2.st_size)
    {
      puts ("stat results for linked file do not match");
      return 1;
    }

  if (fstatat64 (dir_fd, "another-file", &st2, 0) != 0)
    {
      puts ("3rd fstatat64 failed");
      return 1;
    }
  if (st1.st_dev != st2.st_dev
      || st1.st_ino != st2.st_ino
      || st1.st_size != st2.st_size)
    {
      puts ("stat results do not match");
      return 1;
    }

  if (unlinkat (dir_fd, "another-file", 0) != 0)
    {
      puts ("unlinkat failed");
      return 1;
    }
  if (unlinkat (dir_fd, "some-file", 0) != 0)
    {
      puts ("2nd unlinkat failed");
      return 1;
    }

  close (dir_fd);

  return 0;
}
Beispiel #16
0
/*
 * load a message catalog which specified with current locale,
 * and catalog name.
 */
static struct db_info *
load_db(const char *curloc, const char *catname, int *err)
{
	char pathname[PATH_MAX];
	struct	stat64 sb;
	caddr_t	addr;
	struct db_info *db;
	int fd;
	int i;

	*err = 0;

	/* First time called, allocate space */
	if (!db_info) {
		if ((db_info =
		    libc_malloc(MINDB * sizeof (struct db_info))) == NULL) {
			*err = 1;
			return (NULL);
		}
		maxdb = MINDB;
	}

	for (i = 0; i < db_count; i++) {
		if (db_info[i].flag == 0)
			break;
	}
	/* New catalogue */
	if (i == db_count) {
		if (db_count == maxdb) {
			if ((db = libc_realloc(db_info,
			    ++maxdb * sizeof (struct db_info))) == NULL) {
				*err = 1;
				return (NULL);
			}
			db_info = db;
		}
		db_count++;
	}
	db = &db_info[i];
	db->flag = 0;
	(void) strcpy(db->db_name, catname);
	db->saved_locale = libc_strdup(curloc);
	if (db->saved_locale == NULL) {
		*err = 1;
		return (NULL);
	}
	db->flag = DB_OPEN;
	if (snprintf(pathname, sizeof (pathname),
	    _DFLT_LOC_PATH "%s" MESSAGES "%s",
	    db->saved_locale, db->db_name) >= sizeof (pathname)) {
		/*
		 * We won't set err here, because an invalid locale is not
		 * the fatal condition, but we can fall back to "C"
		 * locale.
		 */
		return (NULL);
	}
	if ((fd = open(pathname, O_RDONLY)) != -1 &&
	    fstat64(fd, &sb) != -1 &&
	    (addr = mmap(0, (size_t)sb.st_size, PROT_READ, MAP_SHARED,
	    fd, 0)) != MAP_FAILED) {
		db->flag |= DB_EXIST;
		db->addr = (uintptr_t)addr;
		db->length = (size_t)sb.st_size;
	}
	if (fd != -1)
		(void) close(fd);
	return (db);
}
Beispiel #17
0
#define RESTARTABLE(_cmd, _result) do { \
  do { \
    _result = _cmd; \
  } while ((_result == -1) && (errno == EINTR)); \
} while(0)


JNIEXPORT void JNICALL
Java_sun_nio_ch_FileKey_initIDs(JNIEnv *env, jclass clazz)
{
    key_st_dev = (*env)->GetFieldID(env, clazz, "st_dev", "J");
    key_st_ino = (*env)->GetFieldID(env, clazz, "st_ino", "J");
}


JNIEXPORT void JNICALL
Java_sun_nio_ch_FileKey_init(JNIEnv *env, jobject this, jobject fdo)
{
    struct stat64 fbuf;
    int res;

    RESTARTABLE(fstat64(fdval(env, fdo), &fbuf), res);
    if (res < 0) {
        JNU_ThrowIOExceptionWithLastError(env, "fstat64 failed");
    } else {
        (*env)->SetLongField(env, this, key_st_dev, (jlong)fbuf.st_dev);
        (*env)->SetLongField(env, this, key_st_ino, (jlong)fbuf.st_ino);
    }
}
Beispiel #18
0
struct store *newfstore(char *dir)
{
    struct store *st;
    struct fstore *fst;
    char tbuf[1024];
    struct loghdr lh;
    struct idxhdr ih;
    struct stat64 sb;
    
    fst = calloc(1, sizeof(*fst));
    fst->logfd = -1;
    fst->idxfd = -1;
    
    snprintf(tbuf, sizeof(tbuf), "%s/log", dir);
    if((fst->logfd = open(tbuf, O_RDWR | O_LARGEFILE)) < 0) {
	flog(LOG_ERR, "could not open log %s: %s", tbuf, strerror(errno));
	release(fst);
	return(NULL);
    }
    if(fstat64(fst->logfd, &sb)) {
	flog(LOG_ERR, "could not stat log: %s", strerror(errno));
	release(fst);
	return(NULL);
    }
    fst->logsize = sb.st_size;
    if(readall(fst->logfd, &lh, sizeof(lh), 0)) {
	flog(LOG_ERR, "could not read log header: %s", strerror(errno));
	release(fst);
	return(NULL);
    }
    if(memcmp(lh.magic, LOGMAGIC, sizeof(LOGMAGIC))) {
	flog(LOG_ERR, "invalid log magic");
	release(fst);
	return(NULL);
    }
    
    snprintf(tbuf, sizeof(tbuf), "%s/index", dir);
    if((fst->idxfd = open(tbuf, O_RDWR | O_LARGEFILE)) < 0) {
	flog(LOG_ERR, "could not open index %s: %s", tbuf, strerror(errno));
	release(fst);
	return(NULL);
    }
    if(fstat64(fst->idxfd, &sb)) {
	flog(LOG_ERR, "could not stat index: %s", strerror(errno));
	release(fst);
	return(NULL);
    }
    if(readall(fst->idxfd, &ih, sizeof(ih), 0)) {
	flog(LOG_ERR, "could not read index header: %s", strerror(errno));
	release(fst);
	return(NULL);
    }
    if(memcmp(ih.magic, IDXMAGIC, sizeof(IDXMAGIC))) {
	flog(LOG_ERR, "invalid index magic");
	release(fst);
	return(NULL);
    }
    if(sb.st_size != (sizeof(struct idxhdr) + ih.size * sizeof(struct idxent))) {
	flog(LOG_ERR, "invalid index size");
	release(fst);
	return(NULL);
    }
    fst->idxsize = ih.size;
    
    st = newstore(&fstops);
    st->pdata = fst;
    return(st);
}
Beispiel #19
0
int
main(int argc, char *argv[])
{
	char *progname;
	int fd;
	int c;
	extern char *optarg;
	unsigned nprocs = 0;
	unsigned procno;
	pid_t *pidarray=NULL;
	pid_t pid;
	pid_t wr_pid = 0;
	uchar_t *buf=NULL;
	unsigned int seed;
	int pagesize = sysconf(_SC_PAGE_SIZE);
	int alarmtime = 0;
	struct sigaction sa;
	unsigned i;
	int write_cnt;
	uchar_t data;
	int no_prob = 0;
	int wait_stat;
	time_t t;
#ifdef LARGE_FILE
	off64_t bytes_left;
#else /* LARGE_FILE */
	off_t bytes_left;
#endif /* LARGE_FILE */

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

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

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

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

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

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

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

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

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

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

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

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

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

	(void)close(fd);

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

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

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

		default:
			pidarray[procno] = pid;
		}
	}

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

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

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

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

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

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

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

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

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

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


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

	mapflags = MAP_SHARED;

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


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

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

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

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

	(void)close(fd);

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

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

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

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

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

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

	exit(0);
}

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

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

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


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

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

		p = buf + (off % pagesize);

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

		off += growsize;

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


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

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

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

	readbuf = (uchar_t *)malloc(pagesize);

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

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

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

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

unsigned int
initrand(void)
{
	unsigned int seed;

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


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


int anyfail()
{
  tst_resm(TFAIL, "Test failed\n");
  tst_rmdir();
  tst_exit();
  return(0);
}
Beispiel #20
0
static void
zpool_open_func(void *arg)
{
	rdsk_node_t *rn = arg;
#ifdef __APPLE__
	struct stat statbuf;
#else
	struct stat64 statbuf;
#endif
	nvlist_t *config;
	int num_labels;
	int fd;

	if (rn->rn_nozpool)
		return;
#if defined (__linux__) || defined (__APPLE__)
	/*
	 * Skip devices with well known prefixes there can be side effects
	 * when opening devices which need to be avoided.
	 *
	 * core     - Symlink to /proc/kcore
	 * fd*      - Floppy interface.
	 * fuse     - Fuse control device.
	 * hpet     - High Precision Event Timer
	 * lp*      - Printer interface.
	 * parport* - Parallel port interface.
	 * ppp      - Generic PPP driver.
	 * random   - Random device
	 * rtc      - Real Time Clock
	 * tty*     - Generic serial interface.
	 * urandom  - Random device.
	 * usbmon*  - USB IO monitor.
	 * vcs*     - Virtual console memory.
	 * watchdog - Watchdog must be closed in a special way.
	 */
	if ((strncmp(rn->rn_name, "core", 4) == 0) ||
	    (strncmp(rn->rn_name, "fd", 2) == 0) ||
	    (strncmp(rn->rn_name, "fuse", 4) == 0) ||
	    (strncmp(rn->rn_name, "hpet", 4) == 0) ||
	    (strncmp(rn->rn_name, "lp", 2) == 0) ||
	    (strncmp(rn->rn_name, "parport", 7) == 0) ||
	    (strncmp(rn->rn_name, "ppp", 3) == 0) ||
	    (strncmp(rn->rn_name, "random", 6) == 0) ||
	    (strncmp(rn->rn_name, "rtc", 3) == 0) ||
	    (strncmp(rn->rn_name, "tty", 3) == 0) ||
	    (strncmp(rn->rn_name, "urandom", 7) == 0) ||
	    (strncmp(rn->rn_name, "usbmon", 6) == 0) ||
	    (strncmp(rn->rn_name, "vcs", 3) == 0) ||
#ifdef __APPLE__
		(strncmp(rn->rn_name, "pty", 3) == 0) || // lots, skip for speed
		(strncmp(rn->rn_name, "com", 3) == 0) || // /dev/com_digidesign_semiface
#endif
	    (strncmp(rn->rn_name, "watchdog", 8) == 0))
		return;

	/*
	 * Ignore failed stats.  We only want regular files and block devices.
	 */
	if (fstatat64(rn->rn_dfd, rn->rn_name, &statbuf, 0) != 0 ||
	    (!S_ISREG(statbuf.st_mode) && !S_ISBLK(statbuf.st_mode)))
		return;

#ifdef __APPLE__
	/* It is desirable to skip optical media as well, as they are
	 * also called /dev/diskX
	 */
	if (is_optical_media((char *)rn->rn_name))
		return;
#endif

	if ((fd = openat64(rn->rn_dfd, rn->rn_name, O_RDONLY)) < 0) {
		/* symlink to a device that's no longer there */
		if (errno == ENOENT)
			nozpool_all_slices(rn->rn_avl, rn->rn_name);
		return;
	}

#else /* LINUX, APPLE -> IllumOS */

	if ((fd = openat64(rn->rn_dfd, rn->rn_name, O_RDONLY)) < 0) {
		/* symlink to a device that's no longer there */
		if (errno == ENOENT)
			nozpool_all_slices(rn->rn_avl, rn->rn_name);
		return;
	}
	/*
	 * Ignore failed stats.  We only want regular
	 * files, character devs and block devs.
	 */
	if (fstat64(fd, &statbuf) != 0 ||
	    (!S_ISREG(statbuf.st_mode) &&
	    !S_ISCHR(statbuf.st_mode) &&
	    !S_ISBLK(statbuf.st_mode))) {
		(void) close(fd);
		return;
	}
#endif
	/* this file is too small to hold a zpool */
	if (S_ISREG(statbuf.st_mode) &&
	    statbuf.st_size < SPA_MINDEVSIZE) {
		(void) close(fd);
		return;
	} else if (!S_ISREG(statbuf.st_mode)) {
		/*
		 * Try to read the disk label first so we don't have to
		 * open a bunch of minor nodes that can't have a zpool.
		 */
		check_slices(rn->rn_avl, fd, rn->rn_name);
	}

#ifdef __APPLE__
	int32_t blksz = 0;
	if (S_ISBLK(statbuf.st_mode) &&
		(ioctl(fd, DKIOCGETBLOCKSIZE, &blksz) || blksz == 0)) {
		if (strncmp(rn->rn_name, "vn", 2) != 0)
			fprintf(stderr, "device '%s' failed to report blocksize -- skipping\r\n",
					rn->rn_name);
		close(fd);
		return;
	}

	struct sigaction sact;
	sigemptyset(&sact.sa_mask);
	sact.sa_flags = 0;
	sact.sa_handler = signal_alarm;
	sigaction(SIGALRM, &sact, NULL);

	if (setjmp(buffer) != 0) {
		printf("ZFS: Warning, timeout reading device '%s'\n", rn->rn_name);
		close(fd);
		return;
	}

	alarm(20);
#endif

	if ((zpool_read_label(fd, &config, &num_labels)) != 0) {
#ifdef __APPLE__
		alarm(0);
#endif
		(void) close(fd);
		(void) no_memory(rn->rn_hdl);
		return;
	}

#ifdef __APPLE__
	alarm(0);
#endif

	if (num_labels == 0) {
		(void) close(fd);
		nvlist_free(config);
		return;
	}

	(void) close(fd);

	rn->rn_config = config;
	rn->rn_num_labels = num_labels;
}
Beispiel #21
0
int get_devinfo(struct s_devinfo *outdev, char *indevname, int min, int maj)
{
    char sysblkdevname[512];
    blkid_tag_iterate iter;
    char sysblkinfo[PATH_MAX];
    const char *type, *value;
    struct stat64 statbuf;
    struct dirent *dir;
    char temp[PATH_MAX];
    blkid_dev dev;
    DIR *dirdesc;
    FILE *finfo;
    int found;
    int fd;
    int i;
    
    // init
    memset(outdev, 0, sizeof(struct s_devinfo));
    
    // defaults values
    outdev->devtype=BLKDEV_INVALID;
    snprintf(outdev->label, sizeof(outdev->label), "<unknown>");
    snprintf(outdev->uuid, sizeof(outdev->uuid), "<unknown>");
    snprintf(outdev->fsname, sizeof(outdev->fsname), "<unknown>");
    
    // check the name starts with "/dev/"
    if ((strlen(indevname) < 5) || (memcmp(indevname, "/dev/", 5)!=0))
        return -1;
    
    // get short name ("/dev/sda1" -> "sda1")
    snprintf(outdev->devname, sizeof(outdev->devname), "%s", indevname+5); // skip "/dev/"
    
    // get long name if there is one (eg: LVM / devmapper)
    snprintf(outdev->longname, sizeof(outdev->longname), "%s", indevname);
    if ((dirdesc=opendir("/dev/mapper"))!=NULL)
    {
        found=false;
        while (((dir=readdir(dirdesc)) != NULL) && found==false)
        {
            snprintf(temp, sizeof(temp), "/dev/mapper/%s", dir->d_name);
            if ((stat64(temp, &statbuf)==0) && S_ISBLK(statbuf.st_mode) && 
                (major(statbuf.st_rdev)==maj) && (minor(statbuf.st_rdev)==min))
            {
                snprintf(outdev->longname, sizeof(outdev->longname), "%s", temp);
                found=true;
            }
        }
        closedir(dirdesc);
    }
    
    // get device basic info (size, major, minor)
    if (((fd=open64(outdev->longname, O_RDONLY|O_LARGEFILE))<0) || 
        ((outdev->devsize=lseek64(fd, 0, SEEK_END))<0) ||
        (fstat64(fd, &statbuf)!=0) ||
        (!S_ISBLK(statbuf.st_mode)) ||
        (close(fd)<0))
        return -1;
    outdev->rdev=statbuf.st_rdev;
    outdev->major=major(statbuf.st_rdev);
    outdev->minor=minor(statbuf.st_rdev);
    format_size(outdev->devsize, outdev->txtsize, sizeof(outdev->txtsize), 'h');
    if (outdev->devsize==1024) // ignore extended partitions
        return -1;
    
    // devname shown in /sys/block (eg for HP-cciss: "cciss/c0d0" -> "cciss!c0d0")
    snprintf(sysblkdevname, sizeof(sysblkdevname), "%s", outdev->devname);
    for (i=0; (sysblkdevname[i]!=0) && (i<sizeof(sysblkdevname)); i++)
        if (sysblkdevname[i]=='/')
            sysblkdevname[i]='!';
    
    // check if it's a physical disk (there is a "/sys/block/${devname}/device")
    snprintf(sysblkinfo, sizeof(sysblkinfo), "/sys/block/%s/device", sysblkdevname);
    if (stat64(sysblkinfo, &statbuf)==0)
    {
        outdev->devtype=BLKDEV_PHYSDISK;
        snprintf(sysblkinfo, sizeof(sysblkinfo), "/sys/block/%s/device/model", sysblkdevname);
        if ( ((finfo=fopen(sysblkinfo, "rb")) != NULL) && (fread(temp, 1, sizeof(temp), finfo)>0) && fclose(finfo)==0 )
            for (i=0; (temp[i]!=0) && (temp[i]!='\r') && (temp[i]!='\n'); i++)
                outdev->name[i]=temp[i];
    }
    else
    {
        outdev->devtype=BLKDEV_FILESYSDEV;
    }
    
    // get blkid infos about the device (label, uuid)
    blkid_cache cache = NULL;
    if (blkid_get_cache(&cache, NULL) < 0)
        return -1;
    if ((dev=blkid_get_dev(cache, outdev->longname, BLKID_DEV_NORMAL))!=NULL)
    {
        iter = blkid_tag_iterate_begin(dev);
        while (blkid_tag_next(iter, &type, &value)==0)
        {
            if (strcmp(type, "LABEL")==0)
                snprintf(outdev->label, sizeof(outdev->label), "%s", value);
            else if (strcmp(type, "UUID")==0)
                snprintf(outdev->uuid, sizeof(outdev->uuid), "%s", value);
            else if (strcmp(type, "TYPE")==0)
                snprintf(outdev->fsname, sizeof(outdev->fsname), "%s", value);
        }
        blkid_tag_iterate_end(iter);
        
        // workaround: blkid < 1.41 don't know ext4 and say it is ext3 instead
        if (strcmp(outdev->fsname, "ext3")==0)
        {
            if (ext3_test(outdev->longname)==true)
                snprintf(outdev->fsname, sizeof(outdev->fsname), "ext3");
            else // cannot run ext4_test(): it would fail on an ext4 when e2fsprogs < 1.41
                snprintf(outdev->fsname, sizeof(outdev->fsname), "ext4");
        }
    }
    blkid_put_cache(cache); // free memory allocated by blkid_get_cache
    
    return 0;
}
Beispiel #22
0
Datei: loop.c Projekt: garfee/pv
/*
 * Pipe data from a list of files to standard output, giving information
 * about the transfer on standard error according to the given options.
 *
 * Returns nonzero on error.
 */
int pv_main_loop(pvstate_t state)
{
	long written, lineswritten;
	long long total_written, since_last, cansend;
	long double target;
	int eof_in, eof_out, final_update;
	struct timeval start_time, next_update, next_ratecheck, cur_time;
	struct timeval init_time, next_remotecheck;
	long double elapsed;
	struct stat64 sb;
	int fd, n;

	/*
	 * "written" is ALWAYS bytes written by the last transfer.
	 *
	 * "lineswritten" is the lines written by the last transfer,
	 * but is only updated in line mode.
	 *
	 * "total_written" is the total bytes written since the start,
	 * or in line mode, the total lines written since the start.
	 *
	 * "since_last" is the bytes written since the last display,
	 * or in line mode, the lines written since the last display.
	 *
	 * The remaining variables are all unchanged by linemode.
	 */

	fd = -1;

	pv_crs_init(state);

	eof_in = 0;
	eof_out = 0;
	total_written = 0;
	since_last = 0;

	gettimeofday(&start_time, NULL);
	gettimeofday(&cur_time, NULL);

	next_update.tv_sec = start_time.tv_sec;
	next_update.tv_usec = start_time.tv_usec;
	pv_timeval_add_usec(&next_update,
			    (long) (1000000.0 * state->interval));

	next_ratecheck.tv_sec = start_time.tv_sec;
	next_ratecheck.tv_usec = start_time.tv_usec;
	next_remotecheck.tv_sec = start_time.tv_sec;
	next_remotecheck.tv_usec = start_time.tv_usec;

	target = 0;
	final_update = 0;
	n = 0;

	fd = pv_next_file(state, n, -1);
	if (fd < 0) {
		if (state->cursor)
			pv_crs_fini(state);
		return state->exit_status;
	}

	/*
	 * Set target buffer size if the initial file's block size can be
	 * read and we weren't given a target buffer size.
	 */
	if (0 == fstat64(fd, &sb)) {
		unsigned long long sz;
		sz = sb.st_blksize * 32;
		if (sz > BUFFER_SIZE_MAX)
			sz = BUFFER_SIZE_MAX;
		state->target_buffer_size = sz;
	}

	if (0 == state->target_buffer_size)
		state->target_buffer_size = BUFFER_SIZE;

	while ((!(eof_in && eof_out)) || (!final_update)) {

		cansend = 0;

		/*
		 * Check for remote messages from -R every short while
		 */
		if ((cur_time.tv_sec > next_remotecheck.tv_sec)
		    || (cur_time.tv_sec == next_remotecheck.tv_sec
			&& cur_time.tv_usec >= next_remotecheck.tv_usec)) {
			pv_remote_check(state);
			pv_timeval_add_usec(&next_remotecheck,
					    REMOTE_INTERVAL);
		}

		if (state->pv_sig_abort)
			break;

		if (state->rate_limit > 0) {
			gettimeofday(&cur_time, NULL);
			if ((cur_time.tv_sec > next_ratecheck.tv_sec)
			    || (cur_time.tv_sec == next_ratecheck.tv_sec
				&& cur_time.tv_usec >=
				next_ratecheck.tv_usec)) {
				target +=
				    ((long double) (state->rate_limit)) /
				    (long double) (1000000 /
						   RATE_GRANULARITY);
				pv_timeval_add_usec(&next_ratecheck,
						    RATE_GRANULARITY);
			}
			cansend = target;
		}

		/*
		 * If we have to stop at "size" bytes, make sure we don't
		 * try to write more than we're allowed to.
		 */
		if ((0 < state->size) && (state->stop_at_size)) {
			if ((state->size < (total_written + cansend))
			    || ((0 == cansend)
				&& (0 == state->rate_limit))) {
				cansend = state->size - total_written;
				if (0 >= cansend) {
					eof_in = 1;
					eof_out = 1;
				}
			}
		}

		if ((0 < state->size) && (state->stop_at_size)
		    && (0 >= cansend) && eof_in && eof_out) {
			written = 0;
		} else {
			written =
			    pv_transfer(state, fd, &eof_in, &eof_out,
					cansend, &lineswritten);
		}

		if (written < 0) {
			if (state->cursor)
				pv_crs_fini(state);
			return state->exit_status;
		}

		if (state->linemode) {
			since_last += lineswritten;
			total_written += lineswritten;
			if (state->rate_limit > 0)
				target -= lineswritten;
		} else {
			since_last += written;
			total_written += written;
			if (state->rate_limit > 0)
				target -= written;
		}

		if (eof_in && eof_out && n < (state->input_file_count - 1)) {
			n++;
			fd = pv_next_file(state, n, fd);
			if (fd < 0) {
				if (state->cursor)
					pv_crs_fini(state);
				return state->exit_status;
			}
			eof_in = 0;
			eof_out = 0;
		}

		gettimeofday(&cur_time, NULL);

		if (eof_in && eof_out) {
			final_update = 1;
			next_update.tv_sec = cur_time.tv_sec - 1;
		}

		if (state->no_op)
			continue;

		/*
		 * If -W was given, we don't output anything until we have
		 * written a byte (or line, in line mode), at which point
		 * we then count time as if we started when the first byte
		 * was received.
		 */
		if (state->wait) {
			if (state->linemode) {
				if (lineswritten < 1)
					continue;
			} else {
				if (written < 1)
					continue;
			}

			state->wait = 0;

			/*
			 * Reset the timer offset counter now that data
			 * transfer has begun, otherwise if we had been
			 * stopped and started (with ^Z / SIGTSTOP)
			 * previously (while waiting for data), the timers
			 * will be wrongly offset.
			 *
			 * While we reset the offset counter we must disable
			 * SIGTSTOP so things don't mess up.
			 */
			pv_sig_nopause();
			gettimeofday(&start_time, NULL);
			state->pv_sig_toffset.tv_sec = 0;
			state->pv_sig_toffset.tv_usec = 0;
			pv_sig_allowpause();

			next_update.tv_sec = start_time.tv_sec;
			next_update.tv_usec = start_time.tv_usec;
			pv_timeval_add_usec(&next_update,
					    (long) (1000000.0 *
						    state->interval));
		}

		if ((cur_time.tv_sec < next_update.tv_sec)
		    || (cur_time.tv_sec == next_update.tv_sec
			&& cur_time.tv_usec < next_update.tv_usec)) {
			continue;
		}

		pv_timeval_add_usec(&next_update,
				    (long) (1000000.0 * state->interval));

		if (next_update.tv_sec < cur_time.tv_sec) {
			next_update.tv_sec = cur_time.tv_sec;
			next_update.tv_usec = cur_time.tv_usec;
		} else if (next_update.tv_sec == cur_time.tv_sec
			   && next_update.tv_usec < cur_time.tv_usec) {
			next_update.tv_usec = cur_time.tv_usec;
		}

		init_time.tv_sec =
		    start_time.tv_sec + state->pv_sig_toffset.tv_sec;
		init_time.tv_usec =
		    start_time.tv_usec + state->pv_sig_toffset.tv_usec;
		if (init_time.tv_usec >= 1000000) {
			init_time.tv_sec++;
			init_time.tv_usec -= 1000000;
		}
		if (init_time.tv_usec < 0) {
			init_time.tv_sec--;
			init_time.tv_usec += 1000000;
		}

		elapsed = cur_time.tv_sec - init_time.tv_sec;
		elapsed +=
		    (cur_time.tv_usec - init_time.tv_usec) / 1000000.0;

		if (final_update)
			since_last = -1;

		if (state->pv_sig_newsize) {
			state->pv_sig_newsize = 0;
			pv_screensize(&(state->width), &(state->height));
		}

		pv_display(state, elapsed, since_last, total_written);

		since_last = 0;
	}

	if (state->cursor) {
		pv_crs_fini(state);
	} else {
		if ((!state->numeric) && (!state->no_op))
			write(STDERR_FILENO, "\n", 1);
	}

	if (state->pv_sig_abort)
		state->exit_status |= 32;

	return state->exit_status;
}
int
do_test (int argc, char *argv[])
{
  int fd;
  int fd2;
  int fd3;
  struct stat64 st;
  int val;
  int result = 0;

  /* Create the temporary file.  */
  fd = mkstemp (name);
  if (fd == -1)
    {
      printf ("cannot open temporary file: %m\n");
      return 1;
    }
  if (fstat64 (fd, &st) != 0)
    {
      printf ("cannot stat test file: %m\n");
      return 1;
    }
  if (! S_ISREG (st.st_mode) || st.st_size != 0)
    {
      puts ("file not created correctly");
      return 1;
    }

  /* Get the flags with fcntl().  */
  val = fcntl (fd, F_GETFL);
  if (val == -1)
    {
      printf ("fcntl(fd, F_GETFL) failed: %m\n");
      result = 1;
    }
  else if ((val & O_ACCMODE) != O_RDWR)
    {
      puts ("temporary file not opened for read and write");
      result = 1;
    }

  /* Set the flags to something else.  */
  if (fcntl (fd, F_SETFL, O_RDONLY) == -1)
    {
      printf ("fcntl(fd, F_SETFL, O_RDONLY) failed: %m\n");
      result = 1;
    }

  val = fcntl (fd, F_GETFL);
  if (val == -1)
    {
      printf ("fcntl(fd, F_GETFL) after F_SETFL failed: %m\n");
      result = 1;
    }
  else if ((val & O_ACCMODE) != O_RDWR)
    {
      puts ("temporary file access mode changed");
      result = 1;
    }

  /* Set the flags to something else.  */
  if (fcntl (fd, F_SETFL, O_APPEND) == -1)
    {
      printf ("fcntl(fd, F_SETFL, O_APPEND) failed: %m\n");
      result = 1;
    }

  val = fcntl (fd, F_GETFL);
  if (val == -1)
    {
      printf ("fcntl(fd, F_GETFL) after second F_SETFL failed: %m\n");
      result = 1;
    }
  else if ((val & O_APPEND) == 0)
    {
      puts ("O_APPEND not set");
      result = 1;
    }

  val = fcntl (fd, F_GETFD);
  if (val == -1)
    {
      printf ("fcntl(fd, F_GETFD) failed: %m\n");
      result = 1;
    }
  else if (fcntl (fd, F_SETFD, val | FD_CLOEXEC) == -1)
    {
      printf ("fcntl(fd, F_SETFD, FD_CLOEXEC) failed: %m\n");
      result = 1;
    }
  else
    {
      val = fcntl (fd, F_GETFD);
      if (val == -1)
	{
	  printf ("fcntl(fd, F_GETFD) after F_SETFD failed: %m\n");
	  result = 1;
	}
      else if ((val & FD_CLOEXEC) == 0)
	{
	  puts ("FD_CLOEXEC not set");
	  result = 1;
	}
    }

  /* Get a number of a free descriptor.  If /dev/null is not available
     don't continue testing.  */
  fd2 = open (_PATH_DEVNULL, O_RDWR);
  if (fd2 == -1)
    return result;
  close (fd2);

  fd3 = fcntl (fd, F_DUPFD, fd2 + 1);
  if (fd3 == -1)
    {
      printf ("fcntl(fd, F_DUPFD, %d) failed: %m\n", fd2 + 1);
      result = 1;
    }
  else if (fd3 <= fd2)
    {
      printf ("F_DUPFD returned %d which is not larger than %d\n", fd3, fd2);
      result = 1;
    }

  if (fd3 != -1)
    {
      val = fcntl (fd3, F_GETFD);
      if (val == -1)
	{
	  printf ("fcntl(fd3, F_GETFD) after F_DUPFD failed: %m\n");
	  result = 1;
	}
      else if ((val & FD_CLOEXEC) != 0)
	{
	  puts ("FD_CLOEXEC still set");
	  result = 1;
	}

      close (fd3);
    }

  return result;
}
Beispiel #24
0
file_error osd_open(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize)
{
	UINT32 access;
	const char *src;
	char *dst;
	#if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2)
	struct stat st;
	#else
	struct stat64 st;
	#endif
	char *tmpstr, *envstr;
	int i, j;
	file_error filerr = FILERR_NONE;

	tmpstr = NULL;

	// allocate a file object, plus space for the converted filename
	*file = (osd_file *) osd_malloc_array(sizeof(**file) + sizeof(char) * strlen(path));
	if (*file == NULL)
	{
		filerr = FILERR_OUT_OF_MEMORY;
		goto error;
	}

	if (sdl_check_socket_path(path))
	{
		(*file)->type = SDLFILE_SOCKET;
		filerr = sdl_open_socket(path, openflags, file, filesize);
		goto error;
	}

	if (strlen(sdlfile_ptty_identifier) > 0 && strncmp(path, sdlfile_ptty_identifier, strlen(sdlfile_ptty_identifier)) == 0)
	{
		(*file)->type = SDLFILE_PTTY;
		filerr = sdl_open_ptty(path, openflags, file, filesize);
		goto error;
	}

	(*file)->type = SDLFILE_FILE;

	// convert the path into something compatible
	dst = (*file)->filename;
	for (src = path; *src != 0; src++)
		*dst++ = (*src == INVPATHSEPCH) ? PATHSEPCH : *src;
	*dst++ = 0;

	// select the file open modes
	if (openflags & OPEN_FLAG_WRITE)
	{
		access = (openflags & OPEN_FLAG_READ) ? O_RDWR : O_WRONLY;
		access |= (openflags & OPEN_FLAG_CREATE) ? (O_CREAT | O_TRUNC) : 0;
	}
	else if (openflags & OPEN_FLAG_READ)
	{
		access = O_RDONLY;
	}
	else
	{
		filerr = FILERR_INVALID_ACCESS;
		goto error;
	}

	tmpstr = (char *) osd_malloc_array(strlen((*file)->filename)+1);
	strcpy(tmpstr, (*file)->filename);

	// does path start with an environment variable?
	if (tmpstr[0] == '$')
	{
		char *envval;
		envstr = (char *) osd_malloc_array(strlen(tmpstr)+1);

		strcpy(envstr, tmpstr);

		i = 0;
		while (envstr[i] != PATHSEPCH && envstr[i] != 0 && envstr[i] != '.')
		{
			i++;
		}

		envstr[i] = '\0';

		envval = osd_getenv(&envstr[1]);
		if (envval != NULL)
		{
			j = strlen(envval) + strlen(tmpstr) + 1;
			osd_free(tmpstr);
			tmpstr = (char *) osd_malloc_array(j);

			// start with the value of $HOME
			strcpy(tmpstr, envval);
			// replace the null with a path separator again
			envstr[i] = PATHSEPCH;
			// append it
			strcat(tmpstr, &envstr[i]);
		}
		else
			fprintf(stderr, "Warning: osd_open environment variable %s not found.\n", envstr);
		osd_free(envstr);
	}

	#if defined(SDLMAME_WIN32) || defined(SDLMAME_OS2)
	access |= O_BINARY;
	#endif

	// attempt to open the file
	#if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2)
	(*file)->handle = open(tmpstr, access, 0666);
	#else
	(*file)->handle = open64(tmpstr, access, 0666);
	#endif
	if ((*file)->handle == -1)
	{
		// create the path if necessary
		if ((openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS))
		{
			char *pathsep = strrchr(tmpstr, PATHSEPCH);
			if (pathsep != NULL)
			{
				int error;

				// create the path up to the file
				*pathsep = 0;
				error = create_path_recursive(tmpstr);
				*pathsep = PATHSEPCH;

				// attempt to reopen the file
				if (error == NO_ERROR)
				{
					#if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2)
					(*file)->handle = open(tmpstr, access, 0666);
					#else
					(*file)->handle = open64(tmpstr, access, 0666);
					#endif
				}
			}
		}

		// if we still failed, clean up and osd_free
		if ((*file)->handle == -1)
		{
			osd_free(*file);
			*file = NULL;
			osd_free(tmpstr);
			return error_to_file_error(errno);
		}
	}

	// get the file size
	#if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2)
	fstat((*file)->handle, &st);
	#else
	fstat64((*file)->handle, &st);
	#endif

	*filesize = (UINT64)st.st_size;


error:
	// cleanup
	if (filerr != FILERR_NONE && *file != NULL)
	{
		osd_free(*file);
		*file = NULL;
	}
	if (tmpstr)
		osd_free(tmpstr);
	return filerr;
}
/* Try to get a file descriptor for the shared meory segment
   containing the database.  */
static struct mapped_database *
get_mapping (request_type type, const char *key,
	     struct mapped_database **mappedp)
{
  struct mapped_database *result = NO_MAPPING;
#ifdef SCM_RIGHTS
  const size_t keylen = strlen (key) + 1;
  char resdata[keylen];
  int saved_errno = errno;

  int mapfd = -1;

  /* Send the request.  */
  struct iovec iov[2];
  request_header req;

  int sock = open_socket ();
  if (sock < 0)
    goto out;

  req.version = NSCD_VERSION;
  req.type = type;
  req.key_len = keylen;

  iov[0].iov_base = &req;
  iov[0].iov_len = sizeof (req);
  iov[1].iov_base = (void *) key;
  iov[1].iov_len = keylen;

  if (__builtin_expect (TEMP_FAILURE_RETRY (__writev (sock, iov, 2))
			!= iov[0].iov_len + iov[1].iov_len, 0))
    /* We cannot even write the request.  */
    goto out_close2;

  /* Room for the data sent along with the file descriptor.  We expect
     the key name back.  */
  iov[0].iov_base = resdata;
  iov[0].iov_len = keylen;

  union
  {
    struct cmsghdr hdr;
    char bytes[CMSG_SPACE (sizeof (int))];
  } buf;
  struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1,
			.msg_control = buf.bytes,
			.msg_controllen = sizeof (buf) };
  struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);

  cmsg->cmsg_level = SOL_SOCKET;
  cmsg->cmsg_type = SCM_RIGHTS;
  cmsg->cmsg_len = CMSG_LEN (sizeof (int));

  /* This access is well-aligned since BUF is correctly aligned for an
     int and CMSG_DATA preserves this alignment.  */
  *(int *) CMSG_DATA (cmsg) = -1;

  msg.msg_controllen = cmsg->cmsg_len;

  if (wait_on_socket (sock) <= 0)
    goto out_close2;

# ifndef MSG_NOSIGNAL
#  define MSG_NOSIGNAL 0
# endif
  if (__builtin_expect (TEMP_FAILURE_RETRY (__recvmsg (sock, &msg,
						       MSG_NOSIGNAL))
			!= keylen, 0))
    goto out_close2;

  mapfd = *(int *) CMSG_DATA (cmsg);

  if (__builtin_expect (CMSG_FIRSTHDR (&msg)->cmsg_len
			!= CMSG_LEN (sizeof (int)), 0))
    goto out_close;

  struct stat64 st;
  if (__builtin_expect (strcmp (resdata, key) != 0, 0)
      || __builtin_expect (fstat64 (mapfd, &st) != 0, 0)
      || __builtin_expect (st.st_size < sizeof (struct database_pers_head), 0))
    goto out_close;

  struct database_pers_head head;
  if (__builtin_expect (TEMP_FAILURE_RETRY (__pread (mapfd, &head,
						     sizeof (head), 0))
			!= sizeof (head), 0))
    goto out_close;

  if (__builtin_expect (head.version != DB_VERSION, 0)
      || __builtin_expect (head.header_size != sizeof (head), 0)
      /* This really should not happen but who knows, maybe the update
	 thread got stuck.  */
      || __builtin_expect (! head.nscd_certainly_running
			   && head.timestamp + MAPPING_TIMEOUT < time (NULL),
			   0))
    goto out_close;

  size_t size = (sizeof (head) + roundup (head.module * sizeof (ref_t), ALIGN)
		 + head.data_size);

  if (__builtin_expect (st.st_size < size, 0))
    goto out_close;

  /* The file is large enough, map it now.  */
  void *mapping = __mmap (NULL, size, PROT_READ, MAP_SHARED, mapfd, 0);
  if (__builtin_expect (mapping != MAP_FAILED, 1))
    {
      /* Allocate a record for the mapping.  */
      struct mapped_database *newp = malloc (sizeof (*newp));
      if (newp == NULL)
	{
	  /* Ugh, after all we went through the memory allocation failed.  */
	  __munmap (mapping, size);
	  goto out_close;
	}

      newp->head = mapping;
      newp->data = ((char *) mapping + head.header_size
		    + roundup (head.module * sizeof (ref_t), ALIGN));
      newp->mapsize = size;
      /* Set counter to 1 to show it is usable.  */
      newp->counter = 1;

      result = newp;
    }

 out_close:
  __close (mapfd);
 out_close2:
  __close (sock);
 out:
  __set_errno (saved_errno);
#endif	/* SCM_RIGHTS */

  struct mapped_database *oldval = *mappedp;
  *mappedp = result;

  if (oldval != NULL && atomic_decrement_val (&oldval->counter) == 0)
    __nscd_unmap (oldval);

  return result;
}


struct mapped_database *
__nscd_get_map_ref (request_type type, const char *name,
		    struct locked_map_ptr *mapptr, int *gc_cyclep)
{
  struct mapped_database *cur = mapptr->mapped;
  if (cur == NO_MAPPING)
    return cur;

  int cnt = 0;
  while (atomic_compare_and_exchange_val_acq (&mapptr->lock, 1, 0) != 0)
    {
      // XXX Best number of rounds?
      if (++cnt > 5)
	return NO_MAPPING;

      atomic_delay ();
    }

  cur = mapptr->mapped;

  if (__builtin_expect (cur != NO_MAPPING, 1))
    {
      /* If not mapped or timestamp not updated, request new map.  */
      if (cur == NULL
	  || (cur->head->nscd_certainly_running == 0
	      && cur->head->timestamp + MAPPING_TIMEOUT < time (NULL)))
	cur = get_mapping (type, name, &mapptr->mapped);

      if (__builtin_expect (cur != NO_MAPPING, 1))
	{
	  if (__builtin_expect (((*gc_cyclep = cur->head->gc_cycle) & 1) != 0,
				0))
	    cur = NO_MAPPING;
	  else
	    atomic_increment (&cur->counter);
	}
    }

  mapptr->lock = 0;

  return cur;
}


const struct datahead *
__nscd_cache_search (request_type type, const char *key, size_t keylen,
		     const struct mapped_database *mapped)
{
  unsigned long int hash = __nis_hash (key, keylen) % mapped->head->module;

  ref_t work = mapped->head->array[hash];
  while (work != ENDREF)
    {
      struct hashentry *here = (struct hashentry *) (mapped->data + work);

      if (type == here->type && keylen == here->len
	  && memcmp (key, mapped->data + here->key, keylen) == 0)
	{
	  /* We found the entry.  Increment the appropriate counter.  */
	  const struct datahead *dh
	    = (struct datahead *) (mapped->data + here->packet);

	  /* See whether we must ignore the entry or whether something
	     is wrong because garbage collection is in progress.  */
	  if (dh->usable && ((char *) dh + dh->allocsize
			     <= (char *) mapped->head + mapped->mapsize))
	    return dh;
	}

      work = here->next;
    }

  return NULL;
}
Beispiel #26
0
dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat)
#endif
{
	char fname[MAXPATHLEN];
	struct stat64 st;
	int fd, err, bits;

	dt_module_t *dmp;
	const char *s;
	size_t shstrs;
	GElf_Shdr sh;
	Elf_Data *dp;
	Elf_Scn *sp;

#if defined(sun)
	(void) snprintf(fname, sizeof (fname),
	    "%s/%s/object", OBJFS_ROOT, name);
#else
	GElf_Ehdr ehdr;
	GElf_Phdr ph;
	char name[MAXPATHLEN];
	uintptr_t mapbase, alignmask;
	int i = 0;
	int is_elf_obj;

	(void) strlcpy(name, k_stat->name, sizeof(name));
	(void) strlcpy(fname, k_stat->pathname, sizeof(fname));
#endif

	if ((fd = open(fname, O_RDONLY)) == -1 || fstat64(fd, &st) == -1 ||
	    (dmp = dt_module_create(dtp, name)) == NULL) {
		dt_dprintf("failed to open %s: %s\n", fname, strerror(errno));
		(void) close(fd);
		return;
	}

	/*
	 * Since the module can unload out from under us (and /system/object
	 * will return ENOENT), tell libelf to cook the entire file now and
	 * then close the underlying file descriptor immediately.  If this
	 * succeeds, we know that we can continue safely using dmp->dm_elf.
	 */
	dmp->dm_elf = elf_begin(fd, ELF_C_READ, NULL);
	err = elf_cntl(dmp->dm_elf, ELF_C_FDREAD);
	(void) close(fd);

	if (dmp->dm_elf == NULL || err == -1 ||
	    elf_getshdrstrndx(dmp->dm_elf, &shstrs) == -1) {
		dt_dprintf("failed to load %s: %s\n",
		    fname, elf_errmsg(elf_errno()));
		dt_module_destroy(dtp, dmp);
		return;
	}

	switch (gelf_getclass(dmp->dm_elf)) {
	case ELFCLASS32:
		dmp->dm_ops = &dt_modops_32;
		bits = 32;
		break;
	case ELFCLASS64:
		dmp->dm_ops = &dt_modops_64;
		bits = 64;
		break;
	default:
		dt_dprintf("failed to load %s: unknown ELF class\n", fname);
		dt_module_destroy(dtp, dmp);
		return;
	}
#if defined(__FreeBSD__)
	mapbase = (uintptr_t)k_stat->address;
	gelf_getehdr(dmp->dm_elf, &ehdr);
	is_elf_obj = (ehdr.e_type == ET_REL);
	if (is_elf_obj) {
		dmp->dm_sec_offsets =
		    malloc(ehdr.e_shnum * sizeof(*dmp->dm_sec_offsets));
		if (dmp->dm_sec_offsets == NULL) {
			dt_dprintf("failed to allocate memory\n");
			dt_module_destroy(dtp, dmp);
			return;
		}
	}
#endif
	/*
	 * Iterate over the section headers locating various sections of
	 * interest and use their attributes to flesh out the dt_module_t.
	 */
	for (sp = NULL; (sp = elf_nextscn(dmp->dm_elf, sp)) != NULL; ) {
		if (gelf_getshdr(sp, &sh) == NULL || sh.sh_type == SHT_NULL ||
		    (s = elf_strptr(dmp->dm_elf, shstrs, sh.sh_name)) == NULL)
			continue; /* skip any malformed sections */
#if defined(__FreeBSD__)
		if (sh.sh_size == 0)
			continue;
		if (is_elf_obj && (sh.sh_type == SHT_PROGBITS ||
		    sh.sh_type == SHT_NOBITS)) {
			alignmask = sh.sh_addralign - 1;
			mapbase += alignmask;
			mapbase &= ~alignmask;
			sh.sh_addr = mapbase;
			dmp->dm_sec_offsets[elf_ndxscn(sp)] = sh.sh_addr;
			mapbase += sh.sh_size;
		}
#endif
		if (strcmp(s, ".text") == 0) {
			dmp->dm_text_size = sh.sh_size;
			dmp->dm_text_va = sh.sh_addr;
		} else if (strcmp(s, ".data") == 0) {
			dmp->dm_data_size = sh.sh_size;
			dmp->dm_data_va = sh.sh_addr;
		} else if (strcmp(s, ".bss") == 0) {
			dmp->dm_bss_size = sh.sh_size;
			dmp->dm_bss_va = sh.sh_addr;
		} else if (strcmp(s, ".info") == 0 &&
		    (dp = elf_getdata(sp, NULL)) != NULL) {
			bcopy(dp->d_buf, &dmp->dm_info,
			    MIN(sh.sh_size, sizeof (dmp->dm_info)));
		} else if (strcmp(s, ".filename") == 0 &&
		    (dp = elf_getdata(sp, NULL)) != NULL) {
			(void) strlcpy(dmp->dm_file,
			    dp->d_buf, sizeof (dmp->dm_file));
		}
	}

	dmp->dm_flags |= DT_DM_KERNEL;
#if defined(sun)
	dmp->dm_modid = (int)OBJFS_MODID(st.st_ino);
#else
	/*
	 * Include .rodata and special sections into .text.
	 * This depends on default section layout produced by GNU ld
	 * for ELF objects and libraries:
	 * [Text][R/O data][R/W data][Dynamic][BSS][Non loadable]
	 */
	dmp->dm_text_size = dmp->dm_data_va - dmp->dm_text_va;
#if defined(__i386__)
	/*
	 * Find the first load section and figure out the relocation
	 * offset for the symbols. The kernel module will not need
	 * relocation, but the kernel linker modules will.
	 */
	for (i = 0; gelf_getphdr(dmp->dm_elf, i, &ph) != NULL; i++) {
		if (ph.p_type == PT_LOAD) {
			dmp->dm_reloc_offset = k_stat->address - ph.p_vaddr;
			break;
		}
	}
#endif
#endif

	if (dmp->dm_info.objfs_info_primary)
		dmp->dm_flags |= DT_DM_PRIMARY;

	dt_dprintf("opened %d-bit module %s (%s) [%d]\n",
	    bits, dmp->dm_name, dmp->dm_file, dmp->dm_modid);
}
Beispiel #27
0
static int
do_test (void)
{
  /* fdopendir takes over the descriptor, make a copy.  */
  int dupfd = dup (dir_fd);
  if (dupfd == -1)
    {
      puts ("dup failed");
      return 1;
    }
  if (lseek (dupfd, 0, SEEK_SET) != 0)
    {
      puts ("1st lseek failed");
      return 1;
    }

  /* The directory should be empty safe the . and .. files.  */
  DIR *dir = fdopendir (dupfd);
  if (dir == NULL)
    {
      puts ("fdopendir failed");
      return 1;
    }
  struct dirent64 *d;
  while ((d = readdir64 (dir)) != NULL)
    if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
      {
	printf ("temp directory contains file \"%s\"\n", d->d_name);
	return 1;
      }
  closedir (dir);

  /* Try to create a file.  */
  int fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
  if (fd == -1)
    {
      if (errno == ENOSYS)
	{
	  puts ("*at functions not supported");
	  return 0;
	}

      puts ("file creation failed");
      return 1;
    }
  write (fd, "hello", 5);
  puts ("file created");

  struct stat64 st1;
  if (fstat64 (fd, &st1) != 0)
    {
      puts ("fstat64 failed");
      return 1;
    }

  /* Before closing the file, try using this file descriptor to open
     another file.  This must fail.  */
  if (fchownat (fd, "some-file", 1, 1, 0) != -1)
    {
      puts ("fchownat using descriptor for normal file worked");
      return 1;
    }
  if (errno != ENOTDIR)
    {
      puts ("\
error for fchownat using descriptor for normal file not ENOTDIR ");
      return 1;
    }
static int
find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name,
			const char *debuglink_file, GElf_Word debuglink_crc,
			char **debuginfo_file_name)
{
  bool cancheck = debuglink_crc != (GElf_Word) 0;

  const char *file_basename = file_name == NULL ? NULL : basename (file_name);
  char *localname = NULL;
  if (debuglink_file == NULL)
    {
      /* For a alt debug multi file we need a name, for a separate debug
	 name we may be able to fall back on file_basename.debug.  */
      if (file_basename == NULL || mod->dw != NULL)
	{
	  errno = 0;
	  return -1;
	}

      size_t len = strlen (file_basename);
      localname = malloc (len + sizeof ".debug");
      if (unlikely (localname == NULL))
	return -1;
      memcpy (localname, file_basename, len);
      memcpy (&localname[len], ".debug", sizeof ".debug");
      debuglink_file = localname;
      cancheck = false;
    }

  /* Look for a file named DEBUGLINK_FILE in the directories
     indicated by the debug directory path setting.  */

  const Dwfl_Callbacks *const cb = mod->dwfl->callbacks;
  char *localpath = strdup ((cb->debuginfo_path ? *cb->debuginfo_path : NULL)
			    ?: DEFAULT_DEBUGINFO_PATH);
  if (unlikely (localpath == NULL))
    {
      free (localname);
      return -1;
    }

  /* A leading - or + in the whole path sets whether to check file CRCs.  */
  bool defcheck = true;
  char *path = localpath;
  if (path[0] == '-' || path[0] == '+')
    {
      defcheck = path[0] == '+';
      ++path;
    }

  /* XXX dev/ino should be cached in struct dwfl_file.  */
  struct stat64 main_stat;
  if (unlikely ((mod->main.fd != -1 ? fstat64 (mod->main.fd, &main_stat)
		 : file_name != NULL ? stat64 (file_name, &main_stat)
		 : -1) < 0))
    {
      main_stat.st_dev = 0;
      main_stat.st_ino = 0;
    }

  char *file_dirname = (file_basename == file_name ? NULL
			: strndup (file_name, file_basename - 1 - file_name));
  if (file_basename != file_name && file_dirname == NULL)
    {
      free (localpath);
      free (localname);
      return -1;
    }
  char *p;
  while ((p = strsep (&path, ":")) != NULL)
    {
      /* A leading - or + says whether to check file CRCs for this element.  */
      bool check = defcheck;
      if (*p == '+' || *p == '-')
	check = *p++ == '+';
      check = check && cancheck;

      const char *dir, *subdir, *file;
      switch (p[0])
	{
	case '\0':
	  /* An empty entry says to try the main file's directory.  */
	  dir = file_dirname;
	  subdir = NULL;
	  file = debuglink_file;
	  break;
	case '/':
	  /* An absolute path says to look there for a subdirectory
	     named by the main file's absolute directory.  This cannot
	     be applied to a relative file name.  For alt debug files
	     it means to look for the basename file in that dir or the
	     .dwz subdir (see below).  */
	  if (mod->dw == NULL
	      && (file_dirname == NULL || file_dirname[0] != '/'))
	    continue;
	  dir = p;
	  if (mod->dw == NULL)
	    {
	      subdir = file_dirname;
	      /* We want to explore all sub-subdirs.  Chop off one slash
		 at a time.  */
	    explore_dir:
	      subdir = strchr (subdir, '/');
	      if (subdir != NULL)
		subdir = subdir + 1;
	      if (subdir && *subdir == 0)
		continue;
	      file = debuglink_file;
	    }
	  else
	    {
	      subdir = NULL;
	      file = basename (debuglink_file);
	    }
	  break;
	default:
	  /* A relative path says to try a subdirectory of that name
	     in the main file's directory.  */
	  dir = file_dirname;
	  subdir = p;
	  file = debuglink_file;
	  break;
	}

      char *fname = NULL;
      int fd = try_open (&main_stat, dir, subdir, file, &fname);
      if (fd < 0)
	switch (errno)
	  {
	  case ENOENT:
	  case ENOTDIR:
	    /* If we are looking for the alt file also try the .dwz subdir.
	       But only if this is the empty or absolute path.  */
	    if (mod->dw != NULL && (p[0] == '\0' || p[0] == '/'))
	      {
		fd = try_open (&main_stat, dir, ".dwz",
			       basename (file), &fname);
		if (fd < 0)
		  {
		    if (errno != ENOENT && errno != ENOTDIR)
		      goto fail_free;
		    else
		      continue;
		  }
		break;
	      }
	    /* If possible try again with a sub-subdir.  */
	    if (mod->dw == NULL && subdir)
	      goto explore_dir;
	    continue;
	  default:
	    goto fail_free;
	  }
      if (validate (mod, fd, check, debuglink_crc))
	{
	  free (localpath);
	  free (localname);
	  free (file_dirname);
	  *debuginfo_file_name = fname;
	  return fd;
	}
      free (fname);
      close (fd);
    }

  /* No dice.  */
  errno = 0;
fail_free:
  free (localpath);
  free (localname);
  free (file_dirname);
  return -1;
}
Beispiel #29
0
/*
 * Returns the number of bytes in a partition
 */
blkid_loff_t blkid_get_dev_size(int fd)
{
	int valid_blkgetsize64 = 1;
#ifdef __linux__
	struct 		utsname ut;
#endif
	unsigned long long size64;
	unsigned long size;
	blkid_loff_t high, low;
#ifdef FDGETPRM
	struct floppy_struct this_floppy;
#endif
#ifdef HAVE_SYS_DISKLABEL_H
	int part = -1;
	struct disklabel lab;
	struct partition *pp;
	char ch;
	struct stat st;
#endif /* HAVE_SYS_DISKLABEL_H */

#ifdef DKIOCGETBLOCKCOUNT	/* For Apple Darwin */
	if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
		if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
		    && (size64 << 9 > 0xFFFFFFFF))
			return 0; /* EFBIG */
		return (blkid_loff_t) size64 << 9;
	}
#endif

#ifdef BLKGETSIZE64
#ifdef __linux__
	if ((uname(&ut) == 0) &&
	    ((ut.release[0] == '2') && (ut.release[1] == '.') &&
	     (ut.release[2] < '6') && (ut.release[3] == '.')))
		valid_blkgetsize64 = 0;
#endif
	if (valid_blkgetsize64 &&
	    ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
		if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
		    && ((size64) > 0xFFFFFFFF))
			return 0; /* EFBIG */
		return size64;
	}
#endif

#ifdef BLKGETSIZE
	if (ioctl(fd, BLKGETSIZE, &size) >= 0)
		return (blkid_loff_t)size << 9;
#endif

/* tested on FreeBSD 6.1-RELEASE i386 */
#ifdef DIOCGMEDIASIZE
	if (ioctl(fd, DIOCGMEDIASIZE, &size64) >= 0)
		return (off_t)size64;
#endif /* DIOCGMEDIASIZE */

#ifdef FDGETPRM
	if (ioctl(fd, FDGETPRM, &this_floppy) >= 0)
		return (blkid_loff_t)this_floppy.size << 9;
#endif
#ifdef HAVE_SYS_DISKLABEL_H
	/*
	 * This code works for FreeBSD 4.11 i386, except for the full device
	 * (such as /dev/ad0). It doesn't work properly for newer FreeBSD
	 * though. FreeBSD >= 5.0 should be covered by the DIOCGMEDIASIZE
	 * above however.
	 *
	 * Note that FreeBSD >= 4.0 has disk devices as unbuffered (raw,
	 * character) devices, so we need to check for S_ISCHR, too.
	 */
	if ((fstat(fd, &st) >= 0) && (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)))
		part = st.st_rdev & 7;
	if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
		pp = &lab.d_partitions[part];
		if (pp->p_size)
			return pp->p_size << 9;
	}
#endif /* HAVE_SYS_DISKLABEL_H */
	{
#ifdef HAVE_FSTAT64
		struct stat64   st;
		if (fstat64(fd, &st) == 0)
#else
		struct stat	st;
		if (fstat(fd, &st) == 0)
#endif
			if (S_ISREG(st.st_mode))
				return st.st_size;
	}


	/*
	 * OK, we couldn't figure it out by using a specialized ioctl,
	 * which is generally the best way.  So do binary search to
	 * find the size of the partition.
	 */
	low = 0;
	for (high = 1024; valid_offset(fd, high); high *= 2)
		low = high;
	while (low < high - 1)
	{
		const blkid_loff_t mid = (low + high) / 2;

		if (valid_offset(fd, mid))
			low = mid;
		else
			high = mid;
	}
	return low + 1;
}
Beispiel #30
0
int
charmap_conversion (const char *from_code, struct charmap_t *from_charmap,
		    const char *to_code, struct charmap_t *to_charmap,
		    int argc, int remaining, char *argv[],
		    const char *output_file)
{
  struct convtable *cvtbl;
  int status = EXIT_SUCCESS;

  /* We have three different cases to handle:

     - both, from_charmap and to_charmap, are available.  This means we
       can assume that the symbolic names match and use them to create
       the mapping.

     - only from_charmap is available.  In this case we can only hope that
       the symbolic names used are of the <Uxxxx> form in which case we
       can use a UCS4->"to_code" iconv() conversion for the second step.

     - only to_charmap is available.  This is similar, only that we would
       use iconv() for the "to_code"->UCS4 conversion.

       We first create a table which maps input bytes into output bytes.
       Once this is done we can handle all three of the cases above
       equally.  */
  if (from_charmap != NULL)
    {
      if (to_charmap == NULL)
	cvtbl = use_from_charmap (from_charmap, to_code);
      else
	cvtbl = use_both_charmaps (from_charmap, to_charmap);
    }
  else
    {
      assert (to_charmap != NULL);
      cvtbl = use_to_charmap (from_code, to_charmap);
    }

  /* If we couldn't generate a table stop now.  */
  if (cvtbl == NULL)
    return EXIT_FAILURE;

  /* Determine output file.  */
  FILE *output;
  if (output_file != NULL && strcmp (output_file, "-") != 0)
    {
      output = fopen (output_file, "w");
      if (output == NULL)
	error (EXIT_FAILURE, errno, _("cannot open output file"));
    }
  else
    output = stdout;

  /* We can now start the conversion.  */
  if (remaining == argc)
    {
      if (process_file (cvtbl, stdin, output) != 0)
	status = EXIT_FAILURE;
    }
  else
    do
      {
	int fd;

	if (verbose)
	  printf ("%s:\n", argv[remaining]);
	if (strcmp (argv[remaining], "-") == 0)
	  fd = 0;
	else
	  {
	    fd = open (argv[remaining], O_RDONLY);

	    if (fd == -1)
	      {
		error (0, errno, _("cannot open input file `%s'"),
		       argv[remaining]);
		status = EXIT_FAILURE;
		continue;
	      }
	  }

#ifdef _POSIX_MAPPED_FILES
	struct stat64 st;
	char *addr;
	/* We have possibilities for reading the input file.  First try
	   to mmap() it since this will provide the fastest solution.  */
	if (fstat64 (fd, &st) == 0
	    && ((addr = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE,
			      fd, 0)) != MAP_FAILED))
	  {
	    /* Yes, we can use mmap().  The descriptor is not needed
	       anymore.  */
	    if (close (fd) != 0)
	      error (EXIT_FAILURE, errno,
		     _("error while closing input `%s'"), argv[remaining]);

	    if (process_block (cvtbl, addr, st.st_size, output) < 0)
	      {
		/* Something went wrong.  */
		status = EXIT_FAILURE;

		/* We don't need the input data anymore.  */
		munmap ((void *) addr, st.st_size);

		/* We cannot go on with producing output since it might
		   lead to problem because the last output might leave
		   the output stream in an undefined state.  */
		break;
	      }

	    /* We don't need the input data anymore.  */
	    munmap ((void *) addr, st.st_size);
	  }
	else
#endif	/* _POSIX_MAPPED_FILES */
	  {
	    /* Read the file in pieces.  */
	    if (process_fd (cvtbl, fd, output) != 0)
	      {
		/* Something went wrong.  */
		status = EXIT_FAILURE;

		/* We don't need the input file anymore.  */
		close (fd);

		/* We cannot go on with producing output since it might
		   lead to problem because the last output might leave
		   the output stream in an undefined state.  */
		break;
	      }

	    /* Now close the file.  */
	    close (fd);
	  }
      }
    while (++remaining < argc);

  /* All done.  */
  return status;
}