Exemple #1
0
int main(int argc, char *argv[]) {
	char *path = NULL;
	struct attrlist alist;
	struct directoryinfo dirinfo;
	struct volumeinfo volinfo;
	struct statfs sfs;

	path = argv[1];

	bzero(&alist, sizeof(alist));
	alist.bitmapcount = 5;
	alist.commonattr = ATTR_CMN_OBJID;

	getattrlist(path, &alist, &dirinfo, sizeof(dirinfo), 0);

	printf("directory id: %lu\n", dirinfo.dirid);

	statfs(path, &sfs);

	printf("mountpoint: %s\n", sfs.f_mntonname);

	alist.commonattr = ATTR_CMN_FNDRINFO;
	alist.volattr = ATTR_VOL_INFO;

	getattrlist(sfs.f_mntonname, &alist, &volinfo, sizeof(volinfo), 0);
	volinfo.finderinfo[2] = dirinfo.dirid;
	setattrlist(sfs.f_mntonname, &alist, volinfo.finderinfo, sizeof(volinfo.finderinfo), 0);

	return EXIT_SUCCESS;
} 
Exemple #2
0
int
main(int argc, char **argv)
{
	int i;
	struct attrlist attrs;
	struct attr_buffer attrbuf;

	if (argc < 2) {
		fprintf(stderr, "Usage: checktrigger <pathname>...\n");
		return 1;
	}
	argv++;
	argc--;
	for (i = 0; i < argc; i++) {
		memset(&attrs, 0, sizeof(attrs));
		attrs.bitmapcount = ATTR_BIT_MAP_COUNT;
		attrs.dirattr = ATTR_DIR_MOUNTSTATUS;
		if (getattrlist(argv[i], &attrs, &attrbuf, sizeof attrbuf,
		    FSOPT_NOFOLLOW) == -1) {
			fprintf(stderr, "checktrigger: getattrlist of %s failed: %s\n",
			    argv[i], strerror(errno));
			return 2;
		}
		printf("%s %s a trigger\n", argv[i],
		    (attrbuf.mount_flags & DIR_MNTSTATUS_TRIGGER) ?
		        "is" : "is not");
	}
	return 0;
}
Exemple #3
0
/** Checks that the basename component of the input path exactly
 * matches the canonical case of the path on disk.
 * It only makes sense to call this function on a case insensitive filesystem.
 * If the case does not match, throws an exception. */
static void checkCanonicalBaseName(const char *path) {
#ifdef __APPLE__
  struct attrlist attrlist;
  struct {
    uint32_t len;
    attrreference_t ref;
    char canonical_name[WATCHMAN_NAME_MAX];
  } vomit;
  w_string_piece pathPiece(path);
  auto base = pathPiece.baseName();

  memset(&attrlist, 0, sizeof(attrlist));
  attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
  attrlist.commonattr = ATTR_CMN_NAME;

  if (getattrlist(path, &attrlist, &vomit, sizeof(vomit), FSOPT_NOFOLLOW) ==
      -1) {
    throw std::system_error(errno, std::generic_category(),
                            to<std::string>("checkCanonicalBaseName(", path,
                                            "): getattrlist failed"));
  }

  w_string_piece name(((char *)&vomit.ref) + vomit.ref.attr_dataoffset);
  if (name != base) {
    throw std::system_error(
        ENOENT, std::generic_category(),
        to<std::string>("checkCanonicalBaseName(", path, "): (", name,
                        ") doesn't match canonical base (", base, ")"));
  }
#else
  // Older Linux and BSDish systems are in this category.
  // This is the awful portable fallback used in the absence of
  // a system specific way to detect this.
  w_string_piece pathPiece(path);
  auto parent = pathPiece.dirName().asWString();
  auto dir = w_dir_open(parent.c_str());
  auto base = pathPiece.baseName();

  while (true) {
    auto ent = dir->readDir();
    if (!ent) {
      // We didn't find an entry that exactly matched -> fail
      throw std::system_error(
          ENOENT, std::generic_category(),
          to<std::string>("checkCanonicalBaseName(", path,
                          "): no match found in parent dir"));
    }
    // Note: we don't break out early if we get a case-insensitive match
    // because the dir may contain multiple representations of the same
    // name.  For example, Bash-for-Windows has dirs that contain both
    // "pod" and "Pod" dirs in its perl installation.  We want to make
    // sure that we've observed all of the entries in the dir before
    // giving up.
    if (w_string_piece(ent->d_name) == base) {
      // Exact match; all is good!
      return;
    }
  }
#endif
}
CFStringRef _DAFileSystemCopyName( DAFileSystemRef filesystem, CFURLRef mountpoint )
{
    struct attr_name_t
    {
        uint32_t        size;
        attrreference_t data;
        char            name[MAXNAMLEN + 1];
    };

    struct attr_name_t attr     = { 0 };
    struct attrlist    attrlist = { 0 };
    CFStringRef        name     = NULL;
    char *             path     = NULL;
    int                status   = 0;

    attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
    attrlist.volattr     = ATTR_VOL_INFO | ATTR_VOL_NAME;

    path = ___CFURLCopyFileSystemRepresentation( mountpoint );
    if ( path == NULL )  goto _DAFileSystemCopyNameErr;

    status = getattrlist( path, &attrlist, &attr, sizeof( attr ), 0 );
    if ( status == -1 )  goto _DAFileSystemCopyNameErr;

    if ( attr.data.attr_length )
    {
        name = CFStringCreateWithCString( kCFAllocatorDefault, ( ( char * ) &attr.data ) + attr.data.attr_dataoffset, kCFStringEncodingUTF8 );
    }

_DAFileSystemCopyNameErr:

    if ( path )  free( path );

    return name;
}
Exemple #5
0
struct timespec get_birthtime(const char* path) {
	
	struct attrlist attrlist;
	struct {
		u_int32_t length;
		struct timespec ts;
	} attrbuf;
	int err;

	bzero(&attrlist, sizeof(attrlist));
	attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
	attrlist.commonattr  = ATTR_CMN_CRTIME;
    err = getattrlist(
		path, 
		&attrlist, 
		&attrbuf, 
		sizeof(attrbuf), 
		FSOPT_NOFOLLOW
	);
    if(err != 0) {
		perror("getattrlist");
		exit(EXIT_FAILURE);
    }
	if(attrbuf.length != sizeof(attrbuf)) {
		printf("ERROR: getattrlist failed to get birthtime\n");
		exit(EXIT_FAILURE);
	}
	return attrbuf.ts;
}
int BLGetVolumeFinderInfo(BLContextPtr context, const char * mountpoint, uint32_t * words) {
    int err, i;
    struct volinfobuf vinfo;
    struct attrlist alist;


    alist.bitmapcount = 5;
    alist.reserved = 0;
    alist.commonattr = ATTR_CMN_FNDRINFO;
    alist.volattr = ATTR_VOL_INFO;
    alist.dirattr = 0;
    alist.fileattr = 0;
    alist.forkattr = 0;
    
    err = getattrlist(mountpoint, &alist, &vinfo, sizeof(vinfo), 0);
    if(err) {
      contextprintf(context, kBLLogLevelError,  "Can't get volume information for %s\n", mountpoint );
      return 1;
    }

    /* Finder info words are just opaque and in big-endian format on disk
	for HFS+ */
    
    for(i=0; i<6; i++) {
        words[i] = CFSwapInt32BigToHost(vinfo.finderinfo[i]);
    }

    *(uint64_t *)&words[6] = CFSwapInt64BigToHost(
					(*(uint64_t *)&vinfo.finderinfo[6]));
    
    return 0;
}
Exemple #7
0
long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5)
{
    struct attrlist * attrlist = (void *)arg2;
    long ret;

#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
    gemu_log("SYS_getdirentriesattr unimplemented\n");
    return -ENOTSUP;
#endif
    /* XXX: don't let the %s stay in there */
    DPRINTF("getattrlist(%s, %p, %p, 0x%x, 0x%x)\n",
            (char *)arg1, arg2, arg3, arg4, arg5);

    if(arg2) /* XXX: We should handle that in a copy especially
        if the structure is not writable */
        byteswap_attrlist(attrlist);

    ret = get_errno(getattrlist((const char* )arg1, attrlist, (void *)arg3, arg4, arg5));

    if(!is_error(ret))
    {
        byteswap_attrbuf((void *)arg3, attrlist);
        byteswap_attrlist(attrlist);
    }
    return ret;
}
Exemple #8
0
CAMLprim value getFileInfos (value path, value need_size) {
#ifdef __APPLE__

  CAMLparam1(path);
  CAMLlocal3(res, fInfo, length);
  int retcode;
  struct attrlist attrList;
  unsigned long options = FSOPT_REPORT_FULLSIZE;
  struct {
    u_int32_t length;
    char      finderInfo [32];
    off_t     rsrcLength;
  } __attribute__ ((packed)) attrBuf;

  attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
  attrList.reserved = 0;
  attrList.commonattr = ATTR_CMN_FNDRINFO;
  attrList.volattr = 0;     /* volume attribute group */
  attrList.dirattr = 0;     /* directory attribute group */
  if (Bool_val (need_size))
    attrList.fileattr = ATTR_FILE_RSRCLENGTH;    /* file attribute group */
  else
    attrList.fileattr = 0;
  attrList.forkattr = 0;    /* fork attribute group */

  retcode = getattrlist(String_val (path), &attrList, &attrBuf,
                        sizeof attrBuf, options);

  if (retcode == -1) uerror("getattrlist", path);

  if (Bool_val (need_size)) {
    if (attrBuf.length != sizeof attrBuf)
      unix_error (EINVAL, "getattrlist", path);
  } else {
    if (attrBuf.length != sizeof (u_int32_t) + 32)
      unix_error (EINVAL, "getattrlist", path);
  }

  fInfo = alloc_string (32);
  memcpy (String_val (fInfo), attrBuf.finderInfo, 32);
  if (Bool_val (need_size))
    length = copy_int64 (attrBuf.rsrcLength);
  else
    length = copy_int64 (0);

  res = alloc_small (2, 0);
  Field (res, 0) = fInfo;
  Field (res, 1) = length;

  CAMLreturn (res);

#else

  unix_error (ENOSYS, "getattrlist", path);

#endif
}
int osx_attr_getattrlist
(const char *path, struct attrlist * attrList, void * attrBuf,
 size_t attrBufSize, unsigned long options)
{
  int r;
  caml_release_runtime_system();
  r = getattrlist(path, attrList, attrBuf, attrBufSize, options);
  caml_acquire_runtime_system();
  return r;
}
Exemple #10
0
static int
loopback_getxtimes(const char *path, struct timespec *bkuptime,
                   struct timespec *crtime)
{
    int res = 0;
    struct attrlist attributes;

    attributes.bitmapcount = ATTR_BIT_MAP_COUNT;
    attributes.reserved    = 0;
    attributes.commonattr  = 0;
    attributes.dirattr     = 0;
    attributes.fileattr    = 0;
    attributes.forkattr    = 0;
    attributes.volattr     = 0;



    struct xtimeattrbuf {
        uint32_t size;
        struct timespec xtime;
    } __attribute__ ((packed));


    struct xtimeattrbuf buf;

    attributes.commonattr = ATTR_CMN_BKUPTIME;
    res = getattrlist(path, &attributes, &buf, sizeof(buf), FSOPT_NOFOLLOW);
    if (res == 0) {
        (void)memcpy(bkuptime, &(buf.xtime), sizeof(struct timespec));
    } else {
        (void)memset(bkuptime, 0, sizeof(struct timespec));
    }

    attributes.commonattr = ATTR_CMN_CRTIME;
    res = getattrlist(path, &attributes, &buf, sizeof(buf), FSOPT_NOFOLLOW);
    if (res == 0) {
        (void)memcpy(crtime, &(buf.xtime), sizeof(struct timespec));
    } else {
        (void)memset(crtime, 0, sizeof(struct timespec));
    }

    return 0;
}
uint32_t dirlinkcount(char *path) {
    struct attrlist al;
    bzero(&al, sizeof(al));
    al.bitmapcount = ATTR_BIT_MAP_COUNT;
    al.dirattr = ATTR_DIR_LINKCOUNT;
    
    struct linkcount_buf_t buf;
    if (getattrlist(path, &al, &buf, sizeof(buf), 0))
        die("getattrlist");
    return buf.links;
}
int main(int argc, char *argv[]) {

    char *path = NULL;
    struct attrlist alist;
    struct directoryinfo dirinfo;
    struct volumeinfo volinfo;
    struct statfs sfs;

    if (argc <= 1) {
	fprintf(stderr,"Usage: %s /Volumes/Foo/OpenMe/\n", argv[0]);
	exit(1);
    }

    path = argv[1];

    memset(&alist, 0, sizeof(alist));
    alist.bitmapcount = 5;
    alist.commonattr = ATTR_CMN_OBJID;

    getattrlist(path, &alist, &dirinfo, sizeof(dirinfo), 0);

    printf("directory id: %lu\n", dirinfo.dirid);

    statfs(path, &sfs);

    printf("mountpoint: %s\n", sfs.f_mntonname);

    alist.commonattr = ATTR_CMN_FNDRINFO;
    alist.volattr = ATTR_VOL_INFO;

    getattrlist(sfs.f_mntonname, &alist, &volinfo, sizeof(volinfo), 0);
    volinfo.finderinfo[2] = dirinfo.dirid;
    setattrlist(sfs.f_mntonname, &alist, volinfo.finderinfo, sizeof(volinfo.finderinfo), 0);

    return 0;
}
static int darwin_fs_capabilities(const char * path)
{
	int caps = 0;
	vol_capabilities_attr_t *vcaps;
	struct attrlist	attrlist;
	char attrbuf[sizeof(u_int32_t) + sizeof(vol_capabilities_attr_t)];

#define FORMAT_CAP(vinfo, cap) \
	( ((vinfo)->valid[VOL_CAPABILITIES_FORMAT] & (cap)) && \
	   ((vinfo)->capabilities[VOL_CAPABILITIES_FORMAT] & (cap)) )

#define INTERFACE_CAP(vinfo, cap) \
	( ((vinfo)->valid[VOL_CAPABILITIES_INTERFACES] & (cap)) && \
	   ((vinfo)->capabilities[VOL_CAPABILITIES_INTERFACES] & (cap)) )

	ZERO_STRUCT(attrlist);
	attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
	attrlist.volattr = ATTR_VOL_CAPABILITIES;

	if (getattrlist(path, &attrlist, attrbuf, sizeof(attrbuf), 0) != 0) {
		DEBUG(0, ("getattrlist for %s capabilities failed: %s\n",
			    path, strerror(errno)));
		/* Return no capabilities on failure. */
		return 0;
	}

	vcaps =
	    (vol_capabilities_attr_t *)(attrbuf + sizeof(u_int32_t));

	if (FORMAT_CAP(vcaps, VOL_CAP_FMT_SPARSE_FILES)) {
		caps |= FILE_SUPPORTS_SPARSE_FILES;
	}

	if (FORMAT_CAP(vcaps, VOL_CAP_FMT_CASE_SENSITIVE)) {
		caps |= FILE_CASE_SENSITIVE_SEARCH;
	}

	if (FORMAT_CAP(vcaps, VOL_CAP_FMT_CASE_PRESERVING)) {
		caps |= FILE_CASE_PRESERVED_NAMES;
	}

	if (INTERFACE_CAP(vcaps, VOL_CAP_INT_EXTENDED_SECURITY)) {
		caps |= FILE_PERSISTENT_ACLS;
	}

	return caps;
}
Exemple #14
0
__private_extern__ u_int32_t volumeCapabilities(const char *path)
{
    struct attrlist alist;
    bzero(&alist, sizeof(alist));
    alist.bitmapcount = ATTR_BIT_MAP_COUNT;
    alist.volattr = ATTR_VOL_INFO|ATTR_VOL_CAPABILITIES; // XXX: VOL_INFO must always be set

    struct {
        u_int32_t v_size;
       /* Fixed storage */
       vol_capabilities_attr_t v_caps;
    } vinfo;
    bzero(&vinfo, sizeof(vinfo));
    if (0 == getattrlist(path, &alist, &vinfo, sizeof(vinfo), 0)
        && 0 != (alist.volattr & ATTR_VOL_CAPABILITIES)) {
        return (vinfo.v_caps.capabilities[VOL_CAPABILITIES_INTERFACES]);
    }

    return (0);
}
int main(int argc, char *argv[]) {
    int ret, i;
    struct volinfobuf vinfo;
    struct attrlist alist;


    alist.bitmapcount = 5;
    alist.reserved = 0;
    alist.commonattr = ATTR_CMN_FNDRINFO;
    alist.volattr = ATTR_VOL_INFO;
    alist.dirattr = 0;
    alist.fileattr = 0;
    alist.forkattr = 0;
    
    ret = getattrlist(argv[1], &alist, &vinfo, sizeof(vinfo), 0);
    if(ret)
      err(1, "getattrlist");

    printf("%u\n", ntohl(vinfo.finderinfo[0]));
    
    return 0;
}
Exemple #16
0
__private_extern__ int ___chattr( const char * path, ___attr_t attr, ___attr_t noattr )
{
    /*
     * Change file flags.
     */

    struct __chattrbuf
    {
        uint32_t  size;
        uint8_t   reserved0032[8];
        ___attr_t attr;
        uint8_t   reserved0112[22];
    };

    typedef struct __chattrbuf __chattrbuf;

    struct attrlist attributes;
    __chattrbuf     buffer;
    int             status;

    attributes.bitmapcount = ATTR_BIT_MAP_COUNT;
    attributes.commonattr  = ATTR_CMN_FNDRINFO;
    attributes.dirattr     = 0;
    attributes.fileattr    = 0;
    attributes.forkattr    = 0;
    attributes.volattr     = 0;

    status = getattrlist( path, &attributes, &buffer, sizeof( buffer ), 0 );

    if ( status == 0 )
    {
        buffer.attr = OSSwapHostToBigInt16( ( OSSwapBigToHostInt16( buffer.attr ) & ~noattr ) | attr );

        status = setattrlist( path, &attributes, ( ( uint8_t * ) &buffer ) + sizeof( buffer.size ), sizeof( buffer ) - sizeof( buffer.size ), 0 );
    }

    return status;
}
Exemple #17
0
struct timespec get_bkuptime(const char* filename) {
	struct attrlist alist;
	struct {
		u_int32_t length;
		struct timespec ts;
	} buf;

	bzero(&alist, sizeof(alist));
	alist.bitmapcount = ATTR_BIT_MAP_COUNT;
	alist.commonattr  = ATTR_CMN_BKUPTIME;
    int err = getattrlist(
		filename, 
		&alist, 
		&buf, 
		sizeof(buf), 
		FSOPT_NOFOLLOW
	);
    if(err != 0) {
		perror("getattrlist");
		exit(EXIT_FAILURE);
    }
	if(buf.length != sizeof(buf)) {
		printf("ERROR: failed to obtain backuptime\n");
		exit(EXIT_FAILURE);
	}

/*	// format the date as: 2001_12_28_23_59_59
	time_t t = buf.ts.tv_sec;
	struct tm tm;
    localtime_r(&t, &tm);
	char str[50];
	strftime(str, 50, "%Y_%m_%d_%H_%M_%S", &tm);
	puts(str);*/

	return buf.ts;
}
Exemple #18
0
/*
 * char *realpath(const char *path, char resolved[PATH_MAX]);
 *
 * Find the real name of path, by removing all ".", ".." and symlink
 * components.  Returns (resolved) on success, or (NULL) on failure,
 * in which case the path which caused trouble is left in (resolved).
 */
char *
realpath(const char *path, char inresolved[PATH_MAX])
{
	struct attrs attrs;
	struct stat sb;
	char *p, *q, *s;
	size_t left_len, resolved_len, save_resolved_len;
	unsigned symlinks;
	int serrno, slen, useattrs, islink;
	char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
	dev_t dev, lastdev;
	struct statfs sfs;
	static dev_t rootdev;
	static int rootdev_inited = 0;
	ino_t inode;
	char *resolved;

	if (path == NULL) {
		errno = EINVAL;
		return (NULL);
	}
#if __DARWIN_UNIX03
	if (*path == 0) {
		errno = ENOENT;
		return (NULL);
	}
#endif /* __DARWIN_UNIX03 */
	/*
	 * Extension to the standard; if inresolved == NULL, allocate memory
	 */
	if (!inresolved) {
	    if ((resolved = malloc(PATH_MAX)) == NULL) return (NULL);
	} else {
	    resolved = inresolved;
	}
	if (!rootdev_inited) {
		rootdev_inited = 1;
		if (stat("/", &sb) < 0) {
error_return:
			if (!inresolved) {
				int e = errno;
				free(resolved);
				errno = e;
			}
			return (NULL);
		}
		rootdev = sb.st_dev;
	}
	serrno = errno;
	symlinks = 0;
	if (path[0] == '/') {
		resolved[0] = '/';
		resolved[1] = '\0';
		if (path[1] == '\0') {
			return (resolved);
		}
		resolved_len = 1;
		left_len = strlcpy(left, path + 1, sizeof(left));
	} else {
#if !defined(VARIANT_DARWINEXTSN) && __DARWIN_UNIX03
		/* 4447159: don't use GETPATH, so this will fail if */
		/* if parent directories are not readable, as per POSIX */
		if (__private_getcwd(resolved, PATH_MAX, 0) == NULL)
#else /* VARIANT_DARWINEXTSN || !__DARWIN_UNIX03 */
		if (__private_getcwd(resolved, PATH_MAX, 1) == NULL)
#endif /* !VARIANT_DARWINEXTSN && __DARWIN_UNIX03 */
		{
			strlcpy(resolved, ".", PATH_MAX);
			goto error_return;
		}
		resolved_len = strlen(resolved);
		left_len = strlcpy(left, path, sizeof(left));
	}
	if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
		errno = ENAMETOOLONG;
		goto error_return;
	}
	if (resolved_len > 1) {
		if (stat(resolved, &sb) < 0) {
			goto error_return;
		}
		lastdev = sb.st_dev;
	} else
		lastdev = rootdev;

	/*
	 * Iterate over path components in `left'.
	 */
	while (left_len != 0) {
		/*
		 * Extract the next path component and adjust `left'
		 * and its length.
		 */
		p = strchr(left, '/');
		s = p ? p : left + left_len;
		if (s - left >= sizeof(next_token)) {
			errno = ENAMETOOLONG;
			goto error_return;
		}
		memcpy(next_token, left, s - left);
		next_token[s - left] = '\0';
		left_len -= s - left;
		if (p != NULL)
			memmove(left, s + 1, left_len + 1);
		if (resolved[resolved_len - 1] != '/') {
			if (resolved_len + 1 >= PATH_MAX) {
				errno = ENAMETOOLONG;
				goto error_return;
			}
			resolved[resolved_len++] = '/';
			resolved[resolved_len] = '\0';
		}
		if (next_token[0] == '\0')
			continue;
		else if (strcmp(next_token, ".") == 0)
			continue;
		else if (strcmp(next_token, "..") == 0) {
			/*
			 * Strip the last path component except when we have
			 * single "/"
			 */
			if (resolved_len > 1) {
				resolved[resolved_len - 1] = '\0';
				q = strrchr(resolved, '/') + 1;
				*q = '\0';
				resolved_len = q - resolved;
			}
			continue;
		}

		/*
		 * Save resolved_len, so that we can later null out
		 * the the appended next_token, and replace with the
		 * real name (matters on case-insensitive filesystems).
		 */
		save_resolved_len = resolved_len;

		/*
		 * Append the next path component and lstat() it. If
		 * lstat() fails we still can return successfully if
		 * there are no more path components left.
		 */
		resolved_len = strlcat(resolved, next_token, PATH_MAX);
		if (resolved_len >= PATH_MAX) {
			errno = ENAMETOOLONG;
			goto error_return;
		}
		if (getattrlist(resolved, (void *)&_rp_alist, &attrs, sizeof(attrs), FSOPT_NOFOLLOW) == 0) {
			useattrs = 1;
			islink = (attrs.type == VLNK);
			dev = attrs.dev;
			inode = attrs.id.fid_objno;
		} else if (errno == ENOTSUP || errno == EINVAL) {
			if ((useattrs = lstat(resolved, &sb)) == 0) {
				islink = S_ISLNK(sb.st_mode);
				dev = sb.st_dev;
				inode = sb.st_ino;
			}
		} else
			useattrs = -1;
		if (useattrs < 0) {
#if !__DARWIN_UNIX03
			if (errno == ENOENT && p == NULL) {
				errno = serrno;
				return (resolved);
			}
#endif /* !__DARWIN_UNIX03 */
			goto error_return;
		}
		if (dev != lastdev) {
			/*
			 * We have crossed a mountpoint.  For volumes like UDF
			 * the getattrlist name may not match the actual
			 * mountpoint, so we just copy the mountpoint directly.
			 * (3703138).  However, the mountpoint may not be
			 * accessible, as when chroot-ed, so check first.
			 * There may be a file on the chroot-ed volume with
			 * the same name as the mountpoint, so compare device
			 * and inode numbers.
			 */
			lastdev = dev;
			if (statfs(resolved, &sfs) == 0 && lstat(sfs.f_mntonname, &sb) == 0 && dev == sb.st_dev && inode == sb.st_ino) {
				/*
				 * However, it's possible that the mountpoint
				 * path matches, even though it isn't the real
				 * path in the chroot-ed environment, so check
				 * that each component of the mountpoint
				 * is a directory (and not a symlink)
				 */
				char temp[sizeof(sfs.f_mntonname)];
				char *cp;
				int ok = 1;

				strcpy(temp, sfs.f_mntonname);
				for(;;) {
					if ((cp = strrchr(temp, '/')) == NULL) {
						ok = 0;
						break;
					}
					if (cp <= temp)
						break;
					*cp = 0;
					if (lstat(temp, &sb) < 0 || (sb.st_mode & S_IFMT) != S_IFDIR) {
						ok = 0;
						break;
					}
				}
				if (ok) {
					resolved_len = strlcpy(resolved, sfs.f_mntonname, PATH_MAX);
					continue;
				}
			}
			/* if we fail, use the other methods. */
		}
		if (islink) {
			if (symlinks++ > MAXSYMLINKS) {
				errno = ELOOP;
				goto error_return;
			}
			slen = readlink(resolved, symlink, sizeof(symlink) - 1);
			if (slen < 0) {
				goto error_return;
			}
			symlink[slen] = '\0';
			if (symlink[0] == '/') {
				resolved[1] = 0;
				resolved_len = 1;
				lastdev = rootdev;
			} else if (resolved_len > 1) {
				/* Strip the last path component. */
				resolved[resolved_len - 1] = '\0';
				q = strrchr(resolved, '/') + 1;
				*q = '\0';
				resolved_len = q - resolved;
			}

			/*
			 * If there are any path components left, then
			 * append them to symlink. The result is placed
			 * in `left'.
			 */
			if (p != NULL) {
				if (symlink[slen - 1] != '/') {
					if (slen + 1 >= sizeof(symlink)) {
						errno = ENAMETOOLONG;
						goto error_return;
					}
					symlink[slen] = '/';
					symlink[slen + 1] = 0;
				}
				left_len = strlcat(symlink, left, sizeof(symlink));
				if (left_len >= sizeof(left)) {
					errno = ENAMETOOLONG;
					goto error_return;
				}
			}
			left_len = strlcpy(left, symlink, sizeof(left));
		} else if (useattrs) {
			/*
			 * attrs already has the real name.
			 */

			resolved[save_resolved_len] = '\0';
			resolved_len = strlcat(resolved, (const char *)&attrs.name + attrs.name.attr_dataoffset, PATH_MAX);
			if (resolved_len >= PATH_MAX) {
				errno = ENAMETOOLONG;
				goto error_return;
			}
		}
		/*
		 * For the case of useattrs == 0, we could scan the directory
		 * and try to match the inode.  There are many problems with
		 * this: (1) the directory may not be readable, (2) for multiple
		 * hard links, we would find the first, but not necessarily
		 * the one specified in the path, (3) we can't try to do
		 * a case-insensitive search to match the right one in (2),
		 * because the underlying filesystem may do things like
		 * decompose composed characters.  For most cases, doing
		 * nothing is the right thing when useattrs == 0, so we punt
		 * for now.
		 */
	}

	/*
	 * Remove trailing slash except when the resolved pathname
	 * is a single "/".
	 */
	if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
		resolved[resolved_len - 1] = '\0';
	return (resolved);
}
Exemple #19
0
int statfs_32bit_inode_tests( void * the_argp )
{
	int					my_err, my_count, i;
	int					my_buffer_size;
	int					my_fd = -1;
	int					is_ufs = 0;
	void *				my_bufferp = NULL;
	struct statfs *		my_statfsp;
	long				my_io_size;
	fsid_t				my_fsid;
	struct attrlist		my_attrlist;
	vol_attr_buf		my_attr_buf;
	kern_return_t		my_kr;

	my_buffer_size = (sizeof(struct statfs) * 10);
        my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_bufferp, my_buffer_size, VM_FLAGS_ANYWHERE);
        if(my_kr != KERN_SUCCESS){
                printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
                goto test_failed_exit;
        }

	my_statfsp = (struct statfs *) my_bufferp;
	my_err = statfs( "/", my_statfsp );
	if ( my_err == -1 ) {
		printf( "statfs call failed.  got errno %d - %s. \n", errno, strerror( errno ) );
		goto test_failed_exit;
	}
	if ( memcmp( &my_statfsp->f_fstypename[0], "ufs", 3 ) == 0 ) {
		is_ufs = 1;
	}
	
	my_count = getfsstat( (struct statfs *)my_bufferp, my_buffer_size, MNT_NOWAIT );
	if ( my_count == -1 ) {
		printf( "getfsstat call failed.  got errno %d - %s. \n", errno, strerror( errno ) );
		goto test_failed_exit;
	}

	/* validate results */
	my_statfsp = (struct statfs *) my_bufferp;
	for ( i = 0; i < my_count; i++, my_statfsp++ ) {
		if ( memcmp( &my_statfsp->f_fstypename[0], "hfs", 3 ) == 0 ||
			 memcmp( &my_statfsp->f_fstypename[0], "ufs", 3 ) == 0 ||
			 memcmp( &my_statfsp->f_fstypename[0], "devfs", 5 ) == 0 ||
			 memcmp( &my_statfsp->f_fstypename[0], "volfs", 5 ) == 0 ) {
			/* found a valid entry */
			break;
		}
	}
	if ( i >= my_count ) {
		printf( "getfsstat call failed.  could not find valid f_fstypename! \n" );
		goto test_failed_exit;
	}

	/* set up to validate results via multiple sources.  we use getattrlist to get volume
	 * related attributes to verify against results from fstatfs and statfs - but only if
	 * we are not targeting ufs volume since it doesn't support getattr calls
	 */
	if ( is_ufs == 0 ) {
		memset( &my_attrlist, 0, sizeof(my_attrlist) );
		my_attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
		my_attrlist.volattr = (ATTR_VOL_SIZE | ATTR_VOL_IOBLOCKSIZE);
		my_err = getattrlist( "/", &my_attrlist, &my_attr_buf, sizeof(my_attr_buf), 0 );
		if ( my_err != 0 ) {
			printf( "getattrlist call failed.  got errno %d - %s. \n", errno, strerror( errno ) );
			goto test_failed_exit;
		}
	}
	
	/* open kernel to use as test file for fstatfs */
 	my_fd = open( "/mach_kernel", O_RDONLY, 0 );
	if ( my_fd == -1 ) {
		printf( "open call failed.  got errno %d - %s. \n", errno, strerror( errno ) );
		goto test_failed_exit;
	}
	
	/* testing fstatfs */
	my_statfsp = (struct statfs *) my_bufferp;
	my_err = fstatfs( my_fd, my_statfsp );
	if ( my_err == -1 ) {
		printf( "fstatfs call failed.  got errno %d - %s. \n", errno, strerror( errno ) );
		goto test_failed_exit;
	}
	
	/* validate results */
	if ( !(memcmp( &my_statfsp->f_fstypename[0], "hfs", 3 ) == 0 ||
		   memcmp( &my_statfsp->f_fstypename[0], "ufs", 3 ) == 0) ) {
		printf( "fstatfs call failed.  could not find valid f_fstypename! \n" );
		goto test_failed_exit;
	}
	my_io_size = my_statfsp->f_iosize;
	my_fsid = my_statfsp->f_fsid;
	if ( is_ufs == 0 && my_statfsp->f_iosize != my_attr_buf.io_blksize ) {
		printf( "fstatfs and getattrlist results do not match for volume block size  \n" );
		goto test_failed_exit;
	} 

	/* try again with statfs */
	my_err = statfs( "/mach_kernel", my_statfsp );
	if ( my_err == -1 ) {
		printf( "statfs call failed.  got errno %d - %s. \n", errno, strerror( errno ) );
		goto test_failed_exit;
	}

	/* validate resutls */
	if ( my_io_size != my_statfsp->f_iosize || my_fsid.val[0] != my_statfsp->f_fsid.val[0] ||
		 my_fsid.val[1] != my_statfsp->f_fsid.val[1] ) {
		printf( "statfs call failed.  wrong f_iosize or f_fsid! \n" );
		goto test_failed_exit;
	}
	if ( is_ufs == 0 && my_statfsp->f_iosize != my_attr_buf.io_blksize ) {
		printf( "statfs and getattrlist results do not match for volume block size  \n" );
		goto test_failed_exit;
	} 

	/* We passed the test */
	my_err = 0;

test_failed_exit:
	if(my_err != 0)
		my_err = -1;
	
test_passed_exit:
	if ( my_fd != -1 )
		close( my_fd );
	if ( my_bufferp != NULL ) {
		vm_deallocate(mach_task_self(), (vm_address_t)my_bufferp, my_buffer_size);	
	}
	 
	return( my_err );
}
Exemple #20
0
static int
dirlinkchk(FTSENT *p)
{
	struct links_entry {
		struct links_entry *next;
		struct links_entry *previous;
		int	 links;
		dev_t	 dev;
		ino_t	 ino;
	};
	static const size_t links_hash_initial_size = 8192;
	static struct links_entry **buckets;
	static struct links_entry *free_list;
	static size_t number_buckets;
	static unsigned long number_entries;
	static char stop_allocating;
	struct links_entry *le, **new_buckets;
	struct stat *st;
	size_t i, new_size;
	int hash;
	struct attrbuf {
		int size;
		int linkcount;
	} buf;
	struct attrlist attrList;

	memset(&attrList, 0, sizeof(attrList));
	attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
	attrList.dirattr = ATTR_DIR_LINKCOUNT;
	if (-1 == getattrlist(p->fts_path, &attrList, &buf, sizeof(buf), 0))
		return 0;
	if (buf.linkcount == 1)
		return 0;
	st = p->fts_statp;

	/* If necessary, initialize the hash table. */
	if (buckets == NULL) {
		number_buckets = links_hash_initial_size;
		buckets = malloc(number_buckets * sizeof(buckets[0]));
		if (buckets == NULL)
			errx(1, "No memory for directory hardlink detection");
		for (i = 0; i < number_buckets; i++)
			buckets[i] = NULL;
	}

	/* If the hash table is getting too full, enlarge it. */
	if (number_entries > number_buckets * 10 && !stop_allocating) {
		new_size = number_buckets * 2;
		new_buckets = malloc(new_size * sizeof(struct links_entry *));

		/* Try releasing the free list to see if that helps. */
		if (new_buckets == NULL && free_list != NULL) {
			while (free_list != NULL) {
				le = free_list;
				free_list = le->next;
				free(le);
			}
			new_buckets = malloc(new_size * sizeof(new_buckets[0]));
		}

		if (new_buckets == NULL) {
			stop_allocating = 1;
			warnx("No more memory for tracking directory hard links");
		} else {
			memset(new_buckets, 0,
			    new_size * sizeof(struct links_entry *));
			for (i = 0; i < number_buckets; i++) {
				while (buckets[i] != NULL) {
					/* Remove entry from old bucket. */
					le = buckets[i];
					buckets[i] = le->next;

					/* Add entry to new bucket. */
					hash = (le->dev ^ le->ino) % new_size;

					if (new_buckets[hash] != NULL)
						new_buckets[hash]->previous =
						    le;
					le->next = new_buckets[hash];
					le->previous = NULL;
					new_buckets[hash] = le;
				}
			}
			free(buckets);
			buckets = new_buckets;
			number_buckets = new_size;
		}
	}

	/* Try to locate this entry in the hash table. */
	hash = ( st->st_dev ^ st->st_ino ) % number_buckets;
	for (le = buckets[hash]; le != NULL; le = le->next) {
		if (le->dev == st->st_dev && le->ino == st->st_ino) {
			/*
			 * Save memory by releasing an entry when we've seen
			 * all of it's links.
			 */
			if (--le->links <= 0) {
				if (le->previous != NULL)
					le->previous->next = le->next;
				if (le->next != NULL)
					le->next->previous = le->previous;
				if (buckets[hash] == le)
					buckets[hash] = le->next;
				number_entries--;
				/* Recycle this node through the free list */
				if (stop_allocating) {
					free(le);
				} else {
					le->next = free_list;
					free_list = le;
				}
			}
			return (1);
		}
	}

	if (stop_allocating)
		return (0);
	/* Add this entry to the links cache. */
	if (free_list != NULL) {
		/* Pull a node from the free list if we can. */
		le = free_list;
		free_list = le->next;
	} else
		/* Malloc one if we have to. */
		le = malloc(sizeof(struct links_entry));
	if (le == NULL) {
		stop_allocating = 1;
		warnx("No more memory for tracking hard links");
		return (0);
	}
	le->dev = st->st_dev;
	le->ino = st->st_ino;
	le->links = buf.linkcount - 1;
	number_entries++;
	le->next = buckets[hash];
	le->previous = NULL;
	if (buckets[hash] != NULL)
		buckets[hash]->previous = le;
	buckets[hash] = le;
	return (0);
}