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; }
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; }
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); }
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; }
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 ); }
/** 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(""); }
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; }
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, §orsize) == -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); }
/* * 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; }
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; }
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 */
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 }
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; }
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); }
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); }
/** 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; }
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(¤t_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); }
/* * 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); }
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; }
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; }
/* 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; }
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; }
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 = ∓ 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(¬_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(¬_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); }
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); }
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); }
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; } }