Example #1
0
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;
}
Example #2
0
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);
	}
}
Example #6
0
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;
}
Example #7
0
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;
}