#define S_F_SEC_EPOCH 0x00000080
#define S_F_HDR_ONLY 0x00000100
#define S_F_FILE_LOCKED 0x00000200
-/* Unused 0x00000400*/
+#define S_F_SA_YYYYMMDD 0x00000400
#define S_F_HORIZONTALLY 0x00000800
#define S_F_COMMENT 0x00001000
#define S_F_PERSIST_NAME 0x00002000
#define PRINT_SEC_EPOCH(m) (((m) & S_F_SEC_EPOCH) == S_F_SEC_EPOCH)
#define DISPLAY_HDR_ONLY(m) (((m) & S_F_HDR_ONLY) == S_F_HDR_ONLY)
#define FILE_LOCKED(m) (((m) & S_F_FILE_LOCKED) == S_F_FILE_LOCKED)
+#define USE_SA_YYYYMMDD(m) (((m) & S_F_SA_YYYYMMDD) == S_F_SA_YYYYMMDD)
#define DISPLAY_HORIZONTALLY(m) (((m) & S_F_HORIZONTALLY) == S_F_HORIZONTALLY)
#define DISPLAY_COMMENT(m) (((m) & S_F_COMMENT) == S_F_COMMENT)
#define DISPLAY_PERSIST_NAME_S(m) (((m) & S_F_PERSIST_NAME) == S_F_PERSIST_NAME)
extern void
allocate_structures(struct activity * []);
extern int
- check_alt_sa_dir(char *, int);
+ check_alt_sa_dir(char *, int, int);
extern int
check_disk_reg(struct activity *, int, int, int);
extern void
extern void
set_bitmap(unsigned char [], unsigned char, unsigned int);
extern void
- set_default_file(char *, int);
+ set_default_file(char *, int, int);
extern void
set_hdr_rectime(unsigned int, struct tm *, struct file_header *);
return decode_timestamp(timestamp, tse);
}
+/*
+ ***************************************************************************
+ * Look for the most recent of saDD and saYYYYMMDD to decide which one to
+ * use. If neither exists then use saDD by default.
+ *
+ * IN:
+ * @sa_dir Directory where standard daily data files are saved.
+ * @rectime Structure containing the current date.
+ *
+ * OUT:
+ * @sa_name 0 to use saDD data files,
+ * 1 to use saYYYYMMDD data files.
+ ***************************************************************************
+ */
+void guess_sa_name(char *sa_dir, struct tm *rectime, int *sa_name)
+{
+ char filename[MAX_FILE_LEN];
+ struct stat sb;
+ time_t sa_mtime;
+
+ /* Use saDD by default */
+ *sa_name = 0;
+
+ /* Look for saYYYYMMDD */
+ snprintf(filename, MAX_FILE_LEN,
+ "%s/sa%04d%02d%02d", sa_dir,
+ rectime->tm_year + 1900,
+ rectime->tm_mon + 1,
+ rectime->tm_mday);
+ filename[MAX_FILE_LEN - 1] = '\0';
+
+ if (stat(filename, &sb) < 0)
+ /* Cannot find or access saYYYYMMDD, so use saDD */
+ return;
+ sa_mtime = sb.st_mtime;
+
+ /* Look for saDD */
+ snprintf(filename, MAX_FILE_LEN,
+ "%s/sa%02d", sa_dir,
+ rectime->tm_mday);
+ filename[MAX_FILE_LEN - 1] = '\0';
+
+ if (stat(filename, &sb) < 0) {
+ /* Cannot find or access saDD, so use saYYYYMMDD */
+ *sa_name = 1;
+ return;
+ }
+
+ if (sa_mtime > sb.st_mtime) {
+ /* saYYYYMMDD is more recent than saDD, so use it */
+ *sa_name = 1;
+ }
+}
+
/*
***************************************************************************
* Set current daily data file name.
* @datafile If not an empty string then this is the alternate directory
* location where daily data files will be saved.
* @d_off Day offset (number of days to go back in the past).
+ * @sa_name 0 for saDD data files,
+ * 1 for saYYYYMMDD data files,
+ * -1 if unknown. In this case, will look for the most recent
+ * of saDD and saYYYYMMDD and use it.
*
* OUT:
* @datafile Name of daily data file.
***************************************************************************
*/
-void set_default_file(char *datafile, int d_off)
+void set_default_file(char *datafile, int d_off, int sa_name)
{
char sa_dir[MAX_FILE_LEN];
struct tm rectime;
sa_dir[MAX_FILE_LEN - 1] = '\0';
get_time(&rectime, d_off);
- snprintf(datafile, MAX_FILE_LEN,
- "%s/sa%02d", sa_dir, rectime.tm_mday);
+ if (sa_name < 0) {
+ /*
+ * Look for the most recent of saDD and saYYYYMMDD
+ * and use it. If neither exists then use saDD.
+ * sa_name is set accordingly.
+ */
+ guess_sa_name(sa_dir, &rectime, &sa_name);
+ }
+ if (sa_name) {
+ /* Using saYYYYMMDD data files */
+ snprintf(datafile, MAX_FILE_LEN,
+ "%s/sa%04d%02d%02d", sa_dir,
+ rectime.tm_year + 1900,
+ rectime.tm_mon + 1,
+ rectime.tm_mday);
+ }
+ else {
+ /* Using saDD data files */
+ snprintf(datafile, MAX_FILE_LEN,
+ "%s/sa%02d", sa_dir,
+ rectime.tm_mday);
+ }
datafile[MAX_FILE_LEN - 1] = '\0';
default_file_used = TRUE;
}
* IN:
* @datafile Name of the daily data file. May be a directory.
* @d_off Day offset (number of days to go back in the past).
+ * @sa_name 0 for saDD data files,
+ * 1 for saYYYYMMDD data files,
+ * -1 if unknown. In this case, will look for the most recent
+ * of saDD and saYYYYMMDD and use it.
+ *
*
* OUT:
* @datafile Name of the daily data file. This is now a plain file, not
* 1 if @datafile was a directory, and 0 otherwise.
***************************************************************************
*/
-int check_alt_sa_dir(char *datafile, int d_off)
+int check_alt_sa_dir(char *datafile, int d_off, int sa_name)
{
struct stat sb;
- stat(datafile, &sb);
+ if (stat(datafile, &sb) == 0) {
if (S_ISDIR(sb.st_mode)) {
- /* This is a directory: So append the default file name to it */
- set_default_file(datafile, d_off);
- return 1;
+ /*
+ * This is a directory: So append
+ * the default file name to it.
+ */
+ set_default_file(datafile, d_off, sa_name);
+ return 1;
+ }
}
return 0;
progname);
fprintf(stderr, _("Options are:\n"
- "[ -C <comment> ] [ -F ] [ -L ] [ -V ]\n"
+ "[ -C <comment> ] [ -D ] [ -F ] [ -L ] [ -V ]\n"
"[ -S { INT | DISK | IPV6 | POWER | SNMP | XDISK | ALL | XALL } ]\n"));
exit(1);
}
if (WANT_SA_ROTAT(flags)) {
/* The user specified '-' as the filename to use */
strcpy(new_ofile, sa_dir);
- set_default_file(new_ofile, 0);
+ set_default_file(new_ofile, 0, USE_SA_YYYYMMDD(flags));
if (strcmp(ofile, new_ofile)) {
do_sa_rotat = TRUE;
}
}
+ else if (!strcmp(argv[opt], "-D")) {
+ flags |= S_F_SA_YYYYMMDD;
+ }
+
else if (!strcmp(argv[opt], "-F")) {
flags |= S_F_FORCE_FILE;
}
}
else if (strspn(argv[opt], DIGITS) != strlen(argv[opt])) {
- if (ofile[0]) {
+ if (ofile[0] || WANT_SA_ROTAT(flags)) {
/* Outfile already specified */
usage(argv[0]);
}
stdfd = -1; /* Don't write to STDOUT */
if (!strcmp(argv[opt], "-")) {
/* File name set to '-' */
- set_default_file(ofile, 0);
flags |= S_F_SA_ROTAT;
}
else if (!strncmp(argv[opt], "-", 1)) {
/* Write data to file */
strncpy(ofile, argv[opt], MAX_FILE_LEN);
ofile[MAX_FILE_LEN - 1] = '\0';
- /*
- * Should ofile be a directory, it will be the alternate
- * location for sa files. So save it.
- */
- strcpy(sa_dir, ofile);
- /* Check if this is an alternate directory for sa files */
- if (check_alt_sa_dir(ofile, 0)) {
- /*
- * Yes, it was a directory.
- * ofile now contains the full path to current
- * standard daily data file.
- */
- flags |= S_F_SA_ROTAT;
- }
- else {
- /* No: So we can clear sa_dir */
- sa_dir[0] = '\0';
- }
}
}
}
}
+ /* Process file entered on the command line */
+ if (WANT_SA_ROTAT(flags)) {
+ /* File name set to '-' */
+ set_default_file(ofile, 0, USE_SA_YYYYMMDD(flags));
+ }
+ else if (ofile[0]) {
+ /*
+ * A file (or directory) has been explicitly entered
+ * on the command line.
+ * Should ofile be a directory, it will be the alternate
+ * location for sa files. So save it.
+ */
+ strcpy(sa_dir, ofile);
+ /* Check if this is an alternate directory for sa files */
+ if (check_alt_sa_dir(ofile, 0, USE_SA_YYYYMMDD(flags))) {
+ /*
+ * Yes, it was a directory.
+ * ofile now contains the full path to current
+ * standard daily data file.
+ */
+ flags |= S_F_SA_ROTAT;
+ }
+ else {
+ /* No: So we can clear sa_dir */
+ sa_dir[0] = '\0';
+ }
+ }
+
/*
* If option -z used, write to STDOUT even if a filename
* has been entered on the command line.
}
if (!strcmp(argv[opt], "-")) {
/* File name set to '-' */
- set_default_file(dfile, 0);
+ set_default_file(dfile, 0, -1);
opt++;
}
else if (!strncmp(argv[opt], "-", 1)) {
strncpy(dfile, argv[opt++], MAX_FILE_LEN);
dfile[MAX_FILE_LEN - 1] = '\0';
/* Check if this is an alternate directory for sa files */
- check_alt_sa_dir(dfile, 0);
+ check_alt_sa_dir(dfile, 0, -1);
}
}
/* sadf reads current daily data file by default */
if (!dfile[0]) {
- set_default_file(dfile, 0);
+ set_default_file(dfile, 0, -1);
}
if (tm_start.use && tm_end.use && (tm_end.tm_hour < tm_start.tm_hour)) {
{
print_usage_title(stderr, progname);
fprintf(stderr, _("Options are:\n"
- "[ -A ] [ -B ] [ -b ] [ -C ] [ -d ] [ -F ] [ -H ] [ -h ] [ -p ] [ -q ] [ -R ]\n"
- "[ -r ] [ -S ] [ -t ] [ -u [ ALL ] ] [ -V ] [ -v ] [ -W ] [ -w ] [ -y ]\n"
+ "[ -A ] [ -B ] [ -b ] [ -C ] [ -D ] [ -d ] [ -F ] [ -H ] [ -h ] [ -p ] [ -q ]\n"
+ "[ -R ] [ -r ] [ -S ] [ -t ] [ -u [ ALL ] ] [ -V ] [ -v ] [ -W ] [ -w ] [ -y ]\n"
"[ -I { <int> [,...] | SUM | ALL | XALL } ] [ -P { <cpu> [,...] | ALL } ]\n"
"[ -m { <keyword> [,...] | ALL } ] [ -n { <keyword> [,...] | ALL } ]\n"
"[ -j { ID | LABEL | PATH | UUID | ... } ]\n"
}
}
+ else if (!strcmp(argv[opt], "-D")) {
+ /* Option to tell sar to write to saYYYYMMDD data files */
+ flags |= S_F_SA_YYYYMMDD;
+ opt++;
+ }
+
else if (!strcmp(argv[opt], "-P")) {
/* Parse -P option */
if (parse_sa_P_opt(argv, &opt, &flags, act)) {
strncpy(from_file, argv[opt++], MAX_FILE_LEN);
from_file[MAX_FILE_LEN - 1] = '\0';
/* Check if this is an alternate directory for sa files */
- check_alt_sa_dir(from_file, day_offset);
+ check_alt_sa_dir(from_file, day_offset, -1);
}
else {
- set_default_file(from_file, day_offset);
+ set_default_file(from_file, day_offset, -1);
}
}
/* 'sar' is equivalent to 'sar -f' */
if ((argc == 1) ||
((interval < 0) && !from_file[0] && !to_file[0])) {
- set_default_file(from_file, day_offset);
+ set_default_file(from_file, day_offset, -1);
}
if (tm_start.use && tm_end.use && (tm_end.tm_hour < tm_start.tm_hour)) {
/* Writing data to a file (option -o) */
if (to_file[0]) {
+ /* Set option -D if entered */
+ if (USE_SA_YYYYMMDD(flags)) {
+ salloc(args_idx++, "-D");
+ }
/* Collect all possible activities (option -S XALL for sadc) */
salloc(args_idx++, "-S");
salloc(args_idx++, K_XALL);