Пример #1
0
void mode_to_letters(int mode, char * str)

{

  strcpy(str, "----------");           /* default=无参数 */

 

  if (S_ISDIR(mode))  

    str[0] = 'd';    /* 目录      */

  if (S_ISCHR(mode)) 

    str[0] = 'c';    /* 字符设备   */

  if (S_ISBLK(mode))  

    str[0] = 'b';    /* 块设备     */

 

  if (mode & S_IRUSR) //按位与,看mode是否有S_IRUSR权限

    str[1] = 'r';    /* 用户权限  */

  if (mode & S_IWUSR) 

    str[2] = 'w';

  if (mode & S_IXUSR) 

    str[3] = 'x';

 

  if (mode & S_IRGRP) 

    str[4] = 'r';    /* 组权限 */

  if (mode & S_IWGRP) 

    str[5] = 'w';

  if (mode & S_IXGRP)

    str[6] = 'x';

 

  if (mode & S_IROTH) 

    str[7] = 'r';    /* 其人的权限 */

  if (mode & S_IWOTH) 

    str[8] = 'w';

  if (mode & S_IXOTH) 

    str[9] = 'x';

}
Пример #2
0
/*
 * Display information about the current file.
 *
 * The format here roughly duplicates the output of 'ls -l'.
 * This is based on SUSv2, where 'tar tv' is documented as
 * listing additional information in an "unspecified format,"
 * and 'pax -l' is documented as using the same format as 'ls -l'.
 */
static void
list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
{
	char			 size[32];
	char			 date[32];
	char			 uids[16], gids[16];
	const char 		*uname, *gname;
	FILE			*out = stdout;
	const struct stat	*st;
	const char		*fmt;
	time_t			 tim;
	static time_t		 now;

	st = archive_entry_stat(entry);

	if (!now)
		time(&now);

	if (cpio->option_numeric_uid_gid) {
		/* Format numeric uid/gid for display. */
		snprintf(uids, sizeof(uids), "%d",
		    (int)archive_entry_uid(entry));
		uname = uids;
		snprintf(gids, sizeof(gids), "%d",
		    (int)archive_entry_gid(entry));
		gname = gids;
	} else {
		/* Use uname if it's present, else lookup name from uid. */
		uname = archive_entry_uname(entry);
		if (uname == NULL)
			uname = lookup_uname(cpio, archive_entry_uid(entry));
		/* Use gname if it's present, else lookup name from gid. */
		gname = archive_entry_gname(entry);
		if (gname == NULL)
			gname = lookup_gname(cpio, archive_entry_gid(entry));
	}

	/* Print device number or file size. */
	if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
		snprintf(size, sizeof(size), "%lu,%lu",
		    (unsigned long)major(st->st_rdev),
		    (unsigned long)minor(st->st_rdev)); /* ls(1) also casts here. */
	} else {
		snprintf(size, sizeof(size), CPIO_FILESIZE_PRINTF,
		    (CPIO_FILESIZE_TYPE)st->st_size);
	}

	/* Format the time using 'ls -l' conventions. */
	tim = (time_t)st->st_mtime;
#if defined(_WIN32) && !defined(__CYGWIN__)
	/* Windows' strftime function does not support %e format. */
	if (abs(tim - now) > (365/2)*86400)
		fmt = cpio->day_first ? "%d %b  %Y" : "%b %d  %Y";
	else
		fmt = cpio->day_first ? "%d %b %H:%M" : "%b %d %H:%M";
#else
	if (abs(tim - now) > (365/2)*86400)
		fmt = cpio->day_first ? "%e %b  %Y" : "%b %e  %Y";
	else
		fmt = cpio->day_first ? "%e %b %H:%M" : "%b %e %H:%M";
#endif
	strftime(date, sizeof(date), fmt, localtime(&tim));

	fprintf(out, "%s%3d %-8s %-8s %8s %12s %s",
	    archive_entry_strmode(entry),
	    archive_entry_nlink(entry),
	    uname, gname, size, date,
	    archive_entry_pathname(entry));

	/* Extra information for links. */
	if (archive_entry_hardlink(entry)) /* Hard link */
		fprintf(out, " link to %s", archive_entry_hardlink(entry));
	else if (archive_entry_symlink(entry)) /* Symbolic link */
		fprintf(out, " -> %s", archive_entry_symlink(entry));
	fprintf(out, "\n");
}
Пример #3
0
/*
 * sys_sync_file_range() permits finely controlled syncing over a segment of
 * a file in the range offset .. (offset+nbytes-1) inclusive.  If nbytes is
 * zero then sys_sync_file_range() will operate from offset out to EOF.
 *
 * The flag bits are:
 *
 * SYNC_FILE_RANGE_WAIT_BEFORE: wait upon writeout of all pages in the range
 * before performing the write.
 *
 * SYNC_FILE_RANGE_WRITE: initiate writeout of all those dirty pages in the
 * range which are not presently under writeback. Note that this may block for
 * significant periods due to exhaustion of disk request structures.
 *
 * SYNC_FILE_RANGE_WAIT_AFTER: wait upon writeout of all pages in the range
 * after performing the write.
 *
 * Useful combinations of the flag bits are:
 *
 * SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE: ensures that all pages
 * in the range which were dirty on entry to sys_sync_file_range() are placed
 * under writeout.  This is a start-write-for-data-integrity operation.
 *
 * SYNC_FILE_RANGE_WRITE: start writeout of all dirty pages in the range which
 * are not presently under writeout.  This is an asynchronous flush-to-disk
 * operation.  Not suitable for data integrity operations.
 *
 * SYNC_FILE_RANGE_WAIT_BEFORE (or SYNC_FILE_RANGE_WAIT_AFTER): wait for
 * completion of writeout of all pages in the range.  This will be used after an
 * earlier SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE operation to wait
 * for that operation to complete and to return the result.
 *
 * SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER:
 * a traditional sync() operation.  This is a write-for-data-integrity operation
 * which will ensure that all pages in the range which were dirty on entry to
 * sys_sync_file_range() are committed to disk.
 *
 *
 * SYNC_FILE_RANGE_WAIT_BEFORE and SYNC_FILE_RANGE_WAIT_AFTER will detect any
 * I/O errors or ENOSPC conditions and will return those to the caller, after
 * clearing the EIO and ENOSPC flags in the address_space.
 *
 * It should be noted that none of these operations write out the file's
 * metadata.  So unless the application is strictly performing overwrites of
 * already-instantiated disk blocks, there are no guarantees here that the data
 * will be available after a crash.
 */
SYSCALL_DEFINE(sync_file_range)(int fd, loff_t offset, loff_t nbytes,
				unsigned int flags)
{
#ifdef CONFIG_DYNAMIC_FSYNC
	if (likely(dyn_fsync_active && !power_suspend_active))
		return 0;
	else {
#endif

	int ret;
	struct file *file;
	struct address_space *mapping;
	loff_t endbyte;			/* inclusive */
	int fput_needed;
	umode_t i_mode;

	if (!fsync_enabled)
		return 0;

	ret = -EINVAL;
	if (flags & ~VALID_FLAGS)
		goto out;

	endbyte = offset + nbytes;

	if ((s64)offset < 0)
		goto out;
	if ((s64)endbyte < 0)
		goto out;
	if (endbyte < offset)
		goto out;

	if (sizeof(pgoff_t) == 4) {
		if (offset >= (0x100000000ULL << PAGE_CACHE_SHIFT)) {
			/*
			 * The range starts outside a 32 bit machine's
			 * pagecache addressing capabilities.  Let it "succeed"
			 */
			ret = 0;
			goto out;
		}
		if (endbyte >= (0x100000000ULL << PAGE_CACHE_SHIFT)) {
			/*
			 * Out to EOF
			 */
			nbytes = 0;
		}
	}

	if (nbytes == 0)
		endbyte = LLONG_MAX;
	else
		endbyte--;		/* inclusive */

	ret = -EBADF;
	file = fget_light(fd, &fput_needed);
	if (!file)
		goto out;

	i_mode = file->f_path.dentry->d_inode->i_mode;
	ret = -ESPIPE;
	if (!S_ISREG(i_mode) && !S_ISBLK(i_mode) && !S_ISDIR(i_mode) &&
			!S_ISLNK(i_mode))
		goto out_put;

	mapping = file->f_mapping;
	if (!mapping) {
		ret = -EINVAL;
		goto out_put;
	}

	ret = 0;
	if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) {
		ret = filemap_fdatawait_range(mapping, offset, endbyte);
		if (ret < 0)
			goto out_put;
	}

	if (flags & SYNC_FILE_RANGE_WRITE) {
		ret = filemap_fdatawrite_range(mapping, offset, endbyte);
		if (ret < 0)
			goto out_put;
	}

	if (flags & SYNC_FILE_RANGE_WAIT_AFTER)
		ret = filemap_fdatawait_range(mapping, offset, endbyte);

out_put:
	fput_light(file, fput_needed);
out:
	return ret;
#ifdef CONFIG_DYNAMIC_FSYNC
	}
#endif
}
Пример #4
0
static int ocfs2_read_locked_inode(struct inode *inode,
				   struct ocfs2_find_inode_args *args)
{
	struct super_block *sb;
	struct ocfs2_super *osb;
	struct ocfs2_dinode *fe;
	struct buffer_head *bh = NULL;
	int status, can_lock;
	u32 generation = 0;

	status = -EINVAL;
	sb = inode->i_sb;
	osb = OCFS2_SB(sb);

	/*
	 * To improve performance of cold-cache inode stats, we take
	 * the cluster lock here if possible.
	 *
	 * Generally, OCFS2 never trusts the contents of an inode
	 * unless it's holding a cluster lock, so taking it here isn't
	 * a correctness issue as much as it is a performance
	 * improvement.
	 *
	 * There are three times when taking the lock is not a good idea:
	 *
	 * 1) During startup, before we have initialized the DLM.
	 *
	 * 2) If we are reading certain system files which never get
	 *    cluster locks (local alloc, truncate log).
	 *
	 * 3) If the process doing the iget() is responsible for
	 *    orphan dir recovery. We're holding the orphan dir lock and
	 *    can get into a deadlock with another process on another
	 *    node in ->delete_inode().
	 *
	 * #1 and #2 can be simply solved by never taking the lock
	 * here for system files (which are the only type we read
	 * during mount). It's a heavier approach, but our main
	 * concern is user-accessible files anyway.
	 *
	 * #3 works itself out because we'll eventually take the
	 * cluster lock before trusting anything anyway.
	 */
	can_lock = !(args->fi_flags & OCFS2_FI_FLAG_SYSFILE)
		&& !(args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY)
		&& !ocfs2_mount_local(osb);

	trace_ocfs2_read_locked_inode(
		(unsigned long long)OCFS2_I(inode)->ip_blkno, can_lock);

	/*
	 * To maintain backwards compatibility with older versions of
	 * ocfs2-tools, we still store the generation value for system
	 * files. The only ones that actually matter to userspace are
	 * the journals, but it's easier and inexpensive to just flag
	 * all system files similarly.
	 */
	if (args->fi_flags & OCFS2_FI_FLAG_SYSFILE)
		generation = osb->fs_generation;

	ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_inode_lockres,
				  OCFS2_LOCK_TYPE_META,
				  generation, inode);

	ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_open_lockres,
				  OCFS2_LOCK_TYPE_OPEN,
				  0, inode);

	if (can_lock) {
		status = ocfs2_open_lock(inode);
		if (status) {
			make_bad_inode(inode);
			mlog_errno(status);
			return status;
		}
		status = ocfs2_inode_lock(inode, NULL, 0);
		if (status) {
			make_bad_inode(inode);
			mlog_errno(status);
			return status;
		}
	}

	if (args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY) {
		status = ocfs2_try_open_lock(inode, 0);
		if (status) {
			make_bad_inode(inode);
			return status;
		}
	}

	if (can_lock) {
		status = ocfs2_read_inode_block_full(inode, &bh,
						     OCFS2_BH_IGNORE_CACHE);
	} else {
		status = ocfs2_read_blocks_sync(osb, args->fi_blkno, 1, &bh);
		/*
		 * If buffer is in jbd, then its checksum may not have been
		 * computed as yet.
		 */
		if (!status && !buffer_jbd(bh))
			status = ocfs2_validate_inode_block(osb->sb, bh);
	}
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

	status = -EINVAL;
	fe = (struct ocfs2_dinode *) bh->b_data;

	/*
	 * This is a code bug. Right now the caller needs to
	 * understand whether it is asking for a system file inode or
	 * not so the proper lock names can be built.
	 */
	mlog_bug_on_msg(!!(fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) !=
			!!(args->fi_flags & OCFS2_FI_FLAG_SYSFILE),
			"Inode %llu: system file state is ambigous\n",
			(unsigned long long)args->fi_blkno);

	if (S_ISCHR(le16_to_cpu(fe->i_mode)) ||
	    S_ISBLK(le16_to_cpu(fe->i_mode)))
		inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));

	ocfs2_populate_inode(inode, fe, 0);

	BUG_ON(args->fi_blkno != le64_to_cpu(fe->i_blkno));

	status = 0;

bail:
	if (can_lock)
		ocfs2_inode_unlock(inode, 0);

	if (status < 0)
		make_bad_inode(inode);

	brelse(bh);

	return status;
}
Пример #5
0
static int ex_dir_list2html_process(Vstr_base *s1, Vstr_base *s2,
                                    int *parsed_header, int *row_num)
{
  size_t pos = 0;
  size_t len = 0;
  size_t ns1 = vstr_parse_netstr(s2, 1, s2->len, &pos, &len);
  Vstr_sect_node name[1] = {{0,0}};
  Vstr_sect_node size[1] = {{0,0}};
  Vstr_sect_node type[1] = {{0,0}};
  Vstr_sect_node mtim[1] = {{0,0}};
  Vstr_sect_node perm[1] = {{0,0}};
  
  if (!ns1)
  {
    if ((len     > EX_MAX_R_DATA_INCORE) || 
        (s2->len > EX_MAX_R_DATA_INCORE))
      errx(EXIT_FAILURE, "bad input");
  
    return (FALSE);
  }

  if (!*parsed_header)
  {
    size_t vpos = 0;
    size_t vlen = 0;
    size_t nst  = 0;
    
    if (!(nst = vstr_parse_netstr(s2, pos, len, &vpos, &vlen)))
      errx(EXIT_FAILURE, "bad input");
    pos += nst; len -= nst;
    if (!vstr_cmp_cstr_eq(s2, vpos, vlen, "version"))
      errx(EXIT_FAILURE, "bad input");
    if (!(nst = vstr_parse_netstr(s2, pos, len, &vpos, &vlen)))
      errx(EXIT_FAILURE, "bad input");
    pos += nst; len -= nst;
    if (!vstr_cmp_cstr_eq(s2, vpos, vlen, "2"))
      errx(EXIT_FAILURE, "Unsupported version");
    
    *parsed_header = TRUE;
    len = 0;
  }
  
  while (len)
  {
    size_t kpos = 0;
    size_t klen = 0;
    size_t vpos = 0;
    size_t vlen = 0;
    size_t nst  = 0;
    
    if (!(nst = vstr_parse_netstr(s2, pos, len, &kpos, &klen)))
      errx(EXIT_FAILURE, "bad input");
    pos += nst; len -= nst;
    
    if (!(nst = vstr_parse_netstr(s2, pos, len, &vpos, &vlen)))
      errx(EXIT_FAILURE, "bad input");    
    pos += nst; len -= nst;

    if (0) { }
    else if (vstr_cmp_cstr_eq(s2, kpos, klen, "name"))
    {
      name->pos = vpos;
      name->len = vlen;
    }
    else if (vstr_cmp_cstr_eq(s2, kpos, klen, "type"))
    {
      type->pos = vpos;
      type->len = vlen;
    }
    else if (vstr_cmp_cstr_eq(s2, kpos, klen, "perms"))
    {
      perm->pos = vpos;
      perm->len = vlen;
    }
    else if (vstr_cmp_cstr_eq(s2, kpos, klen, "size"))
    {
      size->pos = vpos;
      size->len = vlen;
    }
    else if (vstr_cmp_cstr_eq(s2, kpos, klen, "mtime"))
    {
      mtim->pos = vpos;
      mtim->len = vlen;
    }
  }

  if (name->pos)
  {
    Vstr_base *href = vstr_dup_vstr(NULL, s2, name->pos, name->len, 0);
    Vstr_base *text = vstr_dup_vstr(NULL, s2, name->pos, name->len, 0);
    VSTR_AUTOCONF_uintmax_t type_val = 0;
    VSTR_AUTOCONF_uintmax_t val = 0;
    time_t tval = 0;
    
    *row_num %= 2;
    ++*row_num;

    if (!href || !vstr_conv_encode_uri(href, 1, href->len))
      errno = ENOMEM, err(EXIT_FAILURE, "html");
    if (!text || !html_conv_encode_data(text, 1, text->len))
      errno = ENOMEM, err(EXIT_FAILURE, "html");

    if (type->pos)
      type_val = vstr_parse_uintmax(s2, type->pos, type->len, 8, NULL, NULL);

    vstr_add_fmt(s1, s1->len, "  <tr class=\"r%d\"> <td class=\"cn\">",
                 *row_num);
                 
    if (type_val && S_ISDIR(type_val))
      vstr_add_fmt(s1, s1->len, "<a class=\"%s\" "
                   "href=\"%s${vstr:%p%zu%zu%u}%s\">${vstr:%p%zu%zu%u}</a>",
                   "dir", def_prefix,
                   href, (size_t)1, href->len, 0, "/",
                   text, (size_t)1, text->len, 0);
    else if (type_val && S_ISLNK(type_val))
      vstr_add_fmt(s1, s1->len, "<a class=\"%s\" "
                   "href=\"%s${vstr:%p%zu%zu%u}%s\">${vstr:%p%zu%zu%u}</a>",
                   "link", def_prefix,
                   href, (size_t)1, href->len, 0, "",
                   text, (size_t)1, text->len, 0);
    else
      vstr_add_fmt(s1, s1->len, "<a class=\"%s\" "
                   "href=\"%s${vstr:%p%zu%zu%u}%s\">${vstr:%p%zu%zu%u}</a>",
                   "file", def_prefix,
                   href, (size_t)1, href->len, 0, "",
                   text, (size_t)1, text->len, 0);
    vstr_add_fmt(s1, s1->len, "</td>");
    
    vstr_free_base(href); href = NULL;
    vstr_free_base(text); text = NULL;
    
    if (!size->pos)
      vstr_add_cstr_buf(s1, s1->len, " <td class=\"csz\"></td>");
    else
    {
      val = vstr_parse_uintmax(s2, size->pos, size->len, 10, NULL, NULL);

      vstr_add_fmt(s1, s1->len, " <td class=\"csz\">${BKMG.ju:%ju}</td>", val);
    }
    
    if (output_mtime && !mtim->pos)
      vstr_add_cstr_buf(s1, s1->len, " <td class=\"cmt\"></td>");
    else if (output_mtime)
    {
      struct tm *tm_val = NULL;

      tval = vstr_parse_uintmax(s2, mtim->pos, mtim->len, 10, NULL, NULL);

      if (!(tm_val = localtime(&tval)))
        vstr_add_cstr_buf(s1, s1->len, " <td class=\"cmt\">unknown</td>");
      else
      {
        char buf[4096];
      
        strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm_val);
      
        vstr_add_fmt(s1, s1->len, " <td class=\"cmt\">%s</td>", buf);
      }
    }
    
    if (output_perms && !perm->pos)
      vstr_add_cstr_buf(s1, s1->len, " <td class=\"cp\"></td>");
    else if (output_perms)
    {
      val = vstr_parse_uintmax(s2, perm->pos, perm->len, 8, NULL, NULL);
      switch (val & 07)
      {
        case 07:
          if (type_val && S_ISDIR(type_val))
            vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>",
                         "Read, write and search", "rwx");
          else
            vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>",
                         "Read, write and execute", "rwx");
          break;
        case 06:
          vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>",
                       "Read and write", "rw-");
          break;
        case 05:
          if (type_val && S_ISDIR(type_val))
            vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>",
                         "Read and search", "r-x");
          else
            vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>",
                         "Read and execute", "r-x");
          break;
        case 04:
          vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>",
                       "Read only", "r--");
          break;
        case 03:
          if (type_val && S_ISDIR(type_val))
            vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>",
                         "Write and search", "-wx");
          else
            vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>",
                         "Write and execute", "-wx");            
          break;
        case 02:
          vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>",
                       "Write only", "-w-");
          break;
        case 01:
          if (type_val && S_ISDIR(type_val))
            vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>",
                         "Search only", "--x");
          else
            vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>",
                         "Execute only", "--x");            
          break;
        case  0:
          vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>",
                       "None", "---");
          break;
      }
    }
    
    if (!type_val)
      vstr_add_cstr_buf(s1, s1->len, " <td class=\"ct\"></td>");
    else
    {
      vstr_add_cstr_buf(s1, s1->len, " <td class=\"ct\">");
      if (0) { }
      else if (S_ISREG(type_val))
      { /* do nothing */ }
      else if (S_ISDIR(type_val))
        vstr_add_cstr_buf(s1, s1->len, "(directory)");
      else if (S_ISCHR(type_val))
        vstr_add_cstr_buf(s1, s1->len, "(character device)");
      else if (S_ISBLK(type_val))
        vstr_add_cstr_buf(s1, s1->len, "(block device)");
      else if (S_ISLNK(type_val))
        vstr_add_cstr_buf(s1, s1->len, "(symbolic link)");
      else if (S_ISSOCK(type_val))
        vstr_add_cstr_buf(s1, s1->len, "(socket)");
      else
        vstr_add_cstr_buf(s1, s1->len, "(UNKNOWN)");
      vstr_add_cstr_buf(s1, s1->len, "</td>");
    }
      
    vstr_add_cstr_buf(s1, s1->len, "</tr>\n");
  }
  
  vstr_del(s2, 1, ns1);

  return (TRUE);
}
Пример #6
0
static int
NativeMatchType(
    Tcl_Interp *interp,       /* Interpreter to receive errors. */
    const char *nativeEntry,  /* Native path to check. */
    const char *nativeName,   /* Native filename to check. */
    Tcl_GlobTypeData *types)  /* Type description to match against. */
{
    Tcl_StatBuf buf;

    if (types == NULL) {
        /*
         * Simply check for the file's existence, but do it with lstat, in
         * case it is a link to a file which doesn't exist (since that case
         * would not show up if we used 'access' or 'stat')
         */

        if (TclOSlstat(nativeEntry, &buf) != 0) {
            return 0;
        }
        return 1;
    }

    if (types->perm != 0) {
        if (TclOSstat(nativeEntry, &buf) != 0) {
            /*
             * Either the file has disappeared between the 'readdir' call and
             * the 'stat' call, or the file is a link to a file which doesn't
             * exist (which we could ascertain with lstat), or there is some
             * other strange problem. In all these cases, we define this to
             * mean the file does not match any defined permission, and
             * therefore it is not added to the list of files to return.
             */

            return 0;
        }

        /*
         * readonly means that there are NO write permissions (even for user),
         * but execute is OK for anybody OR that the user immutable flag is
         * set (where supported).
         */

        if (((types->perm & TCL_GLOB_PERM_RONLY) &&
#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
                !(buf.st_flags & UF_IMMUTABLE) &&
#endif
                (buf.st_mode & (S_IWOTH|S_IWGRP|S_IWUSR))) ||
                ((types->perm & TCL_GLOB_PERM_R) &&
                 (access(nativeEntry, R_OK) != 0)) ||
                ((types->perm & TCL_GLOB_PERM_W) &&
                 (access(nativeEntry, W_OK) != 0)) ||
                ((types->perm & TCL_GLOB_PERM_X) &&
                 (access(nativeEntry, X_OK) != 0))
#ifndef MAC_OSX_TCL
                || ((types->perm & TCL_GLOB_PERM_HIDDEN) &&
                    (*nativeName != '.'))
#endif /* MAC_OSX_TCL */
           ) {
            return 0;
        }
    }
    if (types->type != 0) {
        if (types->perm == 0) {
            /*
             * We haven't yet done a stat on the file.
             */

            if (TclOSstat(nativeEntry, &buf) != 0) {
                /*
                 * Posix error occurred. The only ok case is if this is a link
                 * to a nonexistent file, and the user did 'glob -l'. So we
                 * check that here:
                 */

                if ((types->type & TCL_GLOB_TYPE_LINK)
                        && (TclOSlstat(nativeEntry, &buf) == 0)
                        && S_ISLNK(buf.st_mode)) {
                    return 1;
                }
                return 0;
            }
        }

        /*
         * In order bcdpsfl as in 'find -t'
         */

        if (    ((types->type & TCL_GLOB_TYPE_BLOCK)&& S_ISBLK(buf.st_mode)) ||
                ((types->type & TCL_GLOB_TYPE_CHAR) && S_ISCHR(buf.st_mode)) ||
                ((types->type & TCL_GLOB_TYPE_DIR)  && S_ISDIR(buf.st_mode)) ||
                ((types->type & TCL_GLOB_TYPE_PIPE) && S_ISFIFO(buf.st_mode))||
#ifdef S_ISSOCK
                ((types->type & TCL_GLOB_TYPE_SOCK) && S_ISSOCK(buf.st_mode))||
#endif /* S_ISSOCK */
                ((types->type & TCL_GLOB_TYPE_FILE) && S_ISREG(buf.st_mode))) {
            /*
             * Do nothing - this file is ok.
             */
        } else {
#ifdef S_ISLNK
            if ((types->type & TCL_GLOB_TYPE_LINK)
                    && (TclOSlstat(nativeEntry, &buf) == 0)
                    && S_ISLNK(buf.st_mode)) {
                goto filetypeOK;
            }
#endif /* S_ISLNK */
            return 0;
        }
    }
filetypeOK:

    /*
     * If we're on OSX, we also have to worry about matching the file creator
     * code (if specified). Do that now.
     */

#ifdef MAC_OSX_TCL
    if (types->macType != NULL || types->macCreator != NULL ||
            (types->perm & TCL_GLOB_PERM_HIDDEN)) {
        int matchResult;

        if (types->perm == 0 && types->type == 0) {
            /*
             * We haven't yet done a stat on the file.
             */

            if (TclOSstat(nativeEntry, &buf) != 0) {
                return 0;
            }
        }

        matchResult = TclMacOSXMatchType(interp, nativeEntry, nativeName,
                                         &buf, types);
        if (matchResult != 1) {
            return matchResult;
        }
    }
#endif /* MAC_OSX_TCL */

    return 1;
}
Пример #7
0
/* Returns whether any color sequence was printed. */
bool
_rl_print_color_indicator (const char *f)
{
  enum indicator_no colored_filetype;
  COLOR_EXT_TYPE *ext;	/* Color extension */
  size_t len;		/* Length of name */

  const char* name;
  char *filename;
  struct stat astat, linkstat;
  mode_t mode;
  int linkok;	/* 1 == ok, 0 == dangling symlink, -1 == missing */
  int stat_ok;

  name = f;

  /* This should already have undergone tilde expansion */
  filename = 0;
  if (rl_filename_stat_hook)
    {
      filename = savestring (f);
      (*rl_filename_stat_hook) (&filename);
      name = filename;
    }

#if defined (HAVE_LSTAT)
  stat_ok = lstat(name, &astat);
#else
  stat_ok = stat(name, &astat);
#endif
  if (stat_ok == 0)
    {
      mode = astat.st_mode;
#if defined (HAVE_LSTAT)
      if (S_ISLNK (mode))
	{
	  linkok = stat (name, &linkstat) == 0;
	  if (linkok && strncmp (_rl_color_indicator[C_LINK].string, "target", 6) == 0)
	    mode = linkstat.st_mode;
	}
      else
#endif
	linkok = 1;
    }
  else
    linkok = -1;

  /* Is this a nonexistent file?  If so, linkok == -1.  */

  if (linkok == -1 && _rl_color_indicator[C_MISSING].string != NULL)
    colored_filetype = C_MISSING;
  else if (linkok == 0 && S_ISLNK(mode) && _rl_color_indicator[C_ORPHAN].string != NULL)
    colored_filetype = C_ORPHAN;	/* dangling symlink */
  else if(stat_ok != 0)
    {
      static enum indicator_no filetype_indicator[] = FILETYPE_INDICATORS;
      colored_filetype = filetype_indicator[normal]; //f->filetype];
    }
  else
    {
      if (S_ISREG (mode))
        {
          colored_filetype = C_FILE;

          if ((mode & S_ISUID) != 0 && is_colored (C_SETUID))
            colored_filetype = C_SETUID;
          else if ((mode & S_ISGID) != 0 && is_colored (C_SETGID))
            colored_filetype = C_SETGID;
          else if (is_colored (C_CAP) && 0) //f->has_capability)
            colored_filetype = C_CAP;
          else if ((mode & S_IXUGO) != 0 && is_colored (C_EXEC))
            colored_filetype = C_EXEC;
          else if ((1 < astat.st_nlink) && is_colored (C_MULTIHARDLINK))
            colored_filetype = C_MULTIHARDLINK;
        }
      else if (S_ISDIR (mode))
        {
          colored_filetype = C_DIR;

#if defined (S_ISVTX)
          if ((mode & S_ISVTX) && (mode & S_IWOTH)
              && is_colored (C_STICKY_OTHER_WRITABLE))
            colored_filetype = C_STICKY_OTHER_WRITABLE;
          else
#endif
          if ((mode & S_IWOTH) != 0 && is_colored (C_OTHER_WRITABLE))
            colored_filetype = C_OTHER_WRITABLE;
#if defined (S_ISVTX)
          else if ((mode & S_ISVTX) != 0 && is_colored (C_STICKY))
            colored_filetype = C_STICKY;
#endif
        }
      else if (S_ISLNK (mode))
        colored_filetype = C_LINK;
      else if (S_ISFIFO (mode))
        colored_filetype = C_FIFO;
      else if (S_ISSOCK (mode))
        colored_filetype = C_SOCK;
      else if (S_ISBLK (mode))
        colored_filetype = C_BLK;
      else if (S_ISCHR (mode))
        colored_filetype = C_CHR;
      else
        {
          /* Classify a file of some other type as C_ORPHAN.  */
          colored_filetype = C_ORPHAN;
        }
    }

  /* Check the file's suffix only if still classified as C_FILE.  */
  ext = NULL;
  if (colored_filetype == C_FILE)
    {
      /* Test if NAME has a recognized suffix.  */
      len = strlen (name);
      name += len;		/* Pointer to final \0.  */
      for (ext = _rl_color_ext_list; ext != NULL; ext = ext->next)
        {
          if (ext->ext.len <= len
              && strncmp (name - ext->ext.len, ext->ext.string,
                          ext->ext.len) == 0)
            break;
        }
    }

  free (filename);	/* NULL or savestring return value */

  {
    const struct bin_str *const s
      = ext ? &(ext->seq) : &_rl_color_indicator[colored_filetype];
    if (s->string != NULL)
      {
        /* Need to reset so not dealing with attribute combinations */
        if (is_colored (C_NORM))
	  restore_default_color ();
        _rl_put_indicator (&_rl_color_indicator[C_LEFT]);
        _rl_put_indicator (s);
        _rl_put_indicator (&_rl_color_indicator[C_RIGHT]);
        return 0;
      }
    else
      return 1;
  }
}
Пример #8
0
int main(int argc, char *argv[])
{
    char        *filename;
    struct stat sb;
    int         filekind;
    char        *reason;
    int         status;
    
    // argument check
    if (argc != 2) {
        fprintf(stderr, "Usage: " PROGNAME_S " <device>\n");
        return 1;
    }
    filename = argv[1];
    
    // set input to unbuffered
    fflush(NULL);
    setvbuf(stdin, NULL, _IONBF, 0);
    
    // stat check
    if (stat(filename, &sb) < 0) {
        errore("Can't stat %.300s", filename);
        return 1;
    }
    
    filekind = 0;
    reason = NULL;
    if (S_ISBLK(sb.st_mode))
        filekind = 1;
    else if (S_ISCHR(sb.st_mode))
        filekind = 2;
    else if (S_ISDIR(sb.st_mode))
        reason = "Is a directory";
    else if (S_ISFIFO(sb.st_mode))
        reason = "Is a FIFO";
#ifdef S_ISSOCK
    else if (S_ISSOCK(sb.st_mode))
        reason = "Is a socket";
#endif
    else
        reason = "Is an unknown kind of special file";
    
    if (reason != NULL) {
        error("%.300s: %s", filename, reason);
        return 1;
    }
    
    // open file
    fd = open(filename, O_RDWR);
    if (fd < 0 && errno == EBUSY) {
        fd = open(filename, O_RDONLY);
#ifndef NOREADONLYWARN
        if (fd >= 0)
            printf("Warning: %.300s opened read-only\n", filename);
#endif
    }
    if (fd < 0) {
        errore("Can't open %.300s", filename);
        return 1;
    }
    
    // (try to) guard against TTY character devices
    if (filekind == 2) {
        if (isatty(fd)) {
            error("%.300s: Is a TTY device", filename);
            return 1;
        }
    }
    
    // run sync algorithm
    status = PROGNAME();
    printf("\n");
    
    // close file
    if (close(fd) != 0) {
        errore("Error while closing %.300s", filename);
        return 1;
    }
    
    return status;
}
Пример #9
0
int file_test(const char* name, const char* flags)
{
	struct stat stat_result;
	if(stat(name, &stat_result)==-1)
	{
		//if(flags[0]!=FILE_EXISTS)warn("file_test(\"%s\",\"%s\") failed", name, flags);
		return 0;
	}
	if(flags==NULL || flags[0]=='\0' || flags[1]!='\0')
	{
		warn("file_test(\"%s\",\"%s\"), invalid flags", name, flags);
	}
	time_t now=time(NULL);
	switch (flags[0]) {
	case FILE_READABLE:break;
		//return stat_result.st_mode & S_IRUSR;
	case FILE_WRITABLE:break;
		//return stat_result.st_mode & S_IWUSR;
	case FILE_EXECUTABLE:break;
		//return stat_result.st_mode & S_IXUSR;
	case FILE_OWNED:break;
		return stat_result.st_uid==geteuid();

	case FILE_READABLE_REAL_ID:break;
	case FILE_WRITABLE_REAL_ID:break;
	case FILE_EXECUTABLE_REAL_ID:break;
	case FILE_OWNED_REAL_ID:
		return stat_result.st_uid==getuid();

	case FILE_EXISTS:
		return 1;
	case FILE_EMPTY:
		return stat_result.st_size==0;
	case FILE_SIZE:
		return stat_result.st_size;

	case FILE_PLAIN:
		return S_ISREG(stat_result.st_mode);
	case FILE_DIRECTORY:
		return S_ISDIR(stat_result.st_mode);
	case FILE_LINK:
		return S_ISLNK(stat_result.st_mode);
	case FILE_PIPE:break;
	case FILE_SOCKET:
		return S_ISSOCK(stat_result.st_mode);
	case FILE_BLOCK_DEVICE:
		return S_ISBLK(stat_result.st_mode);
	case FILE_CHARACTER_DEVICE:
		return S_ISCHR(stat_result.st_mode);
	case FILE_TTY:break;

	case FILE_SETUID:
		return stat_result.st_mode & S_ISUID;
	case FILE_SETGID:
		return stat_result.st_mode & S_ISGID;
	case FILE_STICKY:
		return stat_result.st_mode & S_ISVTX;

	case FILE_TEXT:break;
	case FILE_BINARY:break;

	case FILE_MODIFIED_SECONDS:
		return now-stat_result.st_mtime;
	case FILE_ACCESSED_SECONDS:
		return now-stat_result.st_atime;
	case FILE_CHANGED_SECONDS:
		return now-stat_result.st_ctime;
	default:
		warn("unknown file test \"%s\"",flags);
		return 0;
	}
	warn("file_test(\"%s\",\"%s\") not implemented yet", name, flags);
	return 0;
}
Пример #10
0
/*
 * Fill in the given information structure with the file paths and stat
 * details of the given file descriptor within the given process (given
 * within the info structure).
 *
 * Returns nonzero on error - error codes are:
 *
 *  -1 - info or state were NULL
 *   1 - process does not exist
 *   2 - readlink on /proc/pid/fd/N failed
 *   3 - stat or lstat on /proc/pid/fd/N failed
 *   4 - file descriptor is not opened on a regular file
 *
 * If "automatic" is nonzero, then this fd was picked automatically, and so
 * if it's not readable or not a regular file, no error is displayed and the
 * function just returns an error code.
 */
int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, int automatic)
{
	if (NULL == state)
		return -1;
	if (NULL == info)
		return -1;

	if (kill(info->watch_pid, 0) != 0) {
		if (!automatic)
			pv_error(state, "%s %u: %s",
				 _("pid"),
				 info->watch_pid, strerror(errno));
		return 1;
	}

	snprintf(info->file_fdinfo, sizeof(info->file_fdinfo) - 1,
		 "/proc/%u/fdinfo/%d", info->watch_pid, info->watch_fd);
	snprintf(info->file_fd, sizeof(info->file_fd) - 1,
		 "/proc/%u/fd/%d", info->watch_pid, info->watch_fd);

	if (readlink
	    (info->file_fd, info->file_fdpath,
	     sizeof(info->file_fdpath) - 1) < 0) {
		if (!automatic)
			pv_error(state, "%s %u: %s %d: %s",
				 _("pid"),
				 info->watch_pid,
				 _("fd"), info->watch_fd, strerror(errno));
		return 2;
	}

	if (!((0 == stat64(info->file_fd, &(info->sb_fd)))
	      && (0 == lstat64(info->file_fd, &(info->sb_fd_link))))) {
		if (!automatic)
			pv_error(state, "%s %u: %s %d: %s: %s",
				 _("pid"),
				 info->watch_pid,
				 _("fd"),
				 info->watch_fd, info->file_fdpath,
				 strerror(errno));
		return 3;
	}

	info->size = 0;

	if (S_ISBLK(info->sb_fd.st_mode)) {
		int fd;

		/*
		 * Get the size of block devices by opening
		 * them and seeking to the end.
		 */
		fd = open64(info->file_fdpath, O_RDONLY);
		if (fd >= 0) {
			info->size = lseek64(fd, 0, SEEK_END);
			close(fd);
		} else {
			info->size = 0;
		}
	} else if (S_ISREG(info->sb_fd.st_mode)) {
		if ((info->sb_fd_link.st_mode & S_IWUSR) == 0) {
			info->size = info->sb_fd.st_size;
		}
	} else {
		if (!automatic)
			pv_error(state, "%s %u: %s %d: %s: %s",
				 _("pid"),
				 info->watch_pid,
				 _("fd"),
				 info->watch_fd,
				 info->file_fdpath,
				 _("not a regular file or block device"));
		return 4;
	}

	return 0;
}
Пример #11
0
int32_t xar_stat_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) {
	char *tmpstr;
	struct passwd *pw;
	struct group *gr;
	char time[128];
	struct tm t;
	const char *type;

	/* no stat attributes for data from a buffer, it is just a file */
	if(len){
		xar_prop_set(f, "type", "file");
		return 0;
	}
	
	if( S_ISREG(XAR(x)->sbcache.st_mode) && (XAR(x)->sbcache.st_nlink > 1) ) {
		xar_file_t tmpf;
		const char *id = xar_attr_get(f, NULL, "id");
		if( !id ) {
			xar_err_new(x);
			xar_err_set_file(x, f);
			xar_err_set_string(x, "stat: No file id for file");
			xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_CREATION);
			return -1;
		}
		tmpf = xar_link_lookup(x, XAR(x)->sbcache.st_dev, XAR(x)->sbcache.st_ino, f);
		xar_prop_set(f, "type", "hardlink");
		if( tmpf ) {
			const char *id;
			id = xar_attr_get(tmpf, NULL, "id");
			xar_attr_set(f, "type", "link", id);
		} else {
			xar_attr_set(f, "type", "link", "original");
		}
	} else {
		type = filetype_name(XAR(x)->sbcache.st_mode & S_IFMT);
		xar_prop_set(f, "type", type);
	}

	/* Record major/minor device node numbers */
	if( S_ISBLK(XAR(x)->sbcache.st_mode) || S_ISCHR(XAR(x)->sbcache.st_mode)) {
		uint32_t major, minor;
		char tmpstr[12];
		xar_devmake(XAR(x)->sbcache.st_rdev, &major, &minor);
		memset(tmpstr, 0, sizeof(tmpstr));
		snprintf(tmpstr, sizeof(tmpstr)-1, "%u", major);
		xar_prop_set(f, "device/major", tmpstr);
		memset(tmpstr, 0, sizeof(tmpstr));
		snprintf(tmpstr, sizeof(tmpstr)-1, "%u", minor);
		xar_prop_set(f, "device/minor", tmpstr);
	}

	if( S_ISLNK(XAR(x)->sbcache.st_mode) ) {
		char link[4096];
		struct stat lsb;

		memset(link, 0, sizeof(link));
		readlink(file, link, sizeof(link)-1);
		xar_prop_set(f, "link", link);
		if( stat(file, &lsb) != 0 ) {
			xar_attr_set(f, "link", "type", "broken");
		} else {
			type = filetype_name(lsb.st_mode & S_IFMT);
			xar_attr_set(f, "link", "type", type);
		}
	}

	asprintf(&tmpstr, "%04o", XAR(x)->sbcache.st_mode & (~S_IFMT));
	xar_prop_set(f, "mode", tmpstr);
	free(tmpstr);

	asprintf(&tmpstr, "%"PRIu64, (uint64_t)XAR(x)->sbcache.st_uid);
	xar_prop_set(f, "uid", tmpstr);
	free(tmpstr);

	pw = getpwuid(XAR(x)->sbcache.st_uid);
	if( pw )
		xar_prop_set(f, "user", pw->pw_name);

	asprintf(&tmpstr, "%"PRIu64, (uint64_t)XAR(x)->sbcache.st_gid);
	xar_prop_set(f, "gid", tmpstr);
	free(tmpstr);

	gr = getgrgid(XAR(x)->sbcache.st_gid);
	if( gr )
		xar_prop_set(f, "group", gr->gr_name);

	gmtime_r(&XAR(x)->sbcache.st_atime, &t);
	memset(time, 0, sizeof(time));
	strftime(time, sizeof(time), "%FT%T", &t);
	strcat(time, "Z");
	xar_prop_set(f, "atime", time);

	gmtime_r(&XAR(x)->sbcache.st_mtime, &t);
	memset(time, 0, sizeof(time));
	strftime(time, sizeof(time), "%FT%T", &t);
	strcat(time, "Z");
	xar_prop_set(f, "mtime", time);

	gmtime_r(&XAR(x)->sbcache.st_ctime, &t);
	memset(time, 0, sizeof(time));
	strftime(time, sizeof(time), "%FT%T", &t);
	strcat(time, "Z");
	xar_prop_set(f, "ctime", time);

	flags_archive(f, &(XAR(x)->sbcache));

	aacls(f, file);

	return 0;
}
Пример #12
0
/*
 * Read WAV header, leave file seek pointer past WAV header.
 */
off_t 
wavsize(int f)
{
	chunk_t		chunk;
	riff_chunk	riff;
	fmt_chunk	fmt;
	struct stat	sb;
	off_t		cursor;
	BOOL		gotFormat;
	mode_t		mode;
	off_t		size;
	long		ret = AU_BAD_HEADER;

	/*
	 * First check if a bad guy tries to call wavsize()
	 * with an unappropriate file descriptor.
	 * return -1 in this case.
	 */

	if (isatty(f))
		return (-1L);
	if (fstat(f, &sb) < 0)
		return (-1L);
	mode = sb.st_mode & S_IFMT;
	if (!S_ISREG(mode) && !S_ISBLK(mode) && !S_ISCHR(mode))
		return (-1L);

	cursor = (off_t)0;
	gotFormat = FALSE;

	for (;;) {
		if (read(f, &chunk, sizeof (chunk)) != sizeof (chunk))
			goto err;
		size = (off_t)le_a_to_u_long(chunk.cksize);

		if (strncmp((char *)chunk.ckid, WAV_RIFF_MAGIC, 4) == 0) {
			/*
			 * We found (first) RIFF header. Check if a WAVE
			 * magic follows. Set up size to be able to skip
			 * past this header.
			 */
			if (read(f, &riff, sizeof (riff)) != sizeof (riff))
				goto err;
			if (strncmp((char *)riff.wave, WAV_WAVE_MAGIC, 4) != 0)
				goto err;
			size = (off_t)sizeof (riff);

		} else if (strncmp((char *)chunk.ckid, WAV_FMT_MAGIC, 4) == 0) {
			/*
			 * We found WAVE "fmt " header. Check size (if it is
			 * valid for a WAVE file) and coding whether it is
			 * useable for a CD.
			 */
			if (size < (off_t)sizeof (fmt)) goto err;
			if (sizeof (fmt) != read(f, &fmt, sizeof (fmt))) goto err;
			if (le_a_to_u_short(fmt.channels) != 2 ||
			    le_a_to_u_long(fmt.sample_rate) != 44100 ||
			    le_a_to_u_short(fmt.bits_per_sample) != 16) {
				ret = AU_BAD_CODING;
				goto err;
			}
			gotFormat = TRUE;

		} else if (strncmp((char *)chunk.ckid, WAV_DATA_MAGIC, 4) == 0) {
			/*
			 * We found WAVE "data" header. This contains the
			 * size value of the audio part.
			 */
			if (!gotFormat) {
				ret = AU_BAD_CODING;
				goto err;
			}
			if ((cursor + size + sizeof (chunk)) > sb.st_size)
				size = sb.st_size - (cursor  + sizeof (chunk));
			return (size);
		}
		cursor += size + sizeof (chunk);
		lseek(f, cursor, SEEK_SET);	/* Skip over current chunk */
	}
err:
	lseek(f, (off_t)0L, SEEK_SET);
	return (ret);
}
Пример #13
0
static void
statmodeprint(mode_t mode, char *outbuf, int flags)
{
    if (flags & STF_RAW) {
	sprintf(outbuf, (flags & STF_OCTAL) ? "0%lo" : "%lu",
		(unsigned long)mode);
	if (flags & STF_STRING)
	    strcat(outbuf, " (");
    }
    if (flags & STF_STRING) {
	static const char *modes = "?rwxrwxrwx";
#ifdef __CYGWIN__
	static mode_t mflags[9] = { 0 };
#else
	static const mode_t mflags[9] = {
	    S_IRUSR, S_IWUSR, S_IXUSR,
	    S_IRGRP, S_IWGRP, S_IXGRP,
	    S_IROTH, S_IWOTH, S_IXOTH
	};
#endif
	const mode_t *mfp = mflags;
	char pm[11];
	int i;

#ifdef __CYGWIN__
	if (mflags[0] == 0) {
	    mflags[0] = S_IRUSR;
	    mflags[1] = S_IWUSR;
	    mflags[2] = S_IXUSR;
	    mflags[3] = S_IRGRP;
	    mflags[4] = S_IWGRP;
	    mflags[5] = S_IXGRP;
	    mflags[6] = S_IROTH;
	    mflags[7] = S_IWOTH;
	    mflags[8] = S_IXOTH;
	}
#endif

	if (S_ISBLK(mode))
	    *pm = 'b';
	else if (S_ISCHR(mode))
	    *pm = 'c';
	else if (S_ISDIR(mode))
	    *pm = 'd';
	else if (S_ISDOOR(mode))
	    *pm = 'D';
	else if (S_ISFIFO(mode))
	    *pm = 'p';
	else if (S_ISLNK(mode))
	    *pm = 'l';
	else if (S_ISMPC(mode))
	    *pm = 'm';
	else if (S_ISNWK(mode))
	    *pm = 'n';
	else if (S_ISOFD(mode))
	    *pm = 'M';
	else if (S_ISOFL(mode))
	    *pm = 'M';
	else if (S_ISREG(mode))
	    *pm = '-';
	else if (S_ISSOCK(mode))
	    *pm = 's';
	else
	    *pm = '?';

	for (i = 1; i <= 9; i++)
	    pm[i] = (mode & *mfp++) ? modes[i] : '-';
	pm[10] = '\0';

	if (mode & S_ISUID)
	    pm[3] = (mode & S_IXUSR) ? 's' : 'S';
	if (mode & S_ISGID)
	    pm[6] = (mode & S_IXGRP) ? 's' : 'S';
	if (mode & S_ISVTX)
	    pm[9] = (mode & S_IXOTH) ? 't' : 'T';

	pm[10] = 0;
	strcat(outbuf, pm);
	if (flags & STF_RAW)
	    strcat(outbuf, ")");
    }
}
Пример #14
0
void
dir_crawl(GTree *t, GHashTable *linkhash, GHashTable *userhash,
		GHashTable *grouphash, char *path)
{
	DIR 		*dir;
	struct dirent 	*dent;
	struct rdup     *directory;
        struct chown_pack *cp;
	char 		*curpath;
	gchar		*lnk;
	struct stat   	s;
	struct rdup     pop;
	struct remove_path rp;
	dev_t 		current_dev;
	size_t 		curpath_len;

	/* dir stack */
	gint32 d = 0;
	gint32 dstack_cnt  = 1;
	struct rdup **dirstack =
		g_malloc(dstack_cnt * D_STACKSIZE * sizeof(struct rdup *));

	if (!(dir = opendir(path))) {
		/* non-dirs are also allowed, check for this, if it isn't give the error */
		if (access(path, R_OK) == 0) {
			g_free(dirstack);
			return;
		}
		msg(_("Cannot enter directory `%s\': %s"), path, strerror(errno));
		g_free(dirstack);
		return;
	}

	/* get device */
#ifdef HAVE_DIRFD
	if (fstat(dirfd(dir), &s) != 0) {
#else
	if (fstat(rdup_dirfd(dir), &s) != 0) {
#endif
		msg(_("Cannot determine holding device of the directory `%s\': %s"), path,
				strerror(errno));
		closedir(dir);
		g_free(dirstack);
		return;
	}
	current_dev = s.st_dev;

	while((dent = readdir(dir))) {
		if (!strcmp(dent->d_name, ".") ||
				!strcmp(dent->d_name, ".."))
			continue;

                if (opt_chown) {
                        if ( !strncmp(dent->d_name, USRGRPINFO, LEN_USRGRPINFO) ) {
                                continue;
                        }
                }

		if (strcmp(path, "/") == 0)  {
			curpath = g_strdup_printf("/%s", dent->d_name);
			curpath_len = strlen(curpath);
		} else {
			curpath = g_strdup_printf("%s/%s", path, dent->d_name);
			curpath_len = strlen(curpath);
		}

		if (lstat(curpath, &s) != 0) {
			msg(_("Could not stat path `%s\': %s"), curpath, strerror(errno));
			g_free(curpath);
			continue;
		}

		if (strchr(curpath, '\n')) {
			msg(_("Newline (\\n) found in path `%s\', skipping"), curpath);
			g_free(curpath);
			continue;
		}

		if (S_ISREG(s.st_mode) || S_ISLNK(s.st_mode) ||
				S_ISBLK(s.st_mode) || S_ISCHR(s.st_mode) ||
				S_ISFIFO(s.st_mode) || S_ISSOCK(s.st_mode) ) {

			pop.f_name      = curpath;
			pop.f_target	= NULL;
			pop.f_name_size = curpath_len;
			pop.f_uid       = s.st_uid;
			pop.f_user      = lookup_user(userhash, pop.f_uid);
			pop.f_gid       = s.st_gid;
			pop.f_group     = lookup_group(grouphash, pop.f_gid);
			pop.f_ctime     = s.st_ctime;
			pop.f_mtime     = s.st_mtime;
			pop.f_atime     = s.st_atime;
			pop.f_mode      = s.st_mode;
			pop.f_size      = s.st_size;
			pop.f_dev       = s.st_dev;
			pop.f_rdev      = s.st_rdev;
			pop.f_ino       = s.st_ino;
			pop.f_lnk	= 0;

			if (gfunc_regexp(pregex_list, curpath, curpath_len)) {
				g_free(curpath);
				continue;
			}

			if (opt_nobackup && !strcmp(dent->d_name, NOBACKUP)) {
				/* return after seeing .nobackup */
				if (opt_verbose > 0) {
					msg(_("%s found in '%s\'"), NOBACKUP, path);
				}
				/* remove all files found in this path */
				rp.tree = t;
				rp.len  = strlen(path);
				rp.path = path;
				g_tree_foreach(t, gfunc_remove_path, (gpointer)&rp);
				/* add .nobackup back in */
				g_tree_insert(t, (gpointer) entry_dup(&pop), VALUE);
				g_free(dirstack);
				closedir(dir);
				return;
			}

			/* hardlinks */
			if (s.st_nlink > 1) {
				if ((lnk = hlink(linkhash, &pop))) {
					pop.f_target = lnk;
					pop.f_lnk  = 1;
				}
			}
			if (S_ISLNK(s.st_mode))
				pop.f_target = slink(&pop);


			if (S_ISLNK(s.st_mode) || pop.f_lnk) {
				/* fix the name and the sizes */
				pop.f_size = pop.f_name_size;
				pop.f_name_size += 4 + strlen(pop.f_target);
			}
                        /* check for USRGRPINFO file */
                        if ( opt_chown && (cp = chown_parse(path, dent->d_name)) != NULL ) {
                                pop.f_uid = cp->u;
                                pop.f_gid = cp->g;
                                pop.f_user = cp->user;
                                pop.f_group = cp->group;
                        }
			g_tree_insert(t, (gpointer) entry_dup(&pop), VALUE);

			if (pop.f_target != NULL)
				g_free(pop.f_target);
			g_free(curpath);
			continue;
		} else if(S_ISDIR(s.st_mode)) {
			/* one filesystem */
			if (opt_onefilesystem && s.st_dev != current_dev) {
				msg(_("Not walking into different filesystem `%s\'"), curpath);
				g_free(curpath);
				continue;
			}
			/* Exclude list */
			if (gfunc_regexp(pregex_list, curpath, curpath_len)) {
				g_free(curpath);
				continue;
			}
			dirstack[d] = g_malloc(sizeof(struct rdup));
			dirstack[d]->f_name       = g_strdup(curpath);
			dirstack[d]->f_target	  = NULL;
			dirstack[d]->f_name_size  = curpath_len;
			dirstack[d]->f_uid	  = s.st_uid;
			dirstack[d]->f_user	  = lookup_user(userhash, s.st_uid);
			dirstack[d]->f_gid        = s.st_gid;
			dirstack[d]->f_group      = lookup_group(grouphash, s.st_gid);
			dirstack[d]->f_ctime      = s.st_ctime;
			dirstack[d]->f_mtime      = s.st_mtime;
			dirstack[d]->f_atime      = s.st_atime;
			dirstack[d]->f_mode       = s.st_mode;
			dirstack[d]->f_size       = s.st_size;
			dirstack[d]->f_dev        = s.st_dev;
			dirstack[d]->f_rdev       = s.st_rdev;
			dirstack[d]->f_ino        = s.st_ino;
			dirstack[d]->f_lnk        = 0;

                        /* check for USRGRPINFO file */
                        if ( opt_chown && (cp = chown_parse(curpath, NULL)) != NULL ) {
                                dirstack[d]->f_uid = cp->u;
                                dirstack[d]->f_gid = cp->g;
                                dirstack[d]->f_user = cp->user;
                                dirstack[d]->f_group = cp->group;
                        }

			if (d++ % D_STACKSIZE == 0) {
				dirstack = g_realloc(dirstack,
						++dstack_cnt * D_STACKSIZE *
						sizeof(struct rdup *));
			}
			g_free(curpath);
			continue;
		} else {
			if (opt_verbose > 0) {
				msg(_("Neither file nor directory `%s\'"), curpath);
			}
			g_free(curpath);
		}
	}
	closedir(dir);
	if (opt_atime) {
		/* reset dirs atime */
		if (d > 0 && opt_atime) {
			struct utimbuf ut;
			ut.actime  = dirstack[d - 1]->f_atime;
			ut.modtime = dirstack[d - 1]->f_mtime;
			if (utime(dirstack[d - 1]->f_name, &ut) == -1)
				msg(_("Failed to reset atime: '%s\': %s"), dirstack[d - 1]->f_name, strerror(errno));
		}
	}

	while (d > 0) {
		directory = dirstack[--d];
		g_tree_insert(t, (gpointer) entry_dup(directory), VALUE);
		/* recurse */
		/* potentially expensive operation. Better would be to when we hit
		 * .nobackup to go up the tree and delete some nodes.... or not */
		dir_crawl(t, linkhash, userhash, grouphash, directory->f_name);
		entry_free(directory);
	}
	g_free(dirstack);
	return;
}
Пример #15
0
int is_blkdev(int fd)
{
	struct stat st;
	return (fstat(fd, &st) == 0 && S_ISBLK(st.st_mode));
}
int do_sync_pull(const char *rpath, const char *lpath)
{
    unsigned mode;
    struct stat st;

    int fd;

    fd = sdb_connect("sync:");
    if(fd < 0) {
        fprintf(stderr,"error: %s\n", sdb_error());
        return 1;
    }

    if(sync_readmode(fd, rpath, &mode)) {
        return 1;
    }
    if(mode == 0) {
        fprintf(stderr,"remote object '%s' does not exist\n", rpath);
        return 1;
    }

    if(S_ISREG(mode) || S_ISLNK(mode) || S_ISCHR(mode) || S_ISBLK(mode)) {
        if(stat(lpath, &st) == 0) {
            if(S_ISDIR(st.st_mode)) {
                    /* if we're copying a remote file to a local directory,
                    ** we *really* want to copy to localdir + "/" + remotefilename
                    */
                const char *name = sdb_dirstop(rpath);
                if(name == 0) {
                    name = rpath;
                } else {
                    name++;
                }
                int  tmplen = strlen(name) + strlen(lpath) + 2;
                char *tmp = malloc(tmplen);
                if(tmp == 0) return 1;
                snprintf(tmp, tmplen, "%s/%s", lpath, name);
                lpath = tmp;
            }
        }
        BEGIN();
        if(sync_recv(fd, rpath, lpath)) {
            return 1;
        } else {
            END();
            sync_quit(fd);
            return 0;
        }
    } else if(S_ISDIR(mode)) {
        BEGIN();
        if (copy_remote_dir_local(fd, rpath, lpath, 0)) {
            return 1;
        } else {
            END();
            sync_quit(fd);
            return 0;
        }
    } else {
        fprintf(stderr,"remote object '%s' not a file or directory\n", rpath);
        return 1;
    }
}
Пример #17
0
/* get size in bytes */
int
blkdev_get_size(int fd, unsigned long long *bytes)
{
#ifdef DKIOCGETBLOCKCOUNT
	/* Apple Darwin */
	if (ioctl(fd, DKIOCGETBLOCKCOUNT, bytes) >= 0) {
		*bytes <<= 9;
		return 0;
	}
#endif

#ifdef BLKGETSIZE64
	{
#ifdef __linux__
		int ver = get_linux_version();

		/* kernels 2.4.15-2.4.17, had a broken BLKGETSIZE64 */
		if (ver >= KERNEL_VERSION (2,6,0) ||
		   (ver >= KERNEL_VERSION (2,4,18) && ver < KERNEL_VERSION (2,5,0)))
#endif
			if (ioctl(fd, BLKGETSIZE64, bytes) >= 0)
				return 0;
	}
#endif /* BLKGETSIZE64 */

#ifdef BLKGETSIZE
	{
		unsigned long size;

		if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
			*bytes = ((unsigned long long)size << 9);
			return 0;
		}
	}

#endif /* BLKGETSIZE */

#ifdef DIOCGMEDIASIZE
	/* FreeBSD */
	if (ioctl(fd, DIOCGMEDIASIZE, bytes) >= 0)
		return 0;
#endif

#ifdef FDGETPRM
	{
		struct floppy_struct this_floppy;

		if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
			*bytes = ((unsigned long long) this_floppy.size) << 9;
			return 0;
		}
	}
#endif /* FDGETPRM */

#if defined(HAVE_SYS_DISKLABEL_H) && defined(DIOCGDINFO)
	{
		/*
		 * 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.
		 */
		int part = -1;
		struct disklabel lab;
		struct partition *pp;
		struct stat st;

		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) {
				 *bytes = pp->p_size << 9;
				 return 0;
			}
		}
	}
#endif /* defined(HAVE_SYS_DISKLABEL_H) && defined(DIOCGDINFO) */

	{
		struct stat st;

		if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
			*bytes = st.st_size;
			return 0;
		}
		if (!S_ISBLK(st.st_mode))
			return -1;
	}

	*bytes = blkdev_find_size(fd);
	return 0;
}
Пример #18
0
int main(int argc, char *argv[])
{
	int  c;
	char * raw_name;
	char * block_name;
	int  err;
	int  block_major, block_minor;
	int  i, rc;

	struct stat statbuf;

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

	progname = argv[0];

	while ((c = getopt(argc, argv, "ahq")) != -1) {
		switch (c) {
		case 'a':
			do_query_all = 1;
			break;
		case 'h':
			usage(0);
		case 'q':
			do_query = 1;
			break;
		default:
			usage(1);
		}
	}

	/*
	 * Check for, and open, the master raw device, /dev/raw
	 */

	open_raw_ctl();

	if (do_query_all) {
		if (optind < argc)
			usage(1);
		for (i = 1; i < RAW_NR_MINORS; i++)
			query(i, NULL, 1);
		exit(0);
	}

	/*
	 * It's a bind or a single query.  Either way we need a raw device.
	 */

	if (optind >= argc)
		usage(1);
	raw_name = argv[optind++];

	/*
	 * try to check the device name before stat(), because on systems with
	 * udev the raw0 causes a create udev event for char 162/0, which
	 * causes udev to *remove* /dev/rawctl
	 */
	rc = sscanf(raw_name, RAWDEVDIR "raw%d", &raw_minor);
	if (rc != 1)
		usage(1);

	if (raw_minor == 0) {
		fprintf (stderr,
			_("Device '%s' is the control raw device "
			"(use raw<N> where <N> is greater than zero)\n"),
			raw_name);
		exit(2);
	}

	if (do_query)
		return query(raw_minor, raw_name, 0);

	/*
	 * It's not a query, so we still have some parsing to do.  Have
	 * we been given a block device filename or a major/minor pair?
	 */

	switch (argc - optind) {
	case 1:
		block_name = argv[optind];
		err = stat(block_name, &statbuf);
		if (err) {
			fprintf (stderr,
				 _("Cannot locate block device '%s' (%s)\n"),
				 block_name, strerror(errno));
			exit(2);
		}

		if (!S_ISBLK(statbuf.st_mode)) {
			fprintf (stderr, _("Device '%s' is not a block device\n"),
				 block_name);
			exit(2);
		}

		block_major = major(statbuf.st_rdev);
		block_minor = minor(statbuf.st_rdev);
		break;

	case 2:
		block_major = strtol(argv[optind], 0, 0);
		block_minor = strtol(argv[optind+1], 0, 0);
		break;

	default:
		block_major = block_minor = 0; /* just to keep gcc happy */
		usage(1);
	}

	return bind(raw_minor, block_major, block_minor);
	return 0;

}
Пример #19
0
/*****************************************************************************
 * ioctl_Open: Opens a VCD device or file and returns an opaque handle
 *****************************************************************************/
vcddev_t *ioctl_Open( vlc_object_t *p_this, const char *psz_dev )
{
    int i_ret;
    int b_is_file;
    vcddev_t *p_vcddev;
#if !defined( WIN32 ) && !defined( __OS2__ )
    struct stat fileinfo;
#endif

    if( !psz_dev ) return NULL;

    /*
     *  Initialize structure with default values
     */
    p_vcddev = malloc( sizeof(*p_vcddev) );
    if( p_vcddev == NULL )
        return NULL;
    p_vcddev->i_vcdimage_handle = -1;
    p_vcddev->psz_dev = NULL;
    b_is_file = 1;

    /*
     *  Check if we are dealing with a device or a file (vcd image)
     */
#if defined( WIN32 ) || defined( __OS2__ )
    if( (strlen( psz_dev ) == 2 && psz_dev[1] == ':') )
    {
        b_is_file = 0;
    }

#else
    if( vlc_stat( psz_dev, &fileinfo ) < 0 )
    {
        free( p_vcddev );
        return NULL;
    }

    /* Check if this is a block/char device */
    if( S_ISBLK( fileinfo.st_mode ) || S_ISCHR( fileinfo.st_mode ) )
        b_is_file = 0;
#endif

    if( b_is_file )
    {
        i_ret = OpenVCDImage( p_this, psz_dev, p_vcddev );
    }
    else
    {
        /*
         *  open the vcd device
         */

#ifdef WIN32
        i_ret = win32_vcd_open( p_this, psz_dev, p_vcddev );
#elif defined( __OS2__ )
        i_ret = os2_vcd_open( p_this, psz_dev, p_vcddev );
#else
        p_vcddev->i_device_handle = -1;
        p_vcddev->i_device_handle = vlc_open( psz_dev, O_RDONLY | O_NONBLOCK );
        i_ret = (p_vcddev->i_device_handle == -1) ? -1 : 0;
#endif
    }

    if( i_ret == 0 )
    {
        p_vcddev->psz_dev = (char *)strdup( psz_dev );
    }
    else
    {
        free( p_vcddev );
        p_vcddev = NULL;
    }

    return p_vcddev;
}
Пример #20
0
int fuse_valid_type(int m)
{
	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
}
Пример #21
0
int
test_eval(Test_env *te, Test_op op, const char *opnd1, const char *opnd2,
    int do_eval)
{
	int res;
	int not;
	struct stat b1, b2;

	if (!do_eval)
		return 0;

	switch ((int) op) {
	/*
	 * Unary Operators
	 */
	case TO_STNZE: /* -n */
		return *opnd1 != '\0';
	case TO_STZER: /* -z */
		return *opnd1 == '\0';
	case TO_OPTION: /* -o */
		if ((not = *opnd1 == '!'))
			opnd1++;
		if ((res = option(opnd1)) < 0)
			res = 0;
		else {
			res = Flag(res);
			if (not)
				res = !res;
		}
		return res;
	case TO_FILRD: /* -r */
		return test_eaccess(opnd1, R_OK) == 0;
	case TO_FILWR: /* -w */
		return test_eaccess(opnd1, W_OK) == 0;
	case TO_FILEX: /* -x */
		return test_eaccess(opnd1, X_OK) == 0;
	case TO_FILAXST: /* -a */
		return test_stat(opnd1, &b1) == 0;
	case TO_FILEXST: /* -e */
		/* at&t ksh does not appear to do the /dev/fd/ thing for
		 * this (unless the os itself handles it)
		 */
		return stat(opnd1, &b1) == 0;
	case TO_FILREG: /* -r */
		return test_stat(opnd1, &b1) == 0 && S_ISREG(b1.st_mode);
	case TO_FILID: /* -d */
		return test_stat(opnd1, &b1) == 0 && S_ISDIR(b1.st_mode);
	case TO_FILCDEV: /* -c */
		return test_stat(opnd1, &b1) == 0 && S_ISCHR(b1.st_mode);
	case TO_FILBDEV: /* -b */
		return test_stat(opnd1, &b1) == 0 && S_ISBLK(b1.st_mode);
	case TO_FILFIFO: /* -p */
		return test_stat(opnd1, &b1) == 0 && S_ISFIFO(b1.st_mode);
	case TO_FILSYM: /* -h -L */
		return lstat(opnd1, &b1) == 0 && S_ISLNK(b1.st_mode);
	case TO_FILSOCK: /* -S */
		return test_stat(opnd1, &b1) == 0 && S_ISSOCK(b1.st_mode);
	case TO_FILCDF:/* -H HP context dependent files (directories) */
		return 0;
	case TO_FILSETU: /* -u */
		return test_stat(opnd1, &b1) == 0 &&
		    (b1.st_mode & S_ISUID) == S_ISUID;
	case TO_FILSETG: /* -g */
		return test_stat(opnd1, &b1) == 0 &&
		    (b1.st_mode & S_ISGID) == S_ISGID;
	case TO_FILSTCK: /* -k */
		return test_stat(opnd1, &b1) == 0 &&
		    (b1.st_mode & S_ISVTX) == S_ISVTX;
	case TO_FILGZ: /* -s */
		return test_stat(opnd1, &b1) == 0 && b1.st_size > 0L;
	case TO_FILTT: /* -t */
		if (opnd1 && !bi_getn(opnd1, &res)) {
			te->flags |= TEF_ERROR;
			res = 0;
		} else {
			/* generate error if in FPOSIX mode? */
			res = isatty(opnd1 ? res : 0);
		}
		return res;
	case TO_FILUID: /* -O */
		return test_stat(opnd1, &b1) == 0 && b1.st_uid == ksheuid;
	case TO_FILGID: /* -G */
		return test_stat(opnd1, &b1) == 0 && b1.st_gid == getegid();
	/*
	 * Binary Operators
	 */
	case TO_STEQL: /* = */
		if (te->flags & TEF_DBRACKET)
			return gmatch(opnd1, opnd2, false);
		return strcmp(opnd1, opnd2) == 0;
	case TO_STNEQ: /* != */
		if (te->flags & TEF_DBRACKET)
			return !gmatch(opnd1, opnd2, false);
		return strcmp(opnd1, opnd2) != 0;
	case TO_STLT: /* < */
		return strcmp(opnd1, opnd2) < 0;
	case TO_STGT: /* > */
		return strcmp(opnd1, opnd2) > 0;
	case TO_INTEQ: /* -eq */
	case TO_INTNE: /* -ne */
	case TO_INTGE: /* -ge */
	case TO_INTGT: /* -gt */
	case TO_INTLE: /* -le */
	case TO_INTLT: /* -lt */
		{
			long v1, v2;

			if (!evaluate(opnd1, &v1, KSH_RETURN_ERROR, false) ||
			    !evaluate(opnd2, &v2, KSH_RETURN_ERROR, false)) {
				/* error already printed.. */
				te->flags |= TEF_ERROR;
				return 1;
			}
			switch ((int) op) {
			case TO_INTEQ:
				return v1 == v2;
			case TO_INTNE:
				return v1 != v2;
			case TO_INTGE:
				return v1 >= v2;
			case TO_INTGT:
				return v1 > v2;
			case TO_INTLE:
				return v1 <= v2;
			case TO_INTLT:
				return v1 < v2;
			}
		}
	case TO_FILNT: /* -nt */
		{
			int s2;
			/* ksh88/ksh93 succeed if file2 can't be stated
			 * (subtly different from `does not exist').
			 */
			return stat(opnd1, &b1) == 0 &&
			    (((s2 = stat(opnd2, &b2)) == 0 &&
			    b1.st_mtime > b2.st_mtime) || s2 < 0);
		}
	case TO_FILOT: /* -ot */
		{
			int s1;
			/* ksh88/ksh93 succeed if file1 can't be stated
			 * (subtly different from `does not exist').
			 */
			return stat(opnd2, &b2) == 0 &&
			    (((s1 = stat(opnd1, &b1)) == 0 &&
			    b1.st_mtime < b2.st_mtime) || s1 < 0);
		}
	case TO_FILEQ: /* -ef */
		return stat (opnd1, &b1) == 0 && stat (opnd2, &b2) == 0 &&
		    b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino;
	}
	(*te->error)(te, 0, "internal error: unknown op");
	return 1;
}
Пример #22
0
dvd_reader_t *DVDOpen( const char *path )
{
  struct stat fileinfo;
  int ret, have_css;
  char *dev_name = NULL;
  int internal_errno = 0;
  int verbose;

  if( path == NULL ) {
    errno = EINVAL;
    return NULL;
  }
  
  verbose = get_verbose();

#ifdef WIN32
  /* Stat doesn't work on devices under mingwin/cygwin. */
  if( path[0] && path[1] == ':' && path[2] == '\0' )
    {
      /* Don't try to stat the file */
      fileinfo.st_mode = S_IFBLK;
    }
  else
#endif
    {
      ret = stat( path, &fileinfo );
      if( ret < 0 ) {
        int tmp_errno = errno;
        /* If we can't stat the file, give up */
        if(verbose >= 1) {
          fprintf( stderr, "libdvdread: Can't stat '%s': %s\n",
                   path, strerror(errno));
        }
        errno = tmp_errno;
        return NULL;
      }
    }

  /* Try to open libdvdcss or fall back to standard functions */
  have_css = dvdinput_setup();

  /* First check if this is a block/char device or a file*/
  if( S_ISBLK( fileinfo.st_mode ) || 
      S_ISCHR( fileinfo.st_mode ) || 
      S_ISREG( fileinfo.st_mode ) ) {
    /**
     * Block devices and regular files are assumed to be DVD-Video images.
     */
    dvd_reader_t *dvd = NULL;
#if defined(__sun)
    dev_name = sun_block2char( path );
#elif defined(SYS_BSD)
    dev_name = bsd_block2char( path );
#else
    dev_name = strdup( path );
#endif
    dvd = DVDOpenImageFile( dev_name, have_css );
    free( dev_name );
    
    return dvd;
  } else if( S_ISDIR( fileinfo.st_mode ) ) {
    dvd_reader_t *auth_drive = 0;
    char *path_copy;
#if defined(SYS_BSD)
    struct fstab* fe;
#elif defined(__sun) || defined(__linux__)
    FILE *mntfile;
#endif

    /* XXX: We should scream real loud here. */
    if( !(path_copy = strdup( path ) ) ) return 0;

#ifndef WIN32 /* don't have fchdir, and getcwd( NULL, ... ) is strange */
    /* Resolve any symlinks and get the absolut dir name. */
    {
      char *new_path;
      char *current_path;

      current_path = malloc(PATH_MAX);
      if(current_path) {
        if(!getcwd(current_path, PATH_MAX)) {
          free(current_path);
          current_path = NULL;
        }
      }
      if(current_path) {
        chdir( path_copy );
        new_path = malloc(PATH_MAX);
        if(new_path) {
          if(!getcwd(new_path, PATH_MAX )) {
            free(new_path);
            new_path = NULL;
          }
        }

        chdir(current_path);
        free(current_path);
        if( new_path ) {
          free( path_copy );
          path_copy = new_path;
        }
      }
    }
#endif
        
    /**
     * If we're being asked to open a directory, check if that directory
     * is the mountpoint for a DVD-ROM which we can use instead.
     */

    if( strlen( path_copy ) > 1 ) {
      if( path_copy[ strlen( path_copy ) - 1 ] == '/' ) {
        path_copy[ strlen( path_copy ) - 1 ] = '\0';
      }
    }

    if( strlen( path_copy ) >= 9 ) {
      if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]), 
                       "/video_ts" ) ) {
        path_copy[ strlen( path_copy ) - 9 ] = '\0';
        if(path_copy[0] == '\0') {
          path_copy[0] = '/';
          path_copy[1] = '\0';
        }
      }
    }

#if defined(SYS_BSD)
    if( ( fe = getfsfile( path_copy ) ) ) {
      dev_name = bsd_block2char( fe->fs_spec );
      if(verbose >= 1) {
        fprintf( stderr,
                 "libdvdread: Attempting to use device %s"
                 " mounted on %s%s\n",
                 dev_name,
                 fe->fs_file,
                 have_css ? " for CSS authentication" : "");
      }
      auth_drive = DVDOpenImageFile( dev_name, have_css );
      if(!auth_drive) {
        internal_errno = errno;
      }
    }
#elif defined(__sun)
    mntfile = fopen( MNTTAB, "r" );
    if( mntfile ) {
      struct mnttab mp;
      int res;
      
      while( ( res = getmntent( mntfile, &mp ) ) != -1 ) {
        if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) {
          dev_name = sun_block2char( mp.mnt_special );
          if(verbose >= 1) {
            fprintf( stderr, 
                     "libdvdread: Attempting to use device %s"
                     " mounted on %s%s\n",
                     dev_name,
                     mp.mnt_mountp,
                     have_css ? " for CSS authentication" : "");
          }
          auth_drive = DVDOpenImageFile( dev_name, have_css );
          if(!auth_drive) {
            internal_errno = errno;
          }
          break;
        }
      }
      fclose( mntfile );
    }
#elif defined(__linux__)
    mntfile = fopen( MOUNTED, "r" );
    if( mntfile ) {
      struct mntent *me;
 
      while( ( me = getmntent( mntfile ) ) ) {
        if( !strcmp( me->mnt_dir, path_copy ) ) {
          if(verbose >= 1) {
            fprintf( stderr, 
                     "libdvdread: Attempting to use device %s"
                     " mounted on %s%s\n",
                     me->mnt_fsname,
                     me->mnt_dir,
                     have_css ? " for CSS authentication" : "");
          }
          auth_drive = DVDOpenImageFile( me->mnt_fsname, have_css );
          if(!auth_drive) {
            internal_errno = errno;
          }
          dev_name = strdup(me->mnt_fsname);
          break;
        }
      }
      fclose( mntfile );
    }
#endif
    if( !dev_name ) {
      if(verbose >= 1) {
        fprintf( stderr, "libdvdread: Couldn't find device name.\n" );
      }
    } else if( !auth_drive ) {
      if(verbose >= 1) {
        fprintf( stderr, "libdvdread: Device %s inaccessible%s: %s\n",
                 dev_name,
                 have_css ? ", CSS authentication not available" : "",
                 strerror(internal_errno));
      }
    }

    free( dev_name );
    free( path_copy );

    /**
     * If we've opened a drive, just use that.
     */
    if( auth_drive ) {
      return auth_drive;
    }
    /**
     * Otherwise, we now try to open the directory tree instead.
     */
    return DVDOpenPath( path );
  }

  /* If it's none of the above, screw it. */
  if(verbose >= 1) {
    fprintf( stderr, "libdvdread: Could not open %s\n", path );
  }
  return 0;
}
Пример #23
0
int do_create (ext2_filsys e2fs, const char *path, mode_t mode, dev_t dev, const char *fastsymlink)
{
	int rt;
	time_t tm;
	errcode_t rc;

	char *p_path;
	char *r_path;

	ext2_ino_t ino;
	struct ext2_inode inode;
	ext2_ino_t n_ino;

	struct fuse_context *ctx;

	debugf("enter");
	debugf("path = %s, mode: 0%o", path, mode);

	rt=do_check_split(path, &p_path, &r_path);

	debugf("parent: %s, child: %s", p_path, r_path);

	rt = do_readinode(e2fs, p_path, &ino, &inode);
	if (rt) {
		debugf("do_readinode(%s, &ino, &inode); failed", p_path);
		free_split(p_path, r_path);
		return rt;
	}

	rc = ext2fs_new_inode(e2fs, ino, mode, 0, &n_ino);
	if (rc) {
		debugf("ext2fs_new_inode(ep.fs, ino, mode, 0, &n_ino); failed");
		return -ENOMEM;
	}

	do {
		debugf("calling ext2fs_link(e2fs, %d, %s, %d, %d);", ino, r_path, n_ino, do_modetoext2lag(mode));
		rc = ext2fs_link(e2fs, ino, r_path, n_ino, do_modetoext2lag(mode));
		if (rc == EXT2_ET_DIR_NO_SPACE) {
			debugf("calling ext2fs_expand_dir(e2fs, &d)", ino);
			if (ext2fs_expand_dir(e2fs, ino)) {
				debugf("error while expanding directory %s (%d)", p_path, ino);
				free_split(p_path, r_path);
				return -ENOSPC;
			}
		}
	} while (rc == EXT2_ET_DIR_NO_SPACE);
	if (rc) {
		debugf("ext2fs_link(e2fs, %d, %s, %d, %d); failed", ino, r_path, n_ino, do_modetoext2lag(mode));
		free_split(p_path, r_path);
		return -EIO;
	}

	if (ext2fs_test_inode_bitmap(e2fs->inode_map, n_ino)) {
		debugf("inode already set");
	}

	ext2fs_inode_alloc_stats2(e2fs, n_ino, +1, 0);
	memset(&inode, 0, sizeof(inode));
	tm = e2fs->now ? e2fs->now : time(NULL);
	inode.i_mode = mode;
	inode.i_atime = inode.i_ctime = inode.i_mtime = tm;
	inode.i_links_count = 1;
	inode.i_size = 0;
	ctx = fuse_get_context();
	if (ctx) {
		inode.i_uid = ctx->uid;
		inode.i_gid = ctx->gid;
	}

	if (S_ISCHR(mode) || S_ISBLK(mode)) {
		if (old_valid_dev(dev))
			inode.i_block[0]= ext2fs_cpu_to_le32(old_encode_dev(dev));
		else
			inode.i_block[1]= ext2fs_cpu_to_le32(new_encode_dev(dev));
	}

	if (S_ISLNK(mode) && fastsymlink != NULL) {
		inode.i_size = strlen(fastsymlink);
		strncpy((char *)&(inode.i_block[0]),fastsymlink,
				(EXT2_N_BLOCKS * sizeof(inode.i_block[0])));
	}

	rc = ext2fs_write_new_inode(e2fs, n_ino, &inode);
	if (rc) {
		debugf("ext2fs_write_new_inode(e2fs, n_ino, &inode);");
		free_split(p_path, r_path);
		return -EIO;
	}

	/* update parent dir */
	rt = do_readinode(e2fs, p_path, &ino, &inode);
	if (rt) {
		debugf("do_readinode(%s, &ino, &inode); dailed", p_path);
		free_split(p_path, r_path);
		return -EIO;
	}
	inode.i_ctime = inode.i_mtime = tm;
	rc = ext2fs_write_inode(e2fs, ino, &inode);
	if (rc) {
		debugf("ext2fs_write_inode(e2fs, ino, &inode); failed");
		free_split(p_path, r_path);
		return -EIO;
	}

	free_split(p_path, r_path);

	debugf("leave");
	return 0;
}
Пример #24
0
/*
 * Check to see if the special file named 'device' is mounted.
 */
void
check_mtab(const char *device)		/* /dev/hd1 or whatever */
{
#if defined(__minix)
  int n, r;
  struct stat sb;
  char dev[PATH_MAX], mount_point[PATH_MAX],
	type[MNTNAMELEN], flags[MNTFLAGLEN];

  r= stat(device, &sb);
  if (r == -1)
  {
	if (errno == ENOENT)
		return;	/* Does not exist, and therefore not mounted. */
	err(1, "stat %s failed", device);
  }
  if (!S_ISBLK(sb.st_mode))
  {
	/* Not a block device and therefore not mounted. */
	return;
  }

  if (load_mtab(__UNCONST("mkfs")) < 0) return;
  while (1) {
	n = get_mtab_entry(dev, mount_point, type, flags);
	if (n < 0) return;
	if (strcmp(device, dev) == 0) {
		/* Can't mkfs on top of a mounted file system. */
		errx(1, "%s is mounted on %s", device, mount_point);
	}
  }
#elif defined(__linux__)
/* XXX: this code is copyright Theodore T'so and distributed under the GPLv2. Rewrite.
 */
	struct mntent 	*mnt;
	struct stat	st_buf;
	dev_t		file_dev=0, file_rdev=0;
	ino_t		file_ino=0;
	FILE 		*f;
	int		fd;
	char 		*mtab_file = "/proc/mounts";

	if ((f = setmntent (mtab_file, "r")) == NULL)
		goto error;

	if (stat(device, &st_buf) == 0) {
		if (S_ISBLK(st_buf.st_mode)) {
			file_rdev = st_buf.st_rdev;
		} else {
			file_dev = st_buf.st_dev;
			file_ino = st_buf.st_ino;
		}
	}
	
	while ((mnt = getmntent (f)) != NULL) {
		if (strcmp(device, mnt->mnt_fsname) == 0)
			break;
		if (stat(mnt->mnt_fsname, &st_buf) == 0) {
			if (S_ISBLK(st_buf.st_mode)) {
				if (file_rdev && (file_rdev == st_buf.st_rdev))
					break;
			} else {
				if (file_dev && ((file_dev == st_buf.st_dev) &&
						 (file_ino == st_buf.st_ino)))
					break;
			}
		}
	}

	if (mnt == NULL) {
		/*
		 * Do an extra check to see if this is the root device.  We
		 * can't trust /etc/mtab, and /proc/mounts will only list
		 * /dev/root for the root filesystem.  Argh.  Instead we
		 * check if the given device has the same major/minor number
		 * as the device that the root directory is on.
		 */
		if (file_rdev && stat("/", &st_buf) == 0) {
			if (st_buf.st_dev == file_rdev) {
				goto is_root;
			}
		}
		goto test_busy;
	}
	/* Validate the entry in case /etc/mtab is out of date */
	/* 
	 * We need to be paranoid, because some broken distributions
	 * (read: Slackware) don't initialize /etc/mtab before checking
	 * all of the non-root filesystems on the disk.
	 */
	if (stat(mnt->mnt_dir, &st_buf) < 0) {
		if (errno == ENOENT) {
			goto test_busy;
		}
		goto error;
	}
	if (file_rdev && (st_buf.st_dev != file_rdev)) {
		goto error;
	}

	fprintf(stderr, "Device %s is mounted, exiting\n", device);
	exit(-1);

	/*
	 * Check to see if we're referring to the root filesystem.
	 * If so, do a manual check to see if we can open /etc/mtab
	 * read/write, since if the root is mounted read/only, the
	 * contents of /etc/mtab may not be accurate.
	 */
	if (!strcmp(mnt->mnt_dir, "/")) {
is_root:
		fprintf(stderr, "Device %s is mounted as root file system!\n",
				device);
		exit(-1);
	}
	
test_busy:

	endmntent (f);
	if ((stat(device, &st_buf) != 0) ||
			!S_ISBLK(st_buf.st_mode))
		return;
	fd = open(device, O_RDONLY | O_EXCL);
	if (fd < 0) {
		if (errno == EBUSY) {
			fprintf(stderr, "Device %s is used by the system\n", device);
			exit(-1);
		}
	} else
		close(fd);

	return;

error:
	endmntent (f);
	fprintf(stderr, "Error while checking if device %s is mounted\n", device);
	exit(-1);
#else
	(void) device;	/* shut up warnings about unused variable... */
#endif
}
Пример #25
0
static int
nfs_proc_lookup(struct inode *dir, struct qstr *name,
		struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
	struct nfs_diropargs	arg = {
		.fh		= NFS_FH(dir),
		.name		= name->name,
		.len		= name->len
	};
	struct nfs_diropok	res = {
		.fh		= fhandle,
		.fattr		= fattr
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_LOOKUP],
		.rpc_argp	= &arg,
		.rpc_resp	= &res,
	};
	int			status;

	dprintk("NFS call  lookup %s\n", name->name);
	nfs_fattr_init(fattr);
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	dprintk("NFS reply lookup: %d\n", status);
	return status;
}

static int nfs_proc_readlink(struct inode *inode, struct page *page,
		unsigned int pgbase, unsigned int pglen)
{
	struct nfs_readlinkargs	args = {
		.fh		= NFS_FH(inode),
		.pgbase		= pgbase,
		.pglen		= pglen,
		.pages		= &page
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_READLINK],
		.rpc_argp	= &args,
	};
	int			status;

	dprintk("NFS call  readlink\n");
	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
	dprintk("NFS reply readlink: %d\n", status);
	return status;
}

static int
nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
		int flags, struct nameidata *nd)
{
	struct nfs_fh		fhandle;
	struct nfs_fattr	fattr;
	struct nfs_createargs	arg = {
		.fh		= NFS_FH(dir),
		.name		= dentry->d_name.name,
		.len		= dentry->d_name.len,
		.sattr		= sattr
	};
	struct nfs_diropok	res = {
		.fh		= &fhandle,
		.fattr		= &fattr
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_CREATE],
		.rpc_argp	= &arg,
		.rpc_resp	= &res,
	};
	int			status;

	nfs_fattr_init(&fattr);
	dprintk("NFS call  create %s\n", dentry->d_name.name);
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	nfs_mark_for_revalidate(dir);
	if (status == 0)
		status = nfs_instantiate(dentry, &fhandle, &fattr);
	dprintk("NFS reply create: %d\n", status);
	return status;
}

/*
 * In NFSv2, mknod is grafted onto the create call.
 */
static int
nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
	       dev_t rdev)
{
	struct nfs_fh fhandle;
	struct nfs_fattr fattr;
	struct nfs_createargs	arg = {
		.fh		= NFS_FH(dir),
		.name		= dentry->d_name.name,
		.len		= dentry->d_name.len,
		.sattr		= sattr
	};
	struct nfs_diropok	res = {
		.fh		= &fhandle,
		.fattr		= &fattr
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_CREATE],
		.rpc_argp	= &arg,
		.rpc_resp	= &res,
	};
	int status, mode;

	dprintk("NFS call  mknod %s\n", dentry->d_name.name);

	mode = sattr->ia_mode;
	if (S_ISFIFO(mode)) {
		sattr->ia_mode = (mode & ~S_IFMT) | S_IFCHR;
		sattr->ia_valid &= ~ATTR_SIZE;
	} else if (S_ISCHR(mode) || S_ISBLK(mode)) {
		sattr->ia_valid |= ATTR_SIZE;
		sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */
	}

	nfs_fattr_init(&fattr);
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	nfs_mark_for_revalidate(dir);

	if (status == -EINVAL && S_ISFIFO(mode)) {
		sattr->ia_mode = mode;
		nfs_fattr_init(&fattr);
		status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	}
	if (status == 0)
		status = nfs_instantiate(dentry, &fhandle, &fattr);
	dprintk("NFS reply mknod: %d\n", status);
	return status;
}
  
static int
nfs_proc_remove(struct inode *dir, struct qstr *name)
{
	struct nfs_removeargs arg = {
		.fh = NFS_FH(dir),
		.name.len = name->len,
		.name.name = name->name,
	};
	struct rpc_message msg = { 
		.rpc_proc = &nfs_procedures[NFSPROC_REMOVE],
		.rpc_argp = &arg,
	};
	int			status;

	dprintk("NFS call  remove %s\n", name->name);
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	nfs_mark_for_revalidate(dir);

	dprintk("NFS reply remove: %d\n", status);
	return status;
}

static void
nfs_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
{
	msg->rpc_proc = &nfs_procedures[NFSPROC_REMOVE];
}

static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir)
{
	if (nfs_async_handle_expired_key(task))
		return 0;
	nfs_mark_for_revalidate(dir);
	return 1;
}

static int
nfs_proc_rename(struct inode *old_dir, struct qstr *old_name,
		struct inode *new_dir, struct qstr *new_name)
{
	struct nfs_renameargs	arg = {
		.fromfh		= NFS_FH(old_dir),
		.fromname	= old_name->name,
		.fromlen	= old_name->len,
		.tofh		= NFS_FH(new_dir),
		.toname		= new_name->name,
		.tolen		= new_name->len
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_RENAME],
		.rpc_argp	= &arg,
	};
	int			status;

	dprintk("NFS call  rename %s -> %s\n", old_name->name, new_name->name);
	status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
	nfs_mark_for_revalidate(old_dir);
	nfs_mark_for_revalidate(new_dir);
	dprintk("NFS reply rename: %d\n", status);
	return status;
}

static int
nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
{
	struct nfs_linkargs	arg = {
		.fromfh		= NFS_FH(inode),
		.tofh		= NFS_FH(dir),
		.toname		= name->name,
		.tolen		= name->len
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_LINK],
		.rpc_argp	= &arg,
	};
	int			status;

	dprintk("NFS call  link %s\n", name->name);
	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
	nfs_mark_for_revalidate(inode);
	nfs_mark_for_revalidate(dir);
	dprintk("NFS reply link: %d\n", status);
	return status;
}

static int
nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
		 unsigned int len, struct iattr *sattr)
{
	struct nfs_fh fhandle;
	struct nfs_fattr fattr;
	struct nfs_symlinkargs	arg = {
		.fromfh		= NFS_FH(dir),
		.fromname	= dentry->d_name.name,
		.fromlen	= dentry->d_name.len,
		.pages		= &page,
		.pathlen	= len,
		.sattr		= sattr
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_SYMLINK],
		.rpc_argp	= &arg,
	};
	int			status;

	if (len > NFS2_MAXPATHLEN)
		return -ENAMETOOLONG;

	dprintk("NFS call  symlink %s\n", dentry->d_name.name);

	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	nfs_mark_for_revalidate(dir);

	/*
	 * V2 SYMLINK requests don't return any attributes.  Setting the
	 * filehandle size to zero indicates to nfs_instantiate that it
	 * should fill in the data with a LOOKUP call on the wire.
	 */
	if (status == 0) {
		nfs_fattr_init(&fattr);
		fhandle.size = 0;
		status = nfs_instantiate(dentry, &fhandle, &fattr);
	}

	dprintk("NFS reply symlink: %d\n", status);
	return status;
}

static int
nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
{
	struct nfs_fh fhandle;
	struct nfs_fattr fattr;
	struct nfs_createargs	arg = {
		.fh		= NFS_FH(dir),
		.name		= dentry->d_name.name,
		.len		= dentry->d_name.len,
		.sattr		= sattr
	};
	struct nfs_diropok	res = {
		.fh		= &fhandle,
		.fattr		= &fattr
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_MKDIR],
		.rpc_argp	= &arg,
		.rpc_resp	= &res,
	};
	int			status;

	dprintk("NFS call  mkdir %s\n", dentry->d_name.name);
	nfs_fattr_init(&fattr);
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	nfs_mark_for_revalidate(dir);
	if (status == 0)
		status = nfs_instantiate(dentry, &fhandle, &fattr);
	dprintk("NFS reply mkdir: %d\n", status);
	return status;
}

static int
nfs_proc_rmdir(struct inode *dir, struct qstr *name)
{
	struct nfs_diropargs	arg = {
		.fh		= NFS_FH(dir),
		.name		= name->name,
		.len		= name->len
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_RMDIR],
		.rpc_argp	= &arg,
	};
	int			status;

	dprintk("NFS call  rmdir %s\n", name->name);
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	nfs_mark_for_revalidate(dir);
	dprintk("NFS reply rmdir: %d\n", status);
	return status;
}

/*
 * The READDIR implementation is somewhat hackish - we pass a temporary
 * buffer to the encode function, which installs it in the receive
 * the receive iovec. The decode function just parses the reply to make
 * sure it is syntactically correct; the entries itself are decoded
 * from nfs_readdir by calling the decode_entry function directly.
 */
static int
nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
		 u64 cookie, struct page *page, unsigned int count, int plus)
{
	struct inode		*dir = dentry->d_inode;
	struct nfs_readdirargs	arg = {
		.fh		= NFS_FH(dir),
		.cookie		= cookie,
		.count		= count,
		.pages		= &page,
	};
	struct rpc_message	msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_READDIR],
		.rpc_argp	= &arg,
		.rpc_cred	= cred,
	};
	int			status;

	dprintk("NFS call  readdir %d\n", (unsigned int)cookie);
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);

	nfs_invalidate_atime(dir);

	dprintk("NFS reply readdir: %d\n", status);
	return status;
}

static int
nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
			struct nfs_fsstat *stat)
{
	struct nfs2_fsstat fsinfo;
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_STATFS],
		.rpc_argp	= fhandle,
		.rpc_resp	= &fsinfo,
	};
	int	status;

	dprintk("NFS call  statfs\n");
	nfs_fattr_init(stat->fattr);
	status = rpc_call_sync(server->client, &msg, 0);
	dprintk("NFS reply statfs: %d\n", status);
	if (status)
		goto out;
	stat->tbytes = (u64)fsinfo.blocks * fsinfo.bsize;
	stat->fbytes = (u64)fsinfo.bfree  * fsinfo.bsize;
	stat->abytes = (u64)fsinfo.bavail * fsinfo.bsize;
	stat->tfiles = 0;
	stat->ffiles = 0;
	stat->afiles = 0;
out:
	return status;
}

static int
nfs_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
			struct nfs_fsinfo *info)
{
	struct nfs2_fsstat fsinfo;
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_STATFS],
		.rpc_argp	= fhandle,
		.rpc_resp	= &fsinfo,
	};
	int	status;

	dprintk("NFS call  fsinfo\n");
	nfs_fattr_init(info->fattr);
	status = rpc_call_sync(server->client, &msg, 0);
	dprintk("NFS reply fsinfo: %d\n", status);
	if (status)
		goto out;
	info->rtmax  = NFS_MAXDATA;
	info->rtpref = fsinfo.tsize;
	info->rtmult = fsinfo.bsize;
	info->wtmax  = NFS_MAXDATA;
	info->wtpref = fsinfo.tsize;
	info->wtmult = fsinfo.bsize;
	info->dtpref = fsinfo.tsize;
	info->maxfilesize = 0x7FFFFFFF;
	info->lease_time = 0;
out:
	return status;
}

static int
nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
		  struct nfs_pathconf *info)
{
	info->max_link = 0;
	info->max_namelen = NFS2_MAXNAMLEN;
	return 0;
}

static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data)
{
	if (nfs_async_handle_expired_key(task))
		return -EAGAIN;

	nfs_invalidate_atime(data->inode);
	if (task->tk_status >= 0) {
		nfs_refresh_inode(data->inode, data->res.fattr);
		/* Emulate the eof flag, which isn't normally needed in NFSv2
		 * as it is guaranteed to always return the file attributes
		 */
		if (data->args.offset + data->args.count >= data->res.fattr->size)
			data->res.eof = 1;
	}
	return 0;
}

static void nfs_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg)
{
	msg->rpc_proc = &nfs_procedures[NFSPROC_READ];
}

static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data)
{
	if (nfs_async_handle_expired_key(task))
		return -EAGAIN;

	if (task->tk_status >= 0)
		nfs_post_op_update_inode_force_wcc(data->inode, data->res.fattr);
	return 0;
}

static void nfs_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg)
{
	/* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */
	data->args.stable = NFS_FILE_SYNC;
	msg->rpc_proc = &nfs_procedures[NFSPROC_WRITE];
}

static void
nfs_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg)
{
	BUG();
}

static int
nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
{
	struct inode *inode = filp->f_path.dentry->d_inode;

	return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl);
}

/* Helper functions for NFS lock bounds checking */
#define NFS_LOCK32_OFFSET_MAX ((__s32)0x7fffffffUL)
static int nfs_lock_check_bounds(const struct file_lock *fl)
{
	__s32 start, end;

	start = (__s32)fl->fl_start;
	if ((loff_t)start != fl->fl_start)
		goto out_einval;

	if (fl->fl_end != OFFSET_MAX) {
		end = (__s32)fl->fl_end;
		if ((loff_t)end != fl->fl_end)
			goto out_einval;
	} else
		end = NFS_LOCK32_OFFSET_MAX;

	if (start < 0 || start > end)
		goto out_einval;
	return 0;
out_einval:
	return -EINVAL;
}

const struct nfs_rpc_ops nfs_v2_clientops = {
	.version	= 2,		       /* protocol version */
	.dentry_ops	= &nfs_dentry_operations,
	.dir_inode_ops	= &nfs_dir_inode_operations,
	.file_inode_ops	= &nfs_file_inode_operations,
	.getroot	= nfs_proc_get_root,
	.getattr	= nfs_proc_getattr,
	.setattr	= nfs_proc_setattr,
	.lookup		= nfs_proc_lookup,
	.access		= NULL,		       /* access */
	.readlink	= nfs_proc_readlink,
	.create		= nfs_proc_create,
	.remove		= nfs_proc_remove,
	.unlink_setup	= nfs_proc_unlink_setup,
	.unlink_done	= nfs_proc_unlink_done,
	.rename		= nfs_proc_rename,
	.link		= nfs_proc_link,
	.symlink	= nfs_proc_symlink,
	.mkdir		= nfs_proc_mkdir,
	.rmdir		= nfs_proc_rmdir,
	.readdir	= nfs_proc_readdir,
	.mknod		= nfs_proc_mknod,
	.statfs		= nfs_proc_statfs,
	.fsinfo		= nfs_proc_fsinfo,
	.pathconf	= nfs_proc_pathconf,
	.decode_dirent	= nfs_decode_dirent,
	.read_setup	= nfs_proc_read_setup,
	.read_done	= nfs_read_done,
	.write_setup	= nfs_proc_write_setup,
	.write_done	= nfs_write_done,
	.commit_setup	= nfs_proc_commit_setup,
	.lock		= nfs_proc_lock,
	.lock_check_bounds = nfs_lock_check_bounds,
	.close_context	= nfs_close_context,
};
Пример #26
0
/* Turn file (or device node) into class name */
static int affinity_file(struct bitmask *mask, char *cls, const char *file)
{
	struct stat st;
	DIR *dir;
	int n;
	unsigned maj = 0, min = 0;
	dev_t d;
	struct dirent de, *dep;

	cls = "block";
	char fn[sizeof("/sys/class/") + strlen(cls)];
	if (stat(file, &st) < 0) {
		numa_warn(W_blockdev1, "Cannot stat file %s", file);
		return -1;
	}
	d = st.st_dev;
	if (S_ISCHR(st.st_mode)) {
		/* Better choice than misc? Most likely misc will not work
		   anyways unless the kernel is fixed. */
		cls = "misc";
		d = st.st_rdev;
	} else if (S_ISBLK(st.st_mode))
		d = st.st_rdev;

	sprintf(fn, "/sys/class/%s", cls);
	dir = opendir(fn);
	if (!dir) {
		numa_warn(W_blockdev2, "Cannot enumerate %s devices in sysfs",
			  cls);
		return -1;
	}
	while (readdir_r(dir, &de, &dep) == 0 && dep) {
		char *name = dep->d_name;
		if (*name == '.')
			continue;
		char *dev;
		char fn2[sizeof("/sys/class/block//dev") + strlen(name)];

		n = -1;
		if (sprintf(fn2, "/sys/class/block/%s/dev", name) < 0)
			break;
		dev = sysfs_read(fn2);
		if (dev) {
			n = sscanf(dev, "%u:%u", &maj, &min);
			free(dev);
		}
		if (n != 2) {
			numa_warn(W_blockdev3, "Cannot parse sysfs device %s",
				  name);
			continue;
		}

		if (major(d) != maj || minor(d) != min)
			continue;

		closedir(dir);
		return affinity_class(mask, "block", name);
	}
	closedir(dir);
	numa_warn(W_blockdev5, "Cannot find block device %x:%x in sysfs for `%s'",
		  maj, min, file);
	return -1;
}
Пример #27
0
int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
		dev_t device_number)
{
	int rc = -EPERM;
	int xid;
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;
	char *full_path = NULL;
	struct inode *newinode = NULL;

	if (!old_valid_dev(device_number))
		return -EINVAL;

	xid = GetXid();

	cifs_sb = CIFS_SB(inode->i_sb);
	pTcon = cifs_sb->tcon;

	full_path = build_path_from_dentry(direntry);
	if (full_path == NULL)
		rc = -ENOMEM;
	else if (pTcon->unix_ext) {
		struct cifs_unix_set_info_args args = {
			.mode	= mode & ~current->fs->umask,
			.ctime	= NO_CHANGE_64,
			.atime	= NO_CHANGE_64,
			.mtime	= NO_CHANGE_64,
			.device	= device_number,
		};
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
			args.uid = (__u64) current->fsuid;
			args.gid = (__u64) current->fsgid;
		} else {
			args.uid = NO_CHANGE_64;
			args.gid = NO_CHANGE_64;
		}
		rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path,
			&args, cifs_sb->local_nls,
			cifs_sb->mnt_cifs_flags &
				CIFS_MOUNT_MAP_SPECIAL_CHR);

		if (!rc) {
			rc = cifs_get_inode_info_unix(&newinode, full_path,
						inode->i_sb, xid);
			if (pTcon->nocase)
				direntry->d_op = &cifs_ci_dentry_ops;
			else
				direntry->d_op = &cifs_dentry_ops;
			if (rc == 0)
				d_instantiate(direntry, newinode);
		}
	} else {
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
			int oplock = 0;
			u16 fileHandle;
			FILE_ALL_INFO *buf;

			cFYI(1, ("sfu compat create special file"));

			buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
			if (buf == NULL) {
				kfree(full_path);
				FreeXid(xid);
				return -ENOMEM;
			}

			rc = CIFSSMBOpen(xid, pTcon, full_path,
					 FILE_CREATE, /* fail if exists */
					 GENERIC_WRITE /* BB would
					  WRITE_OWNER | WRITE_DAC be better? */,
					 /* Create a file and set the
					    file attribute to SYSTEM */
					 CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
					 &fileHandle, &oplock, buf,
					 cifs_sb->local_nls,
					 cifs_sb->mnt_cifs_flags &
					    CIFS_MOUNT_MAP_SPECIAL_CHR);

			/* BB FIXME - add handling for backlevel servers
			   which need legacy open and check for all
			   calls to SMBOpen for fallback to SMBLeagcyOpen */
			if (!rc) {
				/* BB Do not bother to decode buf since no
				   local inode yet to put timestamps in,
				   but we can reuse it safely */
				unsigned int bytes_written;
				struct win_dev *pdev;
				pdev = (struct win_dev *)buf;
				if (S_ISCHR(mode)) {
					memcpy(pdev->type, "IntxCHR", 8);
					pdev->major =
					      cpu_to_le64(MAJOR(device_number));
					pdev->minor =
					      cpu_to_le64(MINOR(device_number));
					rc = CIFSSMBWrite(xid, pTcon,
						fileHandle,
						sizeof(struct win_dev),
						0, &bytes_written, (char *)pdev,
						NULL, 0);
				} else if (S_ISBLK(mode)) {
					memcpy(pdev->type, "IntxBLK", 8);
					pdev->major =
					      cpu_to_le64(MAJOR(device_number));
					pdev->minor =
					      cpu_to_le64(MINOR(device_number));
					rc = CIFSSMBWrite(xid, pTcon,
						fileHandle,
						sizeof(struct win_dev),
						0, &bytes_written, (char *)pdev,
						NULL, 0);
				} /* else if(S_ISFIFO */
				CIFSSMBClose(xid, pTcon, fileHandle);
				d_drop(direntry);
			}
			kfree(buf);
			/* add code here to set EAs */
		}
	}

	kfree(full_path);
	FreeXid(xid);
	return rc;
}
static int process_directory(int parent, const char *path, int fixstats)
{

	DIR *dir;
	struct dirent *entry;
	char *secontext = NULL;

	nDirectories++;
	
	dir = opendir(path);
	
	if(dir)
	{
		while((entry = readdir(dir)) != NULL)
		{
		
			/* Ignore . and .. */
			if(strcmp(entry->d_name,".") &&
			   strcmp(entry->d_name,".."))
 			{
 				char full_name[500];
				char *suffix, dest_name[500];
				int ret;
				struct stat stats;
				int equivalentObj;
				int newObj;
				
				sprintf(full_name,"%s/%s",path,entry->d_name);
				
				lstat(full_name,&stats);

				if (sehnd) {
					suffix = full_name + seprefixlen;
					ret = snprintf(dest_name,
						       sizeof dest_name,
						       "%s%s", mntpoint,
						       suffix);
					if (ret < 0 ||
					    (size_t) ret >= sizeof dest_name) {
						fprintf(stderr,
							"snprintf failed on %s%s\n",
							mntpoint, suffix);
						exit(1);
					}

					char *sepath = NULL;
					if (dest_name[0] == '/')
					        sepath = strdup(dest_name);
					else if (asprintf(&sepath, "/%s", dest_name) < 0)
                                                sepath = NULL;

					if (!sepath) {
					        perror("malloc");
					        exit(1);
					}

					if (selabel_lookup(sehnd, &secontext,
							   sepath,
							   stats.st_mode) < 0) {
					        perror("selabel_lookup");
					        free(sepath);
					        exit(1);
					}
					free(sepath);
				}

				if(S_ISLNK(stats.st_mode) ||
				    S_ISREG(stats.st_mode) ||
				    S_ISDIR(stats.st_mode) ||
				    S_ISFIFO(stats.st_mode) ||
				    S_ISBLK(stats.st_mode) ||
				    S_ISCHR(stats.st_mode) ||
				    S_ISSOCK(stats.st_mode))
				{
				
					newObj = obj_id++;
					nObjects++;

                    if (fixstats) {
                        fix_stat(full_name, &stats);
                    }

					//printf("Object %d, %s is a ",newObj,full_name);
					
					/* We're going to create an object for it */
					if((equivalentObj = find_obj_in_list(stats.st_dev, stats.st_ino)) > 0)
					{
					 	/* we need to make a hard link */
					 	//printf("hard link to object %d\n",equivalentObj);
						error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_HARDLINK, &stats, parent, entry->d_name, equivalentObj, NULL, secontext);
					}
					else 
					{
						
						add_obj_to_list(stats.st_dev,stats.st_ino,newObj);
						
						if(S_ISLNK(stats.st_mode))
						{
					
							char symname[500];
						
							memset(symname,0, sizeof(symname));
					
							readlink(full_name,symname,sizeof(symname) -1);
						
							//printf("symlink to \"%s\"\n",symname);
							error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname, secontext);

						}
						else if(S_ISREG(stats.st_mode))
						{
							//printf("file, ");
							error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL, secontext);

							if(error >= 0)
							{
								int h;
								__u8 bytes[chunkSize];
								int nBytes;
								int chunk = 0;
								
								h = open(full_name,O_RDONLY);
								if(h >= 0)
								{
									memset(bytes,0xff,sizeof(bytes));
									while((nBytes = read(h,bytes,sizeof(bytes))) > 0)
									{
										chunk++;
										write_chunk(bytes,newObj,chunk,nBytes);
										memset(bytes,0xff,sizeof(bytes));
									}
									if(nBytes < 0) 
									   error = nBytes;
									   
									//printf("%d data chunks written\n",chunk);
								}
								else
								{
									perror("Error opening file");
								}
								close(h);
								
							}							
														
						}
						else if(S_ISSOCK(stats.st_mode))
						{
							//printf("socket\n");
							error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL, secontext);
						}
						else if(S_ISFIFO(stats.st_mode))
						{
							//printf("fifo\n");
							error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL, secontext);
						}
						else if(S_ISCHR(stats.st_mode))
						{
							//printf("character device\n");
							error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL, secontext);
						}
						else if(S_ISBLK(stats.st_mode))
						{
							//printf("block device\n");
							error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL, secontext);
						}
						else if(S_ISDIR(stats.st_mode))
						{
							//printf("directory\n");
							error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL, secontext);
// NCB modified 10/9/2001				process_directory(1,full_name);
							process_directory(newObj,full_name,fixstats);
						}
					}
				}
				else
				{
					//printf(" we don't handle this type\n");
				}
			}
		}
		closedir(dir);
	}
	
	return 0;

}
Пример #29
0
static int jffs2_get_sb(struct file_system_type *fs_type,
			int flags, const char *dev_name,
			void *data, struct vfsmount *mnt)
{
	int err;
	struct nameidata nd;
	int mtdnr;

	if (!dev_name)
		return -EINVAL;

	D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name));

	/* The preferred way of mounting in future; especially when
	   CONFIG_BLK_DEV is implemented - we specify the underlying
	   MTD device by number or by name, so that we don't require
	   block device support to be present in the kernel. */

	/* FIXME: How to do the root fs this way? */

	if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') {
		/* Probably mounting without the blkdev crap */
		if (dev_name[3] == ':') {
			struct mtd_info *mtd;

			/* Mount by MTD device name */
			D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4));
			for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) {
				mtd = get_mtd_device(NULL, mtdnr);
				if (!IS_ERR(mtd)) {
					if (!strcmp(mtd->name, dev_name+4))
						return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
					put_mtd_device(mtd);
				}
			}
			printk(KERN_NOTICE "jffs2_get_sb(): MTD device with name \"%s\" not found.\n", dev_name+4);
		} else if (isdigit(dev_name[3])) {
			/* Mount by MTD device number name */
			char *endptr;

			mtdnr = simple_strtoul(dev_name+3, &endptr, 0);
			if (!*endptr) {
				/* It was a valid number */
				D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr));
				return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt);
			}
		}
	}

	/* Try the old way - the hack where we allowed users to mount
	   /dev/mtdblock$(n) but didn't actually _use_ the blkdev */

	err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);

	D1(printk(KERN_DEBUG "jffs2_get_sb(): path_lookup() returned %d, inode %p\n",
		  err, nd.dentry->d_inode));

	if (err)
		return err;

	err = -EINVAL;

	if (!S_ISBLK(nd.dentry->d_inode->i_mode))
		goto out;

	if (nd.mnt->mnt_flags & MNT_NODEV) {
		err = -EACCES;
		goto out;
	}

	if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR) {
		if (!(flags & MS_SILENT))
			printk(KERN_NOTICE "Attempt to mount non-MTD device \"%s\" as JFFS2\n",
			       dev_name);
		goto out;
	}

	mtdnr = iminor(nd.dentry->d_inode);
	path_release(&nd);

	return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt);

out:
	path_release(&nd);
	return err;
}
Пример #30
0
//获取文件属性并打印
void display_attribute(struct stat *buf, char *path)
{
    char time[32];
    struct passwd *psd;
    struct group *grp;

    //获取并打印文件类型
    if (S_ISLNK(buf->st_mode)) {
        printf("l");
    } else if (S_ISREG(buf->st_mode)) {
        printf("-");
    } else if (S_ISDIR(buf->st_mode)) {
        printf("d");
    } else if (S_ISCHR(buf->st_mode)) {
        printf("c");
    } else if (S_ISBLK(buf->st_mode)) {
        printf("b");
    } else if (S_ISFIFO(buf->st_mode)) {
        printf("f");
    } else if (S_ISSOCK(buf->st_mode)) {
        printf("s");
    }
    //获取所有者的权限
    if (buf->st_mode & S_IRUSR) {
        printf("r");
    } else {
        printf("-");
    }
    if (buf->st_mode & S_IWUSR) {
        printf("w");
    } else {
        printf("-");
    }
    if (buf->st_mode & S_IXUSR) {
        printf("x");
    } else {
        printf("-");
    }
    //获取组权限
    if (buf->st_mode & S_IRGRP) {
        printf("r");
    } else {
        printf("-");
    }
    if (buf->st_mode & S_IWGRP) {
        printf("w");
    } else {
        printf("-");
    }
    if (buf->st_mode & S_IXGRP) {
        printf("x");
    } else {
        printf("-");
    }
    //获取其他用户权限
    if (buf->st_mode & S_IROTH) {
        printf("r");
    } else {
        printf("-");
    }
    if (buf->st_mode & S_IWOTH) {
        printf("w");
    } else {
        printf("-");
    }
    if (buf->st_mode & S_IXOTH) {
        printf("x");
    } else {
        printf("-");
    }
    printf(" ");

    printf("%5lu ", buf->st_nlink);    //打印文件连接数

    //根据uid,gid获取用户名和组名
    psd = getpwuid(buf->st_uid);
    grp = getgrgid(buf->st_gid);
    printf("%-s\t", psd -> pw_name);
    printf("%-s\t", grp -> gr_name);

    printf("%10ld ", buf->st_size);    //打印文件大小

    strcpy(time, ctime(&buf -> st_mtime));
    time[(strlen(time)) - 1] = '\0';
    printf("%s ", time);             //打印时间
    printf("%s\n", path);             //打印文件名
}