Example #1
0
KMountPoint::List KMountPoint::currentMountPoints(int infoNeeded)
{
  KMountPoint::List result;

#ifdef HAVE_GETMNTINFO

#ifdef GETMNTINFO_USES_STATVFS
    struct statvfs *mounted;
#else
    struct statfs *mounted;
#endif

    int num_fs = getmntinfo(&mounted, MNT_NOWAIT);

    for (int i=0;i<num_fs;i++) 
    {
      KMountPoint *mp = new KMountPoint();
      mp->m_mountedFrom = TQFile::decodeName(mounted[i].f_mntfromname);
      mp->m_mountPoint = TQFile::decodeName(mounted[i].f_mntonname);

#ifdef __osf__
      mp->m_mountType = TQFile::decodeName(mnt_names[mounted[i].f_type]);
#else
      mp->m_mountType = TQFile::decodeName(mounted[i].f_fstypename);
#endif      

      if (infoNeeded & NeedMountOptions)
      {
         struct fstab *ft = getfsfile(mounted[i].f_mntonname);
         TQString options = TQFile::decodeName(ft->fs_mntops);
         mp->m_mountOptions = TQStringList::split(',', options);
      }

      if (infoNeeded & NeedRealDeviceName)
      {
         if (mp->m_mountedFrom.startsWith("/"))
            mp->m_device = TDEStandardDirs::realPath(mp->m_mountedFrom);
      }
      // TODO: Strip trailing '/' ?
      result.append(mp);
   }

#elif defined(_AIX)

    struct vmount *mntctl_buffer;
    struct vmount *vm;
    char *mountedfrom;
    char *mountedto;
    int fsname_len, num;
    int buf_sz = 4096;

    mntctl_buffer = (struct vmount*)malloc(buf_sz);
    num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer);
    if (num == 0)
    {
	buf_sz = *(int*)mntctl_buffer;
	free(mntctl_buffer);
	mntctl_buffer = (struct vmount*)malloc(buf_sz);
	num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer);
    }

    if (num > 0)
    {
        /* iterate through items in the vmount structure: */
        vm = (struct vmount *)mntctl_buffer;
        for ( ; num > 0; num-- )
        {
            /* get the name of the mounted file systems: */
            fsname_len = vmt2datasize(vm, VMT_STUB);
            mountedto     = (char*)malloc(fsname_len + 1);
	    mountedto[fsname_len] = '\0';
            strncpy(mountedto, (char *)vmt2dataptr(vm, VMT_STUB), fsname_len);

            fsname_len = vmt2datasize(vm, VMT_OBJECT);
            mountedfrom     = (char*)malloc(fsname_len + 1);
	    mountedfrom[fsname_len] = '\0';
            strncpy(mountedfrom, (char *)vmt2dataptr(vm, VMT_OBJECT), fsname_len);

	    /* Look up the string for the file system type,
             * as listed in /etc/vfs.
             * ex.: nfs,jfs,afs,cdrfs,sfs,cachefs,nfs3,autofs
             */
            struct vfs_ent* ent = getvfsbytype(vm->vmt_gfstype);

            KMountPoint *mp = new KMountPoint();
            mp->m_mountedFrom = TQFile::decodeName(mountedfrom);
            mp->m_mountPoint = TQFile::decodeName(mountedto);
            mp->m_mountType = TQFile::decodeName(ent->vfsent_name);

            free(mountedfrom);
            free(mountedto);

            if (infoNeeded & NeedMountOptions)
            {
              // TODO
            }

            if (infoNeeded & NeedRealDeviceName)
            {
               if (mp->m_mountedFrom.startsWith("/"))
                  mp->m_device = TDEStandardDirs::realPath(mp->m_mountedFrom);
            }
            
            result.append(mp);

            /* goto the next vmount structure: */
            vm = (struct vmount *)((char *)vm + vm->vmt_length);
        }

	endvfsent( );
    }

    free( mntctl_buffer );
#elif defined(Q_WS_WIN)
    //TODO?
#else
   STRUCT_SETMNTENT mnttab;
   if ((mnttab = SETMNTENT(MNTTAB, "r")) == 0)
      return result;

   STRUCT_MNTENT fe;
   while (GETMNTENT(mnttab, fe))
   {
      KMountPoint *mp = new KMountPoint();
      mp->m_mountedFrom = TQFile::decodeName(FSNAME(fe));
         
      mp->m_mountPoint = TQFile::decodeName(MOUNTPOINT(fe));
      mp->m_mountType = TQFile::decodeName(MOUNTTYPE(fe));
      
      //Devices using supermount have their device names in the mount options
      //instead of the device field. That's why we need to read the mount options 
      if (infoNeeded & NeedMountOptions || (mp->m_mountType == "supermount"))
      {
         TQString options = TQFile::decodeName(MOUNTOPTIONS(fe));
         mp->m_mountOptions = TQStringList::split(',', options);
      }

      if (mp->m_mountType == "supermount")
         mp->m_mountedFrom = devNameFromOptions(mp->m_mountOptions);

      if (infoNeeded & NeedRealDeviceName)
      {
         if (mp->m_mountedFrom.startsWith("/"))
            mp->m_device = TDEStandardDirs::realPath(mp->m_mountedFrom);
      }
      // TODO: Strip trailing '/' ?
      result.append(mp);
   }
   ENDMNTENT(mnttab);
#endif
   return result;
}
Example #2
0
int
main(int ac, char **av) {
  int c, i, mntsize;
  char **command;
  struct procfs_status pfs;
  struct ex_types *funcs;
  struct statfs *mntbuf;
  int in_exec = 0;
  char *fname = NULL;
  int sigexit = 0;
  struct trussinfo *trussinfo;

  /* Initialize the trussinfo struct */
  trussinfo = (struct trussinfo *)malloc(sizeof(struct trussinfo));
  if (trussinfo == NULL)
	  errx(1, "malloc() failed");
  bzero(trussinfo, sizeof(struct trussinfo));
  trussinfo->outfile = stderr;

  /* Check where procfs is mounted if it is mounted */
  if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0)
	  err(1, "getmntinfo");
  for (i = 0; i < mntsize; i++) {
	  if (strcasecmp(mntbuf[i].f_mntfromname, "procfs") == 0) {
		  strlcpy(procfs_path, mntbuf[i].f_mntonname, sizeof(procfs_path));
		  have_procfs = 1;
		  break;
	  }
  }
  if (!have_procfs) {
	  errno = 2;
	  err(1, "You must have a mounted procfs to use truss");
  }

  while ((c = getopt(ac, av, "p:o:S")) != -1) {
    switch (c) {
    case 'p':	/* specified pid */
      trussinfo->pid = atoi(optarg);
      if (trussinfo->pid == getpid()) {
	      /* make sure truss doesn't trace itself */
	      fprintf(stderr, "truss: attempt to self trace: %d\n", trussinfo->pid);
	      exit(2);
      }
      break;
    case 'o':	/* Specified output file */
      fname = optarg;
      break;
    case 'S':	/* Don't trace signals */ 
      trussinfo->flags |= NOSIGS;
      break;
    default:
      usage();
    }
  }

  ac -= optind; av += optind;
  if ((trussinfo->pid == 0 && ac == 0) || (trussinfo->pid != 0 && ac != 0))
    usage();

  if (fname != NULL) { /* Use output file */
    if ((trussinfo->outfile = fopen(fname, "w")) == NULL)
      errx(1, "cannot open %s", fname);
  }

  /*
   * If truss starts the process itself, it will ignore some signals --
   * they should be passed off to the process, which may or may not
   * exit.  If, however, we are examining an already-running process,
   * then we restore the event mask on these same signals.
   */

  if (trussinfo->pid == 0) {	/* Start a command ourselves */
    command = av;
    trussinfo->pid = setup_and_wait(command);
    signal(SIGINT, SIG_IGN);
    signal(SIGTERM, SIG_IGN);
    signal(SIGQUIT, SIG_IGN);
  } else {
    signal(SIGINT, restore_proc);
    signal(SIGTERM, restore_proc);
    signal(SIGQUIT, restore_proc);
  }


  /*
   * At this point, if we started the process, it is stopped waiting to
   * be woken up, either in exit() or in execve().
   */

  Procfd = start_tracing(
      trussinfo->pid, S_EXEC | S_SCE | S_SCX | S_CORE | S_EXIT |
		     ((trussinfo->flags & NOSIGS) ? 0 : S_SIG));
  if (Procfd == -1)
    return 0;

  pfs.why = 0;

  funcs = set_etype(trussinfo);
  /*
   * At this point, it's a simple loop, waiting for the process to
   * stop, finding out why, printing out why, and then continuing it.
   * All of the grunt work is done in the support routines.
   */

  do {
    int val = 0;

    if (ioctl(Procfd, PIOCWAIT, &pfs) == -1)
      warn("PIOCWAIT top of loop");
    else {
      switch(i = pfs.why) {
      case S_SCE:
	funcs->enter_syscall(trussinfo, pfs.val);
	break;
      case S_SCX:
	/*
	 * This is so we don't get two messages for an exec -- one
	 * for the S_EXEC, and one for the syscall exit.  It also,
	 * conveniently, ensures that the first message printed out
	 * isn't the return-from-syscall used to create the process.
	 */

	if (in_exec) {
	  in_exec = 0;
	  break;
	}
	funcs->exit_syscall(trussinfo, pfs.val);
	break;
      case S_SIG:
	fprintf(trussinfo->outfile, "SIGNAL %lu\n", pfs.val);
	sigexit = pfs.val;
	break;
      case S_EXIT:
	fprintf (trussinfo->outfile, "process exit, rval = %lu\n", pfs.val);
	break;
      case S_EXEC:
	funcs = set_etype(trussinfo);
	in_exec = 1;
	break;
      default:
	fprintf (trussinfo->outfile, "Process stopped because of:  %d\n", i);
	break;
      }
    }
    if (ioctl(Procfd, PIOCCONT, val) == -1) {
      if (kill(trussinfo->pid, 0) == -1 && errno == ESRCH)
	break;
      else
	warn("PIOCCONT");
    }
  } while (pfs.why != S_EXIT);
  fflush(trussinfo->outfile);
  if (sigexit) {
    if (sigexit == SIGQUIT)
      exit(sigexit);
    (void) signal(sigexit, SIG_DFL);
    (void) kill(getpid(), sigexit);
  }
  return 0;
}
Example #3
0
int
main(int argc, char **argv)
{
	const char *mntfromname, **vfslist, *vfstype;
	struct fstab *fs;
	struct statfs *mntbuf;
	FILE *mountdfp;
	pid_t pid;
	int all, ch, i, init_flags, mntsize, rval, have_fstab;
	char *options;

	all = init_flags = 0;
	options = NULL;
	vfslist = NULL;
	vfstype = "ufs";
	while ((ch = getopt(argc, argv, "adF:fo:prwt:uv")) != -1) {
		switch (ch) {
		case 'a':
			all = 1;
			break;
		case 'd':
			debug = 1;
			break;
		case 'F':
			setfstab(optarg);
			break;
		case 'f':
			init_flags |= MNT_FORCE;
			break;
		case 'o':
			if (*optarg)
				options = catopt(options, optarg);
			break;
		case 'p':
			fstab_style = 1;
			verbose = 1;
			break;
		case 'r':
			options = catopt(options, "ro");
			break;
		case 't':
			if (vfslist != NULL)
				errx(1, "only one -t option may be specified");
			vfslist = makevfslist(optarg);
			vfstype = optarg;
			break;
		case 'u':
			init_flags |= MNT_UPDATE;
			break;
		case 'v':
			verbose = 1;
			break;
		case 'w':
			options = catopt(options, "noro");
			break;
		case '?':
		default:
			usage();
			/* NOTREACHED */
		}
	}
	argc -= optind;
	argv += optind;

#define	BADTYPE(type)							\
	(strcmp(type, FSTAB_RO) &&					\
	    strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ))

	rval = 0;
	switch (argc) {
	case 0:
		if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0)
			err(1, "getmntinfo");
		if (all) {
			while ((fs = getfsent()) != NULL) {
				if (BADTYPE(fs->fs_type))
					continue;
				if (checkvfsname(fs->fs_vfstype, vfslist))
					continue;
				if (hasopt(fs->fs_mntops, "noauto"))
					continue;
				if (!(init_flags & MNT_UPDATE) &&
				    ismounted(fs, mntbuf, mntsize))
					continue;
				options = update_options(options,
				    fs->fs_mntops, mntbuf->f_flags);
				if (mountfs(fs->fs_vfstype, fs->fs_spec,
				    fs->fs_file, init_flags, options,
				    fs->fs_mntops))
					rval = 1;
			}
		} else if (fstab_style) {
			for (i = 0; i < mntsize; i++) {
				if (checkvfsname(mntbuf[i].f_fstypename, vfslist))
					continue;
				putfsent(&mntbuf[i]);
			}
		} else {
			for (i = 0; i < mntsize; i++) {
				if (checkvfsname(mntbuf[i].f_fstypename,
				    vfslist))
					continue;
				prmount(&mntbuf[i]);
			}
		}
		exit(rval);
	case 1:
		if (vfslist != NULL)
			usage();

		rmslashes(*argv, *argv);

		if (init_flags & MNT_UPDATE) {
			mntfromname = NULL;
			have_fstab = 0;
			if ((mntbuf = getmntpt(*argv)) == NULL)
				errx(1, "not currently mounted %s", *argv);
			/*
			 * Only get the mntflags from fstab if both mntpoint
			 * and mntspec are identical. Also handle the special
			 * case where just '/' is mounted and 'spec' is not
			 * identical with the one from fstab ('/dev' is missing
			 * in the spec-string at boot-time).
			 */
			if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL) {
				if (strcmp(fs->fs_spec,
				    mntbuf->f_mntfromname) == 0 &&
				    strcmp(fs->fs_file,
				    mntbuf->f_mntonname) == 0) {
					have_fstab = 1;
					mntfromname = mntbuf->f_mntfromname;
				} else if (argv[0][0] == '/' &&
				    argv[0][1] == '\0') {
					fs = getfsfile("/");
					have_fstab = 1;
					mntfromname = fs->fs_spec;
				}
			}
			if (have_fstab) {
				options = update_options(options, fs->fs_mntops,
				    mntbuf->f_flags);
			} else {
				mntfromname = mntbuf->f_mntfromname;
				options = update_options(options, NULL,
				    mntbuf->f_flags);
			}
			rval = mountfs(mntbuf->f_fstypename, mntfromname,
			    mntbuf->f_mntonname, init_flags, options, 0);
			break;
		}
		if ((fs = getfsfile(*argv)) == NULL &&
		    (fs = getfsspec(*argv)) == NULL)
			errx(1, "%s: unknown special file or file system",
			    *argv);
		if (BADTYPE(fs->fs_type))
			errx(1, "%s has unknown file system type",
			    *argv);
		rval = mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file,
		    init_flags, options, fs->fs_mntops);
		break;
	case 2:
		/*
		 * If -t flag has not been specified, the path cannot be
		 * found.
		 *
		 * If the spec is not a file and contains a ':' then assume
		 * NFS.
		 *
		 * If the spec is a cdev attempt to extract the fstype from
		 * the label.
		 *
		 * When all else fails ufs is assumed.
		 */
		if (vfslist == NULL) {
			if (strpbrk(argv[0], ":") != NULL &&
			    access(argv[0], 0) == -1) {
				vfstype = "nfs";
			} else {
				checkdisklabel(argv[0], &vfstype);
			}
		}

		rval = mountfs(vfstype, getdevpath(argv[0], 0), argv[1],
			       init_flags, options, NULL);
		break;
	default:
		usage();
		/* NOTREACHED */
	}

	/*
	 * If the mount was successfully, and done by root, tell mountd the
	 * good news.  Pid checks are probably unnecessary, but don't hurt.
	 */
	if (rval == 0 && getuid() == 0 &&
	    (mountdfp = fopen(_PATH_MOUNTDPID, "r")) != NULL) {
		if (fscanf(mountdfp, "%d", &pid) == 1 &&
		     pid > 0 && kill(pid, SIGHUP) == -1 && errno != ESRCH)
			err(1, "signal mountd");
		fclose(mountdfp);
	}

	exit(rval);
}
Example #4
0
int is_fs_mounted(const char *dev)
{
    int found = 0;
#ifdef __FreeBSD__
    int count, i;
    struct statfs *mntbuf;

    count = getmntinfo(&mntbuf, 0);
    if ( count > 0 ) {
        for ( i = 0; i < count; ++i ) {
            if ( !strcmp(mntbuf[i].f_mntfromname, dev) ) {
                found = 1;
                break;
            }
        }
    }
#elif defined(hpux)
    const char *mtab, *mnttype;
    FILE *mountfp;
    struct mntent *mntent;

    if ( !access("/etc/pfs_mtab", F_OK) ) {
		mtab = "/etc/pfs_mtab";
		mnttype = "pfs-rrip";
    } else {
		mtab = MOUNTS_FILE;
		mnttype = MNTTYPE_CDROM;
    }

    mountfp = setmntent(mtab, "r" );
	if ( mountfp ) {
		while( (mntent = getmntent( mountfp )) != NULL ) {
            if ( !strcmp(mntent->mnt_type, mnttype) ) {
				found = 1;
				break;
			}
		}
        endmntent( mountfp );
	}
#elif defined(sco)
	FILE *cmd = popen("/etc/mount", "r");
	if ( cmd ) {
		char device[32] = "";
		while ( fscanf(cmd, "%*s on %32s %*[^\n]", device) > 0 ) {
			if ( !strcmp(device, dev) ) {
				found = 1;
				break;
			}
		}
		pclose(cmd);
	}
#elif defined(__svr4__)
	struct mnttab mnt;
	FILE *mtab = fopen(MOUNTS_FILE, "r");
	if ( mtab != NULL ) {
		while ( getmntent(mtab, &mnt)==0 ) {
			if ( !strcmp(mnt.mnt_special, dev) ) {
				found = 1;
				break;
			}
		}
		fclose(mtab);
	}
#elif defined(darwin)
    // Taken from FreeBSD section (since Darwin is based on FreeBSD)
    int count, i;
    struct statfs *mntbuf;

    count = getmntinfo(&mntbuf, 0);
    if ( count > 0 ) {
        for ( i = 0; i < count; ++i ) {
            if ( !strcmp(mntbuf[i].f_mntfromname, dev) ) {
                found = 1;
                break;
            }
        }
    }
#else
    struct mntent *mnt;
    FILE *mtab = setmntent(MOUNTS_FILE, "r" );
    if( mtab != NULL ) {
        while( (mnt = getmntent( mtab )) != NULL ){
            if ( !strcmp(mnt->mnt_fsname, dev) ) {
                found = 1;
                break;
            }
        }
        endmntent(mtab);
    }
#endif
    return found;
}
Example #5
0
static void __DAStageProbeCallback( int status, CFBooleanRef clean, CFStringRef name, CFUUIDRef uuid, void * context )
{
    DADiskRef         disk = context;
    CFMutableArrayRef keys = NULL;
    CFStringRef       kind = NULL;

    DALogDebugHeader( "%s -> %s", gDAProcessNameID, gDAProcessNameID );

    if ( status )
    {
        CFMutableArrayRef candidates;

        candidates = ( void * ) DADiskGetContext( disk );

        if ( DADiskGetFileSystem( disk ) )
        {
            kind = DAFileSystemGetKind( DADiskGetFileSystem( disk ) );

            DALogDebug( "  probed disk, id = %@, with %@, failure.", disk, kind );

            if ( status != FSUR_UNRECOGNIZED )
            {
                DALogError( "unable to probe %@ (status code 0x%08X).", disk, status );
            }
        }

        /*
         * Find a probe candidate for this media object.
         */

        while ( CFArrayGetCount( candidates ) )
        {
            CFDictionaryRef candidate;

            candidate = CFArrayGetValueAtIndex( candidates, 0 );

            if ( candidate )
            {
                DAFileSystemRef filesystem;

                filesystem = ( void * ) CFDictionaryGetValue( candidate, kDAFileSystemKey );

                if ( filesystem )
                {
                    CFDictionaryRef properties;

                    properties = CFDictionaryGetValue( candidate, CFSTR( kFSMediaPropertiesKey ) );

                    if ( properties )
                    {
                        boolean_t match = FALSE;

                        IOServiceMatchPropertyTable( DADiskGetIOMedia( disk ), properties, &match );

                        if ( match )
                        {
                            /*
                             * We have found a probe candidate for this media object.
                             */

                            kind = DAFileSystemGetKind( filesystem );

                            DADiskSetFileSystem( disk, filesystem );

                            if ( CFDictionaryGetValue( candidate, CFSTR( "autodiskmount" ) ) == kCFBooleanFalse )
                            {
                                DADiskSetOption( disk, kDADiskOptionMountAutomatic,        FALSE );
                                DADiskSetOption( disk, kDADiskOptionMountAutomaticNoDefer, FALSE );
                            }

                            CFArrayRemoveValueAtIndex( candidates, 0 );

                            DALogDebug( "  probed disk, id = %@, with %@, ongoing.", disk, kind );

                            DAFileSystemProbe( filesystem, DADiskGetDevice( disk ), __DAStageProbeCallback, context );

                            return;
                        }
                    }
                }
            }

            CFArrayRemoveValueAtIndex( candidates, 0 );
        }
    }

    DADiskSetState( disk, kDADiskStateRequireRepair,       FALSE );
    DADiskSetState( disk, kDADiskStateRequireRepairQuotas, FALSE );

    if ( status )
    {
        /*
         * We have found no probe match for this media object.
         */

        kind = NULL;

        if ( DADiskGetFileSystem( disk ) )
        {
            DADiskSetFileSystem( disk, NULL );

            DALogDebug( "  probed disk, id = %@, no match.", disk );
        }
    }
    else
    {
        /*
         * We have found a probe match for this media object.
         */

        kind = DAFileSystemGetKind( DADiskGetFileSystem( disk ) );

///w:start
        if ( DADiskGetDescription( disk, kDADiskDescriptionMediaWritableKey ) == kCFBooleanFalse )
        {
            clean = kCFBooleanTrue;
        }
///w:stop
        if ( clean == kCFBooleanFalse )
        {
            DADiskSetState( disk, kDADiskStateRequireRepair,       TRUE );
            DADiskSetState( disk, kDADiskStateRequireRepairQuotas, TRUE );
        }

        DALogDebug( "  probed disk, id = %@, with %@, success.", disk, kind );
    }

    keys = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );

    if ( keys )
    {
        CFTypeRef object;

        object = kind ? kCFBooleanTrue : kCFBooleanFalse;

        if ( DADiskCompareDescription( disk, kDADiskDescriptionVolumeMountableKey, object ) )
        {
            DADiskSetDescription( disk, kDADiskDescriptionVolumeMountableKey, object );

            CFArrayAppendValue( keys, kDADiskDescriptionVolumeMountableKey );
        }

        if ( DADiskCompareDescription( disk, kDADiskDescriptionVolumeKindKey, kind ) )
        {
            DADiskSetDescription( disk, kDADiskDescriptionVolumeKindKey, kind );

            CFArrayAppendValue( keys, kDADiskDescriptionVolumeKindKey );
        }

        if ( DADiskCompareDescription( disk, kDADiskDescriptionVolumeNameKey, name ) )
        {
            DADiskSetDescription( disk, kDADiskDescriptionVolumeNameKey, name );

            CFArrayAppendValue( keys, kDADiskDescriptionVolumeNameKey );
        }

        if ( DADiskCompareDescription( disk, kDADiskDescriptionVolumeUUIDKey, uuid ) )
        {
            DADiskSetDescription( disk, kDADiskDescriptionVolumeUUIDKey, uuid );

            CFArrayAppendValue( keys, kDADiskDescriptionVolumeUUIDKey );
        }

        if ( CFArrayGetCount( keys ) )
        {
            if ( DADiskGetState( disk, kDADiskStateStagedAppear ) )
            {
                DADiskDescriptionChangedCallback( disk, keys );
            }
        }

        CFRelease( keys );
    }

    if ( DADiskGetState( disk, kDADiskStateStagedMount ) == FALSE )
    {
        struct statfs * mountList;
        int             mountListCount;
        int             mountListIndex;

        /*
         * Determine whether the disk is mounted.
         */

        mountListCount = getmntinfo( &mountList, MNT_NOWAIT );

        for ( mountListIndex = 0; mountListIndex < mountListCount; mountListIndex++ )
        {
            if ( mountList[mountListIndex].f_fsid.val[0] == DADiskGetBSDNode( disk ) )
            {
                /*
                 * We have determined that the disk is mounted.
                 */

                CFURLRef path;

                path = CFURLCreateFromFileSystemRepresentation( kCFAllocatorDefault,
                                                                ( void * ) mountList[mountListIndex].f_mntonname,
                                                                strlen( mountList[mountListIndex].f_mntonname ),
                                                                TRUE );

                if ( path )
                {
                    _DAMountCreateTrashFolder( disk, path );
                    
                    DADiskSetBypath( disk, path );

                    DADiskSetDescription( disk, kDADiskDescriptionVolumePathKey, path );

                    CFRelease( path );
                }

                if ( strcmp( mountList[mountListIndex].f_mntonname, "/" ) == 0 )
                {
                    path = DAMountCreateMountPointWithAction( disk, kDAMountPointActionLink );

                    if ( path )
                    {
                        DADiskSetBypath( disk, path );

                        CFRelease( path );
                    }

                    DADiskSetOption( disk, kDADiskOptionMountAutomatic,        TRUE );
                    DADiskSetOption( disk, kDADiskOptionMountAutomaticNoDefer, TRUE );
                }

                DADiskSetState( disk, kDADiskStateRequireRepair,       FALSE );
                DADiskSetState( disk, kDADiskStateRequireRepairQuotas, FALSE );

                break;
            }
        }
    }

    DAUnitSetState( disk, kDAUnitStateCommandActive, FALSE );

    DADiskSetState( disk, kDADiskStateCommandActive, FALSE );

    DADiskSetContext( disk, NULL );

    DAStageSignal( );

    CFRelease( disk );
}
Example #6
0
/** resolve device name to mount point / drive letter
 *  @param device device name / disk number
 *  @return mount point / drive letter
 */
QString Utils::resolveMountPoint(QString device)
{
    qDebug() << "[Utils] resolving mountpoint:" << device;

#if defined(Q_OS_LINUX)
    FILE *mn = setmntent("/etc/mtab", "r");
    if(!mn)
        return QString("");

    struct mntent *ent;
    while((ent = getmntent(mn))) {
        // Check for valid filesystem. Allow hfs too, as an Ipod might be a
        // MacPod.
        if(QString(ent->mnt_fsname) == device) {
            QString result;
            if(QString(ent->mnt_type).contains("vfat", Qt::CaseInsensitive)
                    || QString(ent->mnt_type).contains("hfs", Qt::CaseInsensitive)) {
                qDebug() << "[Utils] resolved mountpoint is:" << ent->mnt_dir;
                result = QString(ent->mnt_dir);
            }
            else {
                qDebug() << "[Utils] mountpoint is wrong filesystem!";
            }
            endmntent(mn);
            return result;
        }
    }
    endmntent(mn);

#endif

#if defined(Q_OS_MACX) || defined(Q_OS_OPENBSD)
    int num;
    struct statfs *mntinf;

    num = getmntinfo(&mntinf, MNT_WAIT);
    while(num--) {
        // Check for valid filesystem. Allow hfs too, as an Ipod might be a
        // MacPod.
        if(QString(mntinf->f_mntfromname) == device) {
            if(QString(mntinf->f_fstypename).contains("msdos", Qt::CaseInsensitive)
                || QString(mntinf->f_fstypename).contains("hfs", Qt::CaseInsensitive)) {
                qDebug() << "[Utils] resolved mountpoint is:" << mntinf->f_mntonname;
                return QString(mntinf->f_mntonname);
            }
            else {
                qDebug() << "[Utils] mountpoint is wrong filesystem!";
                return QString();
            }
        }
        mntinf++;
    }
#endif

#if defined(Q_OS_WIN32)
    QString result;
    unsigned int driveno = device.replace(QRegExp("^.*([0-9]+)"), "\\1").toInt();

    int letter;
    for(letter = 'A'; letter <= 'Z'; letter++) {
        if(resolveDevicename(QString(letter)).toUInt() == driveno) {
            result = letter;
            qDebug() << "[Utils] resolved mountpoint is:" << result;
            break;
        }
    }
    if(!result.isEmpty())
        return result + ":/";
#endif
    qDebug() << "[Utils] resolving mountpoint failed!";
    return QString("");
}
Example #7
0
bool GetInfo_Partitions (QListView *lbox)
{
	int num; // number of mounts
	// FIXME: older pkgsrc patches checked ST_RDONLY for this declaration
	// what is ST_RDONLY and how does it affect getmntinfo?
	struct statfs *mnt; // mount data pointer

	// get mount info
	if (!(num=getmntinfo(&mnt, MNT_WAIT))) {
		kdError() << "getmntinfo failed" << endl;
		return false;
	}

	// table headers
	lbox->addColumn(i18n("Device"));
	lbox->addColumn(i18n("Mount Point"));
	lbox->addColumn(i18n("FS Type"));
	lbox->addColumn(i18n("Total Size"));
	lbox->addColumn(i18n("Free Size"));
	lbox->addColumn(i18n("Total Nodes"));
	lbox->addColumn(i18n("Free Nodes"));
	lbox->addColumn(i18n("Flags"));

	// mnt points into a static array (no need to free it)
	for(; num--; ++mnt) {
		unsigned long long big[2];
		QString vv[5];

		big[0] = big[1] = mnt->f_bsize; // coerce the product
		big[0] *= mnt->f_blocks;
		big[1] *= mnt->f_bavail; // FIXME: use f_bfree if root?

		// convert to strings
		vv[0] = KIO::convertSize(big[0]);
		vv[1] = QString::fromLatin1("%1 (%2%%)")
				.arg(KIO::convertSize(big[1]))
				.arg(mnt->f_blocks ? mnt->f_bavail*100/mnt->f_blocks : 0);

		// FIXME: these two are large enough to punctuate
		vv[2] = QString::number(mnt->f_files);
		vv[3] = QString::fromLatin1("%1 (%2%%) ")
				.arg(mnt->f_ffree)
				.arg(mnt->f_files ? mnt->f_ffree*100/mnt->f_files : 0);

		vv[4] = QString::null;
#define MNTF(x) if (mnt->f_flags & MNT_##x) vv[4] += QString::fromLatin1(#x " ");
		MNTF(ASYNC)
		MNTF(DEFEXPORTED)
		MNTF(EXKERB)
		MNTF(EXNORESPORT)
		MNTF(EXPORTANON)
		MNTF(EXPORTED)
		MNTF(EXPUBLIC)
		MNTF(EXRDONLY)
		MNTF(IGNORE)
		MNTF(LOCAL)
		MNTF(NOATIME)
		MNTF(NOCOREDUMP)
		MNTF(NODEV)
		MNTF(NODEVMTIME)
		MNTF(NOEXEC)
		MNTF(NOSUID)
		MNTF(QUOTA)
		MNTF(RDONLY)
		MNTF(ROOTFS)
		MNTF(SOFTDEP)
		MNTF(SYMPERM)
		MNTF(SYNCHRONOUS)
		MNTF(UNION)
#undef MNTF

		// put it in the table
		// FIXME: there're more data but we have limited args (this is wrong! just add!)
		new QListViewItem(lbox,
			// FIXME: names need pad space
			mnt->f_mntfromname,
			mnt->f_mntonname,
			mnt->f_fstypename,
			vv[0], vv[1], vv[2], vv[3], vv[4]);
	}

	// job well done
	return true;
}
Example #8
0
int
main(int argc, char *argv[])
{
	int ch;
	struct partition *pp;
	struct disklabel *lp;
	struct partition oldpartition;
	struct stat st;
	struct statfs *mp;
	struct rlimit rl;
	int fsi = -1, fso, len, n, maxpartitions;
	char *cp = NULL, *s1, *s2, *special, *opstring, *realdev;
	char *fstype = NULL;
	char **saveargv = argv;
	int ffsflag = 1;
	const char *errstr;
	long long fssize_input = 0;
	int fssize_usebytes = 0;
	u_int64_t nsecs;

	getphysmem();
	maxpartitions = getmaxpartitions();
	if (maxpartitions > 26)
		fatal("insane maxpartitions value %d", maxpartitions);

	opstring = "NO:S:T:b:c:e:f:g:h:i:m:o:qs:t:";
	while ((ch = getopt(argc, argv, opstring)) != -1) {
		switch (ch) {
		case 'N':
			Nflag = 1;
			break;
		case 'O':
			Oflag = strtonum(optarg, 0, 2, &errstr);
			if (errstr)
				fatal("%s: invalid ffs version", optarg);
			break;
		case 'S':
			if (scan_scaled(optarg, &sectorsize) == -1 ||
			    sectorsize <= 0 || (sectorsize % DEV_BSIZE))
				fatal("sector size invalid: %s", optarg);
			break;
		case 'T':
			disktype = optarg;
			break;
		case 'b':
			bsize = strtonum(optarg, MINBSIZE, MAXBSIZE, &errstr);
			if (errstr)
				fatal("block size is %s: %s", errstr, optarg);
			break;
		case 'c':
			maxfrgspercg = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("fragments per cylinder group is %s: %s",
				    errstr, optarg);
			break;
		case 'e':
			maxbpg = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("blocks per file in a cylinder group is"
				    " %s: %s", errstr, optarg);
			break;
		case 'f':
			fsize = strtonum(optarg, MINBSIZE / MAXFRAG, MAXBSIZE,
			    &errstr);
			if (errstr)
				fatal("fragment size is %s: %s",
				    errstr, optarg);
			break;
		case 'g':
			avgfilesize = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("average file size is %s: %s",
				    errstr, optarg);
			break;
		case 'h':
			avgfilesperdir = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("average files per dir is %s: %s",
				    errstr, optarg);
			break;
		case 'i':
			density = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("bytes per inode is %s: %s",
				    errstr, optarg);
			break;
		case 'm':
			minfree = strtonum(optarg, 0, 99, &errstr);
			if (errstr)
				fatal("free space %% is %s: %s",
				    errstr, optarg);
			break;
		case 'o':
			if (strcmp(optarg, "space") == 0)
				reqopt = opt = FS_OPTSPACE;
			else if (strcmp(optarg, "time") == 0)
				reqopt = opt = FS_OPTTIME;
			else
				fatal("%s: unknown optimization preference: "
				    "use `space' or `time'.", optarg);
			break;
		case 'q':
			quiet = 1;
			break;
		case 's':
			if (scan_scaled(optarg, &fssize_input) == -1 ||
			    fssize_input == 0)
				fatal("file system size invalid: %s", optarg);
			fssize_usebytes = 0;    /* in case of multiple -s */
			for (s1 = optarg; *s1 != '\0'; s1++)
				if (isalpha((unsigned char)*s1)) {
					fssize_usebytes = 1;
					break;
				}
			break;
		case 't':
			fstype = optarg;
			if (strcmp(fstype, "ffs"))
				ffsflag = 0;
			break;
		case '?':
		default:
			usage();
		}
		if (!ffsflag)
			break;
	}
	argc -= optind;
	argv += optind;

	if (ffsflag && argc != 1)
		usage();

	special = argv[0];

	char execname[MAXPATHLEN], name[MAXPATHLEN];

	if (fstype == NULL)
		fstype = readlabelfs(special, 0);
	if (fstype != NULL && strcmp(fstype, "ffs")) {
		snprintf(name, sizeof name, "newfs_%s", fstype);
		saveargv[0] = name;
		snprintf(execname, sizeof execname, "%s/newfs_%s", _PATH_SBIN,
		    fstype);
		(void)execv(execname, saveargv);
		snprintf(execname, sizeof execname, "%s/newfs_%s",
		    _PATH_USRSBIN, fstype);
		(void)execv(execname, saveargv);
		err(1, "%s not found", name);
	}

	if (Nflag) {
		fso = -1;
	} else {
		fso = opendev(special, O_WRONLY, 0, &realdev);
		if (fso < 0)
			fatal("%s: %s", special, strerror(errno));
		special = realdev;

		/* Bail if target special is mounted */
		n = getmntinfo(&mp, MNT_NOWAIT);
		if (n == 0)
			fatal("%s: getmntinfo: %s", special, strerror(errno));

		len = sizeof(_PATH_DEV) - 1;
		s1 = special;
		if (strncmp(_PATH_DEV, s1, len) == 0)
			s1 += len;

		while (--n >= 0) {
			s2 = mp->f_mntfromname;
			if (strncmp(_PATH_DEV, s2, len) == 0) {
				s2 += len - 1;
				*s2 = 'r';
			}
			if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0)
				fatal("%s is mounted on %s",
				    special, mp->f_mntonname);
			++mp;
		}
	}
	fsi = opendev(special, O_RDONLY, 0, NULL);
	if (fsi < 0)
		fatal("%s: %s", special, strerror(errno));
	if (fstat(fsi, &st) < 0)
		fatal("%s: %s", special, strerror(errno));
	if (S_ISBLK(st.st_mode))
		fatal("%s: block device", special);
	if (!S_ISCHR(st.st_mode))
		warnx("%s: not a character-special device",
		    special);
	if (*argv[0] == '\0')
		fatal("empty partition name supplied");
	cp = argv[0] + strlen(argv[0]) - 1;
	if ((*cp < 'a' || *cp > ('a' + maxpartitions - 1))
	    && !isdigit((unsigned char)*cp))
		fatal("%s: can't figure out file system partition",
		    argv[0]);
	lp = getdisklabel(special, fsi);
	if (pledge("stdio disklabel tty", NULL) == -1)
		err(1, "pledge");
	if (isdigit((unsigned char)*cp))
		pp = &lp->d_partitions[0];
	else
		pp = &lp->d_partitions[*cp - 'a'];
	if (DL_GETPSIZE(pp) == 0)
		fatal("%s: `%c' partition is unavailable",
		    argv[0], *cp);
	if (pp->p_fstype == FS_BOOT)
		fatal("%s: `%c' partition overlaps boot program",
		      argv[0], *cp);
havelabel:
	if (sectorsize == 0) {
		sectorsize = lp->d_secsize;
		if (sectorsize <= 0)
			fatal("%s: no default sector size", argv[0]);
	}

	if (fssize_input < 0) {
#if 1
		fatal("-s < 0 not yet implemented");
#else
		long long gap; /* leave gap at the end of partition */
		fssize_input = -fssize_input;
		if (fssize_usebytes) {
			gap = (daddr_t)fssize_input / (daddr_t)sectorsize;
			if ((daddr_t)fssize_input % (daddr_t)sectorsize != 0)
				gap++;
		} else
			gap = fssize_input;
		if (gap >= DL_GETPSIZE(pp))
			fatal("%s: requested gap of %lld sectors on partition "
			    "'%c' is too big", argv[0], gap, *cp);
		nsecs = DL_GETPSIZE(pp) - gap;
#endif
	} else {
		if (fssize_usebytes) {
			nsecs = fssize_input / sectorsize;
			if (fssize_input % sectorsize != 0)
				nsecs++;
		} else if (fssize_input == 0)
			nsecs = DL_GETPSIZE(pp);
		else
			nsecs = fssize_input;
	}

	if (nsecs > DL_GETPSIZE(pp))
	       fatal("%s: maximum file system size on the `%c' partition is "
		   "%llu sectors", argv[0], *cp, DL_GETPSIZE(pp));

	/* Can't use DL_SECTOBLK() because sectorsize may not be from label! */
	fssize = nsecs * (sectorsize / DEV_BSIZE);
	if (fsize == 0) {
		fsize = DISKLABELV1_FFS_FSIZE(pp->p_fragblock);
		if (fsize <= 0)
			fsize = MAX(DFL_FRAGSIZE, lp->d_secsize);
	}
	if (bsize == 0) {
		bsize = DISKLABELV1_FFS_BSIZE(pp->p_fragblock);
		if (bsize <= 0)
			bsize = MIN(DFL_BLKSIZE, 8 * fsize);
	}
	if (density == 0)
		density = NFPI * fsize;
	if (minfree < MINFREE && opt != FS_OPTSPACE && reqopt == -1) {
		warnx("warning: changing optimization to space "
		    "because minfree is less than %d%%\n", MINFREE);
		opt = FS_OPTSPACE;
	}
	if (maxbpg == 0) {
		if (Oflag <= 1)
			maxbpg = MAXBLKPG_FFS1(bsize);
		else
			maxbpg = MAXBLKPG_FFS2(bsize);
	}
	oldpartition = *pp;

	mkfs(pp, special, fsi, fso);
	if (!Nflag && memcmp(pp, &oldpartition, sizeof(oldpartition)))
		rewritelabel(special, fso, lp);
	if (!Nflag)
		close(fso);
	close(fsi);
	exit(0);
}
Example #9
0
/*
 * Create a snapshot of the file system currently mounted on the first argument
 * using the second argument as backing store and return an open file
 * descriptor for the snapshot.  If the second argument is NULL, use the first
 * as backing store.  If the third argument is not NULL, it gets the time the
 * snapshot was created.  If the fourth argument is not NULL, it gets the
 * snapshot device path.
 */
int
snap_open(char *file, char *backup, time_t *snap_date, char **snap_dev)
{
	int i, n, fd, israw, fsinternal, dounlink;
	char path[MAXPATHLEN], fss_dev[14], *cp;
	dev_t mountdev;
	struct fss_set fss;
	struct fss_get fsg;
	struct stat sb;
	struct statvfs *mntbuf, *fs, fsb;

	dounlink = 0;
	fd = -1;
	mntbuf = NULL;

	/*
	 * Lookup the mount point. `file' is either a directory or a raw
	 * character device.
	 */
	if (lstat(file, &sb) < 0)
		goto fail;
	fss.fss_mount = NULL;
	if (S_ISCHR(sb.st_mode)) {
		if ((cp = strrchr(file, '/')) == NULL || cp[1] != 'r') {
			errno = EINVAL;
			goto fail;
		}
		snprintf(path, sizeof(path), "%.*s/%s",
		    (int)(cp - file), file, cp + 2);
		n = getmntinfo(&mntbuf, MNT_NOWAIT);
		for (fs = mntbuf, i = 0; i < n; i++, fs++) {
			if (strcmp(fs->f_mntfromname, path) == 0) {
				fss.fss_mount = fs->f_mntonname;
				if (stat(fss.fss_mount, &sb) < 0)
					goto fail;
				break;
			}
		}
	} else if (S_ISDIR(sb.st_mode))
		fss.fss_mount = file;
	if (fss.fss_mount == NULL) {
		errno = EINVAL;
		goto fail;
	}
	fss.fss_bstore = backup ? backup : fss.fss_mount;
	fss.fss_csize = 0;
	mountdev = sb.st_dev;

	/*
	 * Prepare the backing store. `backup' is either a raw device,
	 * a file or a directory.  If it is a file, it must not exist.
	 */
	israw = 0;
	if (stat(fss.fss_bstore, &sb) == 0) {
		if (S_ISDIR(sb.st_mode)) {
			snprintf(path, sizeof(path),
			    "%s/XXXXXXXXXX", fss.fss_bstore);
			fd = mkstemp(path);
			fss.fss_bstore = path;
			dounlink = 1;
		} else if (S_ISCHR(sb.st_mode)) {
			fd = open(fss.fss_bstore, O_RDWR);
			israw = 1;
		} else
			goto fail;
	} else {
		fd = open(fss.fss_bstore, O_CREAT|O_EXCL|O_WRONLY, 0600);
		dounlink = 1;
	}
	if (fd < 0)
		goto fail;

	if (fstat(fd, &sb) < 0)
		goto fail;
	fsinternal = (!israw && sb.st_dev == mountdev);

	/*
	 * If the backing store is a plain file and the snapshot
	 * is not file system internal, truncate to file system
	 * free space.
	 */
	if (!israw && !fsinternal) {
		if (statvfs(fss.fss_bstore, &fsb) < 0)
			goto fail;
		if (ftruncate(fd, (off_t)fsb.f_frsize*fsb.f_bavail) < 0)
			goto fail;
	}

	if (close(fd) < 0)
		goto fail;

	fss.fss_flags = FSS_UNCONFIG_ON_CLOSE;
	if (dounlink)
		fss.fss_flags |= FSS_UNLINK_ON_CREATE;
	/*
	 * Create the snapshot on the first free snapshot device.
	 */
	for (i = 0; ; i++) {
		snprintf(fss_dev, sizeof(fss_dev), "/dev/rfss%d", i);
		if ((fd = open(fss_dev, O_RDWR, 0)) < 0)
			goto fail;

		if (ioctl(fd, FSSIOCSET, &fss) < 0) {
			if (errno != EBUSY)
				goto fail;
			close(fd);
			fd = -1;
			continue;
		}
		dounlink = 0;

		if (snap_dev != NULL) {
			*snap_dev = strdup(fss_dev);
			if (*snap_dev == NULL) {
				ioctl(fd, FSSIOCCLR);
				goto fail;
			}
		}

		if (ioctl(fd, FSSIOCGET, &fsg) < 0) {
			ioctl(fd, FSSIOCCLR);
			goto fail;
		}

		if (mntbuf)
			free(mntbuf);
		if (snap_date != NULL)
			*snap_date = fsg.fsg_time.tv_sec;
		return fd;
	}

fail:
	if (mntbuf)
		free(mntbuf);
	if (dounlink)
		unlink(fss.fss_bstore);
	if (fd >= 0)
		close(fd);

	return -1;
}
Example #10
0
int
main(int argc, char *argv[])
{
	struct stat stbuf;
	struct statvfs *mntbuf;
	long mntsize;
	int ch, i, maxwidth, width;
	char *mntpt;

	setprogname(argv[0]);
	(void)setlocale(LC_ALL, "");

	while ((ch = getopt(argc, argv, "aGghiklmnPt:")) != -1)
		switch (ch) {
		case 'a':
			aflag = 1;
			break;
		case 'g':
			hflag = 0;
			usize = 1024 * 1024 * 1024;
			break;
		case 'G':
			gflag = 1;
			break;
		case 'h':
			hflag = 1;
			usize = 0;
			break;
		case 'i':
			iflag = 1;
			break;
		case 'k':
			hflag = 0;
			usize = 1024;
			break;
		case 'l':
			lflag = 1;
			break;
		case 'm':
			hflag = 0;
			usize = 1024 * 1024;
			break;
		case 'n':
			nflag = 1;
			break;
		case 'P':
			Pflag = 1;
			break;
		case 't':
			if (typelist != NULL)
				errx(EXIT_FAILURE,
				    "only one -t option may be specified.");
			maketypelist(optarg);
			break;
		case '?':
		default:
			usage();
		}

	if (gflag && (Pflag || iflag))
		errx(EXIT_FAILURE,
		    "only one of -G and -P or -i may be specified");
	if (Pflag && iflag)
		errx(EXIT_FAILURE,
		    "only one of -P and -i may be specified");
#if 0
	/*
	 * The block size cannot be checked until after getbsize() is called.
	 */
	if (Pflag && (hflag || (usize != 1024 && usize != 512)))
		errx(EXIT_FAILURE,
		    "non-standard block size incompatible with -P");
#endif
	argc -= optind;
	argv += optind;

	mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
	if (mntsize == 0)
		err(EXIT_FAILURE,
		    "retrieving information on mounted file systems");

	if (*argv == NULL) {
		mntsize = regetmntinfo(&mntbuf, mntsize);
	} else {
		if ((mntbuf = malloc(argc * sizeof(*mntbuf))) == NULL)
			err(EXIT_FAILURE, "can't allocate statvfs array");
		mntsize = 0;
		for (/*EMPTY*/; *argv != NULL; argv++) {
			if (stat(*argv, &stbuf) < 0) {
				if ((mntpt = getmntpt(*argv)) == 0) {
					warn("%s", *argv);
					continue;
				}
			} else if (S_ISBLK(stbuf.st_mode)) {
				if ((mntpt = getmntpt(*argv)) == 0)
					mntpt = *argv;
			} else
				mntpt = *argv;
			/*
			 * Statfs does not take a `wait' flag, so we cannot
			 * implement nflag here.
			 */
			if (!statvfs(mntpt, &mntbuf[mntsize]))
				if (lflag &&
				    (mntbuf[mntsize].f_flag & MNT_LOCAL) == 0)
					warnx("Warning: %s is not a local %s",
					    *argv, "file system");
				else if
				    (!selected(mntbuf[mntsize].f_fstypename,
					sizeof(mntbuf[mntsize].f_fstypename)))
					warnx("Warning: %s mounted as a %s %s",
					    *argv,
					    mntbuf[mntsize].f_fstypename,
					    "file system");
				else
					++mntsize;
			else
				warn("%s", *argv);
		}
	}

	maxwidth = 0;
	for (i = 0; i < mntsize; i++) {
		width = (int)strlen(mntbuf[i].f_mntfromname);
		if (width > maxwidth)
			maxwidth = width;
	}
	for (i = 0; i < mntsize; i++)
		prtstat(&mntbuf[i], maxwidth);
	return 0;
}
Example #11
0
static RmMountEntries *rm_mount_list_open(RmMountTable *table) {
    RmMountEntries *self = g_slice_new(RmMountEntries);
    self->entries = NULL;
    self->current = NULL;

#if HAVE_GETMNTENT
    struct mntent *entry = NULL;
    self->mnt_ent_file = setmntent("/etc/mtab", "r");

    if(self->mnt_ent_file != NULL) {
        while((entry = getmntent(self->mnt_ent_file))) {
            RmMountEntry *wrap_entry = g_slice_new(RmMountEntry);
            wrap_entry->fsname = g_strdup(entry->mnt_fsname);
            wrap_entry->dir = g_strdup(entry->mnt_dir);
            self->entries = g_list_prepend(self->entries, wrap_entry);
        }

        endmntent(self->mnt_ent_file);
    } else {
        rm_log_perror("getmntent");
    }
#elif HAVE_GETMNTINFO /* probably FreeBSD or other */
    int mnt_list_n = 0;
    struct statfs *mnt_list = NULL;

    if((mnt_list_n = getmntinfo(&mnt_list, MNT_NOWAIT)) != 0) {
        for(int i = 0; i < mnt_list_n; ++i) {
            RmMountEntry *wrap_entry = g_slice_new(RmMountEntry);
            struct statfs *entry = &mnt_list[i];

            wrap_entry->fsname = g_strdup(entry->f_mntfromname);
            wrap_entry->dir = g_strdup(entry->f_mntonname);
            self->entries = g_list_prepend(self->entries, wrap_entry);
        }
    } else {
        rm_log_perror("getmntinfo");
    }
#endif

    RmMountEntry *wrap_entry = NULL;
    while((wrap_entry = rm_mount_list_next(self))) {
        /* bindfs mounts mirror directory trees.
        * This cannot be detected properly by rmlint since
        * files in it have the same inode as their unmirrored file, but
        * a different dev_t.
        *
        * So better go and ignore it.
        */
        static const char *evilfs_types[] = {"bindfs", "nullfs", NULL};

        const char *evilfs_found = NULL;
        for(int i = 0; evilfs_types[i] && !evilfs_found; ++i) {
            if(strcmp(evilfs_types[i], wrap_entry->fsname) == 0) {
                evilfs_found = evilfs_types[i];
            }
        }

        if(evilfs_found != NULL) {
            RmStat dir_stat;
            rm_sys_stat(wrap_entry->dir, &dir_stat);
            g_hash_table_insert(
                table->evilfs_table,
                GUINT_TO_POINTER(dir_stat.st_dev),
                GUINT_TO_POINTER(1)
            );

            rm_log_error(
                YELLOW"WARNING:"RESET" `%s` mount detected at %s (#%u); Ignoring all files in it.\n",
                evilfs_found,
                wrap_entry->dir,
                (unsigned)dir_stat.st_dev
            );
        }
    }

    return self;
}
/* Stub version for platforms without CD-ROM support. */
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
{
#if (defined PHYSFS_NO_CDROM_SUPPORT)
    /* no-op. */

#elif (defined PHYSFS_HAVE_SYS_UCRED_H)
    int i;
    struct statfs *mntbufp = NULL;
    int mounts = getmntinfo(&mntbufp, MNT_WAIT);

    for (i = 0; i < mounts; i++)
    {
        int add_it = 0;

        if (strcmp(mntbufp[i].f_fstypename, "iso9660") == 0)
            add_it = 1;
        else if (strcmp( mntbufp[i].f_fstypename, "cd9660") == 0)
            add_it = 1;

        /* add other mount types here */

        if (add_it)
            cb(data, mntbufp[i].f_mntonname);
    } /* for */

#elif (defined PHYSFS_HAVE_MNTENT_H)
    FILE *mounts = NULL;
    struct mntent *ent = NULL;

    mounts = setmntent("/etc/mtab", "r");
    BAIL_IF_MACRO(mounts == NULL, ERR_IO_ERROR, /*return void*/);

    while ( (ent = getmntent(mounts)) != NULL )
    {
        int add_it = 0;
        if (strcmp(ent->mnt_type, "iso9660") == 0)
            add_it = 1;
        else if (strcmp(ent->mnt_type, "udf") == 0)
            add_it = 1;

        /* !!! FIXME: these might pick up floppy drives, right? */
        else if (strcmp(ent->mnt_type, "auto") == 0)
            add_it = 1;
        else if (strcmp(ent->mnt_type, "supermount") == 0)
            add_it = 1;

        /* !!! FIXME: udf? automount? */

        /* add other mount types here */

        if (add_it)
            cb(data, ent->mnt_dir);
    } /* while */

    endmntent(mounts);

#elif (defined PHYSFS_HAVE_SYS_MNTTAB_H)
    FILE *mounts = fopen(MNTTAB, "r");
    struct mnttab ent;

    BAIL_IF_MACRO(mounts == NULL, ERR_IO_ERROR, /*return void*/);
    while (getmntent(mounts, &ent) == 0)
    {
        int add_it = 0;
        if (strcmp(ent.mnt_fstype, "hsfs") == 0)
            add_it = 1;

        /* add other mount types here */

        if (add_it)
            cb(data, ent.mnt_mountp);
    } /* while */

    fclose(mounts);

#else
#error Unknown platform. Should have defined PHYSFS_NO_CDROM_SUPPORT, perhaps.
#endif
} /* __PHYSFS_platformDetectAvailableCDs */
Example #13
0
int get_mounted_filesystems(struct fast_statfs *stats, const int size, int *count)
{
#ifdef OS_LINUX
    const char *filename = "/proc/mounts";
    FILE *fp;
    char *p;
    char *mntfromname;
    char *mntonname;
    char *fstypename;
    struct statfs buf;
    char line[1024];
    int result;
    int i;

    *count = 0;
    fp = fopen(filename, "r");
    if (fp == NULL)
    {
        result = errno != 0 ? errno : ENOENT;
		logError("file: "__FILE__", line: %d, "
			 "call fopen %s fail, "
			 "errno: %d, error info: %s",
			 __LINE__, filename, errno, STRERROR(errno));
		return result;
    }

    memset(stats, 0, sizeof(struct fast_statfs) * size);
    result = 0;
    while (fgets(line, sizeof(line), fp) != NULL)
    {
        if (*count >= size)
        {
            result = ENOSPC;
            break;
        }

        p = line;
        mntfromname = strsep(&p, " \t");
        mntonname = strsep(&p, " \t");
        fstypename = strsep(&p, " \t");

        snprintf(stats[*count].f_mntfromname,
                sizeof(stats[*count].f_mntfromname), "%s", mntfromname);
        snprintf(stats[*count].f_mntonname,
                sizeof(stats[*count].f_mntonname), "%s", mntonname);
        snprintf(stats[*count].f_fstypename,
                sizeof(stats[*count].f_fstypename), "%s", fstypename);

        (*count)++;
    }
    fclose(fp);

    for (i=0; i<*count; i++)
    {
        if (statfs(stats[i].f_mntonname, &buf) == 0)
        {
            SET_STATFS_FIELDS(stats[i], buf);
#ifdef HAVE_FILE_SYSTEM_ID
            stats[i].f_fsid = buf.f_fsid;
#endif
        }
        else
        {
            logWarning("file: "__FILE__", line: %d, "
                    "call statfs fail, "
                    "errno: %d, error info: %s",
                    __LINE__, errno, STRERROR(errno));
        }
    }

    return result;

#elif defined(OS_FREEBSD)

    struct statfs *mnts;
    int result;
    int i;

    mnts = NULL;
    *count = getmntinfo(&mnts, 0);
    if (*count == 0)
    {
        result = errno != 0 ? errno : EPERM;
		logError("file: "__FILE__", line: %d, "
			 "call getmntinfo fail, "
			 "errno: %d, error info: %s",
			 __LINE__, errno, STRERROR(errno));
		return result;
    }

    if (*count <= size)
    {
        result = 0;
    }
    else
    {
        *count = size;
        result = ENOSPC;
    }

    for (i=0; i<*count; i++)
    {
        SET_STATFS_FIELDS(stats[i], mnts[i]);
#ifdef HAVE_FILE_SYSTEM_ID
        stats[i].f_fsid = mnts[i].f_fsid;
#endif
        SET_MNT_FIELDS(stats[i], mnts[i].f_fstypename,
                mnts[i].f_mntfromname, mnts[i].f_mntonname);
    }
    return result;
#else
    *count = 0;
    logError("file: "__FILE__", line: %d, "
            "please port me!", __LINE__);
    return EOPNOTSUPP;
#endif
}
Example #14
0
QStringList Utils::mountpoints(enum MountpointsFilter type)
{
    QStringList supported;
    QStringList tempList;
#if defined(Q_OS_WIN32)
    supported << "FAT32" << "FAT16" << "FAT12" << "FAT" << "HFS";
    QFileInfoList list = QDir::drives();
    for(int i=0; i<list.size();i++)
    {
        wchar_t t[32];
        memset(t, 0, 32);
        if(GetVolumeInformationW((LPCWSTR)list.at(i).absolutePath().utf16(),
                NULL, 0, NULL, NULL, NULL, t, 32) == 0) {
            // on error empty retrieved type -- don't rely on
            // GetVolumeInformation not changing it.
            memset(t, 0, sizeof(t));
        }

        QString fstype = QString::fromWCharArray(t);
        if(type == MountpointsAll || supported.contains(fstype)) {
            tempList << list.at(i).absolutePath();
            qDebug() << "[Utils] Added:" << list.at(i).absolutePath()
                     << "type" << fstype;
        }
        else {
            qDebug() << "[Utils] Ignored:" << list.at(i).absolutePath()
                     << "type" << fstype;
        }
    }

#elif defined(Q_OS_MACX) || defined(Q_OS_OPENBSD)
    supported << "vfat" << "msdos" << "hfs";
    int num;
    struct statfs *mntinf;

    num = getmntinfo(&mntinf, MNT_WAIT);
    while(num--) {
        if(type == MountpointsAll || supported.contains(mntinf->f_fstypename)) {
            tempList << QString(mntinf->f_mntonname);
            qDebug() << "[Utils] Added:" << mntinf->f_mntonname
                     << "is" << mntinf->f_mntfromname << "type" << mntinf->f_fstypename;
        }
        else {
            qDebug() << "[Utils] Ignored:" << mntinf->f_mntonname
                     << "is" << mntinf->f_mntfromname << "type" << mntinf->f_fstypename;
        }
        mntinf++;
    }
#elif defined(Q_OS_LINUX)
    supported << "vfat" << "msdos" << "hfsplus";
    FILE *mn = setmntent("/etc/mtab", "r");
    if(!mn)
        return QStringList("");

    struct mntent *ent;
    while((ent = getmntent(mn))) {
        if(type == MountpointsAll || supported.contains(ent->mnt_type)) {
            tempList << QString(ent->mnt_dir);
            qDebug() << "[Utils] Added:" << ent->mnt_dir
                     << "is" << ent->mnt_fsname << "type" << ent->mnt_type;
        }
        else {
            qDebug() << "[Utils] Ignored:" << ent->mnt_dir
                     << "is" << ent->mnt_fsname << "type" << ent->mnt_type;
        }
    }
    endmntent(mn);

#else
#error Unknown Platform
#endif
    return tempList;
}
Example #15
0
File: df.c Project: Mobbe/bitrig
int
main(int argc, char *argv[])
{
	struct stat stbuf;
	struct statfs *mntbuf;
	long mntsize;
	int ch, i;
	int width, maxwidth;
	char *mntpt;

	while ((ch = getopt(argc, argv, "hiklnPt:")) != -1)
		switch (ch) {
		case 'h':
			hflag = 1;
			kflag = 0;
			break;
		case 'i':
			iflag = 1;
			break;
		case 'k':
			kflag = 1;
			hflag = 0;
			break;
		case 'l':
			lflag = 1;
			break;
		case 'n':
			nflag = 1;
			break;
		case 'P':
			Pflag = 1;
			break;
		case 't':
			if (typelist != NULL)
				errx(1, "only one -t option may be specified.");
			maketypelist(optarg);
			break;
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

	if ((iflag || hflag) && Pflag) {
		warnx("-h and -i are incompatible with -P");
		usage();
	}

	mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
	if (mntsize == 0)
		err(1, "retrieving information on mounted file systems");

	if (!*argv) {
		mntsize = regetmntinfo(&mntbuf, mntsize);
	} else {
		mntbuf = calloc(argc, sizeof(struct statfs));
		if (mntbuf == NULL)
			err(1, NULL);
		mntsize = 0;
		for (; *argv; argv++) {
			if (stat(*argv, &stbuf) < 0) {
				if ((mntpt = getmntpt(*argv)) == 0) {
					warn("%s", *argv);
					continue;
				}
			} else if (S_ISCHR(stbuf.st_mode) || S_ISBLK(stbuf.st_mode)) {
				if (!raw_df(*argv, &mntbuf[mntsize]))
					++mntsize;
				continue;
			} else
				mntpt = *argv;
			/*
			 * Statfs does not take a `wait' flag, so we cannot
			 * implement nflag here.
			 */
			if (!statfs(mntpt, &mntbuf[mntsize]))
				if (lflag && (mntbuf[mntsize].f_flags & MNT_LOCAL) == 0)
					warnx("%s is not a local file system",
					    *argv);
				else if (!selected(mntbuf[mntsize].f_fstypename))
					warnx("%s mounted as a %s file system",
					    *argv, mntbuf[mntsize].f_fstypename);
				else
					++mntsize;
			else
				warn("%s", *argv);
		}
	}

	if (mntsize) {
		maxwidth = 0;
		for (i = 0; i < mntsize; i++) {
			width = strlen(mntbuf[i].f_mntfromname);
			if (width > maxwidth)
				maxwidth = width;
		}

		if (maxwidth < 11)
			maxwidth = 11;

		if (Pflag)
			posixprint(mntbuf, mntsize, maxwidth);
		else
			bsdprint(mntbuf, mntsize, maxwidth);
	}

	exit(mntsize ? 0 : 1);
}
Example #16
0
int
main(int argc, char *argv[])
{
	const char *mntfromname, **vfslist, *vfstype;
	struct fstab *fs;
	struct statfs *mntbuf;
	int all, ch, i, init_flags, late, failok, mntsize, rval, have_fstab, ro;
	int onlylate;
	char *cp, *ep, *options;

	all = init_flags = late = onlylate = 0;
	ro = 0;
	options = NULL;
	vfslist = NULL;
	vfstype = "ufs";
	while ((ch = getopt(argc, argv, "adF:fLlno:prt:uvw")) != -1)
		switch (ch) {
		case 'a':
			all = 1;
			break;
		case 'd':
			debug = 1;
			break;
		case 'F':
			setfstab(optarg);
			break;
		case 'f':
			init_flags |= MNT_FORCE;
			break;
		case 'L':
			onlylate = 1;
			late = 1;
			break;
		case 'l':
			late = 1;
			break;
		case 'n':
			/* For compatibility with the Linux version of mount. */
			break;
		case 'o':
			if (*optarg) {
				options = catopt(options, optarg);
				if (specified_ro(optarg))
					ro = 1;
			}
			break;
		case 'p':
			fstab_style = 1;
			verbose = 1;
			break;
		case 'r':
			options = catopt(options, "ro");
			ro = 1;
			break;
		case 't':
			if (vfslist != NULL)
				errx(1, "only one -t option may be specified");
			vfslist = makevfslist(optarg);
			vfstype = optarg;
			break;
		case 'u':
			init_flags |= MNT_UPDATE;
			break;
		case 'v':
			verbose = 1;
			break;
		case 'w':
			options = catopt(options, "noro");
			break;
		case '?':
		default:
			usage();
			/* NOTREACHED */
		}
	argc -= optind;
	argv += optind;

#define	BADTYPE(type)							\
	(strcmp(type, FSTAB_RO) &&					\
	    strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ))

	if ((init_flags & MNT_UPDATE) && (ro == 0))
		options = catopt(options, "noro");

	rval = 0;
	switch (argc) {
	case 0:
		if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0)
			err(1, "getmntinfo");
		if (all) {
			while ((fs = getfsent()) != NULL) {
				if (BADTYPE(fs->fs_type))
					continue;
				if (checkvfsname(fs->fs_vfstype, vfslist))
					continue;
				if (hasopt(fs->fs_mntops, "noauto"))
					continue;
				if (!hasopt(fs->fs_mntops, "late") && onlylate)
					continue;
				if (hasopt(fs->fs_mntops, "late") && !late)
					continue;
				if (hasopt(fs->fs_mntops, "failok"))
					failok = 1;
				else
					failok = 0;
				if (!(init_flags & MNT_UPDATE) &&
				    ismounted(fs, mntbuf, mntsize))
					continue;
				options = update_options(options, fs->fs_mntops,
				    mntbuf->f_flags);
				if (mountfs(fs->fs_vfstype, fs->fs_spec,
				    fs->fs_file, init_flags, options,
				    fs->fs_mntops) && !failok)
					rval = 1;
			}
		} else if (fstab_style) {
			for (i = 0; i < mntsize; i++) {
				if (checkvfsname(mntbuf[i].f_fstypename, vfslist))
					continue;
				putfsent(&mntbuf[i]);
			}
		} else {
			for (i = 0; i < mntsize; i++) {
				if (checkvfsname(mntbuf[i].f_fstypename,
				    vfslist))
					continue;
				if (!verbose &&
				    (mntbuf[i].f_flags & MNT_IGNORE) != 0)
					continue;
				prmount(&mntbuf[i]);
			}
		}
		exit(rval);
	case 1:
		if (vfslist != NULL)
			usage();

		rmslashes(*argv, *argv);
		if (init_flags & MNT_UPDATE) {
			mntfromname = NULL;
			have_fstab = 0;
			if ((mntbuf = getmntpt(*argv)) == NULL)
				errx(1, "not currently mounted %s", *argv);
			/*
			 * Only get the mntflags from fstab if both mntpoint
			 * and mntspec are identical. Also handle the special
			 * case where just '/' is mounted and 'spec' is not
			 * identical with the one from fstab ('/dev' is missing
			 * in the spec-string at boot-time).
			 */
			if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL) {
				if (strcmp(fs->fs_spec,
				    mntbuf->f_mntfromname) == 0 &&
				    strcmp(fs->fs_file,
				    mntbuf->f_mntonname) == 0) {
					have_fstab = 1;
					mntfromname = mntbuf->f_mntfromname;
				} else if (argv[0][0] == '/' &&
				    argv[0][1] == '\0') {
					fs = getfsfile("/");
					have_fstab = 1;
					mntfromname = fs->fs_spec;
				}
			}
			if (have_fstab) {
				options = update_options(options, fs->fs_mntops,
				    mntbuf->f_flags);
			} else {
				mntfromname = mntbuf->f_mntfromname;
				options = update_options(options, NULL,
				    mntbuf->f_flags);
			}
			rval = mountfs(mntbuf->f_fstypename, mntfromname,
			    mntbuf->f_mntonname, init_flags, options, 0);
			break;
		}
		if ((fs = getfsfile(*argv)) == NULL &&
		    (fs = getfsspec(*argv)) == NULL)
			errx(1, "%s: unknown special file or file system",
			    *argv);
		if (BADTYPE(fs->fs_type))
			errx(1, "%s has unknown file system type",
			    *argv);
		rval = mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file,
		    init_flags, options, fs->fs_mntops);
		break;
	case 2:
		/*
		 * If -t flag has not been specified, the path cannot be
		 * found, spec contains either a ':' or a '@', then assume
		 * that an NFS file system is being specified ala Sun.
		 * Check if the hostname contains only allowed characters
		 * to reduce false positives.  IPv6 addresses containing
		 * ':' will be correctly parsed only if the separator is '@'.
		 * The definition of a valid hostname is taken from RFC 1034.
		 */
		if (vfslist == NULL && ((ep = strchr(argv[0], '@')) != NULL ||
		    (ep = strchr(argv[0], ':')) != NULL)) {
			if (*ep == '@') {
				cp = ep + 1;
				ep = cp + strlen(cp);
			} else
				cp = argv[0];
			while (cp != ep) {
				if (!isdigit(*cp) && !isalpha(*cp) &&
				    *cp != '.' && *cp != '-' && *cp != ':')
					break;
				cp++;
			}
			if (cp == ep)
				vfstype = "nfs";
		}
		rval = mountfs(vfstype,
		    argv[0], argv[1], init_flags, options, NULL);
		break;
	default:
		usage();
		/* NOTREACHED */
	}

	/*
	 * If the mount was successfully, and done by root, tell mountd the
	 * good news.
	 */
	if (rval == 0 && getuid() == 0)
		restart_mountd();

	exit(rval);
}
Example #17
0
/** Resolve mountpoint to devicename / disk number
 *  @param path mountpoint path / drive letter
 *  @return devicename / disk number
 */
QString Utils::resolveDevicename(QString path)
{
    qDebug() << "[Utils] resolving device name" << path;
#if defined(Q_OS_LINUX)
    FILE *mn = setmntent("/etc/mtab", "r");
    if(!mn)
        return QString("");

    struct mntent *ent;
    while((ent = getmntent(mn))) {
        // check for valid filesystem type.
        // Linux can handle hfs (and hfsplus), so consider it a valid file
        // system. Otherwise resolving the device name would fail, which in
        // turn would make it impossible to warn about a MacPod.
        if(QString(ent->mnt_dir) == path
           && (QString(ent->mnt_type).contains("vfat", Qt::CaseInsensitive)
            || QString(ent->mnt_type).contains("hfs", Qt::CaseInsensitive))) {
            endmntent(mn);
            qDebug() << "[Utils] device name is" << ent->mnt_fsname;
            return QString(ent->mnt_fsname);
        }
    }
    endmntent(mn);

#endif

#if defined(Q_OS_MACX) || defined(Q_OS_OPENBSD)
    int num;
    struct statfs *mntinf;

    num = getmntinfo(&mntinf, MNT_WAIT);
    while(num--) {
        // check for valid filesystem type. OS X can handle hfs (hfs+ is
        // treated as hfs), BSD should be the same.
        if(QString(mntinf->f_mntonname) == path
           && (QString(mntinf->f_fstypename).contains("msdos", Qt::CaseInsensitive)
            || QString(mntinf->f_fstypename).contains("hfs", Qt::CaseInsensitive))) {
            qDebug() << "[Utils] device name is" << mntinf->f_mntfromname;
            return QString(mntinf->f_mntfromname);
        }
        mntinf++;
    }
#endif

#if defined(Q_OS_WIN32)
    DWORD written;
    HANDLE h;
    TCHAR uncpath[MAX_PATH];
    UCHAR buffer[0x400];
    PVOLUME_DISK_EXTENTS extents = (PVOLUME_DISK_EXTENTS)buffer;

    _stprintf(uncpath, _TEXT("\\\\.\\%c:"), path.toAscii().at(0));
    h = CreateFile(uncpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
            NULL, OPEN_EXISTING, 0, NULL);
    if(h == INVALID_HANDLE_VALUE) {
        //qDebug() << "error getting extents for" << uncpath;
        return "";
    }
    // get the extents
    if(DeviceIoControl(h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
                NULL, 0, extents, sizeof(buffer), &written, NULL)) {
        if(extents->NumberOfDiskExtents > 1) {
            qDebug() << "[Utils] resolving device name: volume spans multiple disks!";
            return "";
        }
        qDebug() << "[Utils] device name is" << extents->Extents[0].DiskNumber;
        return QString("%1").arg(extents->Extents[0].DiskNumber);
    }
#endif
    return QString("");

}
JBoolean
JIsMounted
	(
	const JCharacter*	path,
	JBoolean*			writable,
	JBoolean*			isTop,
	JString*			device,
	JFileSystemType*	fsType,
	JString*			fsTypeString
	)
{
	struct stat stbuf1, stbuf2;
	if (stat(path, &stbuf1) != 0)
		{
		return kJFalse;
		}

	JBoolean isMounted = kJFalse;

	struct statfs* info;
	const JSize count = getmntinfo(&info, MNT_WAIT);

	JString p;
	for (JIndex i=0; i<count; i++)
		{
		if (strcmp(info[i].f_mntonname, "/") != 0 &&
			stat(info[i].f_mntonname, &stbuf2) == 0 &&
			stbuf1.st_dev == stbuf2.st_dev)
			{
			isMounted = kJTrue;
			if (writable != NULL)
				{
				*writable = JNegate((info[i].f_flags & MNT_RDONLY) != 0);
				}
			if (isTop != NULL)
				{
				*isTop = JI2B(stbuf1.st_ino == stbuf2.st_ino);
				}
			if (device != NULL)
				{
				*device = info[i].f_mntfromname;
				}
			if (fsType != NULL)
				{
				*fsType = kOtherFSType;
				if (JStringCompare(info[i].f_fstypename, "vfat", kJFalse) == 0 ||	// UNIX
					JStringCompare(info[i].f_fstypename, "msdos", kJFalse) == 0)	// OSX
					{
					*fsType = kVFATType;
					}
				}
			if (fsTypeString != NULL)
				{
				*fsTypeString = info[i].f_fstypename;
				}
			break;
			}
		}

	return isMounted;
}
Example #19
0
int
main(int argc, char *argv[])
{
	long timeout_val;
	int c;
	int flushcache = 0;
	int unmount_automounted = 0;	// Unmount automounted mounts
	struct autodir *dir, *d;
	char real_mntpnt[PATH_MAX];
	struct stat stbuf;
	char *master_map = "auto_master";
	int null;
	struct statfs *mntp;
	int count = 0;
	char *stack[STACKSIZ];
	char **stkptr;
	char *defval;
	int fd;
	int flags, altflags;
	struct staticmap *static_ent;

	/*
	 * Read in the values from config file first before we check
	 * commandline options so the options override the file.
	 */
	if ((defopen(AUTOFSADMIN)) == 0) {
		if ((defval = defread("AUTOMOUNT_TIMEOUT=")) != NULL) {
			errno = 0;
			timeout_val = strtol(defval, (char **)NULL, 10);
			if (errno == 0 && timeout_val > 0 &&
			    timeout_val <= INT_MAX)
				mount_timeout = (int)timeout_val;
		}
		if ((defval = defread("AUTOMOUNT_VERBOSE=")) != NULL) {
			if (strncasecmp("true", defval, 4) == 0)
				verbose = TRUE;
			else
				verbose = FALSE;
		}
		if ((defval = defread("AUTOMOUNTD_TRACE=")) != NULL) {
			/*
			 * Turn on tracing here too if the automountd
			 * is set up to do it - since automount calls
			 * many of the common library functions.
			 */
			errno = 0;
			trace = (int)strtol(defval, (char **)NULL, 10);
			if (errno != 0)
				trace = 0;
		}

		/* close defaults file */
		defopen(NULL);
	}

	while ((c = getopt(argc, argv, "mM:D:f:t:vcu?")) != EOF) {
		switch (c) {
		case 'm':
			pr_msg("Warning: -m option not supported");
			break;
		case 'M':
			pr_msg("Warning: -M option not supported");
			break;
		case 'D':
			pr_msg("Warning: -D option not supported");
			break;
		case 'f':
			pr_msg("Error: -f option no longer supported");
			usage();
			break;
		case 't':
			if (strchr(optarg, '=')) {
				pr_msg("Error: invalid value for -t");
				usage();
			}
			mount_timeout = atoi(optarg);
			break;
		case 'v':
			verbose++;
			break;
		case 'c':
			flushcache++;
			break;
		case 'u':
			unmount_automounted++;
			break;
		default:
			usage();
			break;
		}
	}

	if (optind < argc) {
		pr_msg("%s: command line mountpoints/maps "
			"no longer supported",
			argv[optind]);
		usage();
	}

	/*
	 * Get an array of current system mounts
	 */
	num_current_mounts = getmntinfo(&current_mounts, MNT_NOWAIT);
	if (num_current_mounts == 0) {
		pr_msg("Couldn't get current mounts: %m");
		exit(1);
	}

	autofs_control_fd = open("/dev/" AUTOFS_CONTROL_DEVICE, O_RDONLY);
	if (autofs_control_fd == -1 && errno == ENOENT) {
		/*
		 * Oops, we probably don't have the autofs kext
		 * loaded.
		 */
		FTS *fts;
		static char *const paths[] = { "/Network", NULL };
		FTSENT *ftsent;
		int error;

		/*
		 * This means there can't be any autofs mounts yet, so
		 * this is the first time we're being run since a reboot.
		 * Clean out any stuff left in /Network from the reboot.
		 */
		fts = fts_open(paths, FTS_NOCHDIR|FTS_PHYSICAL|FTS_XDEV,
		    NULL);
		if (fts != NULL) {
			while ((ftsent = fts_read(fts)) != NULL) {
				/*
				 * We only remove directories - if
				 * there are files, we assume they're
				 * there for a purpose.
				 *
				 * We remove directories after we've
				 * removed their children, so we want
				 * to process directories visited in
				 * post-order.
				 *
				 * We don't remove /Network itself.
				 */
				if (ftsent->fts_info == FTS_DP &&
				    ftsent->fts_level > FTS_ROOTLEVEL)
					rmdir(ftsent->fts_accpath);
			}
			fts_close(fts);
		}

		/*
		 * Now load it.
		 */
		error = load_autofs();
		if (error != 0) {
			pr_msg("can't load autofs kext");
			exit(1);
		}

		/*
		 * Try the open again.
		 */
		autofs_control_fd = open("/dev/" AUTOFS_CONTROL_DEVICE,
		    O_RDONLY);
	}
	if (autofs_control_fd == -1) {
		if (errno == EBUSY)
			pr_msg("Another automount is running");
		else
			pr_msg("Couldn't open %s: %m", "/dev/" AUTOFS_CONTROL_DEVICE);
		exit(1);
	}

	/*
	 * Update the mount timeout.
	 */
	if (ioctl(autofs_control_fd, AUTOFS_SET_MOUNT_TO, &mount_timeout) == -1)
		pr_msg("AUTOFS_SET_MOUNT_TO failed: %m");

	/*
	 * Attempt to unmount any non-busy triggered mounts; this includes
	 * not only autofs mounts, but, for example SMB Dfs mounts.
	 *
	 * This is done before sleep, and after a network change, to
	 * try to get rid of as many network mounts as we can; each
	 * unmounted network mount is a network mount on which we
	 * can't hang.
	 */
	if (unmount_automounted) {
		if (verbose)
			pr_msg("Unmounting triggered mounts");
		if (ioctl(autofs_control_fd, AUTOFS_UNMOUNT_TRIGGERED, 0) == -1)
			pr_msg("AUTOFS_UNMOUNT_TRIGGERED failed: %m");
		exit(0);
	}

	if (flushcache) {
		/*
		 * Notify the automounter that it should flush its caches,
		 * as we might be on a different network with different maps.
		 */
		if (ioctl(autofs_control_fd, AUTOFS_NOTIFYCHANGE, 0) == -1)
			pr_msg("AUTOFS_NOTIFYCHANGE failed: %m");
	}

	(void) umask(0);
	ns_setup(stack, &stkptr);

	(void) loadmaster_map(master_map, "", stack, &stkptr);

	/*
	 * Mount the daemon at its mount points.
	 */
	for (dir = dir_head; dir; dir = dir->dir_next) {

		if (realpath(dir->dir_name, real_mntpnt) == NULL) {
			/*
			 * We couldn't get the real path for this,
			 * perhaps because it doesn't exist.
			 * If it's not because it doesn't exist, just
			 * give up on this entry.  Otherwise, just null
			 * out the real path - we'll try creating the
			 * directory later, and will set dir_realpath
			 * then, if that succeeds.
			 */
			if (errno != ENOENT) {
				pr_msg("%s: Can't convert to real path: %m",
				    dir->dir_name);
				continue;
			}
			dir->dir_realpath = NULL;
		} else {
			dir->dir_realpath = strdup(real_mntpnt);
			if (dir->dir_realpath == NULL) {
				pr_msg("Couldn't allocate real path: %m");
				exit(1);
			}
		}

		/*
		 * Skip null entries
		 */
		if (strcmp(dir->dir_map, "-null") == 0)
			continue;

		/*
		 * Skip null'ed entries
		 */
		null = 0;
		for (d = dir->dir_prev; d; d = d->dir_prev) {
			if (paths_match(dir, d))
				null = 1;
		}
		if (null)
			continue;

		/*
		 * If this is -fstab, and there are no fstab "net" entries,
		 * skip this map if our directory search path doesn't
		 * include Active Directory.  We don't want /Network/Servers
		 * (or wherever it shows up) to exist if this system isn't
		 * using AD (AD supplies fstab entries on the fly, so they
		 * might not exist right now) and we don't have any fstab
		 * entries.
		 */
		if (strcmp(dir->dir_map, "-fstab") == 0) {
			if (!have_ad() && !havefstabkeys()) {
				/*
				 * We're not using AD, and fstab is
				 * inaccessible or devoid of "net" entries.
				 */
				free(dir->dir_map);
				dir->dir_map = strdup("-null");
				continue;
			}
			endfsent();
		}

		/*
		 * If this is -fstab or -static, and there's another entry
		 * that's supposed to mount something on the same directory
		 * and isn't "-fstab" or "-static", ignore this; we might
		 * have a server that's supplying real automounter maps for
		 * the benefit of OS X systems with autofs and also supplying
		 * fstab entries for the benefit of older OS X systems, and
		 * we want to mount the real automounter map, not the -fstab
		 * or -static map, in that case.
		 */
		if (strcmp(dir->dir_map, "-fstab") == 0 ||
		    strcmp(dir->dir_map, "-static") == 0) {
			for (d = dir_head; d; d = d->dir_next) {
				if (paths_match(dir, d) &&
				    strcmp(d->dir_map, "-fstab") != 0 &&
				    strcmp(d->dir_map, "-static") != 0) {
					pr_msg("%s: ignoring redundant %s map",
					    dir->dir_name, dir->dir_map);
					break;
				}
			}
			if (d != NULL) {
				continue;
			}
		}

		/*
		 * Parse the mount options and get additional flags to pass
		 * to mount() (standard mount options) and autofs mount
		 * options.
		 *
		 * XXX - we ignore flags on an update; if they're different
		 * from the current flags for that mount, we'd need to do a
		 * remount.
		 */
		if (!parse_mntopts(dir->dir_opts, &flags, &altflags)) {
			/*
			 * Failed.
			 */
			continue;
		}

		/*
		 * If this is -static, check whether the entry refers
		 * to this host; if so, make the appropriate symlink
		 * exist at the "mount point" path.
		 */
		if (strcmp(dir->dir_map, "-static") == 0) {
			static_ent = get_staticmap_entry(dir->dir_name);
			if (static_ent == NULL) {
				/*
				 * Whiskey tango foxtrot?  There should
				 * be an entry here.  Log an error and
				 * ignore this mount.
				 */
				pr_msg("can't find fstab entry for %s",
				    dir->dir_name);
				continue;
			}
			if (host_is_us(static_ent->host, strlen(static_ent->host)) ||
			    self_check(static_ent->host)) {
				/*
				 * Yup, this is us.
				 * Try to make the appropriate symlink.
				 */
				make_symlink(static_ent->localpath,
				    dir->dir_name);
				release_staticmap_entry(static_ent);
				continue;
			}
			release_staticmap_entry(static_ent);
		}

		/*
		 * Check whether there's already an entry
		 * in the mnttab for this mountpoint.
		 */
		if (dir->dir_realpath != NULL &&
		    (mntp = find_mount(dir->dir_realpath)) != NULL) {
			struct autofs_update_args au;

			/*
			 * If it's not an autofs mount - don't
			 * mount over it.
			 */
			if (strcmp(mntp->f_fstypename, MNTTYPE_AUTOFS) != 0) {
				pr_msg("%s: already mounted on %s",
					mntp->f_mntfromname, dir->dir_realpath);
				continue;
			}

			/*
			 * This is already mounted, so just update it.
			 * We don't bother to check whether any options are
			 * changing, as we'd have to make a trip into the
			 * kernel to get the current options to check them,
			 * so we might as well just make a trip to do the
			 * update.
			 */
			au.fsid		= mntp->f_fsid;
			au.opts		= dir->dir_opts;
			au.map		= dir->dir_map;
			au.mntflags	= altflags;
			au.direct 	= dir->dir_direct;
			au.node_type	= dir->dir_direct ? NT_TRIGGER : 0;

			if (ioctl(autofs_control_fd, AUTOFS_UPDATE_OPTIONS,
			    &au) < 0) {
				pr_msg("update %s: %m", dir->dir_realpath);
				continue;
			}
			if (verbose)
				pr_msg("%s updated", dir->dir_realpath);
		} else {
			struct autofs_args ai;
			int st_flags = 0;

			/*
			 * This trigger isn't already mounted; either
			 * the path doesn't exist at all, or it
			 * exists but nothing is mounted on it.
			 *
			 * Create a mount point if necessary
			 * If the path refers to an existing symbolic
			 * link, refuse to mount on it.  This avoids
			 * future problems.  (We don't use dir->dir_realpath
			 * because that's never a symbolic link.)
			 */
			if (lstat(dir->dir_name, &stbuf) == 0) {
				if ((stbuf.st_mode & S_IFMT) != S_IFDIR) {
					pr_msg("%s: Not a directory", dir->dir_name);
					continue;
				}
				st_flags = stbuf.st_flags;

				/*
				 * Either realpath() succeeded or it
				 * failed with ENOENT; otherwise, we
				 * would have quit before getting here.
				 *
				 * If it failed, report an error, as
				 * the problem isn't that "dir->dir_name"
				 * doesn't exist, the problem is that,
				 * somehow, we got ENOENT even though
				 * it exists.
				 */
				if (dir->dir_realpath == NULL) {
					errno = ENOENT;
					pr_msg("%s: Can't convert to real path: %m",
					    dir->dir_name);
					continue;
				}
			} else {
				/*
				 * Mountpoint doesn't exist.
				 *
				 * Create it unless it's under /Volumes.
				 * At boot time it's possible the volume
				 * containing the mountpoint hasn't mounted yet.
				 */
				if (strncmp(dir->dir_name, "/Volumes/", 9) == 0) {
					pr_msg("%s: mountpoint unavailable", dir->dir_name);
					continue;
				}

				if (mkdir_r(dir->dir_name)) {
					pr_msg("%s: %m", dir->dir_name);
					continue;
				}

				/*
				 * realpath() presumably didn't succeed,
				 * as dir->dir_name couldn't be statted.
				 * Call it again, to get the real path
				 * corresponding to the newly-created
				 * mount point.
				 */
				if (realpath(dir->dir_name, real_mntpnt) == NULL) {
					/*
					 * Failed.
					 */
					pr_msg("%s: Can't convert to real path: %m",
					    dir->dir_name);
					continue;
				}
				dir->dir_realpath = strdup(real_mntpnt);
				if (dir->dir_realpath == NULL) {
					pr_msg("Couldn't allocate real path for %s: %m",
					    dir->dir_name);
					continue;
				}
			}

			/*
			 * If the "hidefromfinder" option is set for
			 * this autofs mountpoint then also set the
			 * UF_HIDDEN bit on the directory so it'll still
			 * be invisible to the Finder even if not mounted on.
			 */
			if (altflags & AUTOFS_MNT_HIDEFROMFINDER)
				st_flags |= UF_HIDDEN;
			else
				st_flags &= ~UF_HIDDEN;
			if (chflags(dir->dir_name, st_flags) < 0)
				pr_msg("%s: can't set hidden", dir->dir_name);

			/*
			 * Mount it.  Use the real path (symlink-free),
			 * for reasons mentioned above.
			 */
			ai.version	= AUTOFS_ARGSVERSION;
			ai.path 	= dir->dir_realpath;
			ai.opts		= dir->dir_opts;
			ai.map		= dir->dir_map;
			ai.subdir	= "";
			ai.direct 	= dir->dir_direct;
			if (dir->dir_direct)
				ai.key = dir->dir_name;
			else
				ai.key = "";
			ai.mntflags	= altflags;
			ai.mount_type	= MOUNT_TYPE_MAP;	/* top-level autofs mount */
			ai.node_type	= dir->dir_direct ? NT_TRIGGER : 0;

			if (mount(MNTTYPE_AUTOFS, dir->dir_realpath,
			    MNT_DONTBROWSE | MNT_AUTOMOUNTED | flags,
			    &ai) < 0) {
				pr_msg("mount %s: %m", dir->dir_realpath);
				continue;
			}
			if (verbose)
				pr_msg("%s mounted", dir->dir_realpath);
		}

		count++;
	}

	if (verbose && count == 0)
		pr_msg("no mounts");

	/*
	 * Now compare the /etc/mnttab with the master
	 * map.  Any autofs mounts in the /etc/mnttab
	 * that are not in the master map must be
	 * unmounted
	 *
	 * XXX - if there are no autofs mounts left, should we
	 * unload autofs, or arrange that it be unloaded?
	 */
	do_unmounts();

	/*
	 * Let PremountHomeDirectoryWithAuthentication() know that we're
	 * done.
	 */
	fd = open("/var/run/automount.initialized", O_CREAT|O_WRONLY, 0600);
	close(fd);

	return (0);
}
Example #20
0
/*
 * Given a name, determine whether or not it's a valid path
 * (starts with '/' or "./").  If so, walk the mnttab trying
 * to match the device number.  If not, treat the path as an
 * fs/vol/snap name.
 */
zfs_handle_t *
zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype)
{
#if _DARWIN_FEATURE_64_BIT_INODE
	
	struct stat statbuf;
#else
	struct stat64 statbuf;
#endif
#ifdef __APPLE__
	struct statfs *sfsp;
	int nitems;
#else
	struct extmnttab entry;
	int ret;
#endif

	if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) {
		/*
		 * It's not a valid path, assume it's a name of type 'argtype'.
		 */
		return (zfs_open(hdl, path, argtype));
	}

#if _DARWIN_FEATURE_64_BIT_INODE
	if (stat(path, &statbuf) != 0) {
#else
	if (stat64(path, &statbuf) != 0) {
#endif
		(void) fprintf(stderr, "%s: %s\n", path, strerror(errno));
		return (NULL);
	}

#ifdef __APPLE__
	if ((nitems = getmntinfo(&sfsp, MNT_WAIT)) == 0) {
		return (NULL);
	}
	while (nitems--) {
		if (sfsp->f_fsid.val[0] == statbuf.st_dev) {
			break;
		}
	}
	if (strcmp(sfsp->f_fstypename, MNTTYPE_ZFS) != 0) {
		(void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"),
		    path);
		return (NULL);
	}
	return (zfs_open(hdl, sfsp->f_mntonname, ZFS_TYPE_FILESYSTEM));
#else
	rewind(hdl->libzfs_mnttab);
	while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) {
		if (makedevice(entry.mnt_major, entry.mnt_minor) ==
		    statbuf.st_dev) {
			break;
		}
	}
	if (ret != 0) {
		return (NULL);
	}

	if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) {
		(void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"),
		    path);
		return (NULL);
	}

	return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM));
#endif
}

/*
 * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from
 * an ioctl().
 */
int
zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
{
	if (len == 0)
		len = 2048;
	zc->zc_nvlist_dst_size = len;
	if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
	    zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == 0)
		return (-1);

	return (0);
}

/*
 * Called when an ioctl() which returns an nvlist fails with ENOMEM.  This will
 * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was
 * filled in by the kernel to indicate the actual required size.
 */
int
zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
{
	free((void *)(uintptr_t)zc->zc_nvlist_dst);
	if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
	    zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == 0)
		return (-1);

	return (0);
}
Example #21
0
int
main(int argc, char **argv)
{
	char all = 0;
	struct statfs *mp;
	struct fstab *fs;
	char dev[MNAMELEN + 1];
	char *nm;
	int cnt;

	func = douser;
#ifndef	COMPAT
	header = getbsize(&headerlen,&blocksize);
#endif
	while (--argc > 0 && **++argv == '-') {
		while (*++*argv) {
			switch (**argv) {
			case 'n':
				func = donames;
				break;
			case 'c':
				func = dofsizes;
				break;
			case 'a':
				all = 1;
				break;
			case 'f':
				count = 1;
				break;
			case 'h':
				estimate = 1;
				break;
#ifndef	COMPAT
			case 'k':
				blocksize = 1024;
				break;
#endif	/* COMPAT */
			case 'v':
				unused = 1;
				break;
			default:
				usage();
			}
		}
	}
	if (all) {
		cnt = getmntinfo(&mp,MNT_NOWAIT);
		for (; --cnt >= 0; mp++) {
			if (!strncmp(mp->f_fstypename, "ufs", MFSNAMELEN)) {
				if ((nm = strrchr(mp->f_mntfromname,'/'))) {
					sprintf(dev,"%s%s",_PATH_DEV,nm + 1);
					nm = dev;
				} else
					nm = mp->f_mntfromname;
				quot(nm,mp->f_mntonname);
			}
		}
	}
	while (--argc >= 0) {
		if ((fs = getfsfile(*argv)) != NULL)
			quot(fs->fs_spec, 0);
		else
			quot(*argv,0);
		argv++;
	}
	return 0;
}
Example #22
0
int get_disk_info(char * _device, char * _uuid, char * _label, char * _name)
{
    int r;
    fslabel_t label;

# ifdef USE_STRUCT_MNTENT
    struct mntent *entry;
# elif defined(USE_STRUCT_MNTTAB)
    struct mnttab *entry, ebuf;
# else
    struct statfs *entry;
# endif

# ifdef HAVE_SETMNTENT
    FILE *table;
    if (!(table = setmntent(_PATH_MOUNTED, "r"))) return -1;
# elif defined(USE_STRUCT_MNTTAB)
    FILE *table;
    if (!(table = fopen(_PATH_MOUNTED, "r"))) return -1;
    resetmnttab(table);
# endif

# ifdef USE_STRUCT_MNTENT
    while ((entry = getmntent(table)) != 0)
# elif defined(USE_STRUCT_MNTTAB)
    entry = &ebuf;
    while (!getmntent(table, entry))
#  define mnt_fsname mnt_special
#  define mnt_dir mnt_mountp
# else
    int mnts;

    if (!(mnts = getmntinfo(&entry, MNT_NOWAIT))) return -1;

    for (mnts--; mnts >= 0; mnts--)
#  define mnt_fsname f_mntfromname
#  define mnt_dir f_mntonname
#  define entry (entry + mnts)
# endif
    {
        if (strcmp(entry->mnt_fsname, _device) == 0 || strcmp(entry->mnt_dir, _device) == 0)
        {
            if ((r = fslabel_identify(entry->mnt_fsname, &label)) == 1)
            {
                strncpy(_uuid, label.uuid, sizeof(label.uuid) - 1);
                _uuid[sizeof(label.uuid) - 1] = 0;

                strncpy(_label, label.label, sizeof(label.label) - 1);
                _label[sizeof(label.label) - 1] = 0;
            }
            else
            {
                _uuid[0] = 0;
                _label[0] = 0;

                /* printf("fslabel: %s: cannot identify filesystem.\n", entry->mnt_fsname); */
            }

            strncpy(_name, entry->mnt_dir, PATH_MAX - 1);
            _name[PATH_MAX - 1] = 0;

            strncpy(_device, entry->mnt_fsname, PATH_MAX - 1);
            _device[PATH_MAX - 1] = 0;

            break;
        }
    }

# ifdef HAVE_SETMNTENT
    endmntent(table);
# elif defined(USE_STRUCT_MNTTAB)
    fclose(table);
# endif

    return 0;
}
Example #23
0
/* Function to detect the MB of diskspace on a path */
int detect_diskspace(const char *path)
{
	long long avail = 0LL;

	if ( path[0] == '/' ) {
#ifdef HAVE_SYS_STATVFS_H
		struct statvfs fs;
#else
		struct statfs fs;
#endif
		char buf[PATH_MAX], *cp;

		strcpy(buf, path);
        cp = buf+strlen(buf);
        while ( buf[0] && (access(buf, F_OK) < 0) ) {
            while ( (cp > (buf+1)) && (*cp != '/') ) {
                --cp;
            }
            *cp = '\0';
        }
		if ( buf[0] ) {
#ifdef HAVE_SYS_STATVFS_H
			if ( statvfs(buf, &fs) ) {
#else
			if ( statfs(buf, &fs) ) {
#endif
				perror("statfs");
				return 0;
			}
			avail = fs.f_bsize;
			avail *= fs.f_bavail;
		}
	}
	return avail / (1024*1024LL);
}

int detect_and_mount_cdrom(char *path[SETUP_MAX_DRIVES])
{
	int num_cdroms = 0;

#ifdef __FreeBSD__
	int mounted;
    struct fstab *fstab;

    /* Try to mount unmounted CDROM filesystems */
    while( (fstab = getfsent()) != NULL ){
        if ( !strcmp(fstab->fs_vfstype, MNTTYPE_CDROM)) {
            if ( !is_fs_mounted(fstab->fs_spec)) {
                if ( ! run_command(NULL, MOUNT_PATH, fstab->fs_spec, 1) ) {
                    add_mounted_entry(fstab->fs_spec, fstab->fs_file);
                    log_normal(_("Mounted device %s"), fstab->fs_spec);
                }
            }
        }
    }
    endfsent();

    mounted = getfsstat(NULL, 0, MNT_WAIT);
    if ( mounted > 0 ) {
        int i;
		struct statfs *mnts = (struct statfs *)malloc(sizeof(struct statfs) * mounted);

		mounted = getfsstat(mnts, mounted * sizeof(struct statfs), MNT_WAIT);
		for ( i = 0; i < mounted && num_cdroms < SETUP_MAX_DRIVES; ++ i ) {
			if ( ! strcmp(mnts[i].f_fstypename, MNTTYPE_CDROM) ) {
				path[num_cdroms ++] = strdup(mnts[i].f_mntonname);
			}
		}
		
		free(mnts);
    }
#elif defined(darwin)
{
    const char *devPrefix = "/dev/";
    int prefixLen = strlen(devPrefix);
    mach_port_t masterPort = 0;
    struct statfs *mntbufp;
    int i, mounts;

    if (IOMasterPort(MACH_PORT_NULL, &masterPort) == KERN_SUCCESS)
    {
        mounts = getmntinfo(&mntbufp, MNT_WAIT);  /* NOT THREAD SAFE! */
        for (i = 0; i < mounts && num_cdroms < SETUP_MAX_DRIVES; i++)
        {
            char *dev = mntbufp[i].f_mntfromname;
            char *mnt = mntbufp[i].f_mntonname;
            if (strncmp(dev, devPrefix, prefixLen) != 0)  /* virtual device? */
                continue;

            /* darwinIsMountedDisc needs to skip "/dev/" part of string... */
            if (darwinIsMountedDisc(dev + prefixLen, masterPort))
            {
                strcpy(darwinEjectThisCDDevice, dev + prefixLen);
                path[num_cdroms ++] = strdup(mnt);
            }
        }
    }
}
#elif defined(sco)
	/* Quite horrible. We have to parse mount's output :( */
	/* And of course, we can't try to mount unmounted filesystems */
	FILE *cmd = popen("/etc/mount", "r");
	if ( cmd ) {
		char device[32] = "", mountp[PATH_MAX] = "";
		while ( fscanf(cmd, "%s on %32s %*[^\n]", mountp, device) > 0 ) {
			if ( !strncmp(device, "/dev/cd", 7) ) {
				path[num_cdroms ++] = strdup(mountp);
				break;
			}
		}
		pclose(cmd);
	}

#elif defined(hpux)
    char mntdevpath[PATH_MAX];
    FILE *mountfp;
    struct mntent *mntent;
    const char *fstab, *mtab, *mount_cmd, *mnttype;

    /* HPUX: We need to support PFS */
    if ( !access("/etc/pfs_fstab", F_OK) ) {
		fstab = "/etc/pfs_fstab";
		mtab = "/etc/pfs_mtab";
		mount_cmd = "/usr/sbin/pfs_mount";
		mnttype = "pfs-rrip";
    } else {
		fstab = SETUP_FSTAB;
		mtab = MOUNTS_FILE;
		mnttype = MNTTYPE_CDROM;
		mount_cmd = MOUNT_PATH;
    }

    /* Try to mount unmounted CDROM filesystems */
    mountfp = setmntent( fstab, "r" );
    if( mountfp != NULL ) {
        while( (mntent = getmntent( mountfp )) != NULL ){
            if ( !strcmp(mntent->mnt_type, mnttype) ) {
                char *fsname = strdup(mntent->mnt_fsname);
                char *dir = strdup(mntent->mnt_dir);
                if ( !is_fs_mounted(fsname)) {
                    if ( ! run_command(NULL, mount_cmd, fsname, 1) ) {
                        add_mounted_entry(fsname, dir);
                        log_normal(_("Mounted device %s"), fsname);
                    }
                }
                free(fsname);
                free(dir);
            }
        }
        endmntent(mountfp);
    }
    
    mountfp = setmntent(mtab, "r" );
    if( mountfp != NULL ) {
        while( (mntent = getmntent( mountfp )) != NULL && num_cdroms < SETUP_MAX_DRIVES){
            char mntdev[1024], mnt_type[32];

            strcpy(mntdev, mntent->mnt_fsname);
            strcpy(mnt_type, mntent->mnt_type);
            if( strncmp(mntdev, "/dev", 4) || 
                realpath(mntdev, mntdevpath) == NULL ) {
                continue;
            }
            if ( strcmp(mnt_type, mnttype) == 0 ) {
				path[num_cdroms ++] = strdup(mntent->mnt_dir);
            }
        }
        endmntent( mountfp );
    }
#elif defined(__svr4__)
	struct mnttab mnt;

	FILE *fstab = fopen(SETUP_FSTAB, "r");
	if ( fstab != NULL ) {
		while ( getmntent(fstab, &mnt)==0 ) {
			if ( !strcmp(mnt.mnt_fstype, MNTTYPE_CDROM) ) {
                char *fsname = strdup(mnt.mnt_special);
                char *dir = strdup(mnt.mnt_mountp);
                if ( !is_fs_mounted(fsname)) {
                    if ( ! run_command(NULL, MOUNT_PATH, fsname, 1) ) {
                        add_mounted_entry(fsname, dir);
                        log_normal(_("Mounted device %s"), fsname);
                    }
                }
                free(fsname);
                free(dir);
				break;
			}
		}
		fclose(fstab);
		fstab = fopen(MOUNTS_FILE, "r");
		if (fstab) {
			while ( getmntent(fstab, &mnt)==0 && num_cdroms < SETUP_MAX_DRIVES) {
				if ( !strcmp(mnt.mnt_fstype, MNTTYPE_CDROM) ) {
					path[num_cdroms ++] = strdup(mnt.mnt_mountp);
				}
			}
			fclose(fstab);
		}
	}
    
#else
//#ifndef darwin
    char mntdevpath[PATH_MAX];
    FILE *mountfp;
    struct mntent *mntent;

    /* Try to mount unmounted CDROM filesystems */
    mountfp = setmntent( SETUP_FSTAB, "r" );
    if( mountfp != NULL ) {
        while( (mntent = getmntent( mountfp )) != NULL ){
            if ( (!strcmp(mntent->mnt_type, MNTTYPE_CDROM) 
#ifdef sgi
				 || !strcmp(mntent->mnt_type, "cdfs")
				 || !strcmp(mntent->mnt_type, "efs")
#endif
				 || !strcmp(mntent->mnt_type, "auto"))
				 && strncmp(mntent->mnt_fsname, DEVICE_FLOPPY, strlen(DEVICE_FLOPPY)) ) {
                char *fsname = strdup(mntent->mnt_fsname);
                char *dir = strdup(mntent->mnt_dir);
                if ( !is_fs_mounted(fsname)) {
                    if ( ! run_command(NULL, MOUNT_PATH, fsname, 1) ) {
                        add_mounted_entry(fsname, dir);
                        log_normal(_("Mounted device %s"), fsname);
                    }
                }
                free(fsname);
                free(dir);
            }
        }
        endmntent(mountfp);
    }
    
    mountfp = setmntent(MOUNTS_FILE, "r" );
    if( mountfp != NULL ) {
        while( (mntent = getmntent( mountfp )) != NULL && num_cdroms < SETUP_MAX_DRIVES){
            char *tmp, mntdev[1024], mnt_type[32];

			if ( strncmp(mntent->mnt_fsname, DEVICE_FLOPPY, strlen(DEVICE_FLOPPY)) == 0)
				continue;

            strcpy(mntdev, mntent->mnt_fsname);
            strcpy(mnt_type, mntent->mnt_type);
            if ( strcmp(mnt_type, MNTTYPE_SUPER) == 0 ) {
                tmp = strstr(mntent->mnt_opts, "fs=");
                if ( tmp ) {
                    strcpy(mnt_type, tmp+strlen("fs="));
                    tmp = strchr(mnt_type, ',');
                    if ( tmp ) {
                        *tmp = '\0';
                    }
                }
		tmp = strstr(mntent->mnt_opts, "dev=");
		if ( tmp ) {
                    strcpy(mntdev, tmp+strlen("dev="));
                    tmp = strchr(mntdev, ',');
                    if ( tmp ) {
                        *tmp = '\0';
                    }
                }
            }
            if( strncmp(mntdev, "/dev", 4) || 
                realpath(mntdev, mntdevpath) == NULL ) {
                continue;
            }
            if ( strcmp(mnt_type, MNTTYPE_CDROM) == 0 ) {
	        path[num_cdroms ++] = strdup(mntent->mnt_dir);
            } else if ( strcmp(mnt_type, "auto") == 0 &&
			strncmp(mntdev, DEVICE_FLOPPY, strlen(DEVICE_FLOPPY))) {
	        path[num_cdroms ++] = strdup(mntent->mnt_dir);		
	    }
#ifdef sgi
            else if ( strcmp(mnt_type, "cdfs") == 0 ||
                      strcmp(mnt_type, "efs")  == 0 ) {
	      path[num_cdroms ++] = strdup(mntent->mnt_dir);
            }
#endif
        }
        endmntent( mountfp );
    }
//#endif
#endif
	return num_cdroms;
}
Example #24
0
int do_macos_iokit(int update_every, usec_t dt) {
    (void)dt;

    static int do_io = -1, do_space = -1, do_inodes = -1, do_bandwidth = -1;

    if (unlikely(do_io == -1)) {
        do_io                   = config_get_boolean("plugin:macos:iokit", "disk i/o", 1);
        do_space                = config_get_boolean("plugin:macos:sysctl", "space usage for all disks", 1);
        do_inodes               = config_get_boolean("plugin:macos:sysctl", "inodes usage for all disks", 1);
        do_bandwidth            = config_get_boolean("plugin:macos:sysctl", "bandwidth", 1);
    }

    RRDSET *st;

    mach_port_t         master_port;
    io_registry_entry_t drive, drive_media;
    io_iterator_t       drive_list;
    CFDictionaryRef     properties, statistics;
    CFStringRef         name;
    CFNumberRef         number;
    kern_return_t       status;
    collected_number    total_disk_reads = 0;
    collected_number    total_disk_writes = 0;
    struct diskstat {
        char name[MAXDRIVENAME];
        collected_number bytes_read;
        collected_number bytes_write;
        collected_number reads;
        collected_number writes;
        collected_number time_read;
        collected_number time_write;
        collected_number latency_read;
        collected_number latency_write;
    } diskstat;
    struct cur_diskstat {
        collected_number duration_read_ns;
        collected_number duration_write_ns;
        collected_number busy_time_ns;
    } cur_diskstat;
    struct prev_diskstat {
        collected_number bytes_read;
        collected_number bytes_write;
        collected_number operations_read;
        collected_number operations_write;
        collected_number duration_read_ns;
        collected_number duration_write_ns;
        collected_number busy_time_ns;
    } prev_diskstat;

    // NEEDED BY: do_space, do_inodes
    struct statfs *mntbuf;
    int mntsize, i;
    char mntonname[MNAMELEN + 1];
    char title[4096 + 1];

    // NEEDED BY: do_bandwidth
    struct ifaddrs *ifa, *ifap;

    /* Get ports and services for drive statistics. */
    if (unlikely(IOMasterPort(bootstrap_port, &master_port))) {
        error("MACOS: IOMasterPort() failed");
        do_io = 0;
        error("DISABLED: system.io");
    /* Get the list of all drive objects. */
    } else if (unlikely(IOServiceGetMatchingServices(master_port, IOServiceMatching("IOBlockStorageDriver"), &drive_list))) {
        error("MACOS: IOServiceGetMatchingServices() failed");
        do_io = 0;
        error("DISABLED: system.io");
    } else {
        while ((drive = IOIteratorNext(drive_list)) != 0) {
            properties = 0;
            statistics = 0;
            number = 0;
            bzero(&diskstat, sizeof(diskstat));

            /* Get drive media object. */
            status = IORegistryEntryGetChildEntry(drive, kIOServicePlane, &drive_media);
            if (unlikely(status != KERN_SUCCESS)) {
                IOObjectRelease(drive);
                continue;
            }

            /* Get drive media properties. */
            if (likely(!IORegistryEntryCreateCFProperties(drive_media, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, 0))) {
                /* Get disk name. */
                if (likely(name = (CFStringRef)CFDictionaryGetValue(properties, CFSTR(kIOBSDNameKey)))) {
                    CFStringGetCString(name, diskstat.name, MAXDRIVENAME, kCFStringEncodingUTF8);
                }
            }

            /* Release. */
            CFRelease(properties);
            IOObjectRelease(drive_media);

            /* Obtain the properties for this drive object. */
            if (unlikely(IORegistryEntryCreateCFProperties(drive, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, 0))) {
                error("MACOS: IORegistryEntryCreateCFProperties() failed");
                do_io = 0;
                error("DISABLED: system.io");
                break;
            } else if (likely(properties)) {
                /* Obtain the statistics from the drive properties. */
                if (likely(statistics = (CFDictionaryRef)CFDictionaryGetValue(properties, CFSTR(kIOBlockStorageDriverStatisticsKey)))) {

                    // --------------------------------------------------------------------

                    /* Get bytes read. */
                    if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey)))) {
                        CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.bytes_read);
                        total_disk_reads += diskstat.bytes_read;
                    }

                    /* Get bytes written. */
                    if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey)))) {
                        CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.bytes_write);
                        total_disk_writes += diskstat.bytes_write;
                    }

                    st = rrdset_find_bytype("disk", diskstat.name);
                    if (unlikely(!st)) {
                        st = rrdset_create("disk", diskstat.name, NULL, diskstat.name, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);

                        rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_INCREMENTAL);
                        rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_INCREMENTAL);
                    }
                    else rrdset_next(st);

                    prev_diskstat.bytes_read = rrddim_set(st, "reads", diskstat.bytes_read);
                    prev_diskstat.bytes_write = rrddim_set(st, "writes", diskstat.bytes_write);
                    rrdset_done(st);

                    // --------------------------------------------------------------------

                    /* Get number of reads. */
                    if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsReadsKey)))) {
                        CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.reads);
                    }

                    /* Get number of writes. */
                    if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsWritesKey)))) {
                        CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.writes);
                    }

                    st = rrdset_find_bytype("disk_ops", diskstat.name);
                    if (unlikely(!st)) {
                        st = rrdset_create("disk_ops", diskstat.name, NULL, diskstat.name, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
                        st->isdetail = 1;

                        rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
                        rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
                    }
                    else rrdset_next(st);

                    prev_diskstat.operations_read = rrddim_set(st, "reads", diskstat.reads);
                    prev_diskstat.operations_write = rrddim_set(st, "writes", diskstat.writes);
                    rrdset_done(st);

                    // --------------------------------------------------------------------

                    /* Get reads time. */
                    if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey)))) {
                        CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.time_read);
                    }

                    /* Get writes time. */
                    if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey)))) {
                        CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.time_write);
                    }

                    st = rrdset_find_bytype("disk_util", diskstat.name);
                    if (unlikely(!st)) {
                        st = rrdset_create("disk_util", diskstat.name, NULL, diskstat.name, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA);
                        st->isdetail = 1;

                        rrddim_add(st, "utilization", NULL, 1, 10000000, RRDDIM_INCREMENTAL);
                    }
                    else rrdset_next(st);

                    cur_diskstat.busy_time_ns = (diskstat.time_read + diskstat.time_write);
                    prev_diskstat.busy_time_ns = rrddim_set(st, "utilization", cur_diskstat.busy_time_ns);
                    rrdset_done(st);

                    // --------------------------------------------------------------------

                    /* Get reads latency. */
                    if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsLatentReadTimeKey)))) {
                        CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.latency_read);
                    }

                    /* Get writes latency. */
                    if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsLatentWriteTimeKey)))) {
                        CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.latency_write);
                    }

                    st = rrdset_find_bytype("disk_iotime", diskstat.name);
                    if (unlikely(!st)) {
                        st = rrdset_create("disk_iotime", diskstat.name, NULL, diskstat.name, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE);
                        st->isdetail = 1;

                        rrddim_add(st, "reads", NULL, 1, 1000000, RRDDIM_INCREMENTAL);
                        rrddim_add(st, "writes", NULL, -1, 1000000, RRDDIM_INCREMENTAL);
                    }
                    else rrdset_next(st);

                    cur_diskstat.duration_read_ns = diskstat.time_read + diskstat.latency_read;
                    cur_diskstat.duration_write_ns = diskstat.time_write + diskstat.latency_write;
                    prev_diskstat.duration_read_ns = rrddim_set(st, "reads", cur_diskstat.duration_read_ns);
                    prev_diskstat.duration_write_ns = rrddim_set(st, "writes", cur_diskstat.duration_write_ns);
                    rrdset_done(st);

                    // --------------------------------------------------------------------
                    // calculate differential charts
                    // only if this is not the first time we run

                    if (likely(dt)) {

                        // --------------------------------------------------------------------

                        st = rrdset_find_bytype("disk_await", diskstat.name);
                        if (unlikely(!st)) {
                            st = rrdset_create("disk_await", diskstat.name, NULL, diskstat.name, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE);
                            st->isdetail = 1;

                            rrddim_add(st, "reads", NULL, 1, 1000000, RRDDIM_ABSOLUTE);
                            rrddim_add(st, "writes", NULL, -1, 1000000, RRDDIM_ABSOLUTE);
                        }
                        else rrdset_next(st);

                        rrddim_set(st, "reads", (diskstat.reads - prev_diskstat.operations_read) ?
                            (cur_diskstat.duration_read_ns - prev_diskstat.duration_read_ns) / (diskstat.reads - prev_diskstat.operations_read) : 0);
                        rrddim_set(st, "writes", (diskstat.writes - prev_diskstat.operations_write) ?
                            (cur_diskstat.duration_write_ns - prev_diskstat.duration_write_ns) / (diskstat.writes - prev_diskstat.operations_write) : 0);
                        rrdset_done(st);

                        // --------------------------------------------------------------------

                        st = rrdset_find_bytype("disk_avgsz", diskstat.name);
                        if (unlikely(!st)) {
                            st = rrdset_create("disk_avgsz", diskstat.name, NULL, diskstat.name, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA);
                            st->isdetail = 1;

                            rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_ABSOLUTE);
                            rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_ABSOLUTE);
                        }
                        else rrdset_next(st);

                        rrddim_set(st, "reads", (diskstat.reads - prev_diskstat.operations_read) ?
                            (diskstat.bytes_read - prev_diskstat.bytes_read) / (diskstat.reads - prev_diskstat.operations_read) : 0);
                        rrddim_set(st, "writes", (diskstat.writes - prev_diskstat.operations_write) ?
                            (diskstat.bytes_write - prev_diskstat.bytes_write) / (diskstat.writes - prev_diskstat.operations_write) : 0);
                        rrdset_done(st);

                        // --------------------------------------------------------------------

                        st = rrdset_find_bytype("disk_svctm", diskstat.name);
                        if (unlikely(!st)) {
                            st = rrdset_create("disk_svctm", diskstat.name, NULL, diskstat.name, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE);
                            st->isdetail = 1;

                            rrddim_add(st, "svctm", NULL, 1, 1000000, RRDDIM_ABSOLUTE);
                        }
                        else rrdset_next(st);

                        rrddim_set(st, "svctm", ((diskstat.reads - prev_diskstat.operations_read) + (diskstat.writes - prev_diskstat.operations_write)) ?
                            (cur_diskstat.busy_time_ns - prev_diskstat.busy_time_ns) / ((diskstat.reads - prev_diskstat.operations_read) + (diskstat.writes - prev_diskstat.operations_write)) : 0);
                        rrdset_done(st);
                    }
                }

                /* Release. */
                CFRelease(properties);
            }

            /* Release. */
            IOObjectRelease(drive);
        }
        IOIteratorReset(drive_list);

        /* Release. */
        IOObjectRelease(drive_list);
    }

    if (likely(do_io)) {
        st = rrdset_find_bytype("system", "io");
        if (unlikely(!st)) {
            st = rrdset_create("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA);
            rrddim_add(st, "in",  NULL,  1, 1024, RRDDIM_INCREMENTAL);
            rrddim_add(st, "out", NULL, -1, 1024, RRDDIM_INCREMENTAL);
        }
        else rrdset_next(st);

        rrddim_set(st, "in", total_disk_reads);
        rrddim_set(st, "out", total_disk_writes);
        rrdset_done(st);
    }

    // Can be merged with FreeBSD plugin
    // --------------------------------------------------------------------------

    if (likely(do_space || do_inodes)) {
        // there is no mount info in sysctl MIBs
        if (unlikely(!(mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)))) {
            error("MACOS: getmntinfo() failed");
            do_space = 0;
            error("DISABLED: disk_space.X");
            do_inodes = 0;
            error("DISABLED: disk_inodes.X");
        } else {
            for (i = 0; i < mntsize; i++) {
                if (mntbuf[i].f_flags == MNT_RDONLY ||
                        mntbuf[i].f_blocks == 0 ||
                        // taken from gnulib/mountlist.c and shortened to FreeBSD related fstypes
                        strcmp(mntbuf[i].f_fstypename, "autofs") == 0 ||
                        strcmp(mntbuf[i].f_fstypename, "procfs") == 0 ||
                        strcmp(mntbuf[i].f_fstypename, "subfs") == 0 ||
                        strcmp(mntbuf[i].f_fstypename, "devfs") == 0 ||
                        strcmp(mntbuf[i].f_fstypename, "none") == 0)
                    continue;

                // --------------------------------------------------------------------------

                if (likely(do_space)) {
                    st = rrdset_find_bytype("disk_space", mntbuf[i].f_mntonname);
                    if (unlikely(!st)) {
                        snprintfz(title, 4096, "Disk Space Usage for %s [%s]", mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname);
                        st = rrdset_create("disk_space", mntbuf[i].f_mntonname, NULL, mntbuf[i].f_mntonname, "disk.space", title, "GB", 2023,
                                           update_every,
                                           RRDSET_TYPE_STACKED);

                        rrddim_add(st, "avail", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRDDIM_ABSOLUTE);
                        rrddim_add(st, "used", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRDDIM_ABSOLUTE);
                        rrddim_add(st, "reserved_for_root", "reserved for root", mntbuf[i].f_bsize, GIGA_FACTOR,
                                   RRDDIM_ABSOLUTE);
                    } else
                        rrdset_next(st);

                    rrddim_set(st, "avail", (collected_number) mntbuf[i].f_bavail);
                    rrddim_set(st, "used", (collected_number) (mntbuf[i].f_blocks - mntbuf[i].f_bfree));
                    rrddim_set(st, "reserved_for_root", (collected_number) (mntbuf[i].f_bfree - mntbuf[i].f_bavail));
                    rrdset_done(st);
                }

                // --------------------------------------------------------------------------

                if (likely(do_inodes)) {
                    st = rrdset_find_bytype("disk_inodes", mntbuf[i].f_mntonname);
                    if (unlikely(!st)) {
                        snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname);
                        st = rrdset_create("disk_inodes", mntbuf[i].f_mntonname, NULL, mntbuf[i].f_mntonname, "disk.inodes", title, "Inodes", 2024,
                                           update_every, RRDSET_TYPE_STACKED);

                        rrddim_add(st, "avail", NULL, 1, 1, RRDDIM_ABSOLUTE);
                        rrddim_add(st, "used", NULL, 1, 1, RRDDIM_ABSOLUTE);
                        rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1, RRDDIM_ABSOLUTE);
                    } else
                        rrdset_next(st);

                    rrddim_set(st, "avail", (collected_number) mntbuf[i].f_ffree);
                    rrddim_set(st, "used", (collected_number) (mntbuf[i].f_files - mntbuf[i].f_ffree));
                    rrdset_done(st);
                }
            }
        }
    }

    // Can be merged with FreeBSD plugin
    // --------------------------------------------------------------------

    if (likely(do_bandwidth)) {
        if (unlikely(getifaddrs(&ifap))) {
            error("MACOS: getifaddrs()");
            do_bandwidth = 0;
            error("DISABLED: system.ipv4");
        } else {
            for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
                if (ifa->ifa_addr->sa_family != AF_LINK)
                        continue;

                // --------------------------------------------------------------------

                st = rrdset_find_bytype("net", ifa->ifa_name);
                if (unlikely(!st)) {
                    st = rrdset_create("net", ifa->ifa_name, NULL, ifa->ifa_name, "net.net", "Bandwidth", "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA);

                    rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "received", IFA_DATA(ibytes));
                rrddim_set(st, "sent", IFA_DATA(obytes));
                rrdset_done(st);

                // --------------------------------------------------------------------

                st = rrdset_find_bytype("net_packets", ifa->ifa_name);
                if (unlikely(!st)) {
                    st = rrdset_create("net_packets", ifa->ifa_name, NULL, ifa->ifa_name, "net.packets", "Packets", "packets/s", 7001, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "multicast_received", NULL, 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "multicast_sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "received", IFA_DATA(ipackets));
                rrddim_set(st, "sent", IFA_DATA(opackets));
                rrddim_set(st, "multicast_received", IFA_DATA(imcasts));
                rrddim_set(st, "multicast_sent", IFA_DATA(omcasts));
                rrdset_done(st);

                // --------------------------------------------------------------------

                st = rrdset_find_bytype("net_errors", ifa->ifa_name);
                if (unlikely(!st)) {
                    st = rrdset_create("net_errors", ifa->ifa_name, NULL, ifa->ifa_name, "net.errors", "Interface Errors", "errors/s", 7002, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "inbound", IFA_DATA(ierrors));
                rrddim_set(st, "outbound", IFA_DATA(oerrors));
                rrdset_done(st);

                // --------------------------------------------------------------------

                st = rrdset_find_bytype("net_drops", ifa->ifa_name);
                if (unlikely(!st)) {
                    st = rrdset_create("net_drops", ifa->ifa_name, NULL, ifa->ifa_name, "net.drops", "Interface Drops", "drops/s", 7003, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "inbound", IFA_DATA(iqdrops));
                rrdset_done(st);

                // --------------------------------------------------------------------

                st = rrdset_find_bytype("net_events", ifa->ifa_name);
                if (unlikely(!st)) {
                    st = rrdset_create("net_events", ifa->ifa_name, NULL, ifa->ifa_name, "net.events", "Network Interface Events", "events/s", 7006, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "frames", NULL, 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "collisions", NULL, -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "carrier", NULL, -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "collisions", IFA_DATA(collisions));
                rrdset_done(st);
            }

            freeifaddrs(ifap);
        }
    }


    return 0;
}
Example #25
0
sg_fs_stats *sg_get_fs_stats(int *entries){
	VECTOR_DECLARE_STATIC(disk_stats, sg_fs_stats, 10,
			      disk_stat_init, disk_stat_destroy);

	int num_disks=0;
#if defined(LINUX) || defined (SOLARIS) || defined(CYGWIN) || defined(HPUX)
	FILE *f;
#endif

	sg_fs_stats *disk_ptr;

#ifdef SOLARIS
	struct mnttab mp;
	struct statvfs fs;
#endif
#if defined(LINUX) || defined(CYGWIN) || defined(HPUX)
	struct mntent *mp;
	struct statvfs fs;
#endif
#ifdef ALLBSD
	int nummnt;
#ifdef HAVE_STATVFS
	struct statvfs *mp, **fs;
#else
	struct statfs *mp, **fs;
#endif
#endif
#ifdef WIN32
	char lp_buf[MAX_PATH];
	char volume_name_buf[BUFSIZE];
	char filesys_name_buf[BUFSIZE];
	char drive[4] = " :\\";
	char *p;
	int drive_type; //@
	lp_buf[0]='\0';
#endif

#ifdef ALLBSD
	nummnt=getmntinfo(&mp, MNT_WAIT);
	if (nummnt<=0){
		sg_set_error_with_errno(SG_ERROR_GETMNTINFO, NULL);
		return NULL;
	}
	for(fs = &mp; nummnt--; (*fs)++){
#endif

#if defined(LINUX) || defined(CYGWIN) || defined(HPUX)
#ifdef MNT_MNTTAB
	if ((f=setmntent(MNT_MNTTAB, "r" ))==NULL){
#else
	if ((f=setmntent("/etc/mtab", "r" ))==NULL){
#endif
		sg_set_error(SG_ERROR_SETMNTENT, NULL);
		return NULL;
	}

	while((mp=getmntent(f))){
		if((statvfs(mp->mnt_dir, &fs)) !=0){
			continue;
		}	

#endif

#ifdef SOLARIS
	if ((f=fopen("/etc/mnttab", "r" ))==NULL){
		sg_set_error_with_errno(SG_ERROR_OPEN, "/etc/mnttab");
		return NULL;
	}
	while((getmntent(f, &mp)) == 0){
		if ((statvfs(mp.mnt_mountp, &fs)) !=0){
			continue;
		}
#endif

#ifdef WIN32
	if (!(GetLogicalDriveStringsA(BUFSIZE-1, lp_buf))) {
		sg_set_error(SG_ERROR_GETMNTINFO, "GetLogicalDriveStrings");
		return NULL;
	}
	p = lp_buf;
	do {
		// Copy drive letter to template string
		*drive = *p;
		// Only interested in harddrives.
		drive_type = GetDriveTypeA(drive);

		if(drive_type == DRIVE_FIXED) {
#else
		if(is_valid_fs_type(SG_MP_FSTYPENAME(mp))){
#endif
			if (VECTOR_RESIZE(disk_stats, num_disks + 1) < 0) {
				return NULL;
			}
			disk_ptr=disk_stats+num_disks;

#ifndef WIN32
			/* Maybe make this char[bigenough] and do strncpy's and put a null in the end? 
			 * Downside is its a bit hungry for a lot of mounts, as MNT_MAX_SIZE would prob 
			 * be upwards of a k each 
			 */
			if (sg_update_string(&disk_ptr->device_name, SG_MP_DEVNAME(mp)) < 0) {
				return NULL;
			}
			if (sg_update_string(&disk_ptr->fs_type, SG_MP_FSTYPENAME(mp)) < 0) {
				return NULL;
			}
			if (sg_update_string(&disk_ptr->mnt_point, SG_MP_MOUNTP(mp)) < 0) {
				return NULL;
			}

			disk_ptr->size  = SG_FS_FRSIZE(fs) * SG_FS_BLOCKS(fs);
			disk_ptr->avail = SG_FS_FRSIZE(fs) * SG_FS_BAVAIL(fs);
			disk_ptr->used  = (disk_ptr->size) - (SG_FS_FRSIZE(fs) * SG_FS_BFREE(fs));
		
			disk_ptr->total_inodes = SG_FS_FILES(fs);
			disk_ptr->free_inodes  = SG_FS_FFREE(fs);
			/* Linux, FreeBSD don't have a "available" inodes */
			disk_ptr->used_inodes  = disk_ptr->total_inodes - disk_ptr->free_inodes;
			disk_ptr->avail_inodes = SG_FS_FAVAIL(fs);

			disk_ptr->io_size      = SG_FS_BSIZE(fs);
			disk_ptr->block_size   = SG_FS_FRSIZE(fs);
			disk_ptr->total_blocks = SG_FS_BLOCKS(fs);
			disk_ptr->free_blocks  = SG_FS_BFREE(fs);
			disk_ptr->avail_blocks = SG_FS_BAVAIL(fs);
			disk_ptr->used_blocks  = disk_ptr->total_blocks - disk_ptr->free_blocks;
#else
			if(!GetVolumeInformationA(drive, volume_name_buf, BUFSIZE,
						NULL, NULL, NULL, 
						filesys_name_buf, BUFSIZE)) {
				sg_set_error_with_errno(SG_ERROR_DISKINFO, 
					"GetVolumeInformation");
				return NULL;
			}

			if (sg_update_string(&disk_ptr->device_name, 
						volume_name_buf) < 0) {
				return NULL;
			}
			if (sg_update_string(&disk_ptr->fs_type, 
						filesys_name_buf) < 0) {
				return NULL;
			}
			if (sg_update_string(&disk_ptr->mnt_point,
						drive) < 0) {
				return NULL;
			}
			if (!GetDiskFreeSpaceExA(drive, NULL,
					(PULARGE_INTEGER)&disk_ptr->size,
					(PULARGE_INTEGER)&disk_ptr->avail)) {
				sg_set_error_with_errno(SG_ERROR_DISKINFO,
					"GetDiskFreeSpaceEx");
				return NULL;
			}
			disk_ptr->used = disk_ptr->size - disk_ptr->avail;
			disk_ptr->total_inodes = 0;
			disk_ptr->free_inodes  = 0;
			disk_ptr->used_inodes  = 0;
			disk_ptr->avail_inodes = 0;

			/* I dunno what to do with these... so have nothing */
			disk_ptr->io_size = 0;
			disk_ptr->block_size = 0;
			disk_ptr->total_blocks = 0;
			disk_ptr->free_blocks = 0;
			disk_ptr->avail_blocks = 0;
			disk_ptr->used_blocks = 0;
#endif
			num_disks++;
		}
#ifdef WIN32
		while(*p++);
	} while(*p);
#else
	}
#endif

	*entries=num_disks;	

	/* If this fails, there is very little i can do about it, so
	   I'll ignore it :) */
#if defined(LINUX) || defined(CYGWIN) || defined(HPUX)
	endmntent(f);
#endif
#if defined(SOLARIS)
	fclose(f);
#endif

	return disk_stats;

}

int sg_fs_compare_device_name(const void *va, const void *vb) {
	const sg_fs_stats *a = (const sg_fs_stats *)va;
	const sg_fs_stats *b = (const sg_fs_stats *)vb;

	return strcmp(a->device_name, b->device_name);
}

int sg_fs_compare_mnt_point(const void *va, const void *vb) {
	const sg_fs_stats *a = (const sg_fs_stats *)va;
	const sg_fs_stats *b = (const sg_fs_stats *)vb;

	return strcmp(a->mnt_point, b->mnt_point);
}

static void diskio_stat_init(sg_disk_io_stats *d) {
	d->disk_name = NULL;
}

static void diskio_stat_destroy(sg_disk_io_stats *d) {
	free(d->disk_name);
}

VECTOR_DECLARE_STATIC(diskio_stats, sg_disk_io_stats, 10,
		      diskio_stat_init, diskio_stat_destroy);

#ifdef LINUX
typedef struct {
	int major;
	int minor;
} partition;
#endif

sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
	int num_diskio;
#ifndef LINUX
	sg_disk_io_stats *diskio_stats_ptr;
#endif

#ifdef HPUX
	long long rbytes = 0, wbytes = 0;
	struct dirent *dinfo = NULL;
	struct stat lstatinfo;
	struct pst_diskinfo pstat_diskinfo[DISK_BATCH];
	char fullpathbuf[1024] = {0};
	dev_t diskid;
	DIR *dh = NULL;
	int diskidx = 0;
	int num, i;
#endif
#ifdef SOLARIS
	kstat_ctl_t *kc;
	kstat_t *ksp;
	kstat_io_t kios;
#endif
#ifdef LINUX
	FILE *f;
	char *line_ptr;
	int major, minor;
	int has_pp_stats = 1;
	VECTOR_DECLARE_STATIC(parts, partition, 16, NULL, NULL);
	int i, n;
	time_t now;
	const char *format;
	static regex_t not_part_re, part_re;
	static int re_compiled = 0;
#endif
#if defined(FREEBSD) || defined(DFBSD)
	static struct statinfo stats;
	static int stats_init = 0;
	int counter;
	struct device_selection *dev_sel = NULL;
	int n_selected, n_selections;
	long sel_gen;
	struct devstat *dev_ptr;
#endif
#ifdef NETBSD
	struct disk_sysctl *stats;
#endif
#ifdef OPENBSD
	int diskcount;
	char *disknames, *name, *bufpp;
	char **dk_name;
	struct diskstats *stats;
#endif
#ifdef NETBSD
#define MIBSIZE 3
#endif
#ifdef OPENBSD
#define MIBSIZE 2
#endif
#if defined(NETBSD) || defined(OPENBSD)
	int num_disks, i;
	int mib[MIBSIZE];
	size_t size;
#endif
#ifdef WIN32
	char *name;
	long long rbytes;
	long long wbytes;
#endif

	num_diskio=0;

#ifdef HPUX
	while (1) {
		num = pstat_getdisk(pstat_diskinfo, sizeof pstat_diskinfo[0],
		                    DISK_BATCH, diskidx);
		if (num == -1) {
			sg_set_error_with_errno(SG_ERROR_PSTAT,
			                        "pstat_getdisk");
			return NULL;
		} else if (num == 0) {
			break;
		}

		for (i = 0; i < num; i++) {
			struct pst_diskinfo *di = &pstat_diskinfo[i];

			/* Skip "disabled" disks. */
			if (di->psd_status == 0) {
				continue;
			}
	
			/* We can't seperate the reads from the writes, we'll
			 * just give the same to each. (This value is in
			 * 64-byte chunks according to the pstat header file,
			 * and can wrap to be negative.)
			 */
			rbytes = wbytes = ((unsigned long) di->psd_dkwds) * 64LL;
	
			/* Skip unused disks. */
			if (rbytes == 0 && wbytes == 0) {
				continue;
			}
	
			if (VECTOR_RESIZE(diskio_stats, num_diskio + 1) < 0) {
				return NULL;
			}
	
			diskio_stats_ptr = diskio_stats + num_diskio;
	
			diskio_stats_ptr->read_bytes = rbytes;
			diskio_stats_ptr->write_bytes = wbytes;
	
			diskio_stats_ptr->systime = time(NULL);
	
			num_diskio++;
	
			/* FIXME This should use a static cache, like the Linux
			 * code below. */
			if (diskio_stats_ptr->disk_name == NULL) {
				dh = opendir("/dev/dsk");
				if (dh == NULL) {
					continue;
				}
	
				diskid = (di->psd_dev.psd_major << 24) | di->psd_dev.psd_minor;
				while (1) {
					dinfo = readdir(dh);
					if (dinfo == NULL) {
						break;
					}
					snprintf(fullpathbuf, sizeof(fullpathbuf), "/dev/dsk/%s", dinfo->d_name);
					if (lstat(fullpathbuf, &lstatinfo) < 0) {
						continue;
					}
	
					if (lstatinfo.st_rdev == diskid) {
						if (sg_update_string(&diskio_stats_ptr->disk_name, dinfo->d_name) < 0) {
							return NULL;
						}
						break;
					}
				}
				closedir(dh);
	
				if (diskio_stats_ptr->disk_name == NULL) {
					if (sg_update_string(&diskio_stats_ptr->disk_name, di->psd_hw_path.psh_name) < 0) {
						return NULL;
					}
				}
			}
		}
		diskidx = pstat_diskinfo[num - 1].psd_idx + 1;
	}
#endif
#ifdef OPENBSD
	mib[0] = CTL_HW;
	mib[1] = HW_DISKCOUNT;

	size = sizeof(diskcount);
	if (sysctl(mib, MIBSIZE, &diskcount, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_DISKCOUNT");
		return NULL;
	}

	mib[0] = CTL_HW;
	mib[1] = HW_DISKNAMES;

	if (sysctl(mib, MIBSIZE, NULL, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_DISKNAMES");
		return NULL;
	}

	disknames = sg_malloc(size);
	if (disknames == NULL) {
		return NULL;
	}

	if (sysctl(mib, MIBSIZE, disknames, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_DISKNAMES");
		return NULL;
	}

	dk_name = sg_malloc(diskcount * sizeof(char *));
	bufpp = disknames;
	for (i = 0; i < diskcount && (name = strsep(&bufpp, ",")) != NULL; i++) {
		dk_name[i] = name;
	}
#endif

#if defined(NETBSD) || defined(OPENBSD)
	mib[0] = CTL_HW;
	mib[1] = HW_DISKSTATS;
#ifdef NETBSD
	mib[2] = sizeof(struct disk_sysctl);
#endif

	if (sysctl(mib, MIBSIZE, NULL, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_DISKSTATS");
		return NULL;
	}

#ifdef NETBSD
	num_disks = size / sizeof(struct disk_sysctl);
#else
	num_disks = size / sizeof(struct diskstats);
#endif

	stats = sg_malloc(size);
	if (stats == NULL) {
		return NULL;
	}

	if (sysctl(mib, MIBSIZE, stats, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_DISKSTATS");
		return NULL;
	}

	for (i = 0; i < num_disks; i++) {
		const char *name;
		u_int64_t rbytes, wbytes;

#ifdef NETBSD
#ifdef HAVE_DK_RBYTES
		rbytes = stats[i].dk_rbytes;
		wbytes = stats[i].dk_wbytes;
#else
		/* Before 2.0, NetBSD merged reads and writes. */
		rbytes = wbytes = stats[i].dk_bytes;
#endif
#else
#ifdef HAVE_DS_RBYTES
		rbytes = stats[i].ds_rbytes;
		wbytes = stats[i].ds_wbytes;
#else
		/* Before 3.5, OpenBSD merged reads and writes */
		rbytes = wbytes = stats[i].ds_bytes;
#endif
#endif

		/* Don't keep stats for disks that have never been used. */
		if (rbytes == 0 && wbytes == 0) {
			continue;
		}

		if (VECTOR_RESIZE(diskio_stats, num_diskio + 1) < 0) {
			return NULL;
		}
		diskio_stats_ptr = diskio_stats + num_diskio;
		
		diskio_stats_ptr->read_bytes = rbytes;
		diskio_stats_ptr->write_bytes = wbytes;
#ifdef NETBSD
		name = stats[i].dk_name;
#else
		name = dk_name[i];
#endif
		if (sg_update_string(&diskio_stats_ptr->disk_name, name) < 0) {
			return NULL;
		}
		diskio_stats_ptr->systime = time(NULL);
	
		num_diskio++;	
	}

	free(stats);
#ifdef OPENBSD
	free(dk_name);
	free(disknames);
#endif
#endif

#if defined(FREEBSD) || defined(DFBSD)
	if (!stats_init) {
		stats.dinfo=sg_malloc(sizeof(struct devinfo));
		if(stats.dinfo==NULL) return NULL;
		bzero(stats.dinfo, sizeof(struct devinfo));
		stats_init = 1;
	}
#ifdef FREEBSD5
	if ((devstat_getdevs(NULL, &stats)) < 0) {
		/* FIXME devstat functions return a string error in
		   devstat_errbuf */
		sg_set_error(SG_ERROR_DEVSTAT_GETDEVS, NULL);
		return NULL;
	}
	/* Not aware of a get all devices, so i said 999. If we ever
	 * find a machine with more than 999 disks, then i'll change
	 * this number :)
	 */
	if (devstat_selectdevs(&dev_sel, &n_selected, &n_selections, &sel_gen, stats.dinfo->generation, stats.dinfo->devices, stats.dinfo->numdevs, NULL, 0, NULL, 0, DS_SELECT_ONLY, 999, 1) < 0) {
		sg_set_error(SG_ERROR_DEVSTAT_SELECTDEVS, NULL);
		return NULL;
	}
#else
	if ((getdevs(&stats)) < 0) {
		sg_set_error(SG_ERROR_DEVSTAT_GETDEVS, NULL);
		return NULL;
	}
	/* Not aware of a get all devices, so i said 999. If we ever
	 * find a machine with more than 999 disks, then i'll change
	 * this number :)
	 */
	if (selectdevs(&dev_sel, &n_selected, &n_selections, &sel_gen, stats.dinfo->generation, stats.dinfo->devices, stats.dinfo->numdevs, NULL, 0, NULL, 0, DS_SELECT_ONLY, 999, 1) < 0) {
		sg_set_error(SG_ERROR_DEVSTAT_SELECTDEVS, NULL);
		return NULL;
	}
#endif

	for(counter=0;counter<stats.dinfo->numdevs;counter++){
		dev_ptr=&stats.dinfo->devices[dev_sel[counter].position];

		/* Throw away devices that have done nothing, ever.. Eg "odd" 
		 * devices.. like mem, proc.. and also doesn't report floppy
		 * drives etc unless they are doing stuff :)
		 */
#ifdef FREEBSD5
		if((dev_ptr->bytes[DEVSTAT_READ]==0) && (dev_ptr->bytes[DEVSTAT_WRITE]==0)) continue;
#else
		if((dev_ptr->bytes_read==0) && (dev_ptr->bytes_written==0)) continue;
#endif

		if (VECTOR_RESIZE(diskio_stats, num_diskio + 1) < 0) {
			return NULL;
		}
		diskio_stats_ptr=diskio_stats+num_diskio;

#ifdef FREEBSD5		
		diskio_stats_ptr->read_bytes=dev_ptr->bytes[DEVSTAT_READ];
		diskio_stats_ptr->write_bytes=dev_ptr->bytes[DEVSTAT_WRITE];
#else
		diskio_stats_ptr->read_bytes=dev_ptr->bytes_read;
		diskio_stats_ptr->write_bytes=dev_ptr->bytes_written;
#endif
		if(diskio_stats_ptr->disk_name!=NULL) free(diskio_stats_ptr->disk_name);
		if (asprintf((&diskio_stats_ptr->disk_name), "%s%d", dev_ptr->device_name, dev_ptr->unit_number) == -1) {
			sg_set_error_with_errno(SG_ERROR_ASPRINTF, NULL);
			return NULL;
		}
		diskio_stats_ptr->systime=time(NULL);

		num_diskio++;
	}
	free(dev_sel);

#endif
#ifdef SOLARIS
	if ((kc = kstat_open()) == NULL) {
		sg_set_error(SG_ERROR_KSTAT_OPEN, NULL);
		return NULL;
	}

	for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
		if (!strcmp(ksp->ks_class, "disk")) {

			if(ksp->ks_type != KSTAT_TYPE_IO) continue;
			/* We dont want metadevices appearins as num_diskio */
			if(strcmp(ksp->ks_module, "md")==0) continue;
			if((kstat_read(kc, ksp, &kios))==-1){	
			}
			
			if (VECTOR_RESIZE(diskio_stats, num_diskio + 1) < 0) {
				kstat_close(kc);
				return NULL;
			}
			diskio_stats_ptr=diskio_stats+num_diskio;
			
			diskio_stats_ptr->read_bytes=kios.nread;
			diskio_stats_ptr->write_bytes=kios.nwritten;
			if (sg_update_string(&diskio_stats_ptr->disk_name,
					     sg_get_svr_from_bsd(ksp->ks_name)) < 0) {
				kstat_close(kc);
				return NULL;
			}
			diskio_stats_ptr->systime=time(NULL);

			num_diskio++;
		}
	}

	kstat_close(kc);
#endif

#ifdef LINUX
	num_diskio = 0;
	n = 0;

	/* Read /proc/partitions to find what devices exist. Recent 2.4 kernels
	   have statistics in here too, so we can use those directly.
	   2.6 kernels have /proc/diskstats instead with almost (but not quite)
	   the same format. */

	f = fopen("/proc/diskstats", "r");
	format = " %d %d %99s %*d %*d %lld %*d %*d %*d %lld";
	if (f == NULL) {
		f = fopen("/proc/partitions", "r");
		format = " %d %d %*d %99s %*d %*d %lld %*d %*d %*d %lld";
	}
	if (f == NULL) goto out;
	now = time(NULL);

	if (!re_compiled) {
		if (regcomp(&part_re, "^(.*/)?[^/]*[0-9]$", REG_EXTENDED | REG_NOSUB) != 0) {
			sg_set_error(SG_ERROR_PARSE, NULL);
			goto out;
		}
		if (regcomp(&not_part_re, "^(.*/)?[^/0-9]+[0-9]+d[0-9]+$", REG_EXTENDED | REG_NOSUB) != 0) {
			sg_set_error(SG_ERROR_PARSE, NULL);
			goto out;
		}
		re_compiled = 1;
	}

	while ((line_ptr = sg_f_read_line(f, "")) != NULL) {
		char name[100];
		long long rsect, wsect;

		int nr = sscanf(line_ptr, format,
			&major, &minor, name, &rsect, &wsect);
		if (nr < 3) continue;

		/* Skip device names ending in numbers, since they're
		   partitions, unless they match the c0d0 pattern that some
		   RAID devices use. */
		/* FIXME: For 2.6+, we should probably be using sysfs to detect
		   this... */
		if ((regexec(&part_re, name, 0, NULL, 0) == 0)
		    && (regexec(&not_part_re, name, 0, NULL, 0) != 0)) {
			continue;
		}

		if (nr < 5) {
			has_pp_stats = 0;
			rsect = 0;
			wsect = 0;
		}

		if (VECTOR_RESIZE(diskio_stats, n + 1) < 0) {
			goto out;
		}
		if (VECTOR_RESIZE(parts, n + 1) < 0) {
			goto out;
		}

		if (sg_update_string(&diskio_stats[n].disk_name, name) < 0) {
			goto out;
		}
		diskio_stats[n].read_bytes = rsect * 512;
		diskio_stats[n].write_bytes = wsect * 512;
		diskio_stats[n].systime = now;
		parts[n].major = major;
		parts[n].minor = minor;

		n++;
	}

	fclose(f);
	f = NULL;

	if (!has_pp_stats) {
		/* This is an older kernel where /proc/partitions doesn't
		   contain stats. Read what we can from /proc/stat instead, and
		   fill in the appropriate bits of the list allocated above. */

		f = fopen("/proc/stat", "r");
		if (f == NULL) goto out;
		now = time(NULL);

		line_ptr = sg_f_read_line(f, "disk_io:");
		if (line_ptr == NULL) goto out;

		while((line_ptr=strchr(line_ptr, ' '))!=NULL){
			long long rsect, wsect;

			if (*++line_ptr == '\0') break;

			if((sscanf(line_ptr,
				"(%d,%d):(%*d, %*d, %lld, %*d, %lld)",
				&major, &minor, &rsect, &wsect)) != 4) {
					continue;
			}

			/* Find the corresponding device from earlier.
			   Just to add to the fun, "minor" is actually the disk
			   number, not the device minor, so we need to figure
			   out the real minor number based on the major!
			   This list is not exhaustive; if you're running
			   an older kernel you probably don't have fancy
			   I2O hardware anyway... */
			switch (major) {
			case 3:
			case 21:
			case 22:
			case 33:
			case 34:
			case 36:
			case 56:
			case 57:
			case 88:
			case 89:
			case 90:
			case 91:
				minor *= 64;
				break;
			case 9:
			case 43:
				break;
			default:
				minor *= 16;
				break;
			}
			for (i = 0; i < n; i++) {
				if (major == parts[i].major
					&& minor == parts[i].minor)
					break;
			}
			if (i == n) continue;

			/* We read the number of blocks. Blocks are stored in
			   512 bytes */
			diskio_stats[i].read_bytes = rsect * 512;
			diskio_stats[i].write_bytes = wsect * 512;
			diskio_stats[i].systime = now;
		}
	}

	num_diskio = n;
out:
	if (f != NULL) fclose(f);
#endif

#ifdef CYGWIN
	sg_set_error(SG_ERROR_UNSUPPORTED, "Cygwin");
	return NULL;
#endif

#ifdef WIN32
	sg_set_error(SG_ERROR_NONE, NULL);

	while((name = get_diskio(num_diskio, &rbytes, &wbytes)) != NULL) {
		if (VECTOR_RESIZE(diskio_stats, num_diskio+1)) {
			return NULL;
		}

		diskio_stats_ptr = diskio_stats + num_diskio;

		if (sg_update_string(&diskio_stats_ptr->disk_name, name) < 0) {
			return NULL;
		}
		sg_update_string(&name, NULL);
		diskio_stats_ptr->read_bytes = rbytes;
		diskio_stats_ptr->write_bytes = wbytes;

		diskio_stats_ptr->systime = 0;

		num_diskio++;
	}
#endif

	*entries=num_diskio;

	return diskio_stats;
}

sg_disk_io_stats *sg_get_disk_io_stats_diff(int *entries){
#ifndef WIN32
	VECTOR_DECLARE_STATIC(diff, sg_disk_io_stats, 1,
			      diskio_stat_init, diskio_stat_destroy);
	sg_disk_io_stats *src = NULL, *dest;
	int i, j, diff_count, new_count;

	if (diskio_stats == NULL) {
		/* No previous stats, so we can't calculate a difference. */
		return sg_get_disk_io_stats(entries);
	}

	/* Resize the results array to match the previous stats. */
	diff_count = VECTOR_SIZE(diskio_stats);
	if (VECTOR_RESIZE(diff, diff_count) < 0) {
		return NULL;
	}

	/* Copy the previous stats into the result. */
	for (i = 0; i < diff_count; i++) {
		src = &diskio_stats[i];
		dest = &diff[i];

		if (sg_update_string(&dest->disk_name, src->disk_name) < 0) {
			return NULL;
		}
		dest->read_bytes = src->read_bytes;
		dest->write_bytes = src->write_bytes;
		dest->systime = src->systime;
	}

	/* Get a new set of stats. */
	if (sg_get_disk_io_stats(&new_count) == NULL) {
		return NULL;
	}

	/* For each previous stat... */
	for (i = 0; i < diff_count; i++) {
		dest = &diff[i];

		/* ... find the corresponding new stat ... */
		for (j = 0; j < new_count; j++) {
			/* Try the new stat in the same position first,
			   since that's most likely to be it. */
			src = &diskio_stats[(i + j) % new_count];
			if (strcmp(src->disk_name, dest->disk_name) == 0) {
				break;
			}
		}
		if (j == new_count) {
			/* No match found. */
			continue;
		}

		/* ... and subtract the previous stat from it to get the
		   difference. */
		dest->read_bytes = src->read_bytes - dest->read_bytes;
		dest->write_bytes = src->write_bytes - dest->write_bytes;
		dest->systime = src->systime - dest->systime;
	}

	*entries = diff_count;
	return diff;
#else /* WIN32 */
	return sg_get_disk_io_stats(entries);
#endif
}

int sg_disk_io_compare_name(const void *va, const void *vb) {
	const sg_disk_io_stats *a = (const sg_disk_io_stats *)va;
	const sg_disk_io_stats *b = (const sg_disk_io_stats *)vb;

	return strcmp(a->disk_name, b->disk_name);
}
Example #26
0
int
bsde_rule_to_string(struct mac_bsdextended_rule *rule, char *buf, size_t buflen)
{
	struct group *grp;
	struct passwd *pwd;
	struct statfs *mntbuf;
	char *cur, type[sizeof(rule->mbr_object.mbo_type) * CHAR_BIT + 1];
	size_t left, len;
	int anymode, unknownmode, truncated, numfs, i, notdone;

	cur = buf;
	left = buflen;
	truncated = 0;

	len = snprintf(cur, left, "subject ");
	if (len < 0 || len > left)
		goto truncated;
	left -= len;
	cur += len;
	if (rule->mbr_subject.mbs_flags) {
		if (rule->mbr_subject.mbs_neg == MBS_ALL_FLAGS) {
			len = snprintf(cur, left, "not ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
			notdone = 1;
		} else {
			notdone = 0;
		}

		if (!notdone && (rule->mbr_subject.mbs_neg & MBO_UID_DEFINED)) {
			len = snprintf(cur, left, "! ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
		if (rule->mbr_subject.mbs_flags & MBO_UID_DEFINED) {
			pwd = getpwuid(rule->mbr_subject.mbs_uid_min);
			if (pwd != NULL) {
				len = snprintf(cur, left, "uid %s",
				    pwd->pw_name);
				if (len < 0 || len > left)
					goto truncated;
				left -= len;
				cur += len;
			} else {
				len = snprintf(cur, left, "uid %u",
				    rule->mbr_subject.mbs_uid_min);
				if (len < 0 || len > left)
					goto truncated;
				left -= len;
				cur += len;
			}
			if (rule->mbr_subject.mbs_uid_min !=
			    rule->mbr_subject.mbs_uid_max) {
				pwd = getpwuid(rule->mbr_subject.mbs_uid_max);
				if (pwd != NULL) {
					len = snprintf(cur, left, ":%s ",
					    pwd->pw_name);
					if (len < 0 || len > left)
						goto truncated;
					left -= len;
					cur += len;
				} else {
					len = snprintf(cur, left, ":%u ",
					    rule->mbr_subject.mbs_uid_max);
					if (len < 0 || len > left)
						goto truncated;
					left -= len;
					cur += len;
				}
			} else {
				len = snprintf(cur, left, " ");
				if (len < 0 || len > left)
					goto truncated;
				left -= len;
				cur += len;
			}
		}
		if (!notdone && (rule->mbr_subject.mbs_neg & MBO_GID_DEFINED)) {
			len = snprintf(cur, left, "! ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
		if (rule->mbr_subject.mbs_flags & MBO_GID_DEFINED) {
			grp = getgrgid(rule->mbr_subject.mbs_gid_min);
			if (grp != NULL) {
				len = snprintf(cur, left, "gid %s",
				    grp->gr_name);
				if (len < 0 || len > left)
					goto truncated;
				left -= len;
				cur += len;
			} else {
				len = snprintf(cur, left, "gid %u",
				    rule->mbr_subject.mbs_gid_min);
				if (len < 0 || len > left)
					goto truncated;
				left -= len;
				cur += len;
			}
			if (rule->mbr_subject.mbs_gid_min !=
			    rule->mbr_subject.mbs_gid_max) {
				grp = getgrgid(rule->mbr_subject.mbs_gid_max);
				if (grp != NULL) {
					len = snprintf(cur, left, ":%s ",
					    grp->gr_name);
					if (len < 0 || len > left)
						goto truncated;
					left -= len;
					cur += len;
				} else {
					len = snprintf(cur, left, ":%u ",
					    rule->mbr_subject.mbs_gid_max);
					if (len < 0 || len > left)
						goto truncated;
					left -= len;
					cur += len;
				}
			} else {
				len = snprintf(cur, left, " ");
				if (len < 0 || len > left)
					goto truncated;
				left -= len;
				cur += len;
			}
		}
		if (!notdone && (rule->mbr_subject.mbs_neg & MBS_PRISON_DEFINED)) {
			len = snprintf(cur, left, "! ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
		if (rule->mbr_subject.mbs_flags & MBS_PRISON_DEFINED) {
			len = snprintf(cur, left, "jailid %d ", 
			    rule->mbr_subject.mbs_prison);
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
	}

	len = snprintf(cur, left, "object ");
	if (len < 0 || len > left)
		goto truncated;
	left -= len;
	cur += len;
	if (rule->mbr_object.mbo_flags) {
		if (rule->mbr_object.mbo_neg == MBO_ALL_FLAGS) {
			len = snprintf(cur, left, "not ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
			notdone = 1;
		} else {
			notdone = 0;
		}

		if (!notdone && (rule->mbr_object.mbo_neg & MBO_UID_DEFINED)) {
			len = snprintf(cur, left, "! ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
		if (rule->mbr_object.mbo_flags & MBO_UID_DEFINED) {
			pwd = getpwuid(rule->mbr_object.mbo_uid_min);
			if (pwd != NULL) {
				len = snprintf(cur, left, "uid %s",
				    pwd->pw_name);
				if (len < 0 || len > left)
					goto truncated;
				left -= len;
				cur += len;
			} else {
				len = snprintf(cur, left, "uid %u",
				    rule->mbr_object.mbo_uid_min);
				if (len < 0 || len > left)
					goto truncated;
				left -= len;
				cur += len;
			}
			if (rule->mbr_object.mbo_uid_min !=
			    rule->mbr_object.mbo_uid_max) {
				pwd = getpwuid(rule->mbr_object.mbo_uid_max);
				if (pwd != NULL) {
					len = snprintf(cur, left, ":%s ",
					    pwd->pw_name);
					if (len < 0 || len > left)
						goto truncated;
					left -= len;
					cur += len;
				} else {
					len = snprintf(cur, left, ":%u ",
					    rule->mbr_object.mbo_uid_max);
					if (len < 0 || len > left)
						goto truncated;
					left -= len;
					cur += len;
				}
			} else {
				len = snprintf(cur, left, " ");
				if (len < 0 || len > left)
					goto truncated;
				left -= len;
				cur += len;
			}
		}
		if (!notdone && (rule->mbr_object.mbo_neg & MBO_GID_DEFINED)) {
			len = snprintf(cur, left, "! ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
		if (rule->mbr_object.mbo_flags & MBO_GID_DEFINED) {
			grp = getgrgid(rule->mbr_object.mbo_gid_min);
			if (grp != NULL) {
				len = snprintf(cur, left, "gid %s",
				    grp->gr_name);
				if (len < 0 || len > left)
					goto truncated;
				left -= len;
				cur += len;
			} else {
				len = snprintf(cur, left, "gid %u",
				    rule->mbr_object.mbo_gid_min);
				if (len < 0 || len > left)
					goto truncated;
				left -= len;
				cur += len;
			}
			if (rule->mbr_object.mbo_gid_min !=
			    rule->mbr_object.mbo_gid_max) {
				grp = getgrgid(rule->mbr_object.mbo_gid_max);
				if (grp != NULL) {
					len = snprintf(cur, left, ":%s ",
					    grp->gr_name);
					if (len < 0 || len > left)
						goto truncated;
					left -= len;
					cur += len;
				} else {
					len = snprintf(cur, left, ":%u ",
					    rule->mbr_object.mbo_gid_max);
					if (len < 0 || len > left)
						goto truncated;
					left -= len;
					cur += len;
				}
			} else {
				len = snprintf(cur, left, " ");
				if (len < 0 || len > left)
					goto truncated;
				left -= len;
				cur += len;
			}
		}
		if (!notdone && (rule->mbr_object.mbo_neg & MBO_FSID_DEFINED)) {
			len = snprintf(cur, left, "! ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
		if (rule->mbr_object.mbo_flags & MBO_FSID_DEFINED) {
			numfs = getmntinfo(&mntbuf, MNT_NOWAIT);
			for (i = 0; i < numfs; i++)
				if (memcmp(&(rule->mbr_object.mbo_fsid),
				    &(mntbuf[i].f_fsid),
				    sizeof(mntbuf[i].f_fsid)) == 0)
					break;
			len = snprintf(cur, left, "filesys %s ", 
			    i == numfs ? "???" : mntbuf[i].f_mntonname);
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
		if (!notdone && (rule->mbr_object.mbo_neg & MBO_SUID)) {
			len = snprintf(cur, left, "! ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
		if (rule->mbr_object.mbo_flags & MBO_SUID) {
			len = snprintf(cur, left, "suid ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
		if (!notdone && (rule->mbr_object.mbo_neg & MBO_SGID)) {
			len = snprintf(cur, left, "! ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
		if (rule->mbr_object.mbo_flags & MBO_SGID) {
			len = snprintf(cur, left, "sgid ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
		if (!notdone && (rule->mbr_object.mbo_neg & MBO_UID_SUBJECT)) {
			len = snprintf(cur, left, "! ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
		if (rule->mbr_object.mbo_flags & MBO_UID_SUBJECT) {
			len = snprintf(cur, left, "uid_of_subject ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
		if (!notdone && (rule->mbr_object.mbo_neg & MBO_GID_SUBJECT)) {
			len = snprintf(cur, left, "! ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
		if (rule->mbr_object.mbo_flags & MBO_GID_SUBJECT) {
			len = snprintf(cur, left, "gid_of_subject ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
		if (!notdone && (rule->mbr_object.mbo_neg & MBO_TYPE_DEFINED)) {
			len = snprintf(cur, left, "! ");
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
		if (rule->mbr_object.mbo_flags & MBO_TYPE_DEFINED) {
			i = 0;
			if (rule->mbr_object.mbo_type & MBO_TYPE_REG)
				type[i++] = 'r';
			if (rule->mbr_object.mbo_type & MBO_TYPE_DIR)
				type[i++] = 'd';
			if (rule->mbr_object.mbo_type & MBO_TYPE_BLK)
				type[i++] = 'b';
			if (rule->mbr_object.mbo_type & MBO_TYPE_CHR)
				type[i++] = 'c';
			if (rule->mbr_object.mbo_type & MBO_TYPE_LNK)
				type[i++] = 'l';
			if (rule->mbr_object.mbo_type & MBO_TYPE_SOCK)
				type[i++] = 's';
			if (rule->mbr_object.mbo_type & MBO_TYPE_FIFO)
				type[i++] = 'p';
			if (rule->mbr_object.mbo_type == MBO_ALL_TYPE) {
				i = 0;
				type[i++] = 'a';
			}
			type[i++] = '\0';
			len = snprintf(cur, left, "type %s ", type);
			if (len < 0 || len > left)
				goto truncated;
			left -= len;
			cur += len;
		}
	}

	len = snprintf(cur, left, "mode ");
	if (len < 0 || len > left)
		goto truncated;
	left -= len;
	cur += len;

	anymode = (rule->mbr_mode & MBI_ALLPERM);
	unknownmode = (rule->mbr_mode & ~MBI_ALLPERM);

	if (rule->mbr_mode & MBI_ADMIN) {
		len = snprintf(cur, left, "a");
		if (len < 0 || len > left)
			goto truncated;

		left -= len;
		cur += len;
	}
	if (rule->mbr_mode & MBI_READ) {
		len = snprintf(cur, left, "r");
		if (len < 0 || len > left)
			goto truncated;

		left -= len;
		cur += len;
	}
	if (rule->mbr_mode & MBI_STAT) {
		len = snprintf(cur, left, "s");
		if (len < 0 || len > left)
			goto truncated;

		left -= len;
		cur += len;
	}
	if (rule->mbr_mode & MBI_WRITE) {
		len = snprintf(cur, left, "w");
		if (len < 0 || len > left)
			goto truncated;

		left -= len;
		cur += len;
	}
	if (rule->mbr_mode & MBI_EXEC) {
		len = snprintf(cur, left, "x");
		if (len < 0 || len > left)
			goto truncated;

		left -= len;
		cur += len;
	}
	if (!anymode) {
		len = snprintf(cur, left, "n");
		if (len < 0 || len > left)
			goto truncated;

		left -= len;
		cur += len;
	}
	if (unknownmode) {
		len = snprintf(cur, left, "?");
		if (len < 0 || len > left)
			goto truncated;

		left -= len;
		cur += len;
	}

	return (0);

truncated:
	return (-1);
}
Example #27
0
int
main(int argc, char *argv[])
{
	struct stat stbuf;
	struct statfs statfsbuf, totalbuf;
	struct maxwidths maxwidths;
	struct statfs *mntbuf;
	const char *fstype;
	char *mntpath, *mntpt;
	const char **vfslist;
	int i, mntsize;
	int ch, rv;

	fstype = "ufs";
	(void)setlocale(LC_ALL, "");
	memset(&totalbuf, 0, sizeof(totalbuf));
	totalbuf.f_bsize = DEV_BSIZE;
	strlcpy(totalbuf.f_mntfromname, "total", MNAMELEN);
	vfslist = NULL;
	while ((ch = getopt(argc, argv, "abcgHhiklmnPt:T,")) != -1)
		switch (ch) {
		case 'a':
			aflag = 1;
			break;
		case 'b':
				/* FALLTHROUGH */
		case 'P':
			/*
			 * POSIX specifically discusses the behavior of
			 * both -k and -P. It states that the blocksize should
			 * be set to 1024. Thus, if this occurs, simply break
			 * rather than clobbering the old blocksize.
			 */
			if (kflag)
				break;
			setenv("BLOCKSIZE", "512", 1);
			hflag = 0;
			break;
		case 'c':
			cflag = 1;
			break;
		case 'g':
			setenv("BLOCKSIZE", "1g", 1);
			hflag = 0;
			break;
		case 'H':
			hflag = UNITS_SI;
			break;
		case 'h':
			hflag = UNITS_2;
			break;
		case 'i':
			iflag = 1;
			break;
		case 'k':
			kflag++;
			setenv("BLOCKSIZE", "1024", 1);
			hflag = 0;
			break;
		case 'l':
			if (vfslist != NULL)
				errx(1, "-l and -t are mutually exclusive.");
			vfslist = makevfslist(makenetvfslist());
			lflag = 1;
			break;
		case 'm':
			setenv("BLOCKSIZE", "1m", 1);
			hflag = 0;
			break;
		case 'n':
			nflag = 1;
			break;
		case 't':
			if (lflag)
				errx(1, "-l and -t are mutually exclusive.");
			if (vfslist != NULL)
				errx(1, "only one -t option may be specified");
			fstype = optarg;
			vfslist = makevfslist(optarg);
			break;
		case 'T':
			Tflag = 1;
			break;
		case ',':
			thousands = 1;
			break;
		case '?':
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

	rv = 0;
	if (!*argv) {
		/* everything (modulo -t) */
		mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
		mntsize = regetmntinfo(&mntbuf, mntsize, vfslist);
	} else {
		/* just the filesystems specified on the command line */
		mntbuf = malloc(argc * sizeof(*mntbuf));
		if (mntbuf == 0)
			err(1, "malloc()");
		mntsize = 0;
		/* continued in for loop below */
	}

	/* iterate through specified filesystems */
	for (; *argv; argv++) {
		if (stat(*argv, &stbuf) < 0) {
			if ((mntpt = getmntpt(*argv)) == 0) {
				warn("%s", *argv);
				rv = 1;
				continue;
			}
		} else if (S_ISCHR(stbuf.st_mode)) {
			if ((mntpt = getmntpt(*argv)) == 0) {
				mdev.fspec = *argv;
				mntpath = strdup("/tmp/df.XXXXXX");
				if (mntpath == NULL) {
					warn("strdup failed");
					rv = 1;
					continue;
				}
				mntpt = mkdtemp(mntpath);
				if (mntpt == NULL) {
					warn("mkdtemp(\"%s\") failed", mntpath);
					rv = 1;
					free(mntpath);
					continue;
				}
				if (mount(fstype, mntpt, MNT_RDONLY,
				    &mdev) != 0) {
					warn("%s", *argv);
					rv = 1;
					(void)rmdir(mntpt);
					free(mntpath);
					continue;
				} else if (statfs(mntpt, &statfsbuf) == 0) {
					statfsbuf.f_mntonname[0] = '\0';
					prtstat(&statfsbuf, &maxwidths);
					if (cflag)
						addstat(&totalbuf, &statfsbuf);
				} else {
					warn("%s", *argv);
					rv = 1;
				}
				(void)unmount(mntpt, 0);
				(void)rmdir(mntpt);
				free(mntpath);
				continue;
			}
		} else
			mntpt = *argv;

		/*
		 * Statfs does not take a `wait' flag, so we cannot
		 * implement nflag here.
		 */
		if (statfs(mntpt, &statfsbuf) < 0) {
			warn("%s", mntpt);
			rv = 1;
			continue;
		}

		/*
		 * Check to make sure the arguments we've been given are
		 * satisfied.  Return an error if we have been asked to
		 * list a mount point that does not match the other args
		 * we've been given (-l, -t, etc.).
		 */
		if (checkvfsname(statfsbuf.f_fstypename, vfslist)) {
			rv = 1;
			continue;
		}

		/* the user asked for it, so ignore the ignore flag */
		statfsbuf.f_flags &= ~MNT_IGNORE;

		/* add to list */
		mntbuf[mntsize++] = statfsbuf;
	}

	bzero(&maxwidths, sizeof(maxwidths));
	for (i = 0; i < mntsize; i++) {
		if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0) {
			update_maxwidths(&maxwidths, &mntbuf[i]);
			if (cflag)
				addstat(&totalbuf, &mntbuf[i]);
		}
	}
	for (i = 0; i < mntsize; i++)
		if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0)
			prtstat(&mntbuf[i], &maxwidths);
	if (cflag)
		prtstat(&totalbuf, &maxwidths);
	return (rv);
}
Example #28
0
int
main(int argc, char **argv)
{
	char *path;
	struct stat st;
	struct statfs *mntbuf;
	int all = 0, ch, done = 0, fscount, n;

	while ((ch = getopt(argc, argv, "adv")) != -1) {
		switch (ch) {
		case 'a':
			all++;
			break;
		case 'd':
			/* continue to search when matching inode is found 
			 * this feature is not documented */
			cont_search++;
			break;
		case 'v':
			verbose++;
			break;
		default:
			usage();
		}
	}

	argc -= optind;
	argv += optind;

	if ((all == 0 && argc != 1) || (all == 1 && argc > 0))
		usage();

	if (!all) {
		char resolved[PATH_MAX];

		path = *argv;
		/*
		 * mount(8) use realpath(3) before mounting file system,
		 * so let's do the same with the given path.
		 */
		if (realpath(path, resolved) == NULL ||	/* can create full path */
		    stat(resolved, &st) == -1 ||	/* is it stat'able */
		    !S_ISDIR(st.st_mode)) {		/* is it a directory */
			usage();
		}
		path = resolved;
	}

	fscount = getmntinfo(&mntbuf, MNT_WAIT);
	for (n = 0; n < fscount; n++) {
		if (!strncmp(mntbuf[n].f_fstypename, "ufs", 3)) {
			if (all || strcmp(path, mntbuf[n].f_mntonname) == 0) {
				find_snapshot(&mntbuf[n]);
				done++;
			}
		}
	}

	if (done == 0)
		usage();

	return (0);
}
void CDarwinStorageProvider::GetLocalDrives(VECSOURCES &localDrives)
{
  CMediaSource share;

  // User home folder
  share.strPath = getenv("HOME");
  share.strName = g_localizeStrings.Get(21440);
  share.m_ignore = true;
  localDrives.push_back(share);

#if defined(TARGET_DARWIN_OSX)
  // User desktop folder
  share.strPath = getenv("HOME");
  share.strPath += "/Desktop";
  share.strName = "Desktop";
  share.m_ignore = true;
  localDrives.push_back(share);

  // Volumes (all mounts are present here)
  share.strPath = "/Volumes";
  share.strName = "Volumes";
  share.m_ignore = true;
  localDrives.push_back(share);

  // This will pick up all local non-removable disks including the Root Disk.
  DASessionRef session = DASessionCreate(kCFAllocatorDefault);
  if (session)
  {
    unsigned i, count = 0;
    struct statfs *buf = NULL;
    std::string mountpoint, devicepath;

    count = getmntinfo(&buf, 0);
    for (i=0; i<count; i++)
    {
      mountpoint = buf[i].f_mntonname;
      devicepath = buf[i].f_mntfromname;

      DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, devicepath.c_str());
      if (disk)
      {
        CFDictionaryRef details = DADiskCopyDescription(disk);
        if (details)
        {
          if (kCFBooleanFalse == CFDictionaryGetValue(details, kDADiskDescriptionMediaRemovableKey))
          {
            CMediaSource share;

            share.strPath = mountpoint;
            Cocoa_GetVolumeNameFromMountPoint(mountpoint.c_str(), share.strName);
            share.m_ignore = true;
            localDrives.push_back(share);
          }
          CFRelease(details);
        }
        CFRelease(disk);
      }
    }

    CFRelease(session);
  }
#endif
}
struct mount_entry *
read_file_system_list (bool need_fs_type)
{
  struct mount_entry *mount_list;
  struct mount_entry *me;
  struct mount_entry **mtail = &mount_list;

#ifdef MOUNTED_LISTMNTENT
  {
    struct tabmntent *mntlist, *p;
    struct mntent *mnt;
    struct mount_entry *me;

    /* the third and fourth arguments could be used to filter mounts,
       but Crays doesn't seem to have any mounts that we want to
       remove. Specifically, automount create normal NFS mounts.
       */

    if (listmntent (&mntlist, KMTAB, NULL, NULL) < 0)
      return NULL;
    for (p = mntlist; p; p = p->next) {
      mnt = p->ment;
      me = xmalloc (sizeof *me);
      me->me_devname = xstrdup (mnt->mnt_fsname);
      me->me_mountdir = xstrdup (mnt->mnt_dir);
      me->me_type = xstrdup (mnt->mnt_type);
      me->me_type_malloced = 1;
      me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
      me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
      me->me_dev = -1;
      *mtail = me;
      mtail = &me->me_next;
    }
    freemntlist (mntlist);
  }
#endif

#ifdef MOUNTED_GETMNTENT1 /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix.  */
  {
    struct mntent *mnt;
    char *table = MOUNTED;
    FILE *fp;

    fp = setmntent (table, "r");
    if (fp == NULL)
      return NULL;

    while ((mnt = getmntent (fp)))
      {
	me = xmalloc (sizeof *me);
	me->me_devname = xstrdup (mnt->mnt_fsname);
	me->me_mountdir = xstrdup (mnt->mnt_dir);
	me->me_type = xstrdup (mnt->mnt_type);
	me->me_type_malloced = 1;
	me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
	me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
	me->me_dev = dev_from_mount_options (mnt->mnt_opts);

	/* Add to the linked list. */
	*mtail = me;
	mtail = &me->me_next;
      }

    if (endmntent (fp) == 0)
      goto free_then_fail;
  }
#endif /* MOUNTED_GETMNTENT1. */

#ifdef MOUNTED_GETMNTINFO	/* 4.4BSD.  */
  {
    struct statfs *fsp;
    int entries;

    entries = getmntinfo (&fsp, MNT_NOWAIT);
    if (entries < 0)
      return NULL;
    for (; entries-- > 0; fsp++)
      {
	char *fs_type = fsp_to_string (fsp);

	me = xmalloc (sizeof *me);
	me->me_devname = xstrdup (fsp->f_mntfromname);
	me->me_mountdir = xstrdup (fsp->f_mntonname);
	me->me_type = fs_type;
	me->me_type_malloced = 0;
	me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
	me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
	me->me_dev = (dev_t) -1;	/* Magic; means not known yet. */

	/* Add to the linked list. */
	*mtail = me;
	mtail = &me->me_next;
      }
  }
#endif /* MOUNTED_GETMNTINFO */

#ifdef MOUNTED_GETMNTINFO2	/* NetBSD 3.0.  */
  {
    struct statvfs *fsp;
    int entries;

    entries = getmntinfo (&fsp, MNT_NOWAIT);
    if (entries < 0)
      return NULL;
    for (; entries-- > 0; fsp++)
      {
	me = xmalloc (sizeof *me);
	me->me_devname = xstrdup (fsp->f_mntfromname);
	me->me_mountdir = xstrdup (fsp->f_mntonname);
	me->me_type = xstrdup (fsp->f_fstypename);
	me->me_type_malloced = 1;
	me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
	me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
	me->me_dev = (dev_t) -1;	/* Magic; means not known yet. */

	/* Add to the linked list. */
	*mtail = me;
	mtail = &me->me_next;
      }
  }
#endif /* MOUNTED_GETMNTINFO2 */

#ifdef MOUNTED_GETMNT		/* Ultrix.  */
  {
    int offset = 0;
    int val;
    struct fs_data fsd;

    while (errno = 0,
	   0 < (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
			      (char *) 0)))
      {
	me = xmalloc (sizeof *me);
	me->me_devname = xstrdup (fsd.fd_req.devname);
	me->me_mountdir = xstrdup (fsd.fd_req.path);
	me->me_type = gt_names[fsd.fd_req.fstype];
	me->me_type_malloced = 0;
	me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
	me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
	me->me_dev = fsd.fd_req.dev;

	/* Add to the linked list. */
	*mtail = me;
	mtail = &me->me_next;
      }
    if (val < 0)
      goto free_then_fail;
  }
#endif /* MOUNTED_GETMNT. */

#if defined MOUNTED_FS_STAT_DEV /* BeOS */
  {
    /* The next_dev() and fs_stat_dev() system calls give the list of
       all file systems, including the information returned by statvfs()
       (fs type, total blocks, free blocks etc.), but without the mount
       point. But on BeOS all file systems except / are mounted in the
       rootfs, directly under /.
       The directory name of the mount point is often, but not always,
       identical to the volume name of the device.
       We therefore get the list of subdirectories of /, and the list
       of all file systems, and match the two lists.  */

    DIR *dirp;
    struct rootdir_entry
      {
        char *name;
        dev_t dev;
        ino_t ino;
        struct rootdir_entry *next;
      };
    struct rootdir_entry *rootdir_list;
    struct rootdir_entry **rootdir_tail;
    int32 pos;
    dev_t dev;
    fs_info fi;

    /* All volumes are mounted in the rootfs, directly under /. */
    rootdir_list = NULL;
    rootdir_tail = &rootdir_list;
    dirp = opendir ("/");
    if (dirp)
      {
        struct dirent *d;

        while ((d = readdir (dirp)) != NULL)
          {
            char *name;
            struct stat statbuf;

            if (strcmp (d->d_name, "..") == 0)
              continue;

            if (strcmp (d->d_name, ".") == 0)
              name = xstrdup ("/");
            else
              {
                name = xmalloc (1 + strlen (d->d_name) + 1);
                name[0] = '/';
                strcpy (name + 1, d->d_name);
              }

            if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))
              {
		struct rootdir_entry *re = xmalloc (sizeof *re);
                re->name = name;
                re->dev = statbuf.st_dev;
                re->ino = statbuf.st_ino;

                /* Add to the linked list.  */
                *rootdir_tail = re;
                rootdir_tail = &re->next;
              }
            else
              free (name);
          }
        closedir (dirp);
      }
    *rootdir_tail = NULL;

    for (pos = 0; (dev = next_dev (&pos)) >= 0; )
      if (fs_stat_dev (dev, &fi) >= 0)
        {
          /* Note: fi.dev == dev. */
          struct rootdir_entry *re;

          for (re = rootdir_list; re; re = re->next)
            if (re->dev == fi.dev && re->ino == fi.root)
              break;

	  me = xmalloc (sizeof *me);
          me->me_devname = xstrdup (fi.device_name[0] != '\0' ? fi.device_name : fi.fsh_name);
          me->me_mountdir = xstrdup (re != NULL ? re->name : fi.fsh_name);
          me->me_type = xstrdup (fi.fsh_name);
	  me->me_type_malloced = 1;
          me->me_dev = fi.dev;
          me->me_dummy = 0;
          me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0;

          /* Add to the linked list. */
          *mtail = me;
          mtail = &me->me_next;
        }
    *mtail = NULL;

    while (rootdir_list != NULL)
      {
        struct rootdir_entry *re = rootdir_list;
        rootdir_list = re->next;
        free (re->name);
        free (re);
      }
  }
#endif /* MOUNTED_FS_STAT_DEV */

#if defined MOUNTED_GETFSSTAT	/* __alpha running OSF_1 */
  {
    int numsys, counter;
    size_t bufsize;
    struct statfs *stats;

    numsys = getfsstat ((struct statfs *)0, 0L, MNT_NOWAIT);
    if (numsys < 0)
      return (NULL);
    if (SIZE_MAX / sizeof *stats <= numsys)
      xalloc_die ();

    bufsize = (1 + numsys) * sizeof *stats;
    stats = xmalloc (bufsize);
    numsys = getfsstat (stats, bufsize, MNT_NOWAIT);

    if (numsys < 0)
      {
	free (stats);
	return (NULL);
      }

    for (counter = 0; counter < numsys; counter++)
      {
	me = xmalloc (sizeof *me);
	me->me_devname = xstrdup (stats[counter].f_mntfromname);
	me->me_mountdir = xstrdup (stats[counter].f_mntonname);
	me->me_type = xstrdup (FS_TYPE (stats[counter]));
	me->me_type_malloced = 1;
	me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
	me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
	me->me_dev = (dev_t) -1;	/* Magic; means not known yet. */

	/* Add to the linked list. */
	*mtail = me;
	mtail = &me->me_next;
      }

    free (stats);
  }
#endif /* MOUNTED_GETFSSTAT */

#if defined MOUNTED_FREAD || defined MOUNTED_FREAD_FSTYP /* SVR[23].  */
  {
    struct mnttab mnt;
    char *table = "/etc/mnttab";
    FILE *fp;

    fp = fopen (table, "r");
    if (fp == NULL)
      return NULL;

    while (fread (&mnt, sizeof mnt, 1, fp) > 0)
      {
	me = xmalloc (sizeof *me);
# ifdef GETFSTYP			/* SVR3.  */
	me->me_devname = xstrdup (mnt.mt_dev);
# else
	me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
	strcpy (me->me_devname, "/dev/");
	strcpy (me->me_devname + 5, mnt.mt_dev);
# endif
	me->me_mountdir = xstrdup (mnt.mt_filsys);
	me->me_dev = (dev_t) -1;	/* Magic; means not known yet. */
	me->me_type = "";
	me->me_type_malloced = 0;
# ifdef GETFSTYP			/* SVR3.  */
	if (need_fs_type)
	  {
	    struct statfs fsd;
	    char typebuf[FSTYPSZ];

	    if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
		&& sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
	      {
		me->me_type = xstrdup (typebuf);
		me->me_type_malloced = 1;
	      }
	  }
# endif
	me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
	me->me_remote = ME_REMOTE (me->me_devname, me->me_type);

	/* Add to the linked list. */
	*mtail = me;
	mtail = &me->me_next;
      }

    if (ferror (fp))
      {
	/* The last fread() call must have failed.  */
	int saved_errno = errno;
	fclose (fp);
	errno = saved_errno;
	goto free_then_fail;
      }

    if (fclose (fp) == EOF)
      goto free_then_fail;
  }
#endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP.  */

#ifdef MOUNTED_GETMNTTBL	/* DolphinOS goes its own way.  */
  {
    struct mntent **mnttbl = getmnttbl (), **ent;
    for (ent=mnttbl;*ent;ent++)
      {
	me = xmalloc (sizeof *me);
	me->me_devname = xstrdup ( (*ent)->mt_resource);
	me->me_mountdir = xstrdup ( (*ent)->mt_directory);
	me->me_type = xstrdup ((*ent)->mt_fstype);
	me->me_type_malloced = 1;
	me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
	me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
	me->me_dev = (dev_t) -1;	/* Magic; means not known yet. */

	/* Add to the linked list. */
	*mtail = me;
	mtail = &me->me_next;
      }
    endmnttbl ();
  }
#endif

#ifdef MOUNTED_GETMNTENT2	/* SVR4.  */
  {
    struct mnttab mnt;
    char *table = MNTTAB;
    FILE *fp;
    int ret;
    int lockfd = -1;

# if defined F_RDLCK && defined F_SETLKW
    /* MNTTAB_LOCK is a macro name of our own invention; it's not present in
       e.g. Solaris 2.6.  If the SVR4 folks ever define a macro
       for this file name, we should use their macro name instead.
       (Why not just lock MNTTAB directly?  We don't know.)  */
#  ifndef MNTTAB_LOCK
#   define MNTTAB_LOCK "/etc/.mnttab.lock"
#  endif
    lockfd = open (MNTTAB_LOCK, O_RDONLY);
    if (0 <= lockfd)
      {
	struct flock flock;
	flock.l_type = F_RDLCK;
	flock.l_whence = SEEK_SET;
	flock.l_start = 0;
	flock.l_len = 0;
	while (fcntl (lockfd, F_SETLKW, &flock) == -1)
	  if (errno != EINTR)
	    {
	      int saved_errno = errno;
	      close (lockfd);
	      errno = saved_errno;
	      return NULL;
	    }
      }
    else if (errno != ENOENT)
      return NULL;
# endif

    errno = 0;
    fp = fopen (table, "r");
    if (fp == NULL)
      ret = errno;
    else
      {
	while ((ret = getmntent (fp, &mnt)) == 0)
	  {
	    me = xmalloc (sizeof *me);
	    me->me_devname = xstrdup (mnt.mnt_special);
	    me->me_mountdir = xstrdup (mnt.mnt_mountp);
	    me->me_type = xstrdup (mnt.mnt_fstype);
	    me->me_type_malloced = 1;
	    me->me_dummy = MNT_IGNORE (&mnt) != 0;
	    me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
	    me->me_dev = dev_from_mount_options (mnt.mnt_mntopts);

	    /* Add to the linked list. */
	    *mtail = me;
	    mtail = &me->me_next;
	  }

	ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
      }

    if (0 <= lockfd && close (lockfd) != 0)
      ret = errno;

    if (0 <= ret)
      {
	errno = ret;
	goto free_then_fail;
      }
  }
#endif /* MOUNTED_GETMNTENT2.  */

#ifdef MOUNTED_VMOUNT		/* AIX.  */
  {
    int bufsize;
    char *entries, *thisent;
    struct vmount *vmp;
    int n_entries;
    int i;

    /* Ask how many bytes to allocate for the mounted file system info.  */
    if (mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize) != 0)
      return NULL;
    entries = xmalloc (bufsize);

    /* Get the list of mounted file systems.  */
    n_entries = mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
    if (n_entries < 0)
      {
	int saved_errno = errno;
	free (entries);
	errno = saved_errno;
	return NULL;
      }

    for (i = 0, thisent = entries;
	 i < n_entries;
	 i++, thisent += vmp->vmt_length)
      {
	char *options, *ignore;

	vmp = (struct vmount *) thisent;
	me = xmalloc (sizeof *me);
	if (vmp->vmt_flags & MNT_REMOTE)
	  {
	    char *host, *dir;

	    me->me_remote = 1;
	    /* Prepend the remote dirname.  */
	    host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
	    dir = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
	    me->me_devname = xmalloc (strlen (host) + strlen (dir) + 2);
	    strcpy (me->me_devname, host);
	    strcat (me->me_devname, ":");
	    strcat (me->me_devname, dir);
	  }
	else
	  {
	    me->me_remote = 0;
	    me->me_devname = xstrdup (thisent +
				      vmp->vmt_data[VMT_OBJECT].vmt_off);
	  }
	me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
	me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
	me->me_type_malloced = 1;
	options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off;
	ignore = strstr (options, "ignore");
	me->me_dummy = (ignore
			&& (ignore == options || ignore[-1] == ',')
			&& (ignore[sizeof "ignore" - 1] == ','
			    || ignore[sizeof "ignore" - 1] == '\0'));
	me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want.  */

	/* Add to the linked list. */
	*mtail = me;
	mtail = &me->me_next;
      }
    free (entries);
  }
#endif /* MOUNTED_VMOUNT. */

  *mtail = NULL;
  return mount_list;


 free_then_fail:
  {
    int saved_errno = errno;
    *mtail = NULL;

    while (mount_list)
      {
	me = mount_list->me_next;
	free (mount_list->me_devname);
	free (mount_list->me_mountdir);
	if (mount_list->me_type_malloced)
	  free (mount_list->me_type);
	free (mount_list);
	mount_list = me;
      }

    errno = saved_errno;
    return NULL;
  }
}