off_t final_size_dump( int level, char * topdir) { struct fs_usage fsusage; off_t mapsize; char *s; /* calculate the map sizes */ s = g_strconcat(topdir, "/.", NULL); if(get_fs_usage(s, NULL, &fsusage) == -1) { error("statfs %s: %s", s, strerror(errno)); /*NOTREACHED*/ } amfree(s); mapsize = (fsusage.fsu_files + (off_t)7) / (off_t)8; /* in bytes */ mapsize = (mapsize + (off_t)1023) / (off_t)1024; /* in kbytes */ /* the dump contains three maps plus the files */ return (mapsize * (off_t)3) + dumpstats[level].total_size; }
static void check_space( char * dir, off_t kbytes) { struct fs_usage fsusage; char *quoted = quote_string(dir); intmax_t kb_avail; if(get_fs_usage(dir, NULL, &fsusage) == -1) { g_printf(_("ERROR [cannot get filesystem usage for %s: %s]\n"), quoted, strerror(errno)); amfree(quoted); return; } /* do the division first to avoid potential integer overflow */ kb_avail = fsusage.fsu_bavail / 1024 * fsusage.fsu_blocksize; if (fsusage.fsu_bavail_top_bit_set || fsusage.fsu_bavail == 0) { g_printf(_("ERROR [dir %s needs %lldKB, has nothing available.]\n"), quoted, (long long)kbytes); } else if (kb_avail < kbytes) { g_printf(_("ERROR [dir %s needs %lldKB, only has %lldKB available.]\n"), quoted, (long long)kbytes, (long long)kb_avail); } else { g_printf(_("OK %s has more than %lldKB available.\n"), quoted, (long long)kbytes); } amfree(quoted); }
void get_stats (struct parameter_list *p, struct fs_usage *fsp) { struct parameter_list *p_list; struct fs_usage tmpfsp; int first = 1; if (p->group == NULL) { get_path_stats(p,fsp); } else { /* find all group members */ for (p_list = path_select_list; p_list; p_list=p_list->name_next) { #ifdef __CYGWIN__ if (strncmp(p_list->name, "/cygdrive/", 10) != 0) continue; #endif if (p_list->group && ! (strcmp(p_list->group, p->group))) { stat_path(p_list); get_fs_usage (p_list->best_match->me_mountdir, p_list->best_match->me_devname, &tmpfsp); get_path_stats(p_list, &tmpfsp); if (verbose >= 3) printf("Group %s: adding %llu blocks sized %llu, (%s) used_units=%g free_units=%g total_units=%g fsu_blocksize=%llu mult=%llu\n", p_list->group, tmpfsp.fsu_bavail, tmpfsp.fsu_blocksize, p_list->best_match->me_mountdir, p_list->dused_units, p_list->dfree_units, p_list->dtotal_units, mult); /* prevent counting the first FS of a group twice since its parameter_list entry * is used to carry the information of all file systems of the entire group */ if (! first) { p->total += p_list->total; p->available += p_list->available; p->available_to_root += p_list->available_to_root; p->used += p_list->used; p->dused_units += p_list->dused_units; p->dfree_units += p_list->dfree_units; p->dtotal_units += p_list->dtotal_units; p->inodes_total += p_list->inodes_total; p->inodes_free += p_list->inodes_free; } first = 0; } if (verbose >= 3) printf("Group %s now has: used_units=%g free_units=%g total_units=%g fsu_blocksize=%llu mult=%llu\n", p->group, tmpfsp.fsu_bavail, tmpfsp.fsu_blocksize, p->best_match->me_mountdir, p->dused_units, p->dfree_units, p->dtotal_units, mult); } /* modify devname and mountdir for output */ p->best_match->me_mountdir = p->best_match->me_devname = p->group; } /* finally calculate percentages for either plain FS or summed up group */ p->dused_pct = calculate_percent( p->used, p->used + p->available ); /* used + available can never be > uintmax */ p->dfree_pct = 100 - p->dused_pct; p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total); p->dfree_inodes_percent = 100 - p->dused_inodes_percent; }
void* CInfoViewerBB::hddperThread(void *arg) { CInfoViewerBB *infoViewerBB = (CInfoViewerBB*) arg; uint64_t t, u; if (get_fs_usage(g_settings.network_nfs_recordingdir, t, u)) infoViewerBB->hddpercent = (int)((u * 100ULL) / t); else infoViewerBB->hddpercent = 0; infoViewerBB->hddperTflag=false; pthread_exit(NULL); }
void CInfoViewerBB::showSysfsHdd() { if (g_settings.infobar_show_sysfs_hdd) { //sysFS info int percent = 0; uint64_t t, u; #if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE if (get_fs_usage("/var", t, u)) #else if (get_fs_usage("/", t, u)) #endif percent = (int)((u * 100ULL) / t); showBarSys(percent); if (check_dir(g_settings.network_nfs_recordingdir) == 0) showBarHdd(hddpercent); else showBarHdd(-1); } }
bool GetInfo_Partitions ( QListView *lbox ) { #define NUMCOLS 5 QString Title[NUMCOLS]; int n; struct fstab *fstab_ent; struct statvfs svfs; long total,avail; QString str; QString MB(i18n("MB")+ " "); // International Text for MB=Mega-Byte if (setfsent() != 1) // Try to open fstab return false; Title[0] = i18n("Device"); Title[1] = i18n("Mount Point"); Title[2] = i18n("FS Type"); Title[3] = i18n("Total Size"); Title[4] = i18n("Free Size"); for (n=0; n<NUMCOLS; ++n) { lbox->addColumn(Title[n] ); } while ((fstab_ent=getfsent())!=NULL) { /* fstab_ent->fs_type holds only "rw","xx","ro"... */ memset(&svfs,0,sizeof(svfs)); statvfs(fstab_ent->fs_file,&svfs); get_fs_usage(fstab_ent->fs_file, &total, &avail); if (!strcmp(fstab_ent->fs_type,FSTAB_XX)) // valid drive ? svfs.f_basetype[0] = 0; if(svfs.f_basetype[0]) { new QListViewItem(lbox, QString(fstab_ent->fs_spec), QString(fstab_ent->fs_file) + QString(" "), (svfs.f_basetype[0] ? QString(svfs.f_basetype) : i18n("n/a")), Value((total+512)/1024,6) + MB, Value((avail+512)/1024,6) + MB); } else { new QListViewItem(lbox, QString(fstab_ent->fs_spec), QString(fstab_ent->fs_file) + QString(" "), (svfs.f_basetype[0] ? QString(svfs.f_basetype) : i18n("n/a"))); } } endfsent(); return true; }
int main (int argc, char **argv) { int result = STATE_UNKNOWN; int disk_result = STATE_UNKNOWN; char *output; char *details; char *perf; char *preamble; double inode_space_pct; double warning_high_tide; double critical_high_tide; int temp_result; struct mount_entry *me; struct fs_usage fsp, tmpfsp; struct parameter_list *temp_list, *path; preamble = strdup (" - free space:"); output = strdup (""); details = strdup (""); perf = strdup (""); stat_buf = malloc(sizeof *stat_buf); setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); mount_list = read_file_system_list (0); /* Parse extra opts if any */ argv = np_extra_opts (&argc, argv, progname); if (process_arguments (argc, argv) == ERROR) usage4 (_("Could not parse arguments")); /* If a list of paths has not been selected, find entire mount list and create list of paths */ if (path_selected == FALSE) { for (me = mount_list; me; me = me->me_next) { if (! (path = np_find_parameter(path_select_list, me->me_mountdir))) { path = np_add_parameter(&path_select_list, me->me_mountdir); } path->best_match = me; path->group = group; set_all_thresholds(path); } } np_set_best_match(path_select_list, mount_list, exact_match); /* Error if no match found for specified paths */ temp_list = path_select_list; while (temp_list) { if (! temp_list->best_match) { die (STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), temp_list->name); } temp_list = temp_list->name_next; } /* Process for every path in list */ for (path = path_select_list; path; path=path->name_next) { if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL) printf("Thresholds(pct) for %s warn: %f crit %f\n",path->name, path->freespace_percent->warning->end, path->freespace_percent->critical->end); if (verbose >= 3 && path->group != NULL) printf("Group of %s: %s\n",path->name,path->group); /* reset disk result */ disk_result = STATE_UNKNOWN; me = path->best_match; /* Filters */ /* Remove filesystems already seen */ if (np_seen_name(seen, me->me_mountdir)) { continue; } np_add_name(&seen, me->me_mountdir); if (path->group == NULL) { /* Skip remote filesystems if we're not interested in them */ if (me->me_remote && show_local_fs) { if (stat_remote_fs) stat_path(path); continue; /* Skip pseudo fs's if we haven't asked for all fs's */ } else if (me->me_dummy && !show_all_fs) { continue; /* Skip excluded fstypes */ } else if (fs_exclude_list && np_find_name (fs_exclude_list, me->me_type)) { continue; /* Skip excluded fs's */ } else if (dp_exclude_list && (np_find_name (dp_exclude_list, me->me_devname) || np_find_name (dp_exclude_list, me->me_mountdir))) { continue; /* Skip not included fstypes */ } else if (fs_include_list && !np_find_name (fs_include_list, me->me_type)) { continue; } } stat_path(path); get_fs_usage (me->me_mountdir, me->me_devname, &fsp); if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) { get_stats (path, &fsp); if (verbose >= 3) { printf ("For %s, used_pct=%g free_pct=%g used_units=%g free_units=%g total_units=%g used_inodes_pct=%g free_inodes_pct=%g fsp.fsu_blocksize=%llu mult=%llu\n", me->me_mountdir, path->dused_pct, path->dfree_pct, path->dused_units, path->dfree_units, path->dtotal_units, path->dused_inodes_percent, path->dfree_inodes_percent, fsp.fsu_blocksize, mult); } /* Threshold comparisons */ temp_result = get_status(path->dfree_units, path->freespace_units); if (verbose >=3) printf("Freespace_units result=%d\n", temp_result); disk_result = max_state( disk_result, temp_result ); temp_result = get_status(path->dfree_pct, path->freespace_percent); if (verbose >=3) printf("Freespace%% result=%d\n", temp_result); disk_result = max_state( disk_result, temp_result ); temp_result = get_status(path->dused_units, path->usedspace_units); if (verbose >=3) printf("Usedspace_units result=%d\n", temp_result); disk_result = max_state( disk_result, temp_result ); temp_result = get_status(path->dused_pct, path->usedspace_percent); if (verbose >=3) printf("Usedspace_percent result=%d\n", temp_result); disk_result = max_state( disk_result, temp_result ); temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent); if (verbose >=3) printf("Usedinodes_percent result=%d\n", temp_result); disk_result = max_state( disk_result, temp_result ); temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent); if (verbose >=3) printf("Freeinodes_percent result=%d\n", temp_result); disk_result = max_state( disk_result, temp_result ); result = max_state(result, disk_result); /* What a mess of units. The output shows free space, the perf data shows used space. Yikes! Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf data. Assumption that start=0. Roll on new syntax... */ /* *_high_tide must be reinitialized at each run */ warning_high_tide = UINT_MAX; critical_high_tide = UINT_MAX; if (path->freespace_units->warning != NULL) { warning_high_tide = path->dtotal_units - path->freespace_units->warning->end; } if (path->freespace_percent->warning != NULL) { warning_high_tide = abs( min( (double) warning_high_tide, (double) (1.0 - path->freespace_percent->warning->end/100)*path->dtotal_units )); } if (path->freespace_units->critical != NULL) { critical_high_tide = path->dtotal_units - path->freespace_units->critical->end; } if (path->freespace_percent->critical != NULL) { critical_high_tide = abs( min( (double) critical_high_tide, (double) (1.0 - path->freespace_percent->critical->end/100)*path->dtotal_units )); } /* Nb: *_high_tide are unset when == UINT_MAX */ xasprintf (&perf, "%s %s", perf, perfdata ((!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, path->dused_units, units, (warning_high_tide != UINT_MAX ? TRUE : FALSE), warning_high_tide, (critical_high_tide != UINT_MAX ? TRUE : FALSE), critical_high_tide, TRUE, 0, TRUE, path->dtotal_units)); if (disk_result==STATE_OK && erronly && !verbose) continue; xasprintf (&output, "%s %s %.0f %s (%.0f%%", output, (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, path->dfree_units, units, path->dfree_pct); /* Whether or not to put all disks on new line */ if (newlines) { if (path->dused_inodes_percent < 0) { xasprintf(&output, "%s inode=-);\n", output); } else { xasprintf(&output, "%s inode=%.0f%%);\n", output, path->dfree_inodes_percent ); } } else { if (path->dused_inodes_percent < 0) { xasprintf(&output, "%s inode=-);", output); } else { xasprintf(&output, "%s inode=%.0f%%);", output, path->dfree_inodes_percent ); } } /* TODO: Need to do a similar debug line xasprintf (&details, _("%s\n\ %.0f of %.0f %s (%.0f%% inode=%.0f%%) free on %s (type %s mounted on %s) warn:%lu crit:%lu warn%%:%.0f%% crit%%:%.0f%%"), details, dfree_units, dtotal_units, units, dfree_pct, inode_space_pct, me->me_devname, me->me_type, me->me_mountdir, (unsigned long)w_df, (unsigned long)c_df, w_dfp, c_dfp); */ } } if (verbose >= 2) xasprintf (&output, "%s%s", output, details); if (newlines) { printf ("DISK %s%s\n%s|%s\n", state_text (result), (erronly && result==STATE_OK) ? "" : preamble, output, perf); } else { printf ("DISK %s%s%s|%s\n", state_text (result), (erronly && result==STATE_OK) ? "" : preamble, output, perf); } return result; }
int main (int argc, char **argv) { int result = STATE_UNKNOWN; int disk_result = STATE_UNKNOWN; char *output; char *details; char *perf; char *preamble; double inode_space_pct; uintmax_t total, available, available_to_root, used; double dfree_pct = -1, dused_pct = -1; double dused_units, dfree_units, dtotal_units; double dused_inodes_percent, dfree_inodes_percent; double warning_high_tide; double critical_high_tide; int temp_result; struct mount_entry *me; struct fs_usage fsp, tmpfsp; struct parameter_list *temp_list, *path; struct name_list *seen = NULL; preamble = strdup (" - free space:"); output = strdup (""); details = strdup (""); perf = strdup (""); stat_buf = malloc(sizeof *stat_buf); setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); mount_list = read_file_system_list (0); /* Parse extra opts if any */ argv = np_extra_opts (&argc, argv, progname); if (process_arguments (argc, argv) == ERROR) usage4 (_("Could not parse arguments")); /* If a list of paths has not been selected, find entire mount list and create list of paths */ if (path_selected == FALSE) { for (me = mount_list; me; me = me->me_next) { if (! (path = np_find_parameter(path_select_list, me->me_mountdir))) { path = np_add_parameter(&path_select_list, me->me_mountdir); } path->best_match = me; path->group = group; set_all_thresholds(path); } } np_set_best_match(path_select_list, mount_list, exact_match); /* Error if no match found for specified paths */ temp_list = path_select_list; while (temp_list) { if (! temp_list->best_match) { die (STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), temp_list->name); } temp_list = temp_list->name_next; } /* Process for every path in list */ for (path = path_select_list; path; path=path->name_next) { if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL) printf("Thresholds(pct) for %s warn: %f crit %f\n",path->name, path->freespace_percent->warning->end, path->freespace_percent->critical->end); if (verbose >= 3 && path->group != NULL) printf("Group of %s: %s\n",path->name,path->group); /* reset disk result */ disk_result = STATE_UNKNOWN; me = path->best_match; /* Filters */ /* Remove filesystems already seen */ if (np_seen_name(seen, me->me_mountdir)) { continue; } else { if (path->group != NULL) { /* find all group members */ fsp.fsu_blocksize = 0; fsp.fsu_blocks = 0; fsp.fsu_bfree = 0; fsp.fsu_bavail = 0; fsp.fsu_files = 0; fsp.fsu_ffree = 0; for (temp_list = path_select_list; temp_list; temp_list=temp_list->name_next) { if (temp_list->group && ! (strcmp(temp_list->group, path->group))) { stat_path(path); get_fs_usage (temp_list->best_match->me_mountdir, temp_list->best_match->me_devname, &tmpfsp); /* possibly differing blocksizes if disks are grouped. Calculating average */ fsp.fsu_blocksize = (fsp.fsu_blocksize * fsp.fsu_blocks + tmpfsp.fsu_blocksize * tmpfsp.fsu_blocks) / \ (fsp.fsu_blocks + tmpfsp.fsu_blocks); /* Size of a block. */ fsp.fsu_blocks += tmpfsp.fsu_blocks; /* Total blocks. */ fsp.fsu_bfree += tmpfsp.fsu_bfree; /* Free blocks available to superuser. */ /* Gnulib workaround - see comment about it a few lines below */ fsp.fsu_bavail += (tmpfsp.fsu_bavail > tmpfsp.fsu_bfree ? 0 : tmpfsp.fsu_bavail); /* Free blocks available to non-superuser. */ fsp.fsu_files += tmpfsp.fsu_files; /* Total file nodes. */ fsp.fsu_ffree += tmpfsp.fsu_ffree; /* Free file nodes. */ if (verbose >= 3) printf("Group %s: add %llu blocks (%s) \n", path->group, tmpfsp.fsu_bavail, temp_list->name); /* printf("Group %s: add %u blocks (%s)\n", temp_list->name); *//* path->group, tmpfsp.fsu_bavail, temp_list->name); */ np_add_name(&seen, temp_list->best_match->me_mountdir); } } /* modify devname and mountdir for output */ me->me_mountdir = me->me_devname = path->group; } else np_add_name(&seen, me->me_mountdir); } if (path->group == NULL) { /* Skip remote filesystems if we're not interested in them */ if (me->me_remote && show_local_fs) { if (stat_remote_fs) stat_path(path); continue; /* Skip pseudo fs's if we haven't asked for all fs's */ } else if (me->me_dummy && !show_all_fs) { continue; /* Skip excluded fstypes */ } else if (fs_exclude_list && np_find_name (fs_exclude_list, me->me_type)) { continue; /* Skip excluded fs's */ } else if (dp_exclude_list && (np_find_name (dp_exclude_list, me->me_devname) || np_find_name (dp_exclude_list, me->me_mountdir))) { continue; } stat_path(path); get_fs_usage (me->me_mountdir, me->me_devname, &fsp); } if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) { total = fsp.fsu_blocks; /* 2007-12-08 - Workaround for Gnulib reporting insanely high available * space on BSD (the actual value should be negative but fsp.fsu_bavail * is unsigned) */ available = fsp.fsu_bavail > fsp.fsu_bfree ? 0 : fsp.fsu_bavail; available_to_root = fsp.fsu_bfree; used = total - available_to_root; if (verbose >= 3) printf ("For %s, total=%llu, available=%llu, available_to_root=%llu, used=%llu, fsp.fsu_files=%llu, fsp.fsu_ffree=%llu\n", me->me_mountdir, total, available, available_to_root, used, fsp.fsu_files, fsp.fsu_ffree); dused_pct = calculate_percent( used, used + available ); /* used + available can never be > uintmax */ dfree_pct = 100 - dused_pct; dused_units = used*fsp.fsu_blocksize/mult; dfree_units = available*fsp.fsu_blocksize/mult; dtotal_units = total*fsp.fsu_blocksize/mult; dused_inodes_percent = calculate_percent(fsp.fsu_files - fsp.fsu_ffree, fsp.fsu_files); dfree_inodes_percent = 100 - dused_inodes_percent; if (verbose >= 3) { printf ("For %s, used_pct=%g free_pct=%g used_units=%g free_units=%g total_units=%g used_inodes_pct=%g free_inodes_pct=%g fsp.fsu_blocksize=%llu mult=%llu\n", me->me_mountdir, dused_pct, dfree_pct, dused_units, dfree_units, dtotal_units, dused_inodes_percent, dfree_inodes_percent, fsp.fsu_blocksize, mult); } /* Threshold comparisons */ temp_result = get_status(dfree_units, path->freespace_units); if (verbose >=3) printf("Freespace_units result=%d\n", temp_result); disk_result = max_state( disk_result, temp_result ); temp_result = get_status(dfree_pct, path->freespace_percent); if (verbose >=3) printf("Freespace%% result=%d\n", temp_result); disk_result = max_state( disk_result, temp_result ); temp_result = get_status(dused_units, path->usedspace_units); if (verbose >=3) printf("Usedspace_units result=%d\n", temp_result); disk_result = max_state( disk_result, temp_result ); temp_result = get_status(dused_pct, path->usedspace_percent); if (verbose >=3) printf("Usedspace_percent result=%d\n", temp_result); disk_result = max_state( disk_result, temp_result ); temp_result = get_status(dused_inodes_percent, path->usedinodes_percent); if (verbose >=3) printf("Usedinodes_percent result=%d\n", temp_result); disk_result = max_state( disk_result, temp_result ); temp_result = get_status(dfree_inodes_percent, path->freeinodes_percent); if (verbose >=3) printf("Freeinodes_percent result=%d\n", temp_result); disk_result = max_state( disk_result, temp_result ); result = max_state(result, disk_result); /* What a mess of units. The output shows free space, the perf data shows used space. Yikes! Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf data. Assumption that start=0. Roll on new syntax... */ /* *_high_tide must be reinitialized at each run */ warning_high_tide = UINT_MAX; critical_high_tide = UINT_MAX; if (path->freespace_units->warning != NULL) { warning_high_tide = dtotal_units - path->freespace_units->warning->end; } if (path->freespace_percent->warning != NULL) { warning_high_tide = abs( min( (double) warning_high_tide, (double) (1.0 - path->freespace_percent->warning->end/100)*dtotal_units )); } if (path->freespace_units->critical != NULL) { critical_high_tide = dtotal_units - path->freespace_units->critical->end; } if (path->freespace_percent->critical != NULL) { critical_high_tide = abs( min( (double) critical_high_tide, (double) (1.0 - path->freespace_percent->critical->end/100)*dtotal_units )); } /* Nb: *_high_tide are unset when == UINT_MAX */ asprintf (&perf, "%s %s", perf, perfdata ((!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, dused_units, units, (warning_high_tide != UINT_MAX ? TRUE : FALSE), warning_high_tide, (critical_high_tide != UINT_MAX ? TRUE : FALSE), critical_high_tide, TRUE, 0, TRUE, dtotal_units)); if (disk_result==STATE_OK && erronly && !verbose) continue; asprintf (&output, "%s %s %.0f %s (%.0f%%", output, (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, dfree_units, units, dfree_pct); if (dused_inodes_percent < 0) { asprintf(&output, "%s inode=-);", output); } else { asprintf(&output, "%s inode=%.0f%%);", output, dfree_inodes_percent ); } /* TODO: Need to do a similar debug line asprintf (&details, _("%s\n\ %.0f of %.0f %s (%.0f%% inode=%.0f%%) free on %s (type %s mounted on %s) warn:%lu crit:%lu warn%%:%.0f%% crit%%:%.0f%%"), details, dfree_units, dtotal_units, units, dfree_pct, inode_space_pct, me->me_devname, me->me_type, me->me_mountdir, (unsigned long)w_df, (unsigned long)c_df, w_dfp, c_dfp); */ } } if (verbose >= 2) asprintf (&output, "%s%s", output, details); printf ("DISK %s%s%s|%s\n", state_text (result), (erronly && result==STATE_OK) ? "" : preamble, output, perf); return result; }
bool CFlashTool::program( const std::string & filename, int globalProgressEndErase, int globalProgressEndFlash ) { int fd1; ssize_t filesize; int globalProgressBegin = 0; if(g_settings.epg_save) CNeutrinoApp::getInstance()->saveEpg(true); if(statusViewer) statusViewer->showLocalStatus(0); if (mtdDevice.empty()) { ErrorMessage = "mtd-device not set"; return false; } char buf1[1024]; memset(buf1, 0, sizeof(buf1)); strncpy(buf1, filename.c_str(), sizeof(buf1)-1); char* dn = dirname(buf1); std::string flashfile; bool skipCopy = false; #ifdef BOXMODEL_APOLLO if (strcmp(dn, "/tmp") != 0) { uint64_t btotal = 0, bused = 0; long bsize = 0; if (get_fs_usage("/tmp", btotal, bused, &bsize)) { uint64_t fileSize = (uint64_t)file_size(filename.c_str()) / 1024ULL; uint64_t backupMaxSize = (int)((btotal - bused) * bsize); uint64_t res = 10; // Reserved 10% of available space backupMaxSize = (backupMaxSize - ((backupMaxSize * res) / 100ULL)) / 1024ULL; if (backupMaxSize < fileSize) skipCopy = true; } else skipCopy = true; } #endif if ((strcmp(dn, "/tmp") != 0) && !skipCopy) { memset(buf1, 0, sizeof(buf1)); strncpy(buf1, filename.c_str(), sizeof(buf1)-1); flashfile = (std::string)"/tmp/" + basename(buf1); CFileHelpers fh; printf("##### [CFlashTool::program] copy flashfile to %s\n", flashfile.c_str()); if(statusViewer) statusViewer->showStatusMessageUTF(g_Locale->getText(LOCALE_FLASHUPDATE_COPY_IMAGE)); fh.copyFile(filename.c_str(), flashfile.c_str(), 0644); sync(); if(statusViewer) statusViewer->showGlobalStatus(statusViewer->getGlobalStatus()+5); } else flashfile = filename; // Unmount all NFS & CIFS volumes if (!skipCopy) { nfs_mounted_once = false; CFSMounter::umount(); } if( (fd1 = open( flashfile.c_str(), O_RDONLY )) < 0 ) { ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENFILE); return false; } filesize = (ssize_t)lseek( fd1, 0, SEEK_END); lseek( fd1, 0, SEEK_SET); if(filesize==0) { ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_FILEIS0BYTES); close(fd1); return false; } if(statusViewer) { statusViewer->showLocalStatus(0); statusViewer->showStatusMessageUTF(g_Locale->getText(LOCALE_FLASHUPDATE_ERASING)); // UTF-8 } if(!erase(globalProgressEndErase)) { close(fd1); return false; } if(statusViewer) { if(globalProgressEndErase!=-1) statusViewer->showGlobalStatus(globalProgressEndErase); statusViewer->showLocalStatus(0); statusViewer->showStatusMessageUTF(g_Locale->getText(LOCALE_FLASHUPDATE_PROGRAMMINGFLASH)); // UTF-8 } #ifndef VFD_UPDATE CVFD::getInstance()->ShowText("Write Flash"); #endif if( (fd = open( mtdDevice.c_str(), O_WRONLY )) < 0 ) { ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENMTD); close(fd1); return false; } if(statusViewer) globalProgressBegin = statusViewer->getGlobalStatus(); unsigned char buf[meminfo.writesize]; unsigned mtdoffset = 0; unsigned fsize = filesize; printf("CFlashTool::program: file %s write size %d, erase size %d\n", flashfile.c_str(), meminfo.writesize, meminfo.erasesize); while(fsize > 0) { unsigned block = meminfo.writesize; if (block > fsize) block = fsize; unsigned res = read(fd1, buf, block); if (res != block) { printf("CFlashTool::program: read from %s failed: %d from %d\n", flashfile.c_str(), res, block); } if (isnand) { if (block < (unsigned) meminfo.writesize) { printf("CFlashTool::program: padding at %x\n", mtdoffset); memset(buf + res, 0, meminfo.writesize - res); } unsigned blockstart = mtdoffset & ~(meminfo.erasesize - 1); if (blockstart == mtdoffset) { while (mtdoffset < meminfo.size) { printf("CFlashTool::program: write block at %x\n", mtdoffset); loff_t offset = mtdoffset; int ret = ioctl(fd, MEMGETBADBLOCK, &offset); if (ret == 0) break; printf("CFlashTool::program: bad block at %x, skipping..\n", mtdoffset); mtdoffset += meminfo.erasesize; lseek(fd, mtdoffset, SEEK_SET); continue; } if (mtdoffset >= meminfo.size) { printf("CFlashTool::program: not enough space to write, left: %d\n", fsize); break; } } } write(fd, buf, meminfo.writesize); fsize -= block; mtdoffset += meminfo.writesize; int prog = int(100-(100./filesize*fsize)); if(statusViewer) { statusViewer->showLocalStatus(prog); if(globalProgressEndFlash!=-1) { int globalProg = globalProgressBegin + int((globalProgressEndFlash-globalProgressBegin) * prog/100. ); statusViewer->showGlobalStatus(globalProg); } } printf( "Writing %u Kbyte @ 0x%08X -- %2u %% complete.\n", block/1024, mtdoffset, prog); } if(statusViewer) statusViewer->showLocalStatus(100); close(fd1); close(fd); // FIXME error message if (fsize) return false; CVFD::getInstance()->ShowText("Flash OK."); return true; }
bool CExtUpdate::readBackupList(const std::string & dstPath) { char buf[PATH_MAX]; static struct stat FileInfo; vector<std::string>::iterator it; f1 = fopen(backupList.c_str(), "r"); if (f1 == NULL) { f1 = fopen(backupList.c_str(), "w"); if (f1 != NULL) { char tmp1[1024]; snprintf(tmp1, sizeof(tmp1), "Log=%d\nLogFile=%s\n\n%s\n\n", fLogEnabled, fLogfile.c_str(), defaultBackup.c_str()); fwrite(tmp1, 1, strlen(tmp1), f1); fclose(f1); } else return ErrorReset(0, "cannot create missing backuplist file: " + backupList); } f1 = fopen(backupList.c_str(), "r"); if (f1 == NULL) return ErrorReset(0, "cannot read backuplist file: " + backupList); fpos_t fz; fseek(f1, 0, SEEK_END); fgetpos(f1, &fz); fseek(f1, 0, SEEK_SET); if (fz.__pos == 0) return ErrorReset(CLOSE_F1, "backuplist filesize is 0"); size_t pos; std::string line; // read blacklist and config vars copyList.clear(); blackList.clear(); deleteList.clear(); while(fgets(buf, sizeof(buf), f1) != NULL) { std::string tmpLine; line = buf; line = trim(line); // ignore comments if (line.find_first_of("#") == 0) { // config vars if (line.find_first_of(":") == 1) { if (line.length() > 1) readConfig(line); } continue; } pos = line.find_first_of("#"); if (pos != std::string::npos) { line = line.substr(0, pos); line = trim(line); } // find blackList entry if (line.find_first_of("-") == 0) { tmpLine = line.substr(1); if ((tmpLine.length() > 1) && (lstat(tmpLine.c_str(), &FileInfo) != -1)) { if (S_ISREG(FileInfo.st_mode)) blackList.push_back(tmpLine); } } // find deleteList entry else if (line.find_first_of("~") == 0) { tmpLine = line.substr(1); if (checkSpecialFolders(tmpLine, false)) continue; tmpLine = dstPath + tmpLine; if (line.length() > 2) deleteList.push_back(tmpLine); } // find copyList entry else { tmpLine = (line.find_first_of("+") == 0) ? line.substr(1) : line; // '+' add entry = default if (checkSpecialFolders(tmpLine, true)) continue; if (tmpLine.length() > 1) copyList.push_back(tmpLine); } } fclose(f1); // read DeleteList for(it = deleteList.begin(); it != deleteList.end(); ++it) { line = *it; if ((line.find("*") != std::string::npos) || (line.find("?") != std::string::npos)) { // Wildcards WRITE_UPDATE_LOG("delete file list: %s\n", line.c_str()); deleteFileList(line.c_str()); } else if (lstat(line.c_str(), &FileInfo) != -1) { if (S_ISREG(FileInfo.st_mode)) { // File WRITE_UPDATE_LOG("delete file: %s\n", line.c_str()); unlink(line.c_str()); } else if (S_ISDIR(FileInfo.st_mode)){ // Directory WRITE_UPDATE_LOG("delete directory: %s\n", line.c_str()); FileHelpers->removeDir(line.c_str()); } } } sync(); if (get_fs_usage(mountPkt.c_str(), total, used, &bsize)) free2 = (total * bsize) / 1024 - (used * bsize) / 1024; // read copyList for(it = copyList.begin(); it != copyList.end(); ++it) { line = *it; line = trim(line); // remove '/' from line end size_t len = line.length(); pos = line.find_last_of("/"); if (len == pos+1) line = line.substr(0, pos); std::string dst = dstPath + line; if ((line.find("*") != std::string::npos) || (line.find("?") != std::string::npos)) { // Wildcards DBG_MSG("Wildcards: %s\n", dst.c_str()); WRITE_UPDATE_LOG("\n"); WRITE_UPDATE_LOG("--------------------\n"); WRITE_UPDATE_LOG("Wildcards: %s\n", dst.c_str()); copyFileList(line, dstPath); } else { if (lstat(line.c_str(), &FileInfo) != -1) { if (S_ISREG(FileInfo.st_mode)) { // one file only pos = dst.find_last_of("/"); std::string dir = dst.substr(0, pos); FileHelpers->createDir(dir.c_str(), 0755); DBG_MSG("file: %s => %s\n", line.c_str(), dst.c_str()); WRITE_UPDATE_LOG("\n"); WRITE_UPDATE_LOG("file: %s => %s\n", line.c_str(), dst.c_str()); WRITE_UPDATE_LOG("--------------------\n"); std::string save = (isBlacklistEntry(line)) ? ".save" : ""; if (!FileHelpers->copyFile(line.c_str(), (dst + save).c_str(), FileInfo.st_mode & 0x0FFF)) return ErrorReset(0, "copyFile error"); } else if (S_ISDIR(FileInfo.st_mode)) { // directory DBG_MSG("directory: %s => %s\n", line.c_str(), dst.c_str()); WRITE_UPDATE_LOG("\n"); WRITE_UPDATE_LOG("directory: %s => %s\n", line.c_str(), dst.c_str()); WRITE_UPDATE_LOG("--------------------\n"); FileHelpers->copyDir(line.c_str(), dst.c_str(), true); } } } } sync(); if (get_fs_usage(mountPkt.c_str(), total, used, &bsize)) { uint64_t flashWarning = 1000; // 1MB uint64_t flashError = 600; // 600KB char buf1[1024]; total = (total * bsize) / 1024; free3 = total - (used * bsize) / 1024; printf("##### [%s] %llu KB free org, %llu KB free after delete, %llu KB free now\n", __FUNCTION__, free1, free2, free3); memset(buf1, '\0', sizeof(buf1)); if (free3 <= flashError) { snprintf(buf1, sizeof(buf1)-1, g_Locale->getText(LOCALE_FLASHUPDATE_UPDATE_WITH_SETTINGS_ERROR), free3, total); ShowMsg(LOCALE_MESSAGEBOX_ERROR, buf1, CMessageBox::mbrOk, CMessageBox::mbOk, NEUTRINO_ICON_ERROR); flashErrorFlag = true; return false; } else if (free3 <= flashWarning) { snprintf(buf1, sizeof(buf1)-1, g_Locale->getText(LOCALE_FLASHUPDATE_UPDATE_WITH_SETTINGS_WARNING), free3, total); if (ShowMsg(LOCALE_MESSAGEBOX_INFO, buf1, CMessageBox::mbrNo, CMessageBox::mbYes | CMessageBox::mbNo, NEUTRINO_ICON_INFO) != CMessageBox::mbrYes) { flashErrorFlag = true; return false; } } } return true; }
bool CExtUpdate::applySettings() { if(!hintBox) hintBox = new CHintBox(LOCALE_MESSAGEBOX_INFO, g_Locale->getText(LOCALE_FLASHUPDATE_UPDATE_WITH_SETTINGS_PROCESSED)); hintBox->paint(); mtdRamError = ""; std::string osrelease = ""; mtdramDriver = ""; // driver path char buf1[256] = ""; char buf2[256] = ""; CMTDInfo * mtdInfo = CMTDInfo::getInstance(); std::string mtdFilename = mtdInfo->findMTDsystem(); // /dev/mtdX if (mtdFilename.empty()) return ErrorReset(0, "error system mtd not found"); #ifdef BOXMODEL_APOLLO uint64_t mtdSize = 65536*1024; // FIXME hack, mtd size more than free RAM #else uint64_t mtdSize = mtdInfo->getMTDSize(mtdFilename); #endif uint64_t mtdEraseSize = mtdInfo->getMTDEraseSize(mtdFilename); mtdNumber = mtdInfo->findMTDNumber(mtdFilename); // get osrelease struct utsname uts_info; if( uname(&uts_info) == 0 ) { osrelease = uts_info.release; size_t pos = osrelease.find_first_of(" "); if (pos != std::string::npos) osrelease = osrelease.substr(0, pos); } else return ErrorReset(0, "error no kernel info"); // check if mtdram driver is already loaded if (!isMtdramLoad()) { // check if exist mtdram driver snprintf(buf1, sizeof(buf1), "/lib/modules/%s/mtdram.ko", osrelease.c_str()); mtdramDriver = buf1; if ( !file_exists(mtdramDriver.c_str()) ) return ErrorReset(0, "no mtdram driver available"); // load mtdram driver snprintf(buf1, sizeof(buf1), "total_size=%llu", mtdSize/1024); snprintf(buf2, sizeof(buf2), "erase_size=%llu", mtdEraseSize/1024); my_system(4, "insmod", mtdramDriver.c_str(), buf1, buf2); // check if mtdram driver is now loaded if (!isMtdramLoad()) return ErrorReset(0, "error load mtdram driver"); } else { DBG_MSG("mtdram driver is already loaded"); } // find mtdram device std::string mtdRamFilename = "", mtdBlockFileName = ""; uint64_t mtdRamSize = 0, mtdRamEraseSize = 0; int mtdRamNr = 0; f1 = fopen("/proc/mtd", "r"); if(!f1) return ErrorReset(RESET_UNLOAD, "cannot read /proc/mtd"); fgets(buf1, sizeof(buf1), f1); while(!feof(f1)) { if(fgets(buf1, sizeof(buf1), f1)!=NULL) { char dummy[50] = ""; uint32_t tmp1, tmp2; sscanf(buf1, "mtd%1d: %8x %8x \"%48s\"\n", &mtdRamNr, &tmp1, &tmp2, dummy); mtdRamSize = (uint64_t)tmp1; mtdRamEraseSize = (uint64_t)tmp2; if (strstr(buf1, "mtdram test device") != NULL) { sprintf(buf1, "/dev/mtd%d", mtdRamNr); mtdRamFilename = buf1; sprintf(buf1, "/dev/mtdblock%d", mtdRamNr); mtdBlockFileName = buf1; break; } } } fclose(f1); if (mtdRamFilename.empty()) return ErrorReset(RESET_UNLOAD, "no mtdram test device found"); else { // check mtdRamSize / mtdRamEraseSize if ((mtdRamSize != mtdSize) || (mtdRamEraseSize != mtdEraseSize)) { snprintf(buf2, sizeof(buf2), "error MTDSize(%08llx/%08llx) or MTDEraseSize(%08llx/%08llx)\n", mtdSize, mtdRamSize, mtdEraseSize, mtdRamEraseSize); return ErrorReset(RESET_UNLOAD, buf2); } } int MTDBufSize = 0xFFFF; MTDBuf = new char[MTDBufSize]; // copy image to mtdblock if (MTDBuf == NULL) return ErrorReset(RESET_UNLOAD, "memory allocation error"); fd1 = open(imgFilename.c_str(), O_RDONLY); if (fd1 < 0) return ErrorReset(RESET_UNLOAD | DELETE_MTDBUF, "cannot read image file: " + imgFilename); uint64_t filesize = (uint64_t)lseek(fd1, 0, SEEK_END); lseek(fd1, 0, SEEK_SET); if(filesize == 0) return ErrorReset(RESET_UNLOAD | CLOSE_FD1 | DELETE_MTDBUF, "image filesize is 0"); if(filesize > mtdSize) return ErrorReset(RESET_UNLOAD | CLOSE_FD1 | DELETE_MTDBUF, "image filesize too large"); fd2 = -1; int tmpCount = 0; while (fd2 < 0) { fd2 = open(mtdBlockFileName.c_str(), O_WRONLY); tmpCount++; if (tmpCount > 3) break; sleep(1); } if (fd2 < 0) return ErrorReset(RESET_UNLOAD | CLOSE_FD1 | DELETE_MTDBUF, "cannot open mtdBlock"); uint64_t fsize = filesize; uint32_t block; while(fsize > 0) { block = (uint32_t)fsize; if(block > (uint32_t)MTDBufSize) block = MTDBufSize; read(fd1, MTDBuf, block); write(fd2, MTDBuf, block); fsize -= block; } close(fd1); close(fd2); FileHelpers->createDir(mountPkt.c_str(), 0755); int res = mount(mtdBlockFileName.c_str(), mountPkt.c_str(), "jffs2", 0, NULL); if (res) return ErrorReset(RESET_UNLOAD | DELETE_MTDBUF, "mount error"); if (get_fs_usage(mountPkt.c_str(), total, used, &bsize)) free1 = (total * bsize) / 1024 - (used * bsize) / 1024; if (!readBackupList(mountPkt)) { if (MTDBuf != NULL) delete[] MTDBuf; MTDBuf = NULL; if (flashErrorFlag) return false; return ErrorReset(0, "error readBackupList"); } res = umount(mountPkt.c_str()); if (res) return ErrorReset(RESET_UNLOAD | DELETE_MTDBUF, "unmount error"); unlink(imgFilename.c_str()); // copy mtdblock to image if (MTDBuf == NULL) return ErrorReset(RESET_UNLOAD, "memory allocation error"); fd1 = open(mtdBlockFileName.c_str(), O_RDONLY); if (fd1 < 0) return ErrorReset(RESET_UNLOAD | DELETE_MTDBUF, "cannot read mtdBlock"); fsize = mtdRamSize; fd2 = open(imgFilename.c_str(), O_WRONLY | O_CREAT); if (fd2 < 0) return ErrorReset(RESET_UNLOAD | CLOSE_FD1 | DELETE_MTDBUF, "cannot open image file: ", imgFilename); while(fsize > 0) { block = (uint32_t)fsize; if(block > (uint32_t)MTDBufSize) block = MTDBufSize; read(fd1, MTDBuf, block); write(fd2, MTDBuf, block); fsize -= block; } lseek(fd2, 0, SEEK_SET); uint64_t fsizeDst = (uint64_t)lseek(fd2, 0, SEEK_END); close(fd1); close(fd2); // check image file size if (mtdRamSize != fsizeDst) { unlink(imgFilename.c_str()); return ErrorReset(DELETE_MTDBUF, "error file size: ", imgFilename); } // unload mtdramDriver only ErrorReset(RESET_UNLOAD); if(hintBox) hintBox->hide(); if (MTDBuf != NULL) delete[] MTDBuf; MTDBuf = NULL; sync(); return true; }