/* * disk.c */ #include /* workaround for bug in autoconf 2.60b and 2.61 */ #ifdef HAVE_GETMNTENT #undef HAVE_GETMNTENT #define HAVE_GETMNTENT 1 /* previously might be only "#define HAVE_GETMNTENT" */ #endif #include #if HAVE_STDLIB_H #include #endif #if HAVE_UNISTD_H #include #endif #if HAVE_FCNTL_H #include #endif #include #if HAVE_MACHINE_PARAM_H #include #endif #if HAVE_SYS_VMMETER_H #if !(defined(bsdi2) || defined(netbsd1)) #include #endif #endif #if HAVE_SYS_PARAM_H #include #endif #if HAVE_SYS_CONF_H #include #endif #if HAVE_ASM_PAGE_H #include #endif #if HAVE_SYS_SWAP_H #include #endif #if HAVE_SYS_FS_H #include #else #if HAVE_UFS_FS_H #include #else #ifdef HAVE_SYS_STAT_H #include #endif #if !defined(dragonfly) #ifdef HAVE_SYS_VNODE_H #include #endif #endif #ifdef HAVE_UFS_UFS_QUOTA_H #include #endif #ifdef HAVE_UFS_UFS_INODE_H #include #endif #if HAVE_UFS_FFS_FS_H #include #endif #endif #endif #if HAVE_MTAB_H #include #endif #include #include #if HAVE_SYS_STATFS_H #include #endif #if HAVE_SYS_STATVFS_H #include #endif #if HAVE_SYS_VFS_H #include #endif #if defined(__FreeBSD__) && __FreeBSD_version >= 700055 /* Or HAVE_SYS_UCRED_H */ #include #endif #if defined(HAVE_STATFS) #if HAVE_SYS_MOUNT_H #include #endif #if HAVE_SYS_SYSCTL_H #include #endif #if !defined(HAVE_STATVFS) #define statvfs statfs #endif #endif #if HAVE_VM_VM_H #include #endif #if HAVE_VM_SWAP_PAGER_H #include #endif #if HAVE_SYS_FIXPOINT_H #include #endif #if HAVE_MALLOC_H #include #endif #if HAVE_STRING_H #include #endif #if HAVE_FSTAB_H #include #endif #if HAVE_MNTENT_H #include #endif #if HAVE_SYS_MNTTAB_H #include #endif #if HAVE_NETINET_IN_H #include #endif #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #include #include #include #include "struct.h" #include "disk.h" #include "util_funcs/header_simple_table.h" #if USING_UCD_SNMP_ERRORMIB_MODULE #include "errormib.h" #else #define setPerrorstatus(x) snmp_log_perror(x) #endif /* * * config file parsing routines * */ static void disk_free_config(void); static void disk_parse_config(const char *, char *); static void disk_parse_config_all(const char *, char *); #if HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS static void find_and_add_allDisks(int minpercent); static void add_device(char *path, char *device, int minspace, int minpercent, int override); static void modify_disk_parameters(int index, int minspace, int minpercent); static int disk_exists(char *path); static char *find_device(char *path); #endif struct diskpart { char device[STRMAX]; char path[STRMAX]; int minimumspace; int minpercent; }; #define MAX_INT_32 0x7fffffff #define MAX_UINT_32 0xffffffff unsigned int numdisks; int allDisksIncluded = 0; unsigned int maxdisks = 0; struct diskpart *disks; struct variable2 extensible_disk_variables[] = { {MIBINDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {MIBINDEX}}, {ERRORNAME, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {ERRORNAME}}, {DISKDEVICE, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {DISKDEVICE}}, {DISKMINIMUM, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {DISKMINIMUM}}, {DISKMINPERCENT, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {DISKMINPERCENT}}, {DISKTOTAL, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {DISKTOTAL}}, {DISKAVAIL, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {DISKAVAIL}}, {DISKUSED, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {DISKUSED}}, {DISKPERCENT, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {DISKPERCENT}}, {DISKPERCENTNODE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {DISKPERCENTNODE}}, {ERRORFLAG, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {ERRORFLAG}}, {ERRORMSG, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {ERRORMSG}}, {DISKTOTALLOW, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {DISKTOTALLOW}}, {DISKTOTALHIGH, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {DISKTOTALHIGH}}, {DISKAVAILLOW, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {DISKAVAILLOW}}, {DISKAVAILHIGH, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {DISKAVAILHIGH}}, {DISKUSEDLOW, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {DISKUSEDLOW}}, {DISKUSEDHIGH, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY, var_extensible_disk, 1, {DISKUSEDHIGH}}, }; /* * Define the OID pointer to the top of the mib tree that we're * registering underneath */ oid disk_variables_oid[] = { NETSNMP_UCDAVIS_MIB, NETSNMP_DISKMIBNUM, 1 }; void init_disk(void) { /* * register ourselves with the agent to handle our mib tree */ REGISTER_MIB("ucd-snmp/disk", extensible_disk_variables, variable2, disk_variables_oid); snmpd_register_config_handler("disk", disk_parse_config, disk_free_config, "path [ minspace | minpercent% ]"); snmpd_register_config_handler("includeAllDisks", disk_parse_config_all, disk_free_config, "minpercent%"); allDisksIncluded = 0; } static void disk_free_config(void) { unsigned int i; numdisks = 0; for (i = 0; i < maxdisks; i++) { /* init/erase disk db */ disks[i].device[0] = 0; disks[i].path[0] = 0; disks[i].minimumspace = -1; disks[i].minpercent = -1; } allDisksIncluded = 0; } static void disk_parse_config(const char *token, char *cptr) { #if HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS char path[STRMAX]; int minpercent; int minspace; if (numdisks == maxdisks) { if (maxdisks == 0) { maxdisks = 50; disks = (struct diskpart *)malloc(maxdisks * sizeof(struct diskpart)); if (!disks) { config_perror("malloc failed for new disk allocation."); netsnmp_config_error("\tignoring: %s", cptr); return; } memset(disks, 0, maxdisks * sizeof(struct diskpart)); } else { maxdisks *= 2; disks = (struct diskpart *)realloc(disks, maxdisks * sizeof(struct diskpart)); if (!disks) { config_perror("malloc failed for new disk allocation."); netsnmp_config_error("\tignoring: %s", cptr); return; } memset(disks + maxdisks/2, 0, maxdisks/2 * sizeof(struct diskpart)); } } /* * read disk path (eg, /1 or /usr) */ copy_nword(cptr, path, sizeof(path)); cptr = skip_not_white(cptr); cptr = skip_white(cptr); /* * read optional minimum disk usage spec */ if(cptr != NULL) { if(strchr(cptr, '%') == NULL) { minspace = atoi(cptr); minpercent = -1; } else { minspace = -1; minpercent = atoi(cptr); } } else { minspace = NETSNMP_DEFDISKMINIMUMSPACE; minpercent = -1; } /* * check if the disk already exists, if so then modify its * parameters. if it does not exist then add it */ add_device(path, find_device(path), minspace, minpercent, 1); #endif /* HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS */ } static void disk_parse_config_all(const char *token, char *cptr) { #if HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS int minpercent = DISKMINPERCENT; if (numdisks == maxdisks) { if (maxdisks == 0) { maxdisks = 50; disks = (struct diskpart *)malloc(maxdisks * sizeof(struct diskpart)); if (!disks) { config_perror("malloc failed for new disk allocation."); netsnmp_config_error("\tignoring: %s", cptr); return; } memset(disks, 0, maxdisks * sizeof(struct diskpart)); } else { maxdisks *= 2; disks = (struct diskpart *)realloc(disks, maxdisks * sizeof(struct diskpart)); if (!disks) { config_perror("malloc failed for new disk allocation."); netsnmp_config_error("\tignoring: %s", cptr); return; } memset(disks + maxdisks/2, 0, maxdisks/2 * sizeof(struct diskpart)); } } /* * read the minimum disk usage percent */ if(cptr != NULL) { if(strchr(cptr, '%') != NULL) { minpercent = atoi(cptr); } } /* * if we have already seen the "includeAllDisks" directive * then search for the disk in the "disks" array and modify * the values. if we havent seen the "includeAllDisks" * directive then include this disk */ if(allDisksIncluded) { config_perror("includeAllDisks already specified."); netsnmp_config_error("\tignoring: includeAllDisks %s", cptr); } else { allDisksIncluded = 1; find_and_add_allDisks(minpercent); } #endif /* HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS */ } #if HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS static void add_device(char *path, char *device, int minspace, int minpercent, int override) { int index; if (!path || !strcmp(path, "none")) { DEBUGMSGTL(("ucd-snmp/disk", "Skipping null path device (%s)\n", device)); return; } if (numdisks == maxdisks) { if (maxdisks == 0) { maxdisks = 50; disks = (struct diskpart *)malloc(maxdisks * sizeof(struct diskpart)); if (!disks) { netsnmp_config_error("\tignoring: %s", device); return; } memset(disks, 0, maxdisks * sizeof(struct diskpart)); } else { maxdisks *= 2; disks = (struct diskpart *)realloc(disks, maxdisks * sizeof(struct diskpart)); if (!disks) { config_perror("malloc failed for new disk allocation."); netsnmp_config_error("\tignoring: %s", device); return; } memset(disks + maxdisks/2, 0, maxdisks/2 * sizeof(struct diskpart)); } } index = disk_exists(path); if((index != -1) && (index < maxdisks) && (override==1)) { modify_disk_parameters(index, minspace, minpercent); } else if(index == -1){ /* add if and only if the device was found */ if(device[0] != 0) { /* The following buffers are cleared above, no need to add '\0' */ strlcpy(disks[numdisks].path, path, sizeof(disks[numdisks].path)); strlcpy(disks[numdisks].device, device, sizeof(disks[numdisks].device)); disks[numdisks].minimumspace = minspace; disks[numdisks].minpercent = minpercent; numdisks++; } else { disks[numdisks].minimumspace = -1; disks[numdisks].minpercent = -1; disks[numdisks].path[0] = 0; disks[numdisks].device[0] = 0; } } } void modify_disk_parameters(int index, int minspace, int minpercent) { disks[index].minimumspace = minspace; disks[index].minpercent = minpercent; } int disk_exists(char *path) { unsigned int index; for(index = 0; index < numdisks; index++) { DEBUGMSGTL(("ucd-snmp/disk", "Checking for %s. Found %s at %d\n", path, disks[index].path, index)); if(strcmp(path, disks[index].path) == 0) { return index; } } return -1; } static void find_and_add_allDisks(int minpercent) { #if HAVE_GETMNTENT #if HAVE_SYS_MNTTAB_H struct mnttab mnttab; #else struct mntent *mntent; #endif FILE *mntfp; #elif HAVE_FSTAB_H struct fstab *fstab1; #elif HAVE_STATFS struct statfs statf; #endif #if defined(HAVE_GETMNTENT) && !defined(HAVE_SETMNTENT) int i; #endif #if defined(HAVE_GETMNTENT) || defined(HAVE_FSTAB_H) int dummy = 0; #endif /* * find the device for the path and copy the device into the * string declared above and at the end of the routine return it * to the caller */ #if HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS #if HAVE_GETMNTENT #if HAVE_SETMNTENT mntfp = setmntent(ETC_MNTTAB, "r"); if (!mntfp) { netsnmp_config_error("Can't open %s (setmntent)\n", ETC_MNTTAB); return; } while (mntfp && NULL != (mntent = getmntent(mntfp))) { add_device(mntent->mnt_dir, mntent->mnt_fsname, -1, minpercent, 0); dummy = 1; } if (mntfp) endmntent(mntfp); if(dummy != 0) { /* * dummy clause for else below */ } #else /* getmentent but not setmntent */ mntfp = fopen(ETC_MNTTAB, "r"); if (!mntfp) { netsnmp_config_error("Can't open %s (fopen)\n", ETC_MNTTAB); return; } while ((i = getmntent(mntfp, &mnttab)) == 0) { add_device(mnttab.mnt_mountp, mnttab.mnt_special, -1, minpercent, 0); dummy = 1; } fclose(mntfp); if(dummy != 0) { /* * dummy clause for else below */ } #endif /* HAVE_SETMNTENT */ #elif HAVE_FSTAB_H setfsent(); /* open /etc/fstab */ while((fstab1 = getfsent()) != NULL) { add_device(fstab1->fs_file, fstab1->fs_spec, -1, minpercent, 0); dummy = 1; } endfsent(); /* close /etc/fstab */ #if defined(__FreeBSD__) && __FreeBSD_version >= 700055 { struct statfs *mntbuf; size_t i, mntsize; mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); for (i = 0; i < mntsize; i++) { if (strncmp(mntbuf[i].f_fstypename, "zfs", 3) == 0) { add_device(mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname, -1, minpercent, 0); } } } #endif if(dummy != 0) { /* * dummy clause for else below */ } #elif HAVE_STATFS /* * since there is no way to get all the mounted systems with just * statfs we default to the root partition "/" */ if (statfs("/", &statf) == 0) { add_device("/", statf.f_mntfromname, -1, minpercent, 0); } #endif else { if (numdisks == maxdisks) { return; } netsnmp_config_warn("Couldn't find device for disk %s", disks[numdisks].path); disks[numdisks].minimumspace = -1; disks[numdisks].minpercent = -1; disks[numdisks].path[0] = 0; } #else config_perror("'disk' checks not supported on this architecture."); #endif /* HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS */ } static char * find_device(char *path) { #if HAVE_GETMNTENT #if HAVE_SYS_MNTTAB_H struct mnttab mnttab; #else struct mntent *mntent; #endif FILE *mntfp; #elif HAVE_FSTAB_H struct fstab *fstab; #elif HAVE_STATFS struct statfs statf; #endif static char device[STRMAX]; #if defined(HAVE_GETMNTENT) && !defined(HAVE_SETMNTENT) int i; #endif device[0] = '\0'; /* null terminate the device */ /* find the device for the path and copy the device into the * string declared above and at the end of the routine return it * to the caller */ #if HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS #if HAVE_GETMNTENT #if HAVE_SETMNTENT mntfp = setmntent(ETC_MNTTAB, "r"); if (!mntfp) { netsnmp_config_error("Can't open %s (setmntent)\n", ETC_MNTTAB); return NULL; } while (mntfp && NULL != (mntent = getmntent(mntfp))) if (strcmp(path, mntent->mnt_dir) == 0) { strlcpy(device, mntent->mnt_fsname, sizeof(device)); DEBUGMSGTL(("ucd-snmp/disk", "Disk: %s\n", mntent->mnt_fsname)); break; } else { DEBUGMSGTL(("ucd-snmp/disk", " %s != %s\n", path, mntent->mnt_dir)); } if (mntfp) endmntent(mntfp); #else /* getmentent but not setmntent */ mntfp = fopen(ETC_MNTTAB, "r"); if (!mntfp) { netsnmp_config_error("Can't open %s (fopen)\n", ETC_MNTTAB); return NULL; } while ((i = getmntent(mntfp, &mnttab)) == 0) if (strcmp(path, mnttab.mnt_mountp) == 0) break; else { DEBUGMSGTL(("ucd-snmp/disk", " %s != %s\n", path, mnttab.mnt_mountp)); } fclose(mntfp); if (i == 0) strlcpy(device, mnttab.mnt_special, sizeof(device)); #endif /* HAVE_SETMNTENT */ #elif HAVE_FSTAB_H setfsent(); if ((fstab = getfsfile(path))) strlcpy(device, fstab->fs_spec, sizeof(device)); endfsent(); if (device[0] != '\0') { /* * dummy clause for else below */ } #elif HAVE_STATFS if (statfs(path, &statf) == 0) { strlcpy(device, statf.f_mntfromname, sizeof(device)); DEBUGMSGTL(("ucd-snmp/disk", "Disk: %s\n", statf.f_mntfromname)); } #endif else { netsnmp_config_warn("Couldn't find device for disk %s", path); } #else config_perror("'disk' checks not supported on this architecture."); #endif /* HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS */ return device; } #endif /* * Part of UCD-SNMP-MIB::dskEntry, which is so hard to fill * (i.e. platform dependent parts). */ struct dsk_entry { unsigned long long dskTotal; unsigned long long dskUsed; unsigned long long dskAvail; unsigned long dskPercent; unsigned long dskPercentInode; unsigned long dskErrorFlag; }; /** * Fill in the provided dsk_entry structure. * Returns -1 on error, 0 on success. */ static int fill_dsk_entry(int disknum, struct dsk_entry *entry) { #if defined(HAVE_STATVFS) || defined(HAVE_STATFS) float multiplier; #endif #if defined(HAVE_FSTAB_H) && !defined(HAVE_SYS_STATVFS_H) && !defined(HAVE_STATFS) double totalblks, free, used, avail, availblks; #endif #if defined(HAVE_STATVFS) || defined(HAVE_STATFS) #ifdef STAT_STATFS_FS_DATA struct fs_data fsd; struct { u_int f_blocks, f_bfree, f_bavail, f_bsize; } vfs; #else struct statvfs vfs; #endif #else #if HAVE_FSTAB_H int file; union { struct fs iu_fs; char dummy[SBSIZE]; } sb; #define filesys sb.iu_fs #endif #endif entry->dskPercentInode = -1; #if defined(HAVE_STATVFS) || defined(HAVE_STATFS) #ifdef STAT_STATFS_FS_DATA if (statvfs(disks[disknum].path, &fsd) == -1) #else if (statvfs(disks[disknum].path, &vfs) == -1) #endif { snmp_log(LOG_ERR, "Couldn't open device %s\n", disks[disknum].device); setPerrorstatus("statvfs dev/disk"); return -1; } #ifdef STAT_STATFS_FS_DATA vfs.f_blocks = fsd.fd_btot; vfs.f_bfree = fsd.fd_bfree; vfs.f_bavail = fsd.fd_bfreen; vfs.f_bsize = 1024; /* Ultrix f_bsize is a VM parameter apparently. */ #endif #if defined(HAVE_ODS) vfs.f_blocks = vfs.f_spare[0]; vfs.f_bfree = vfs.f_spare[1]; vfs.f_bavail = vfs.f_spare[2]; #endif multiplier = (float)vfs.f_bsize / (float)1024.0; #ifdef HAVE_STRUCT_STATVFS_F_FRSIZE if (vfs.f_frsize > 255) multiplier = (float)vfs.f_frsize / (float)1024.0; #endif entry->dskTotal = (unsigned long long)(vfs.f_blocks * multiplier); entry->dskAvail = (unsigned long long)(vfs.f_bavail * multiplier); entry->dskUsed = (unsigned long long)((vfs.f_blocks - vfs.f_bfree) * multiplier); entry->dskPercent = vfs.f_blocks == 0 ? 0 : vfs.f_bavail <= 0 ? 100 : (int) ((double) (vfs.f_blocks - vfs.f_bfree) / (double) (vfs.f_blocks - (vfs.f_bfree - vfs.f_bavail)) * 100.0 + 0.5); #if defined(HAVE_STRUCT_STATVFS_F_FILES) || defined HAVE_STRUCT_STATFS_F_FAVAIL entry->dskPercentInode = vfs.f_favail <= 0 ? 100 : (int) ((double) (vfs.f_files - vfs.f_ffree) / (double) (vfs.f_files - (vfs.f_ffree - vfs.f_favail)) * 100.0 + 0.5); #else #if defined(HAVE_STRUCT_STATFS_F_FILES) && defined(HAVE_STRUCT_STATFS_F_FFREE) entry->dskPercentInode = vfs.f_files == 0 ? 100.0 : (int) ((double) (vfs.f_files - vfs.f_ffree) / (double) (vfs.f_files) * 100.0 + 0.5); #endif #endif /* defined(HAVE_STRUCT_STATVFS_F_FILES) */ #elif HAVE_FSTAB_H /* * read the disk information */ if ((file = open(disks[disknum].device, 0)) < 0) { snmp_log(LOG_ERR, "Couldn't open device %s\n", disks[disknum].device); setPerrorstatus("open dev/disk"); return -1; } lseek(file, (long) (SBLOCK * DEV_BSIZE), 0); if (read(file, (char *) &filesys, SBSIZE) != SBSIZE) { setPerrorstatus("open dev/disk"); snmp_log(LOG_ERR, "Error reading device %s\n", disks[disknum].device); close(file); return -1; } close(file); totalblks = filesys.fs_dsize; free = filesys.fs_cstotal.cs_nbfree * filesys.fs_frag + filesys.fs_cstotal.cs_nffree; used = totalblks - free; availblks = totalblks * (100 - filesys.fs_minfree) / 100; avail = availblks > used ? availblks - used : 0; entry->dskPercent = totalblks == 0 ? 0 : availblks == 0 ? 100 : (int) ((double) used / (double) totalblks * 100.0 + 0.5); multiplier = (float)filesys.fs_fsize / (float)1024.0; entry->dskTotal = (unsigned long long)(totalblks * multiplier); entry->dskAvail = (unsigned long long)(avail * multiplier); entry->dskUsed = (unsigned long long)(used * multiplier); #else /* MinGW */ entry->dskPercent = 0; entry->dskTotal = 0; entry->dskAvail = 0; entry->dskUsed = 0; #endif entry->dskErrorFlag = (disks[disknum].minimumspace >= 0 ? entry->dskAvail < (unsigned long long)disks[disknum].minimumspace : 100 - entry->dskPercent <= (unsigned int)disks[disknum].minpercent) ? 1 : 0; return 0; } /* * var_extensible_disk(... * Arguments: * vp IN - pointer to variable entry that points here * name IN/OUT - IN/name requested, OUT/name found * length IN/OUT - length of IN/OUT oid's * exact IN - TRUE if an exact match was requested * var_len OUT - length of variable or 0 if function returned * write_method * */ u_char * var_extensible_disk(struct variable *vp, oid * name, size_t * length, int exact, size_t * var_len, WriteMethod ** write_method) { int ret; unsigned int disknum = 0; struct dsk_entry entry; static long long_ret; static char *errmsg; tryAgain: if (header_simple_table (vp, name, length, exact, var_len, write_method, numdisks)) return (NULL); disknum = name[*length - 1] - 1; if (disknum > maxdisks) return NULL; switch (vp->magic) { case MIBINDEX: long_ret = disknum + 1; return ((u_char *) (&long_ret)); case ERRORNAME: /* DISKPATH */ *var_len = strlen(disks[disknum].path); return ((u_char *) disks[disknum].path); case DISKDEVICE: *var_len = strlen(disks[disknum].device); return ((u_char *) disks[disknum].device); case DISKMINIMUM: long_ret = disks[disknum].minimumspace; return ((u_char *) (&long_ret)); case DISKMINPERCENT: long_ret = disks[disknum].minpercent; return ((u_char *) (&long_ret)); } ret = fill_dsk_entry(disknum, &entry); if (ret < 0) { if (!exact) goto tryAgain; return NULL; } switch (vp->magic) { case DISKTOTAL: if (entry.dskTotal > MAX_INT_32) long_ret = MAX_INT_32; else long_ret = (long)(entry.dskTotal); return ((u_char *) (&long_ret)); case DISKTOTALLOW: long_ret = entry.dskTotal & MAX_UINT_32; return ((u_char *) (&long_ret)); case DISKTOTALHIGH: long_ret = entry.dskTotal >> 32; return ((u_char *) (&long_ret)); case DISKAVAIL: if (entry.dskAvail > MAX_INT_32) long_ret = MAX_INT_32; else long_ret = (long)(entry.dskAvail); return ((u_char *) (&long_ret)); case DISKAVAILLOW: long_ret = entry.dskAvail & MAX_UINT_32; return ((u_char *) (&long_ret)); case DISKAVAILHIGH: long_ret = entry.dskAvail >> 32; return ((u_char *) (&long_ret)); case DISKUSED: if (entry.dskUsed > MAX_INT_32) long_ret = MAX_INT_32; else long_ret = (long)(entry.dskUsed); return ((u_char *) (&long_ret)); case DISKUSEDLOW: long_ret = entry.dskUsed & MAX_UINT_32; return ((u_char *) (&long_ret)); case DISKUSEDHIGH: long_ret = entry.dskUsed >> 32; return ((u_char *) (&long_ret)); case DISKPERCENT: long_ret = entry.dskPercent; return ((u_char *) (&long_ret)); case DISKPERCENTNODE: long_ret = entry.dskPercentInode; return ((u_char *) (&long_ret)); case ERRORFLAG: long_ret = entry.dskErrorFlag; return ((u_char *) (&long_ret)); case ERRORMSG: free(errmsg); errmsg = NULL; *var_len = 0; if (entry.dskErrorFlag) { if ((disks[disknum].minimumspace >= 0 && asprintf(&errmsg, "%s: less than %d free (= %d)", disks[disknum].path, disks[disknum].minimumspace, (int) entry.dskAvail) >= 0) || (disks[disknum].minimumspace < 0 && asprintf(&errmsg, "%s: less than %d%% free (= %d%%)", disks[disknum].path, disks[disknum].minpercent, (int)entry.dskPercent) >= 0)) { *var_len = strlen(errmsg); } } return (u_char *) (errmsg); } return NULL; }