int sys_getdiskinfo(const char *path, unsigned long *total, unsigned long *available, unsigned short *block_size) { ULARGE_INTEGER free, size; DWORD bytes_per_sector, d1, d2, d3; // Fetch the block size from the old interface as this information // is not provided by the new one anymore. if (GetDiskFreeSpace(path, &d1, &bytes_per_sector, &d2, &d3)) { *block_size = bytes_per_sector; } else { *block_size = 0; } // The disk size is queried via the new interface that supports // drives with more than 2GB (although we currently only support // return values of 4GB! if (!GetDiskFreeSpaceExA(path, &free, &size, NULL)) { *total = 0; *available = 0; *block_size = 0; return -1; } *available = free.QuadPart > 0xffffffffUL ? 0xffffffffUL : free.QuadPart; *total = size.QuadPart > 0xffffffffUL ? 0xffffffffUL : size.QuadPart; return 0; }
double VMPI_getTotalDiskSpace(const char *path) { ULARGE_INTEGER total; if(!GetDiskFreeSpaceExA(path, NULL, &total, NULL)) { return -1; } return static_cast<double>(total.QuadPart); }
double VMPI_getFreeDiskSpace(const char *path) { ULARGE_INTEGER available; if(!GetDiskFreeSpaceExA(path, &available, NULL, NULL)) { return -1; } return static_cast<double>(available.QuadPart); }
BOOL My_GetDiskFreeSpaceExA() { LPCSTR lpDirectoryName=NULL; PULARGE_INTEGER lpFreeBytesAvailableToCaller=NULL; PULARGE_INTEGER lpTotalNumberOfBytes=NULL; PULARGE_INTEGER lpTotalNumberOfFreeBytes=NULL; BOOL returnVal_Real = NULL; BOOL returnVal_Intercepted = NULL; DWORD error_Real = 0; DWORD error_Intercepted = 0; disableInterception(); returnVal_Real = GetDiskFreeSpaceExA (lpDirectoryName,lpFreeBytesAvailableToCaller,lpTotalNumberOfBytes,lpTotalNumberOfFreeBytes); error_Real = GetLastError(); enableInterception(); returnVal_Intercepted = GetDiskFreeSpaceExA (lpDirectoryName,lpFreeBytesAvailableToCaller,lpTotalNumberOfBytes,lpTotalNumberOfFreeBytes); error_Intercepted = GetLastError(); return ((returnVal_Real == returnVal_Intercepted) && (error_Real == error_Intercepted)); }
/* * Arguments: path (string) * Returns: [total_bytes (number), available_bytes (number), * free_bytes (number)] */ static int sys_statfs (lua_State *L) { const char *path = luaL_checkstring(L, 1); int64_t ntotal, navail, nfree; int res; #ifndef _WIN32 struct statvfs buf; sys_vm_leave(L); res = statvfs(path, &buf); sys_vm_enter(L); ntotal = buf.f_blocks * buf.f_frsize; nfree = buf.f_bfree * buf.f_bsize; navail = buf.f_bavail * buf.f_bsize; #else ULARGE_INTEGER na, nt, nf; SetErrorMode(SEM_FAILCRITICALERRORS); /* for floppy disks */ { void *os_path = utf8_to_filename(path); if (!os_path) return sys_seterror(L, ERROR_NOT_ENOUGH_MEMORY); sys_vm_leave(L); res = is_WinNT ? !GetDiskFreeSpaceExW(os_path, &na, &nt, &nf) : !GetDiskFreeSpaceExA(os_path, &na, &nt, &nf); free(os_path); sys_vm_enter(L); } ntotal = (int64_t) nt.QuadPart; nfree = (int64_t) nf.QuadPart; navail = (int64_t) na.QuadPart; #endif if (!res) { lua_pushnumber(L, (lua_Number) ntotal); lua_pushnumber(L, (lua_Number) navail); lua_pushnumber(L, (lua_Number) nfree); return 3; } return sys_seterror(L, 0); }
bool get_diskspace(const char *path, int64 *total, int64 *avail) { ULARGE_INTEGER availBytes; ULARGE_INTEGER totalBytes; ULARGE_INTEGER freeBytes; if (!GetDiskFreeSpaceExA(path, &availBytes, &totalBytes, &freeBytes)) { _dosmaperr(GetLastError()); return false; } *total = (int64) totalBytes.QuadPart; *avail = (int64) availBytes.QuadPart; return true; }
int DiskMuninNodePlugin::GetValues(char *buffer, int len) { ULARGE_INTEGER uliTotal = { 0 }; ULARGE_INTEGER uliFree = { 0 }; int index = 0; int ret; while (drives[index][0] != NULL) { ret = GetDiskFreeSpaceExA(drives[index], NULL, &uliTotal, &uliFree); ret = _snprintf(buffer, len, "_dev_%i_.value %i\n", index, 100-(int)(100.0f / uliTotal.QuadPart * uliFree.QuadPart)); len -= ret; buffer += ret; index++; } strncat(buffer, ".\n", len); return 0; }
bool getDiskSpace(const QString &anyPath, uint &totalMb, uint &freeMb) { #ifdef _WIN32 SetErrorMode(SEM_FAILCRITICALERRORS); ULARGE_INTEGER free,total; if (GetDiskFreeSpaceExA( QString(anyPath.left(2)+"\\").toUtf8().constData(), &free, &total, 0)) { quint64 MB = quint64(1024*1024); freeMb = (uint)(( free.QuadPart) / MB); totalMb = (uint)((total.QuadPart) / MB); SetErrorMode(0); return true; } #endif return false; }
int main(int argc, char** argv) { #if !defined(_WIN32) && !defined(_WIN64) printf("Only Windows OS is supported.\n"); #else if(argc < 3) { printf("usage: %s <dir> <command>\n", argv[0]); return -1; } char path[512]; sprintf_s(path, 511, "%s\\%s.pid", argv[1], argv[2]); DWORD pid = 0; FILE* f = NULL; fopen_s(&f, path, "r"); if(!f) { fprintf(stderr, "Can't open file %s\n", path); } else { char* pidbuf[32]; int numread = fread(pidbuf, sizeof(char), 31, f); if(numread > 0) { pidbuf[numread] = '\0'; pid = atoi((const char*)pidbuf); } } if(pid > 0) { printf("ProcessID: %d\n", pid); HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, false, pid); if(h <= 0) { fprintf(stderr, "Process %d can't be opened.\n", pid); printf("ProcessUpTime: \n"); } else { //Process elapsed time. BIGTIME CreateTime, ExitTime, ElapsedTime, Now; FILETIME KernelTime, UserTime; GetProcessTimes(h, &CreateTime.ft, &ExitTime.ft, &KernelTime, &UserTime); if(ExitTime.li > CreateTime.li) ElapsedTime.li = ExitTime.li - CreateTime.li; else { GetSystemTimeAsFileTime(&Now.ft); ElapsedTime.li = Now.li - CreateTime.li; } unsigned elapsedsecs = (unsigned)(ElapsedTime.li/10000000); TSpan span(elapsedsecs); printf("ProcessUpTime: %d-%02d:%02d:%02d\n", span.d, span.h, span.m, span.s); } } else { printf("ProcessID: \nProcessUpTime: \n"); } //CPU usage BIGTIME idle1, kernel1, user1, idle2, kernel2, user2; GetSystemTimes(&idle1.ft, &kernel1.ft, &user1.ft); Sleep(1000); GetSystemTimes(&idle2.ft, &kernel2.ft, &user2.ft); int IdleTime = (int)(idle2.li - idle1.li); int TotalTime = (int)((kernel2.li + user2.li) - (kernel1.li + user1.li)); int idleRate = (int)(100.0 * IdleTime / TotalTime); printf("CPU-Idle: %d%%\n", idleRate); //Computer uptime LARGE_INTEGER ticks, unit; QueryPerformanceCounter(&ticks); QueryPerformanceFrequency(&unit); int secs = (int)(ticks.QuadPart/unit.QuadPart); TSpan u((int)secs); printf("ComputerUpTime: %d days, %d:%d\n", u.d, u.h, u.m); printf("---SpaceUsedAndFree---\n"); //Physical and virtual memory usage. MEMORYSTATUS memstatus; GlobalMemoryStatus(&memstatus); printf("Physical Memory: %d %d\nVirtual Memory: %d %d\n", (memstatus.dwTotalPhys - memstatus.dwAvailPhys)/1024, memstatus.dwAvailPhys/1024, (memstatus.dwTotalVirtual - memstatus.dwAvailVirtual)/1024, memstatus.dwAvailVirtual/1024); // Disk Usage char drivePath[] = "?:\\"; char driveName; for( driveName = 'A'; driveName <= 'Z'; driveName++ ) { drivePath[0] = driveName; int dtype = GetDriveTypeA(drivePath); if(dtype == DRIVE_FIXED || dtype == DRIVE_RAMDISK || dtype == DRIVE_REMOVABLE || dtype == DRIVE_CDROM) { ULARGE_INTEGER diskAvailStruct; ULARGE_INTEGER diskTotalStruct; diskAvailStruct.QuadPart = 0; diskTotalStruct.QuadPart = 0; GetDiskFreeSpaceExA(drivePath, &diskAvailStruct, &diskTotalStruct, 0); double DiskSize = diskTotalStruct.QuadPart / 1024.0; double FreeSize = diskAvailStruct.QuadPart / 1024.0; printf("%s: %.0f %.0f\n", drivePath, DiskSize - FreeSize, FreeSize); } } #endif 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); }
// HasEnoughDiskSpace //------------------------------------------------------------------------------ bool Worker::HasEnoughDiskSpace() { #if defined( __WINDOWS__ ) // Only check disk space every few seconds float elapsedTime = m_TimerLastDiskSpaceCheck.GetElapsedMS(); if ( ( elapsedTime < 15000.0f ) && ( m_LastDiskSpaceResult != -1 ) ) { return ( m_LastDiskSpaceResult != 0 ); } m_TimerLastDiskSpaceCheck.Start(); static const uint64_t MIN_DISK_SPACE = 1024 * 1024 * 1024; // 1 GiB DWORD logicalDrives = GetLogicalDrives(); DWORD driveMask = 1; char driveLetter = 'a'; char drivePath[32]; int validDriveCount = 0; // This is to insure we find at least one drive... // Enumerate all drive letters. for ( uint32_t i = 0; i < 26; ++i, ++driveLetter, driveMask *= 2 ) { if ( (logicalDrives & driveMask) != 0 ) { // This letter is used. sprintf_s( drivePath, sizeof(drivePath), "%c:\\", driveLetter ); UINT driveType = GetDriveType( drivePath ); if ( driveType == DRIVE_FIXED ) { // This is a fixed frive. unsigned __int64 freeBytesAvailable = 0; unsigned __int64 totalNumberOfBytes = 0; unsigned __int64 totalNumberOfFreeBytes = 0; // Check available disk space BOOL result = GetDiskFreeSpaceExA( drivePath, (PULARGE_INTEGER)&freeBytesAvailable, (PULARGE_INTEGER)&totalNumberOfBytes, (PULARGE_INTEGER)&totalNumberOfFreeBytes ); if ( result ) { if ( freeBytesAvailable < MIN_DISK_SPACE ) { // The drive doesn't have enough free space. Exclude this machine from workers. // It is simpler to exclude the machine from the build when any of its drive has not enough space // than trying to figure out which drives are really used by Fastbuild especially in the context of symlinks, hardlinks, etc... m_LastDiskSpaceResult = 0; return false; } // At least one drive found. ++validDriveCount; } else { // There is something wrong with the drives... m_LastDiskSpaceResult = 0; return false; } } } } // return true if we've found at least one disk drive. // This is paranoid but I like being paranoid. If we reach this line it is pretty much impossible for validDriveCount to be 0. m_LastDiskSpaceResult = validDriveCount > 0; return m_LastDiskSpaceResult != 0; #else return true; // TODO:MAC TODO:LINUX Implement disk space checks #endif }
unsigned long long Platform_Windows::DiskSpaceTotal() { unsigned __int64 lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes, lpTotalNumberOfFreeBytes; GetDiskFreeSpaceExA ("C:", (PULARGE_INTEGER)&lpFreeBytesAvailableToCaller, (PULARGE_INTEGER)&lpTotalNumberOfBytes, (PULARGE_INTEGER)&lpTotalNumberOfFreeBytes); return lpTotalNumberOfBytes; }
static void * worker_thread_handler(void * x) { WorkerThread * wt = (WorkerThread *)x; for (;;) { AsyncReqInfo * req = wt->req; assert(req != NULL); req->error = 0; switch(req->type) { case AsyncReqTimer: #if defined(_WIN32) && !defined(__CYGWIN__) Sleep(EVENTS_TIMER_RESOLUTION); events_timer_ms = GetTickCount(); #else { struct timespec timenow; usleep(EVENTS_TIMER_RESOLUTION * 1000); if (clock_gettime(CLOCK_REALTIME, &timenow) == 0) { events_timer_ms = (uint32_t)(timenow.tv_nsec / 1000000 + timenow.tv_sec * 1000); } } #endif break; case AsyncReqRead: /* File read */ req->u.fio.rval = read(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqWrite: /* File write */ req->u.fio.rval = write(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqSeekRead: /* File read at offset */ req->u.fio.rval = pread(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz, (off_t)req->u.fio.offset); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqSeekWrite: /* File write at offset */ req->u.fio.rval = pwrite(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz, (off_t)req->u.fio.offset); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqRecv: /* Socket recv */ req->u.sio.rval = recv(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags); if (req->u.sio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqSend: /* Socket send */ req->u.sio.rval = send(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags); if (req->u.sio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqRecvFrom: /* Socket recvfrom */ req->u.sio.rval = recvfrom(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags, req->u.sio.addr, &req->u.sio.addrlen); if (req->u.sio.rval == -1) { req->error = errno; trace(LOG_ASYNCREQ, "AsyncReqRecvFrom: req %p, type %d, error %d", req, req->type, req->error); assert(req->error); } break; case AsyncReqSendTo: /* Socket sendto */ req->u.sio.rval = sendto(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags, req->u.sio.addr, req->u.sio.addrlen); if (req->u.sio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqAccept: /* Accept socket connections */ req->u.acc.rval = accept(req->u.acc.sock, req->u.acc.addr, req->u.acc.addr ? &req->u.acc.addrlen : NULL); if (req->u.acc.rval == -1) { req->error = errno; trace(LOG_ASYNCREQ, "AsyncReqAccept: req %p, type %d, error %d", req, req->type, req->error); assert(req->error); } break; case AsyncReqConnect: /* Connect to socket */ req->u.con.rval = connect(req->u.con.sock, req->u.con.addr, req->u.con.addrlen); if (req->u.con.rval == -1) { req->error = errno; trace(LOG_ASYNCREQ, "AsyncReqConnect: req %p, type %d, error %d", req, req->type, req->error); assert(req->error); } break; /* Platform dependant IO methods */ #if defined(_WIN32) || defined(__CYGWIN__) case AsyncReqConnectPipe: req->u.cnp.rval = ConnectNamedPipe(req->u.cnp.pipe, NULL); if (!req->u.cnp.rval) { req->error = set_win32_errno(GetLastError()); assert(req->error); } break; #elif defined(_WRS_KERNEL) #else case AsyncReqWaitpid: /* Wait for process change */ req->u.wpid.rval = waitpid(req->u.wpid.pid, &req->u.wpid.status, req->u.wpid.options); if (req->u.wpid.rval == -1) { req->error = errno; assert(req->error); } break; #endif case AsyncReqSelect: { struct timeval tv; tv.tv_sec = (long)req->u.select.timeout.tv_sec; tv.tv_usec = req->u.select.timeout.tv_nsec / 1000; req->u.select.rval = select(req->u.select.nfds, &req->u.select.readfds, &req->u.select.writefds, &req->u.select.errorfds, &tv); if (req->u.select.rval == -1) { req->error = errno; assert(req->error); } } break; case AsyncReqClose: req->u.fio.rval = close(req->u.fio.fd); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqCloseDir: req->u.dio.rval = closedir((DIR *)req->u.dio.dir); if (req->u.dio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqOpen: req->u.fio.rval = open(req->u.fio.file_name, req->u.fio.flags, req->u.fio.permission); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqOpenDir: req->u.dio.dir = opendir(req->u.dio.path); if (req->u.dio.dir == NULL) { req->error = errno; assert(req->error); } break; case AsyncReqFstat: memset(&req->u.fio.statbuf, 0, sizeof(req->u.fio.statbuf)); req->u.fio.rval = fstat(req->u.fio.fd, &req->u.fio.statbuf); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } #if defined(_WIN32) || defined(__CYGWIN__) req->u.fio.win32_attrs = req->error || !req->u.fio.file_name ? INVALID_FILE_ATTRIBUTES : GetFileAttributes(req->u.fio.file_name); #endif break; case AsyncReqStat: memset(&req->u.fio.statbuf, 0, sizeof(req->u.fio.statbuf)); req->u.fio.rval = stat(req->u.fio.file_name, &req->u.fio.statbuf); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } #if defined(_WIN32) || defined(__CYGWIN__) req->u.fio.win32_attrs = req->error ? INVALID_FILE_ATTRIBUTES : GetFileAttributes(req->u.fio.file_name); #endif break; case AsyncReqLstat: memset(&req->u.fio.statbuf, 0, sizeof(req->u.fio.statbuf)); req->u.fio.rval = lstat(req->u.fio.file_name, &req->u.fio.statbuf); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } #if defined(_WIN32) || defined(__CYGWIN__) req->u.fio.win32_attrs = req->error ? INVALID_FILE_ATTRIBUTES : GetFileAttributes(req->u.fio.file_name); #endif break; case AsyncReqSetStat: { int err = 0; if (req->u.fio.set_stat_flags & AsyncReqSetSize) { if (truncate(req->u.fio.file_name, (off_t)req->u.fio.statbuf.st_size) < 0) err = errno; } if (req->u.fio.set_stat_flags & AsyncReqSetPermissions) { if (chmod(req->u.fio.file_name, req->u.fio.statbuf.st_mode) < 0) err = errno; } #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WRS_KERNEL) # if defined(_WIN32) || defined(__CYGWIN__) if (req->u.fio.win32_attrs != INVALID_FILE_ATTRIBUTES) { if (SetFileAttributes(req->u.fio.file_name, req->u.fio.win32_attrs) == 0) err = set_win32_errno(GetLastError()); } # endif #else if (req->u.fio.set_stat_flags & AsyncReqSetUidGid) { if (chown(req->u.fio.file_name, req->u.fio.statbuf.st_uid, req->u.fio.statbuf.st_gid) < 0) err = errno; } #endif if (req->u.fio.set_stat_flags & AsyncReqSetAcModTime) { struct utimbuf buf; buf.actime = req->u.fio.statbuf.st_atime; buf.modtime = req->u.fio.statbuf.st_mtime; if (utime(req->u.fio.file_name, &buf) < 0) err = errno; } req->error = err; } break; case AsyncReqFSetStat: { int err = 0; if (req->u.fio.set_stat_flags & AsyncReqSetSize) { if (ftruncate(req->u.fio.fd, (off_t)req->u.fio.statbuf.st_size) < 0) err = errno; } #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WRS_KERNEL) if (req->u.fio.set_stat_flags & AsyncReqSetPermissions) { if (chmod(req->u.fio.file_name, req->u.fio.statbuf.st_mode) < 0) err = errno; } # if defined(_WIN32) || defined(__CYGWIN__) if (req->u.fio.win32_attrs != INVALID_FILE_ATTRIBUTES) { if (SetFileAttributes(req->u.fio.file_name, req->u.fio.win32_attrs) == 0) err = set_win32_errno(GetLastError()); } # endif #else if (req->u.fio.set_stat_flags & AsyncReqSetUidGid) { if (fchown(req->u.fio.fd, req->u.fio.statbuf.st_uid, req->u.fio.statbuf.st_gid) < 0) err = errno; } if (req->u.fio.set_stat_flags & AsyncReqSetPermissions) { if (fchmod(req->u.fio.fd, req->u.fio.statbuf.st_mode) < 0) err = errno; } #endif if (req->u.fio.set_stat_flags & AsyncReqSetAcModTime) { struct utimbuf buf; buf.actime = req->u.fio.statbuf.st_atime; buf.modtime = req->u.fio.statbuf.st_mtime; #if defined(_WIN32) && !defined(__MINGW32__) if (futime(req->u.fio.fd, &buf) < 0) err = errno; #else if (utime(req->u.fio.file_name, &buf) < 0) err = errno; #endif } req->error = err; } break; case AsyncReqRemove: req->u.fio.rval = remove(req->u.fio.file_name); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqReadDir: { int cnt = 0; while (cnt < req->u.dio.max_files) { char path[FILE_PATH_SIZE]; struct DirFileNode * file = req->u.dio.files + cnt; struct dirent * e; struct stat st; errno = 0; e = readdir((DIR *)req->u.dio.dir); if (e == NULL) { req->error = errno; if (req->error == 0) req->u.dio.eof = 1; break; } if (strcmp(e->d_name, ".") == 0) continue; if (strcmp(e->d_name, "..") == 0) continue; file->path = loc_strdup(e->d_name); memset(&st, 0, sizeof(st)); snprintf(path, sizeof(path), "%s/%s", req->u.dio.path, e->d_name); if (stat(path, &st) == 0) { #if defined(_WIN32) || defined(__CYGWIN__) file->win32_attrs = GetFileAttributes(path); #endif file->statbuf = (struct stat *)loc_alloc(sizeof(struct stat)); memcpy(file->statbuf, &st, sizeof(struct stat)); } cnt++; } } break; case AsyncReqRoots: { struct stat st; struct RootDevNode * newDevNode = NULL; #if defined(_WIN32) || defined(__CYGWIN__) { struct RootDevNode * curDevNode = NULL; int disk = 0; DWORD disks = GetLogicalDrives(); for (disk = 0; disk <= 30; disk++) { if (disks & (1 << disk)) { char path[32]; newDevNode = (struct RootDevNode *)loc_alloc_zero(sizeof(struct RootDevNode)); if (curDevNode == NULL) req->u.root.lst = newDevNode; else curDevNode->next = newDevNode; curDevNode = newDevNode; snprintf(path, sizeof(path), "%c:\\", 'A' + disk); newDevNode->devname = loc_strdup(path); if (disk >= 2) { ULARGE_INTEGER total_number_of_bytes; BOOL has_size = GetDiskFreeSpaceExA(path, NULL, &total_number_of_bytes, NULL); memset(&st, 0, sizeof(st)); #if defined(__CYGWIN__) snprintf(path, sizeof(path), "/cygdrive/%c", 'a' + disk); #endif if (has_size && stat(path, &st) == 0) { newDevNode->win32_attrs = GetFileAttributes(path); newDevNode->statbuf = (struct stat *)loc_alloc_zero(sizeof(struct stat)); memcpy(newDevNode->statbuf, &st, sizeof(struct stat)); } } } } } #elif defined(_WRS_KERNEL) { struct RootDevNode * curDevNode = NULL; extern DL_LIST iosDvList; DEV_HDR * dev; for (dev = (DEV_HDR *)DLL_FIRST(&iosDvList); dev != NULL; dev = (DEV_HDR *)DLL_NEXT(&dev->node)) { char path[FILE_PATH_SIZE]; if (strcmp(dev->name, "host:") == 0) { /* Windows host is special case */ int d; for (d = 'a'; d < 'z'; d++) { snprintf(path, sizeof(path), "%s%c:/", dev->name, d); if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { newDevNode = (struct RootDevNode *)loc_alloc_zero(sizeof(struct RootDevNode)); if (curDevNode == NULL) req->u.root.lst = newDevNode; else curDevNode->next = newDevNode; curDevNode = newDevNode; newDevNode->devname = loc_strdup(path); newDevNode->statbuf = (struct stat *)loc_alloc_zero(sizeof(struct stat)); memcpy(newDevNode->statbuf, &st, sizeof(struct stat)); } } } snprintf(path, sizeof(path), "%s/", dev->name); if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { newDevNode = (struct RootDevNode *)loc_alloc_zero(sizeof(struct RootDevNode)); if (curDevNode == NULL) req->u.root.lst = newDevNode; else curDevNode->next = newDevNode; curDevNode = newDevNode; newDevNode->devname = loc_strdup(path); newDevNode->statbuf = (struct stat *)loc_alloc_zero(sizeof(struct stat)); memcpy(newDevNode->statbuf, &st, sizeof(struct stat)); } } } #else req->u.root.lst = newDevNode = (struct RootDevNode *)loc_alloc_zero(sizeof(struct RootDevNode)); newDevNode->devname = loc_strdup("/"); if (stat("/", &st) == 0) { newDevNode->statbuf = (struct stat *)loc_alloc_zero(sizeof(struct stat)); memcpy(newDevNode->statbuf, &st, sizeof(struct stat)); } #endif } break; case AsyncReqUser: /* User defined request */ req->u.user.rval = req->u.user.func(req->u.user.data); if (req->u.user.rval == -1) { req->error = errno; assert(req->error); } break; default: req->error = ENOSYS; break; } if (req->type == AsyncReqTimer) { if (async_shutdown.state == SHUTDOWN_STATE_PENDING) break; continue; } trace(LOG_ASYNCREQ, "async_req_complete: req %p, type %d, error %d", req, req->type, req->error); check_error(pthread_mutex_lock(&wtlock)); /* Post event inside lock to make sure a new worker thread is not created unnecessarily */ post_event(req->done, req); wt->req = NULL; if (wtlist_size >= MAX_WORKER_THREADS || async_shutdown.state == SHUTDOWN_STATE_PENDING) { check_error(pthread_mutex_unlock(&wtlock)); break; } list_add_last(&wt->wtlink, &wtlist); wtlist_size++; for (;;) { check_error(pthread_cond_wait(&wt->cond, &wtlock)); if (wt->req != NULL) break; } check_error(pthread_mutex_unlock(&wtlock)); if (wt->req == &shutdown_req) break; } post_event(worker_thread_exit, wt); return NULL; }
T_CM_DISK_PARTITION_STAT_ALL * cm_get_host_disk_partition_stat (T_CM_ERROR * err_buf) { int i, len; char buf[160] = { 0 }; ULONGLONG total_size[32], free_size[32]; char names[32][4] = { 0 }; char *token; T_CM_DISK_PARTITION_STAT_ALL *res; len = GetLogicalDriveStringsA (sizeof (buf), buf); for (i = 0; i < len; i++) { if (buf[i] == 0) { buf[i] = ';'; } } buf[len - 1] = 0; i = 0; for (token = strtok (buf, ";"); token != NULL && i < 32; token = strtok (NULL, ";")) { if (GetDriveTypeA (token) == DRIVE_FIXED) { ULARGE_INTEGER ul_total, ul_free; GetDiskFreeSpaceExA (token, &ul_free, &ul_total, NULL); total_size[i] = ul_total.QuadPart; free_size[i] = ul_free.QuadPart; strcpy_limit (names[i], token, sizeof (names[i])); i++; } } res = malloc (sizeof (T_CM_DISK_PARTITION_STAT_ALL)); if (res == NULL) { return NULL; } res->num_stat = i; res->partitions = malloc (sizeof (T_CM_DISK_PARTITION_STAT) * i); if (res->partitions == NULL) { FREE_MEM (res); return NULL; } for (i = 0; i < res->num_stat; i++) { res->partitions[i].avail = free_size[i]; res->partitions[i].size = total_size[i]; res->partitions[i].used = total_size[i] - free_size[i]; strcpy_limit (res->partitions[i].name, names[i], sizeof (res->partitions[i].name)); } return res; }