17917SReza.Sabdar@Sun.COM /*
212764SReza.Sabdar@Sun.COM * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
37917SReza.Sabdar@Sun.COM */
47917SReza.Sabdar@Sun.COM
57917SReza.Sabdar@Sun.COM /*
67917SReza.Sabdar@Sun.COM * BSD 3 Clause License
77917SReza.Sabdar@Sun.COM *
87917SReza.Sabdar@Sun.COM * Copyright (c) 2007, The Storage Networking Industry Association.
97917SReza.Sabdar@Sun.COM *
107917SReza.Sabdar@Sun.COM * Redistribution and use in source and binary forms, with or without
117917SReza.Sabdar@Sun.COM * modification, are permitted provided that the following conditions
127917SReza.Sabdar@Sun.COM * are met:
137917SReza.Sabdar@Sun.COM * - Redistributions of source code must retain the above copyright
147917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer.
157917SReza.Sabdar@Sun.COM *
167917SReza.Sabdar@Sun.COM * - Redistributions in binary form must reproduce the above copyright
177917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer in
187917SReza.Sabdar@Sun.COM * the documentation and/or other materials provided with the
197917SReza.Sabdar@Sun.COM * distribution.
207917SReza.Sabdar@Sun.COM *
217917SReza.Sabdar@Sun.COM * - Neither the name of The Storage Networking Industry Association (SNIA)
227917SReza.Sabdar@Sun.COM * nor the names of its contributors may be used to endorse or promote
237917SReza.Sabdar@Sun.COM * products derived from this software without specific prior written
247917SReza.Sabdar@Sun.COM * permission.
257917SReza.Sabdar@Sun.COM *
267917SReza.Sabdar@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
277917SReza.Sabdar@Sun.COM * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
287917SReza.Sabdar@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
297917SReza.Sabdar@Sun.COM * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
307917SReza.Sabdar@Sun.COM * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
317917SReza.Sabdar@Sun.COM * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
327917SReza.Sabdar@Sun.COM * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
337917SReza.Sabdar@Sun.COM * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
347917SReza.Sabdar@Sun.COM * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
357917SReza.Sabdar@Sun.COM * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
367917SReza.Sabdar@Sun.COM * POSSIBILITY OF SUCH DAMAGE.
377917SReza.Sabdar@Sun.COM */
387917SReza.Sabdar@Sun.COM
397917SReza.Sabdar@Sun.COM #include <sys/param.h>
407917SReza.Sabdar@Sun.COM #include <sys/types.h>
417917SReza.Sabdar@Sun.COM #include <ctype.h>
427917SReza.Sabdar@Sun.COM #include <errno.h>
437917SReza.Sabdar@Sun.COM #include <fcntl.h>
447917SReza.Sabdar@Sun.COM #include <limits.h>
457917SReza.Sabdar@Sun.COM #include <stdarg.h>
467917SReza.Sabdar@Sun.COM #include <stdio.h>
477917SReza.Sabdar@Sun.COM #include <stdlib.h>
487917SReza.Sabdar@Sun.COM #include <string.h>
497917SReza.Sabdar@Sun.COM #include <time.h>
507917SReza.Sabdar@Sun.COM #include <unistd.h>
517917SReza.Sabdar@Sun.COM #include <libnvpair.h>
527917SReza.Sabdar@Sun.COM #include "ndmpd_log.h"
537917SReza.Sabdar@Sun.COM #include "ndmpd.h"
547917SReza.Sabdar@Sun.COM
557917SReza.Sabdar@Sun.COM /*
567917SReza.Sabdar@Sun.COM * The dumpdates file on file system.
577917SReza.Sabdar@Sun.COM */
587917SReza.Sabdar@Sun.COM #define NDMP_DUMPDATES "dumpdates"
597917SReza.Sabdar@Sun.COM
607917SReza.Sabdar@Sun.COM
617917SReza.Sabdar@Sun.COM /*
627917SReza.Sabdar@Sun.COM * Offsets into the ctime string to various parts.
637917SReza.Sabdar@Sun.COM */
647917SReza.Sabdar@Sun.COM #define E_MONTH 4
657917SReza.Sabdar@Sun.COM #define E_DAY 8
667917SReza.Sabdar@Sun.COM #define E_HOUR 11
677917SReza.Sabdar@Sun.COM #define E_MINUTE 14
687917SReza.Sabdar@Sun.COM #define E_SECOND 17
697917SReza.Sabdar@Sun.COM #define E_YEAR 20
707917SReza.Sabdar@Sun.COM
717917SReza.Sabdar@Sun.COM
727917SReza.Sabdar@Sun.COM /*
737917SReza.Sabdar@Sun.COM * The contents of the file dumpdates is maintained on a linked list.
747917SReza.Sabdar@Sun.COM */
757917SReza.Sabdar@Sun.COM typedef struct dumpdates {
767917SReza.Sabdar@Sun.COM char dd_name[TLM_MAX_PATH_NAME];
777917SReza.Sabdar@Sun.COM char dd_level;
787917SReza.Sabdar@Sun.COM time_t dd_ddate;
797917SReza.Sabdar@Sun.COM struct dumpdates *dd_next;
807917SReza.Sabdar@Sun.COM } dumpdates_t;
817917SReza.Sabdar@Sun.COM
827917SReza.Sabdar@Sun.COM
837917SReza.Sabdar@Sun.COM /*
847917SReza.Sabdar@Sun.COM * Month names used in ctime string.
857917SReza.Sabdar@Sun.COM */
867917SReza.Sabdar@Sun.COM static char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
877917SReza.Sabdar@Sun.COM
887917SReza.Sabdar@Sun.COM
897917SReza.Sabdar@Sun.COM /*
907917SReza.Sabdar@Sun.COM * Binary lock for accessing the dumpdates file.
917917SReza.Sabdar@Sun.COM */
927917SReza.Sabdar@Sun.COM mutex_t ndmp_dd_lock = DEFAULTMUTEX;
937917SReza.Sabdar@Sun.COM
947917SReza.Sabdar@Sun.COM int ndmp_isdst = -1;
957917SReza.Sabdar@Sun.COM
967917SReza.Sabdar@Sun.COM char *zfs_dumpdate_props[] = {
977917SReza.Sabdar@Sun.COM "dumpdates:level0",
987917SReza.Sabdar@Sun.COM "dumpdates:level1",
997917SReza.Sabdar@Sun.COM "dumpdates:level2",
1007917SReza.Sabdar@Sun.COM "dumpdates:level3",
1017917SReza.Sabdar@Sun.COM "dumpdates:level4",
1027917SReza.Sabdar@Sun.COM "dumpdates:level5",
1037917SReza.Sabdar@Sun.COM "dumpdates:level6",
1047917SReza.Sabdar@Sun.COM "dumpdates:level7",
1057917SReza.Sabdar@Sun.COM "dumpdates:level8",
1067917SReza.Sabdar@Sun.COM "dumpdates:level9",
1077917SReza.Sabdar@Sun.COM };
1087917SReza.Sabdar@Sun.COM
1097917SReza.Sabdar@Sun.COM
1107917SReza.Sabdar@Sun.COM /*
1117917SReza.Sabdar@Sun.COM * lookup
1127917SReza.Sabdar@Sun.COM *
1137917SReza.Sabdar@Sun.COM * Look up the month (3-character) name and return its number.
1147917SReza.Sabdar@Sun.COM *
1157917SReza.Sabdar@Sun.COM * Returns -1 if the months name is not valid.
1167917SReza.Sabdar@Sun.COM */
1177917SReza.Sabdar@Sun.COM static int
lookup(char * str)1187917SReza.Sabdar@Sun.COM lookup(char *str)
1197917SReza.Sabdar@Sun.COM {
1207917SReza.Sabdar@Sun.COM register char *cp, *cp2;
1217917SReza.Sabdar@Sun.COM
1227917SReza.Sabdar@Sun.COM if (!str)
1237917SReza.Sabdar@Sun.COM return (-1);
1247917SReza.Sabdar@Sun.COM
1257917SReza.Sabdar@Sun.COM for (cp = months, cp2 = str; *cp != '\0'; cp += 3)
1267917SReza.Sabdar@Sun.COM if (strncmp(cp, cp2, 3) == 0)
1277917SReza.Sabdar@Sun.COM return ((cp-months) / 3);
1287917SReza.Sabdar@Sun.COM return (-1);
1297917SReza.Sabdar@Sun.COM }
1307917SReza.Sabdar@Sun.COM
1317917SReza.Sabdar@Sun.COM
1327917SReza.Sabdar@Sun.COM /*
1337917SReza.Sabdar@Sun.COM * unctime
1347917SReza.Sabdar@Sun.COM *
1357917SReza.Sabdar@Sun.COM * Convert a ctime(3) format string into a system format date.
1367917SReza.Sabdar@Sun.COM * Return the date thus calculated.
1377917SReza.Sabdar@Sun.COM *
1387917SReza.Sabdar@Sun.COM * Return -1 if the string is not in ctime format.
1397917SReza.Sabdar@Sun.COM */
1407917SReza.Sabdar@Sun.COM static int
unctime(char * str,time_t * t)1417917SReza.Sabdar@Sun.COM unctime(char *str, time_t *t)
1427917SReza.Sabdar@Sun.COM {
1437917SReza.Sabdar@Sun.COM struct tm then;
1447917SReza.Sabdar@Sun.COM char dbuf[26];
1457917SReza.Sabdar@Sun.COM
1467917SReza.Sabdar@Sun.COM if (!str || !t)
1477917SReza.Sabdar@Sun.COM return (-1);
1487917SReza.Sabdar@Sun.COM
1497917SReza.Sabdar@Sun.COM (void) memset(&then, 0, sizeof (then));
1507917SReza.Sabdar@Sun.COM (void) strlcpy(dbuf, str, sizeof (dbuf) - 1);
1517917SReza.Sabdar@Sun.COM dbuf[sizeof (dbuf) - 1] = '\0';
1527917SReza.Sabdar@Sun.COM dbuf[E_MONTH+3] = '\0';
1537917SReza.Sabdar@Sun.COM if ((then.tm_mon = lookup(&dbuf[E_MONTH])) < 0)
1547917SReza.Sabdar@Sun.COM return (-1);
1557917SReza.Sabdar@Sun.COM
1567917SReza.Sabdar@Sun.COM then.tm_mday = atoi(&dbuf[E_DAY]);
1577917SReza.Sabdar@Sun.COM then.tm_hour = atoi(&dbuf[E_HOUR]);
1587917SReza.Sabdar@Sun.COM then.tm_min = atoi(&dbuf[E_MINUTE]);
1597917SReza.Sabdar@Sun.COM then.tm_sec = atoi(&dbuf[E_SECOND]);
1607917SReza.Sabdar@Sun.COM then.tm_year = atoi(&dbuf[E_YEAR]) - 1900;
1617917SReza.Sabdar@Sun.COM then.tm_isdst = ndmp_isdst;
1627917SReza.Sabdar@Sun.COM
1637917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
1647917SReza.Sabdar@Sun.COM "yday %d wday %d %d/%d/%d %02d:%02d:%02d",
1657917SReza.Sabdar@Sun.COM then.tm_yday, then.tm_wday, then.tm_year, then.tm_mon,
1667917SReza.Sabdar@Sun.COM then.tm_mday, then.tm_hour, then.tm_min, then.tm_sec);
1677917SReza.Sabdar@Sun.COM
1687917SReza.Sabdar@Sun.COM *t = mktime(&then);
1697917SReza.Sabdar@Sun.COM
1707917SReza.Sabdar@Sun.COM return (0);
1717917SReza.Sabdar@Sun.COM }
1727917SReza.Sabdar@Sun.COM
1737917SReza.Sabdar@Sun.COM
1747917SReza.Sabdar@Sun.COM /*
1757917SReza.Sabdar@Sun.COM * ddates_pathname
1767917SReza.Sabdar@Sun.COM *
1777917SReza.Sabdar@Sun.COM * Create the dumpdates file full path name.
1787917SReza.Sabdar@Sun.COM */
1797917SReza.Sabdar@Sun.COM static char *
ddates_pathname(char * buf)1807917SReza.Sabdar@Sun.COM ddates_pathname(char *buf)
1817917SReza.Sabdar@Sun.COM {
1827917SReza.Sabdar@Sun.COM return (ndmpd_make_bk_dir_path(buf, NDMP_DUMPDATES));
1837917SReza.Sabdar@Sun.COM }
1847917SReza.Sabdar@Sun.COM
1857917SReza.Sabdar@Sun.COM
1867917SReza.Sabdar@Sun.COM /*
187*13093SRoger.Faulkner@Oracle.COM * getaline
1887917SReza.Sabdar@Sun.COM *
1897917SReza.Sabdar@Sun.COM * Get a line from the file and handle the continued lines.
1907917SReza.Sabdar@Sun.COM */
1917917SReza.Sabdar@Sun.COM static char *
getaline(FILE * fp,char * line,int llen)192*13093SRoger.Faulkner@Oracle.COM getaline(FILE *fp, char *line, int llen)
1937917SReza.Sabdar@Sun.COM {
1947917SReza.Sabdar@Sun.COM char *save;
1957917SReza.Sabdar@Sun.COM int len;
1967917SReza.Sabdar@Sun.COM
1977917SReza.Sabdar@Sun.COM if (!fp || !line)
1987917SReza.Sabdar@Sun.COM return (NULL);
1997917SReza.Sabdar@Sun.COM
2007917SReza.Sabdar@Sun.COM *(save = line) = '\0';
2017917SReza.Sabdar@Sun.COM do {
2027917SReza.Sabdar@Sun.COM if (fgets(line, llen, fp) != line)
2037917SReza.Sabdar@Sun.COM return (NULL);
2047917SReza.Sabdar@Sun.COM
2057917SReza.Sabdar@Sun.COM /* comment line? */
2067917SReza.Sabdar@Sun.COM if (*line == '#')
2077917SReza.Sabdar@Sun.COM continue;
2087917SReza.Sabdar@Sun.COM
2097917SReza.Sabdar@Sun.COM len = strlen(line);
2107917SReza.Sabdar@Sun.COM /* short line */
2117917SReza.Sabdar@Sun.COM if (len <= 0)
2127917SReza.Sabdar@Sun.COM continue;
2137917SReza.Sabdar@Sun.COM
2147917SReza.Sabdar@Sun.COM line += len-1;
2157917SReza.Sabdar@Sun.COM if (*line != '\n')
2167917SReza.Sabdar@Sun.COM return (NULL);
2177917SReza.Sabdar@Sun.COM
2187917SReza.Sabdar@Sun.COM /* trim the trailing new line */
2197917SReza.Sabdar@Sun.COM *line = '\0';
2207917SReza.Sabdar@Sun.COM if (--len <= 0)
2217917SReza.Sabdar@Sun.COM break;
2227917SReza.Sabdar@Sun.COM
2237917SReza.Sabdar@Sun.COM if (*(line-1) != '\\')
2247917SReza.Sabdar@Sun.COM break;
2257917SReza.Sabdar@Sun.COM
2267917SReza.Sabdar@Sun.COM *(line-1) = '\n';
2277917SReza.Sabdar@Sun.COM llen -= len;
2287917SReza.Sabdar@Sun.COM } while (llen > 0);
2297917SReza.Sabdar@Sun.COM
2307917SReza.Sabdar@Sun.COM return (save);
2317917SReza.Sabdar@Sun.COM }
2327917SReza.Sabdar@Sun.COM
2337917SReza.Sabdar@Sun.COM
2347917SReza.Sabdar@Sun.COM /*
2357917SReza.Sabdar@Sun.COM * get_ddname
2367917SReza.Sabdar@Sun.COM *
2377917SReza.Sabdar@Sun.COM * Get the path name from the buffer passed.
2387917SReza.Sabdar@Sun.COM *
2397917SReza.Sabdar@Sun.COM * Returns the beginning of the path name. The buffer pointer is moved
2407917SReza.Sabdar@Sun.COM * forward to point to where the next field (the dump level) begins.
2417917SReza.Sabdar@Sun.COM */
2427917SReza.Sabdar@Sun.COM static char *
get_ddname(char ** bpp)2437917SReza.Sabdar@Sun.COM get_ddname(char **bpp)
2447917SReza.Sabdar@Sun.COM {
2457917SReza.Sabdar@Sun.COM char *h, *t, *save;
2467917SReza.Sabdar@Sun.COM
2477917SReza.Sabdar@Sun.COM if (!bpp || !*bpp)
2487917SReza.Sabdar@Sun.COM return (NULL);
2497917SReza.Sabdar@Sun.COM
2507917SReza.Sabdar@Sun.COM *bpp += strspn(*bpp, "\t ");
2517917SReza.Sabdar@Sun.COM save = h = t = *bpp;
2527917SReza.Sabdar@Sun.COM while (*t) {
2537917SReza.Sabdar@Sun.COM if (*t == '\t' || *t == ' ') {
2547917SReza.Sabdar@Sun.COM /* consume the '\t' or space character */
2557917SReza.Sabdar@Sun.COM t++;
2567917SReza.Sabdar@Sun.COM break;
2577917SReza.Sabdar@Sun.COM }
2587917SReza.Sabdar@Sun.COM
2597917SReza.Sabdar@Sun.COM if (*t == '\\')
2607917SReza.Sabdar@Sun.COM switch (*(t+1)) {
2617917SReza.Sabdar@Sun.COM case '\t':
2627917SReza.Sabdar@Sun.COM case ' ':
2637917SReza.Sabdar@Sun.COM t++; /* skip the '\\' */
2647917SReza.Sabdar@Sun.COM default:
2657917SReza.Sabdar@Sun.COM break; /* nothing */
2667917SReza.Sabdar@Sun.COM }
2677917SReza.Sabdar@Sun.COM
2687917SReza.Sabdar@Sun.COM *h++ = *t++;
2697917SReza.Sabdar@Sun.COM }
2707917SReza.Sabdar@Sun.COM
2717917SReza.Sabdar@Sun.COM *bpp = t;
2727917SReza.Sabdar@Sun.COM *h++ = '\0';
2737917SReza.Sabdar@Sun.COM return (save);
2747917SReza.Sabdar@Sun.COM }
2757917SReza.Sabdar@Sun.COM
2767917SReza.Sabdar@Sun.COM
2777917SReza.Sabdar@Sun.COM /*
2787917SReza.Sabdar@Sun.COM * get_ddlevel
2797917SReza.Sabdar@Sun.COM *
2807917SReza.Sabdar@Sun.COM * Get the dump level from the buffer passed.
2817917SReza.Sabdar@Sun.COM *
2827917SReza.Sabdar@Sun.COM * Returns the dump level found. The buffer pointer is moved
2837917SReza.Sabdar@Sun.COM * forward to point to where the next field (the dump date) begins.
2847917SReza.Sabdar@Sun.COM */
2857917SReza.Sabdar@Sun.COM static int
get_ddlevel(char ** bpp)2867917SReza.Sabdar@Sun.COM get_ddlevel(char **bpp)
2877917SReza.Sabdar@Sun.COM {
2887917SReza.Sabdar@Sun.COM char *t, *save;
2897917SReza.Sabdar@Sun.COM
2907917SReza.Sabdar@Sun.COM if (!bpp || !*bpp)
2917917SReza.Sabdar@Sun.COM return (-1);
2927917SReza.Sabdar@Sun.COM
2937917SReza.Sabdar@Sun.COM *bpp += strspn(*bpp, "\t ");
2947917SReza.Sabdar@Sun.COM save = t = *bpp;
2957917SReza.Sabdar@Sun.COM
2967917SReza.Sabdar@Sun.COM /*
2977917SReza.Sabdar@Sun.COM * For 'F', 'A', 'I', and 'D' return the character itself.
2987917SReza.Sabdar@Sun.COM */
2997917SReza.Sabdar@Sun.COM if (IS_LBR_BKTYPE(*t)) {
3007917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Lbr bk type %c", *t);
3017917SReza.Sabdar@Sun.COM /*
3027917SReza.Sabdar@Sun.COM * Skip the backup type character and null terminate the
3037917SReza.Sabdar@Sun.COM * string.
3047917SReza.Sabdar@Sun.COM */
3057917SReza.Sabdar@Sun.COM *++t = '\0';
3067917SReza.Sabdar@Sun.COM *bpp = ++t;
3077917SReza.Sabdar@Sun.COM return (toupper(*save));
3087917SReza.Sabdar@Sun.COM }
3097917SReza.Sabdar@Sun.COM
3107917SReza.Sabdar@Sun.COM while (isdigit(*t))
3117917SReza.Sabdar@Sun.COM t++;
3127917SReza.Sabdar@Sun.COM
3137917SReza.Sabdar@Sun.COM *t++ = '\0';
3147917SReza.Sabdar@Sun.COM *bpp = t;
3157917SReza.Sabdar@Sun.COM return (atoi(save));
3167917SReza.Sabdar@Sun.COM }
3177917SReza.Sabdar@Sun.COM
3187917SReza.Sabdar@Sun.COM
3197917SReza.Sabdar@Sun.COM /*
3207917SReza.Sabdar@Sun.COM * get_ddate
3217917SReza.Sabdar@Sun.COM *
3227917SReza.Sabdar@Sun.COM * Get the dump date from the buffer passed.
3237917SReza.Sabdar@Sun.COM *
3247917SReza.Sabdar@Sun.COM * Returns the dump date string. The buffer pointer is moved
3257917SReza.Sabdar@Sun.COM * forward. It points to the end of the buffer now.
3267917SReza.Sabdar@Sun.COM */
3277917SReza.Sabdar@Sun.COM static char *
get_ddate(char ** bpp)3287917SReza.Sabdar@Sun.COM get_ddate(char **bpp)
3297917SReza.Sabdar@Sun.COM {
3307917SReza.Sabdar@Sun.COM char *save;
3317917SReza.Sabdar@Sun.COM
3327917SReza.Sabdar@Sun.COM if (!bpp || !*bpp)
3337917SReza.Sabdar@Sun.COM return (NULL);
3347917SReza.Sabdar@Sun.COM
3357917SReza.Sabdar@Sun.COM *bpp += strspn(*bpp, "\t ");
3367917SReza.Sabdar@Sun.COM save = *bpp;
3377917SReza.Sabdar@Sun.COM *bpp += strlen(*bpp);
3387917SReza.Sabdar@Sun.COM return (save);
3397917SReza.Sabdar@Sun.COM }
3407917SReza.Sabdar@Sun.COM
3417917SReza.Sabdar@Sun.COM
3427917SReza.Sabdar@Sun.COM /*
3437917SReza.Sabdar@Sun.COM * put_ddname
3447917SReza.Sabdar@Sun.COM *
3457917SReza.Sabdar@Sun.COM * Print the dump path name to the dumpdates file. It escapes the space,
3467917SReza.Sabdar@Sun.COM * '\t' and new line characters in the path name. The same characters are
3477917SReza.Sabdar@Sun.COM * considered in the get_ddname().
3487917SReza.Sabdar@Sun.COM */
3497917SReza.Sabdar@Sun.COM static void
put_ddname(FILE * fp,char * nm)3507917SReza.Sabdar@Sun.COM put_ddname(FILE *fp, char *nm)
3517917SReza.Sabdar@Sun.COM {
3527917SReza.Sabdar@Sun.COM if (!nm)
3537917SReza.Sabdar@Sun.COM return;
3547917SReza.Sabdar@Sun.COM
3557917SReza.Sabdar@Sun.COM while (*nm)
3567917SReza.Sabdar@Sun.COM switch (*nm) {
3577917SReza.Sabdar@Sun.COM case ' ':
3587917SReza.Sabdar@Sun.COM case '\n':
3597917SReza.Sabdar@Sun.COM case '\t':
3607917SReza.Sabdar@Sun.COM (void) fputc('\\', fp);
3617917SReza.Sabdar@Sun.COM /* FALLTHROUGH */
3627917SReza.Sabdar@Sun.COM default:
3637917SReza.Sabdar@Sun.COM (void) fputc(*nm++, fp);
3647917SReza.Sabdar@Sun.COM }
3657917SReza.Sabdar@Sun.COM }
3667917SReza.Sabdar@Sun.COM
3677917SReza.Sabdar@Sun.COM
3687917SReza.Sabdar@Sun.COM /*
3697917SReza.Sabdar@Sun.COM * put_ddlevel
3707917SReza.Sabdar@Sun.COM *
3717917SReza.Sabdar@Sun.COM * Print the dump level into the dumpdates file.
3727917SReza.Sabdar@Sun.COM */
3737917SReza.Sabdar@Sun.COM static void
put_ddlevel(FILE * fp,int level)3747917SReza.Sabdar@Sun.COM put_ddlevel(FILE *fp, int level)
3757917SReza.Sabdar@Sun.COM {
3767917SReza.Sabdar@Sun.COM if (!fp)
3777917SReza.Sabdar@Sun.COM return;
3787917SReza.Sabdar@Sun.COM
3797917SReza.Sabdar@Sun.COM (void) fprintf(fp, IS_LBR_BKTYPE(level) ? "%c" : "%d", level);
3807917SReza.Sabdar@Sun.COM }
3817917SReza.Sabdar@Sun.COM
3827917SReza.Sabdar@Sun.COM
3837917SReza.Sabdar@Sun.COM /*
3847917SReza.Sabdar@Sun.COM * put_ddate
3857917SReza.Sabdar@Sun.COM *
3867917SReza.Sabdar@Sun.COM * Print the dump date into the dumpdates file.
3877917SReza.Sabdar@Sun.COM */
put_ddate(FILE * fp,time_t t)3887917SReza.Sabdar@Sun.COM static void put_ddate(FILE *fp,
3897917SReza.Sabdar@Sun.COM time_t t)
3907917SReza.Sabdar@Sun.COM {
3917917SReza.Sabdar@Sun.COM char tbuf[64];
3927917SReza.Sabdar@Sun.COM
3937917SReza.Sabdar@Sun.COM if (!fp)
3947917SReza.Sabdar@Sun.COM return;
3957917SReza.Sabdar@Sun.COM
3967917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "[%u]", t);
3977917SReza.Sabdar@Sun.COM
3987917SReza.Sabdar@Sun.COM (void) ctime_r(&t, tbuf, sizeof (tbuf));
3997917SReza.Sabdar@Sun.COM /* LINTED variable format specifier */
4007917SReza.Sabdar@Sun.COM (void) fprintf(fp, tbuf);
4017917SReza.Sabdar@Sun.COM }
4027917SReza.Sabdar@Sun.COM
4037917SReza.Sabdar@Sun.COM
4047917SReza.Sabdar@Sun.COM /*
4057917SReza.Sabdar@Sun.COM * dd_free
4067917SReza.Sabdar@Sun.COM *
4077917SReza.Sabdar@Sun.COM * Free the linked list of dumpdates entries.
4087917SReza.Sabdar@Sun.COM */
4097917SReza.Sabdar@Sun.COM static void
dd_free(dumpdates_t * ddheadp)4107917SReza.Sabdar@Sun.COM dd_free(dumpdates_t *ddheadp)
4117917SReza.Sabdar@Sun.COM {
4127917SReza.Sabdar@Sun.COM dumpdates_t *save;
4137917SReza.Sabdar@Sun.COM
4147917SReza.Sabdar@Sun.COM if (!ddheadp)
4157917SReza.Sabdar@Sun.COM return;
4167917SReza.Sabdar@Sun.COM
4177917SReza.Sabdar@Sun.COM ddheadp = ddheadp->dd_next;
4187917SReza.Sabdar@Sun.COM while (ddheadp) {
4197917SReza.Sabdar@Sun.COM save = ddheadp->dd_next;
4207917SReza.Sabdar@Sun.COM free(ddheadp);
4217917SReza.Sabdar@Sun.COM ddheadp = save;
4227917SReza.Sabdar@Sun.COM }
4237917SReza.Sabdar@Sun.COM }
4247917SReza.Sabdar@Sun.COM
4257917SReza.Sabdar@Sun.COM
4267917SReza.Sabdar@Sun.COM /*
4277917SReza.Sabdar@Sun.COM * makedumpdate
4287917SReza.Sabdar@Sun.COM *
4297917SReza.Sabdar@Sun.COM * Make the dumpdate node based on the string buffer passed to it.
4307917SReza.Sabdar@Sun.COM */
4317917SReza.Sabdar@Sun.COM static int
makedumpdate(dumpdates_t * ddp,char * tbuf)4327917SReza.Sabdar@Sun.COM makedumpdate(dumpdates_t *ddp, char *tbuf)
4337917SReza.Sabdar@Sun.COM {
4347917SReza.Sabdar@Sun.COM char *nmp, *un_buf;
4357917SReza.Sabdar@Sun.COM int rv;
4367917SReza.Sabdar@Sun.COM
4377917SReza.Sabdar@Sun.COM /*
4387917SReza.Sabdar@Sun.COM * While parsing each line, if a line contains one of the
4397917SReza.Sabdar@Sun.COM * LBR-type levels, then checking the return value of
4407917SReza.Sabdar@Sun.COM * get_ddlevel() against negative values, it OK. Because
4417917SReza.Sabdar@Sun.COM * neither of the 'F', 'A', 'I' nor 'D' have negative
4427917SReza.Sabdar@Sun.COM * ASCII value.
4437917SReza.Sabdar@Sun.COM */
4447917SReza.Sabdar@Sun.COM if (!ddp || !tbuf)
4457917SReza.Sabdar@Sun.COM rv = -1;
4467917SReza.Sabdar@Sun.COM else if (!(nmp = get_ddname(&tbuf))) {
4477917SReza.Sabdar@Sun.COM rv = -1;
4487917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "get_ddname failed 0x%p", nmp);
4497917SReza.Sabdar@Sun.COM } else if ((ddp->dd_level = get_ddlevel(&tbuf)) < 0) {
4507917SReza.Sabdar@Sun.COM rv = -1;
4517917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "dd_level < 0 %d", ddp->dd_level);
4527917SReza.Sabdar@Sun.COM } else if (!(un_buf = get_ddate(&tbuf))) {
4537917SReza.Sabdar@Sun.COM rv = -1;
4547917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "get_ddate failed 0x%p", un_buf);
4557917SReza.Sabdar@Sun.COM } else if (unctime(un_buf, &ddp->dd_ddate) < 0) {
4567917SReza.Sabdar@Sun.COM rv = -1;
4577917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "unctime failed \"%s\"", un_buf);
4587917SReza.Sabdar@Sun.COM } else {
4597917SReza.Sabdar@Sun.COM (void) strlcpy(ddp->dd_name, nmp, TLM_MAX_PATH_NAME);
4607917SReza.Sabdar@Sun.COM rv = 0;
4617917SReza.Sabdar@Sun.COM }
4627917SReza.Sabdar@Sun.COM
4637917SReza.Sabdar@Sun.COM return (rv);
4647917SReza.Sabdar@Sun.COM }
4657917SReza.Sabdar@Sun.COM
4667917SReza.Sabdar@Sun.COM
4677917SReza.Sabdar@Sun.COM /*
4687917SReza.Sabdar@Sun.COM * getrecord
4697917SReza.Sabdar@Sun.COM *
4707917SReza.Sabdar@Sun.COM * Read a record of dumpdates file and parse it.
4717917SReza.Sabdar@Sun.COM * The records that span multiple lines are covered.
4727917SReza.Sabdar@Sun.COM *
4737917SReza.Sabdar@Sun.COM * Returns:
4747917SReza.Sabdar@Sun.COM * 0 on success
4757917SReza.Sabdar@Sun.COM * < 0 on error
4767917SReza.Sabdar@Sun.COM */
4777917SReza.Sabdar@Sun.COM static int
getrecord(FILE * fp,dumpdates_t * ddatep,int * recno)4787917SReza.Sabdar@Sun.COM getrecord(FILE *fp, dumpdates_t *ddatep, int *recno)
4797917SReza.Sabdar@Sun.COM {
4807917SReza.Sabdar@Sun.COM char tbuf[BUFSIZ];
4817917SReza.Sabdar@Sun.COM
4827917SReza.Sabdar@Sun.COM if (!fp || !ddatep || !recno)
4837917SReza.Sabdar@Sun.COM return (-1);
4847917SReza.Sabdar@Sun.COM
4857917SReza.Sabdar@Sun.COM do {
486*13093SRoger.Faulkner@Oracle.COM if (getaline(fp, tbuf, sizeof (tbuf)) != tbuf)
4877917SReza.Sabdar@Sun.COM return (-1);
4887917SReza.Sabdar@Sun.COM } while (!*tbuf);
4897917SReza.Sabdar@Sun.COM
4907917SReza.Sabdar@Sun.COM if (makedumpdate(ddatep, tbuf) < 0)
4917917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
4927917SReza.Sabdar@Sun.COM "Unknown intermediate format in %s, line %d", tbuf, *recno);
4937917SReza.Sabdar@Sun.COM
4947917SReza.Sabdar@Sun.COM (*recno)++;
4957917SReza.Sabdar@Sun.COM
4967917SReza.Sabdar@Sun.COM if (IS_LBR_BKTYPE(ddatep->dd_level & 0xff)) {
4977917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Lbr: [%s][%c][%u]",
4987917SReza.Sabdar@Sun.COM ddatep->dd_name, ddatep->dd_level, ddatep->dd_ddate);
4997917SReza.Sabdar@Sun.COM } else
5007917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "[%s][%d][%u]",
5017917SReza.Sabdar@Sun.COM ddatep->dd_name, ddatep->dd_level, ddatep->dd_ddate);
5027917SReza.Sabdar@Sun.COM
5037917SReza.Sabdar@Sun.COM return (0);
5047917SReza.Sabdar@Sun.COM }
5057917SReza.Sabdar@Sun.COM
5067917SReza.Sabdar@Sun.COM
5077917SReza.Sabdar@Sun.COM /*
5087917SReza.Sabdar@Sun.COM * readdumptimes
5097917SReza.Sabdar@Sun.COM *
5107917SReza.Sabdar@Sun.COM * Read the dumpdates file and make a linked list of its entries.
5117917SReza.Sabdar@Sun.COM *
5127917SReza.Sabdar@Sun.COM * Returns:
5137917SReza.Sabdar@Sun.COM * 0 on success
5147917SReza.Sabdar@Sun.COM * < 0 on error
5157917SReza.Sabdar@Sun.COM */
5167917SReza.Sabdar@Sun.COM static int
readdumptimes(FILE * fp,dumpdates_t * ddheadp)5177917SReza.Sabdar@Sun.COM readdumptimes(FILE *fp, dumpdates_t *ddheadp)
5187917SReza.Sabdar@Sun.COM {
5197917SReza.Sabdar@Sun.COM int recno;
5207917SReza.Sabdar@Sun.COM register struct dumpdates *ddwalk;
5217917SReza.Sabdar@Sun.COM
5227917SReza.Sabdar@Sun.COM if (!fp || !ddheadp)
5237917SReza.Sabdar@Sun.COM return (-1);
5247917SReza.Sabdar@Sun.COM
5257917SReza.Sabdar@Sun.COM recno = 1;
5267917SReza.Sabdar@Sun.COM (void) memset((void *)ddheadp, 0, sizeof (*ddheadp));
5277917SReza.Sabdar@Sun.COM for (; ; ) {
5287917SReza.Sabdar@Sun.COM ddwalk = ndmp_malloc(sizeof (*ddwalk));
5297917SReza.Sabdar@Sun.COM if (!ddwalk)
5307917SReza.Sabdar@Sun.COM return (-1);
5317917SReza.Sabdar@Sun.COM
5327917SReza.Sabdar@Sun.COM if (getrecord(fp, ddwalk, &recno) < 0) {
5337917SReza.Sabdar@Sun.COM free(ddwalk);
5347917SReza.Sabdar@Sun.COM break;
5357917SReza.Sabdar@Sun.COM }
5367917SReza.Sabdar@Sun.COM
5377917SReza.Sabdar@Sun.COM ddwalk->dd_next = ddheadp->dd_next;
5387917SReza.Sabdar@Sun.COM ddheadp->dd_next = ddwalk;
5397917SReza.Sabdar@Sun.COM ddheadp = ddwalk;
5407917SReza.Sabdar@Sun.COM }
5417917SReza.Sabdar@Sun.COM
5427917SReza.Sabdar@Sun.COM return (0);
5437917SReza.Sabdar@Sun.COM }
5447917SReza.Sabdar@Sun.COM
5457917SReza.Sabdar@Sun.COM
5467917SReza.Sabdar@Sun.COM /*
5477917SReza.Sabdar@Sun.COM * dumprecout
5487917SReza.Sabdar@Sun.COM *
5497917SReza.Sabdar@Sun.COM * Print a record into the dumpdates file.
5507917SReza.Sabdar@Sun.COM */
5517917SReza.Sabdar@Sun.COM static void
dumprecout(FILE * fp,dumpdates_t * ddp)5527917SReza.Sabdar@Sun.COM dumprecout(FILE *fp, dumpdates_t *ddp)
5537917SReza.Sabdar@Sun.COM {
5547917SReza.Sabdar@Sun.COM if (!ddp)
5557917SReza.Sabdar@Sun.COM return;
5567917SReza.Sabdar@Sun.COM
5577917SReza.Sabdar@Sun.COM if (IS_LBR_BKTYPE(ddp->dd_level)) {
5587917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Lbr: [%s][%c][%u]",
5597917SReza.Sabdar@Sun.COM ddp->dd_name, ddp->dd_level, ddp->dd_ddate);
5607917SReza.Sabdar@Sun.COM } else
5617917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "[%s][%d][%u]",
5627917SReza.Sabdar@Sun.COM ddp->dd_name, ddp->dd_level, ddp->dd_ddate);
5637917SReza.Sabdar@Sun.COM
5647917SReza.Sabdar@Sun.COM put_ddname(fp, ddp->dd_name);
5657917SReza.Sabdar@Sun.COM (void) fputc('\t', fp);
5667917SReza.Sabdar@Sun.COM put_ddlevel(fp, ddp->dd_level);
5677917SReza.Sabdar@Sun.COM (void) fputc('\t', fp);
5687917SReza.Sabdar@Sun.COM put_ddate(fp, ddp->dd_ddate);
5697917SReza.Sabdar@Sun.COM }
5707917SReza.Sabdar@Sun.COM
5717917SReza.Sabdar@Sun.COM
5727917SReza.Sabdar@Sun.COM /*
5737917SReza.Sabdar@Sun.COM * initdumptimes
5747917SReza.Sabdar@Sun.COM *
5757917SReza.Sabdar@Sun.COM * Open the dumpdates file and read it into memory.
5767917SReza.Sabdar@Sun.COM *
5777917SReza.Sabdar@Sun.COM * Returns:
5787917SReza.Sabdar@Sun.COM * 0 on success
5797917SReza.Sabdar@Sun.COM * < 0 on error
5807917SReza.Sabdar@Sun.COM *
5817917SReza.Sabdar@Sun.COM */
5827917SReza.Sabdar@Sun.COM static int
initdumptimes(dumpdates_t * ddheadp)5837917SReza.Sabdar@Sun.COM initdumptimes(dumpdates_t *ddheadp)
5847917SReza.Sabdar@Sun.COM {
5857917SReza.Sabdar@Sun.COM char fname[PATH_MAX];
5867917SReza.Sabdar@Sun.COM int rv;
5877917SReza.Sabdar@Sun.COM FILE *fp;
5887917SReza.Sabdar@Sun.COM
5897917SReza.Sabdar@Sun.COM if (!ddheadp)
5907917SReza.Sabdar@Sun.COM return (-1);
5917917SReza.Sabdar@Sun.COM
5927917SReza.Sabdar@Sun.COM if (!ddates_pathname(fname))
5937917SReza.Sabdar@Sun.COM return (-1);
5947917SReza.Sabdar@Sun.COM
5957917SReza.Sabdar@Sun.COM fp = fopen(fname, "r");
5967917SReza.Sabdar@Sun.COM if (!fp) {
5977917SReza.Sabdar@Sun.COM if (errno != ENOENT) {
5987917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Cannot read %s: %m.", fname);
5997917SReza.Sabdar@Sun.COM return (-1);
6007917SReza.Sabdar@Sun.COM }
6017917SReza.Sabdar@Sun.COM /*
6027917SReza.Sabdar@Sun.COM * Dumpdates does not exist, make an empty one.
6037917SReza.Sabdar@Sun.COM */
6047917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
6057917SReza.Sabdar@Sun.COM "No file `%s', making an empty one", fname);
6067917SReza.Sabdar@Sun.COM
6077917SReza.Sabdar@Sun.COM fp = fopen(fname, "w");
6087917SReza.Sabdar@Sun.COM if (!fp) {
6097917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Cannot create %s: %m.", fname);
6107917SReza.Sabdar@Sun.COM return (-1);
6117917SReza.Sabdar@Sun.COM }
6127917SReza.Sabdar@Sun.COM (void) fclose(fp);
6137917SReza.Sabdar@Sun.COM
6147917SReza.Sabdar@Sun.COM fp = fopen(fname, "r");
6157917SReza.Sabdar@Sun.COM if (!fp) {
6167917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR,
6177917SReza.Sabdar@Sun.COM "Cannot read %s after creating it. %m.", fname);
6187917SReza.Sabdar@Sun.COM return (-1);
6197917SReza.Sabdar@Sun.COM }
6207917SReza.Sabdar@Sun.COM }
6217917SReza.Sabdar@Sun.COM
6227917SReza.Sabdar@Sun.COM rv = readdumptimes(fp, ddheadp);
6237917SReza.Sabdar@Sun.COM (void) fclose(fp);
6247917SReza.Sabdar@Sun.COM
6257917SReza.Sabdar@Sun.COM return (rv);
6267917SReza.Sabdar@Sun.COM }
6277917SReza.Sabdar@Sun.COM
6287917SReza.Sabdar@Sun.COM
6297917SReza.Sabdar@Sun.COM /*
6307917SReza.Sabdar@Sun.COM * putdumptime
6317917SReza.Sabdar@Sun.COM *
6327917SReza.Sabdar@Sun.COM * Put the record specified by path, level and backup date to the file.
6337917SReza.Sabdar@Sun.COM * Update the record if such entry already exists; append if not.
6347917SReza.Sabdar@Sun.COM *
6357917SReza.Sabdar@Sun.COM * Returns:
6367917SReza.Sabdar@Sun.COM * 0 on success
6377917SReza.Sabdar@Sun.COM * < 0 on error
6387917SReza.Sabdar@Sun.COM */
6397917SReza.Sabdar@Sun.COM static int
putdumptime(char * path,int level,time_t ddate)6407917SReza.Sabdar@Sun.COM putdumptime(char *path, int level, time_t ddate)
6417917SReza.Sabdar@Sun.COM {
6427917SReza.Sabdar@Sun.COM int found;
6437917SReza.Sabdar@Sun.COM char fname[PATH_MAX], bakfname[PATH_MAX];
6447917SReza.Sabdar@Sun.COM FILE *rfp, *wfp;
6457917SReza.Sabdar@Sun.COM dumpdates_t ddhead, tmpdd;
6467917SReza.Sabdar@Sun.COM register dumpdates_t *ddp;
6477917SReza.Sabdar@Sun.COM int rv;
6487917SReza.Sabdar@Sun.COM
6497917SReza.Sabdar@Sun.COM if (!path)
6507917SReza.Sabdar@Sun.COM return (-1);
6517917SReza.Sabdar@Sun.COM
6527917SReza.Sabdar@Sun.COM if (IS_LBR_BKTYPE(level)) {
6537917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Lbr: [%s][%c][%u]", path, level, ddate);
6547917SReza.Sabdar@Sun.COM } else {
6557917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "[%s][%d][%u]", path, level, ddate);
6567917SReza.Sabdar@Sun.COM }
6577917SReza.Sabdar@Sun.COM
6587917SReza.Sabdar@Sun.COM if (!ddates_pathname(fname)) {
6597917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Cannot get dumpdate file path name.");
6607917SReza.Sabdar@Sun.COM return (-1);
6617917SReza.Sabdar@Sun.COM }
6627917SReza.Sabdar@Sun.COM
6637917SReza.Sabdar@Sun.COM rfp = fopen(fname, "r");
6647917SReza.Sabdar@Sun.COM if (!rfp) {
6657917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Creating %s.", fname);
6667917SReza.Sabdar@Sun.COM (void) memset((void *)&ddhead, 0, sizeof (ddhead));
6677917SReza.Sabdar@Sun.COM if (initdumptimes(&ddhead) < 0) {
6687917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Could not initialize %s.",
6697917SReza.Sabdar@Sun.COM NDMP_DUMPDATES);
6707917SReza.Sabdar@Sun.COM dd_free(&ddhead);
6717917SReza.Sabdar@Sun.COM return (-1);
6727917SReza.Sabdar@Sun.COM }
6737917SReza.Sabdar@Sun.COM } else {
6747917SReza.Sabdar@Sun.COM rv = readdumptimes(rfp, &ddhead);
6757917SReza.Sabdar@Sun.COM
6767917SReza.Sabdar@Sun.COM if (rv < 0) {
6777917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Error reading dumpdates file.");
6787917SReza.Sabdar@Sun.COM (void) fclose(rfp);
6797917SReza.Sabdar@Sun.COM dd_free(&ddhead);
6807917SReza.Sabdar@Sun.COM return (-1);
6817917SReza.Sabdar@Sun.COM }
6827917SReza.Sabdar@Sun.COM (void) fclose(rfp);
6837917SReza.Sabdar@Sun.COM }
6847917SReza.Sabdar@Sun.COM
6857917SReza.Sabdar@Sun.COM (void) snprintf(bakfname, PATH_MAX, "%s.bak", fname);
6867917SReza.Sabdar@Sun.COM wfp = fopen(bakfname, "w");
6877917SReza.Sabdar@Sun.COM if (!wfp) {
6887917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Cannot open %s: %m.", bakfname);
6897917SReza.Sabdar@Sun.COM dd_free(&ddhead);
6907917SReza.Sabdar@Sun.COM return (-1);
6917917SReza.Sabdar@Sun.COM }
6927917SReza.Sabdar@Sun.COM
6937917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "[%s][%s]", fname, bakfname);
6947917SReza.Sabdar@Sun.COM
6957917SReza.Sabdar@Sun.COM /* try to locate the entry in the file */
6967917SReza.Sabdar@Sun.COM found = 0;
6977917SReza.Sabdar@Sun.COM for (ddp = ddhead.dd_next; ddp; ddp = ddp->dd_next) {
6987917SReza.Sabdar@Sun.COM if (ddp->dd_level != level)
6997917SReza.Sabdar@Sun.COM continue;
7007917SReza.Sabdar@Sun.COM if (strcmp(path, ddp->dd_name))
7017917SReza.Sabdar@Sun.COM continue;
7027917SReza.Sabdar@Sun.COM
7037917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Found: [%s][%d][%u]",
7047917SReza.Sabdar@Sun.COM ddp->dd_name, ddp->dd_level, ddp->dd_ddate);
7057917SReza.Sabdar@Sun.COM
7067917SReza.Sabdar@Sun.COM /* update the record for the entry */
7077917SReza.Sabdar@Sun.COM found = 1;
7087917SReza.Sabdar@Sun.COM ddp->dd_ddate = ddate;
7097917SReza.Sabdar@Sun.COM
7107917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
7117917SReza.Sabdar@Sun.COM "Updated to: [%s][%d][%u]",
7127917SReza.Sabdar@Sun.COM ddp->dd_name, ddp->dd_level, ddp->dd_ddate);
7137917SReza.Sabdar@Sun.COM }
7147917SReza.Sabdar@Sun.COM
7157917SReza.Sabdar@Sun.COM /* dump all the read records */
7167917SReza.Sabdar@Sun.COM for (ddp = ddhead.dd_next; ddp; ddp = ddp->dd_next)
7177917SReza.Sabdar@Sun.COM dumprecout(wfp, ddp);
7187917SReza.Sabdar@Sun.COM
7197917SReza.Sabdar@Sun.COM dd_free(&ddhead);
7207917SReza.Sabdar@Sun.COM
7217917SReza.Sabdar@Sun.COM /* append a new record */
7227917SReza.Sabdar@Sun.COM if (!found) {
7237917SReza.Sabdar@Sun.COM (void) strlcpy(tmpdd.dd_name, path, TLM_MAX_PATH_NAME);
7247917SReza.Sabdar@Sun.COM tmpdd.dd_level = level;
7257917SReza.Sabdar@Sun.COM tmpdd.dd_ddate = ddate;
7267917SReza.Sabdar@Sun.COM dumprecout(wfp, &tmpdd);
7277917SReza.Sabdar@Sun.COM }
7287917SReza.Sabdar@Sun.COM
7297917SReza.Sabdar@Sun.COM (void) fclose(wfp);
7307917SReza.Sabdar@Sun.COM (void) rename(bakfname, fname);
7317917SReza.Sabdar@Sun.COM
7327917SReza.Sabdar@Sun.COM return (0);
7337917SReza.Sabdar@Sun.COM }
7347917SReza.Sabdar@Sun.COM
7357917SReza.Sabdar@Sun.COM
7367917SReza.Sabdar@Sun.COM /*
7377917SReza.Sabdar@Sun.COM * append_dumptime
7387917SReza.Sabdar@Sun.COM *
7397917SReza.Sabdar@Sun.COM * Append the record specified by path, level and backup date to the file.
7407917SReza.Sabdar@Sun.COM */
7417917SReza.Sabdar@Sun.COM static int
append_dumptime(char * fname,char * path,int level,time_t ddate)7427917SReza.Sabdar@Sun.COM append_dumptime(char *fname, char *path, int level, time_t ddate)
7437917SReza.Sabdar@Sun.COM {
7447917SReza.Sabdar@Sun.COM char fpath[PATH_MAX], bakfpath[PATH_MAX];
7457917SReza.Sabdar@Sun.COM FILE *fp;
7467917SReza.Sabdar@Sun.COM dumpdates_t tmpdd;
7477917SReza.Sabdar@Sun.COM
7487917SReza.Sabdar@Sun.COM if (!fname || !*fname || !path || !*path)
7497917SReza.Sabdar@Sun.COM return (-1);
7507917SReza.Sabdar@Sun.COM
7517917SReza.Sabdar@Sun.COM if (IS_LBR_BKTYPE(level & 0xff)) {
7527917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
7537917SReza.Sabdar@Sun.COM "Lbr: [%s][%s][%c][%u]",
7547917SReza.Sabdar@Sun.COM fname, path, level, ddate);
7557917SReza.Sabdar@Sun.COM } else
7567917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "[%s][%s][%d][%u]",
7577917SReza.Sabdar@Sun.COM fname, path, level, ddate);
7587917SReza.Sabdar@Sun.COM
7597917SReza.Sabdar@Sun.COM if (!ndmpd_make_bk_dir_path(fpath, fname)) {
7607917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Cannot get dumpdate file path name %s.",
7617917SReza.Sabdar@Sun.COM fname);
7627917SReza.Sabdar@Sun.COM return (-1);
7637917SReza.Sabdar@Sun.COM }
7647917SReza.Sabdar@Sun.COM
7657917SReza.Sabdar@Sun.COM (void) snprintf(bakfpath, PATH_MAX, "%s.bak", fpath);
7667917SReza.Sabdar@Sun.COM
7677917SReza.Sabdar@Sun.COM /*
7687917SReza.Sabdar@Sun.COM * If the file is there and can be opened then make a
7697917SReza.Sabdar@Sun.COM * backup copy it.
7707917SReza.Sabdar@Sun.COM */
7717917SReza.Sabdar@Sun.COM fp = fopen(fpath, "r");
7727917SReza.Sabdar@Sun.COM if (fp) {
7737917SReza.Sabdar@Sun.COM (void) fclose(fp);
7747917SReza.Sabdar@Sun.COM if (filecopy(bakfpath, fpath) != 0) {
7757917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Cannot copy %s to %s: %m.",
7767917SReza.Sabdar@Sun.COM fpath, bakfpath);
7777917SReza.Sabdar@Sun.COM return (-1);
7787917SReza.Sabdar@Sun.COM }
7797917SReza.Sabdar@Sun.COM }
7807917SReza.Sabdar@Sun.COM
7817917SReza.Sabdar@Sun.COM /* open the new copy to append the record to it */
7827917SReza.Sabdar@Sun.COM fp = fopen(bakfpath, "a");
7837917SReza.Sabdar@Sun.COM if (!fp) {
7847917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Cannot open %s: %m.", bakfpath);
7857917SReza.Sabdar@Sun.COM return (-1);
7867917SReza.Sabdar@Sun.COM }
7877917SReza.Sabdar@Sun.COM
7887917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "[%s][%s]", fpath, bakfpath);
7897917SReza.Sabdar@Sun.COM
7907917SReza.Sabdar@Sun.COM /* append a new record */
7917917SReza.Sabdar@Sun.COM (void) strlcpy(tmpdd.dd_name, path, TLM_MAX_PATH_NAME);
7927917SReza.Sabdar@Sun.COM tmpdd.dd_level = level;
7937917SReza.Sabdar@Sun.COM tmpdd.dd_ddate = ddate;
7947917SReza.Sabdar@Sun.COM dumprecout(fp, &tmpdd);
7957917SReza.Sabdar@Sun.COM
7967917SReza.Sabdar@Sun.COM (void) fclose(fp);
7977917SReza.Sabdar@Sun.COM (void) rename(bakfpath, fpath);
7987917SReza.Sabdar@Sun.COM
7997917SReza.Sabdar@Sun.COM return (0);
8007917SReza.Sabdar@Sun.COM }
8017917SReza.Sabdar@Sun.COM
8027917SReza.Sabdar@Sun.COM
8037917SReza.Sabdar@Sun.COM /*
8047917SReza.Sabdar@Sun.COM * find_date
8057917SReza.Sabdar@Sun.COM *
8067917SReza.Sabdar@Sun.COM * Find the specified date
8077917SReza.Sabdar@Sun.COM */
8087917SReza.Sabdar@Sun.COM static dumpdates_t *
find_date(dumpdates_t * ddp,char * path,int level,time_t t)8097917SReza.Sabdar@Sun.COM find_date(dumpdates_t *ddp, char *path, int level, time_t t)
8107917SReza.Sabdar@Sun.COM {
8117917SReza.Sabdar@Sun.COM for (; ddp; ddp = ddp->dd_next)
8127917SReza.Sabdar@Sun.COM if (ddp->dd_level == level && ddp->dd_ddate > t &&
8137917SReza.Sabdar@Sun.COM strcmp(path, ddp->dd_name) == 0)
8147917SReza.Sabdar@Sun.COM break;
8157917SReza.Sabdar@Sun.COM
8167917SReza.Sabdar@Sun.COM return (ddp);
8177917SReza.Sabdar@Sun.COM }
8187917SReza.Sabdar@Sun.COM
8197917SReza.Sabdar@Sun.COM
8207917SReza.Sabdar@Sun.COM /*
8217917SReza.Sabdar@Sun.COM * Get the dumpdate of the last level backup done on the path.
82212764SReza.Sabdar@Sun.COM * The last level normally is (level - 1) in case of NetBackup
82312764SReza.Sabdar@Sun.COM * but some DMAs allow that previous level could be anything
82412764SReza.Sabdar@Sun.COM * between 0 and the current level.
8257917SReza.Sabdar@Sun.COM *
8267917SReza.Sabdar@Sun.COM * Returns:
8277917SReza.Sabdar@Sun.COM * 0 on success
8287917SReza.Sabdar@Sun.COM * < 0 on error
8297917SReza.Sabdar@Sun.COM */
8307917SReza.Sabdar@Sun.COM int
ndmpd_get_dumptime(char * path,int * level,time_t * ddate)8317917SReza.Sabdar@Sun.COM ndmpd_get_dumptime(char *path, int *level, time_t *ddate)
8327917SReza.Sabdar@Sun.COM {
8337917SReza.Sabdar@Sun.COM int i;
8347917SReza.Sabdar@Sun.COM dumpdates_t ddhead, *ddp, *save;
8357917SReza.Sabdar@Sun.COM char vol[ZFS_MAXNAMELEN];
8367917SReza.Sabdar@Sun.COM nvlist_t *userprops;
8377917SReza.Sabdar@Sun.COM zfs_handle_t *zhp;
83812764SReza.Sabdar@Sun.COM nvlist_t *propval = NULL;
83912764SReza.Sabdar@Sun.COM char *strval = NULL;
8407917SReza.Sabdar@Sun.COM
8417917SReza.Sabdar@Sun.COM if (!path || !level || !ddate)
8427917SReza.Sabdar@Sun.COM return (-1);
8437917SReza.Sabdar@Sun.COM
8447917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "[%s] level %d",
8457917SReza.Sabdar@Sun.COM path, *level);
8467917SReza.Sabdar@Sun.COM
8477917SReza.Sabdar@Sun.COM if (*level == 0) {
8487917SReza.Sabdar@Sun.COM *ddate = (time_t)0;
8497917SReza.Sabdar@Sun.COM return (0);
8507917SReza.Sabdar@Sun.COM }
8517917SReza.Sabdar@Sun.COM
8527917SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx);
8537917SReza.Sabdar@Sun.COM /* Check if this is a ZFS dataset */
8547917SReza.Sabdar@Sun.COM if ((zlibh != NULL) &&
8557917SReza.Sabdar@Sun.COM (get_zfsvolname(vol, sizeof (vol), path) == 0) &&
8567917SReza.Sabdar@Sun.COM ((zhp = zfs_open(zlibh, vol, ZFS_TYPE_DATASET)) != NULL)) {
85712764SReza.Sabdar@Sun.COM if ((userprops = zfs_get_user_props(zhp)) == NULL) {
8587917SReza.Sabdar@Sun.COM *level = 0;
8597917SReza.Sabdar@Sun.COM *ddate = (time_t)0;
8607917SReza.Sabdar@Sun.COM zfs_close(zhp);
8617917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
8627917SReza.Sabdar@Sun.COM return (0);
8637917SReza.Sabdar@Sun.COM }
86412764SReza.Sabdar@Sun.COM for (i = *level - 1; i >= 0; i--) {
86512764SReza.Sabdar@Sun.COM if (nvlist_lookup_nvlist(userprops,
86612764SReza.Sabdar@Sun.COM zfs_dumpdate_props[i], &propval) == 0) {
86712764SReza.Sabdar@Sun.COM *level = i;
86812764SReza.Sabdar@Sun.COM break;
86912764SReza.Sabdar@Sun.COM }
87012764SReza.Sabdar@Sun.COM }
87112764SReza.Sabdar@Sun.COM if (propval == NULL ||
87212764SReza.Sabdar@Sun.COM nvlist_lookup_string(propval, ZPROP_VALUE,
8737917SReza.Sabdar@Sun.COM &strval) != 0) {
8747917SReza.Sabdar@Sun.COM *level = 0;
8757917SReza.Sabdar@Sun.COM *ddate = (time_t)0;
8767917SReza.Sabdar@Sun.COM zfs_close(zhp);
8777917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
8787917SReza.Sabdar@Sun.COM return (0);
8797917SReza.Sabdar@Sun.COM }
88012764SReza.Sabdar@Sun.COM if (unctime(strval, ddate) < 0) {
8817917SReza.Sabdar@Sun.COM zfs_close(zhp);
8827917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
8837917SReza.Sabdar@Sun.COM return (-1);
8847917SReza.Sabdar@Sun.COM }
8857917SReza.Sabdar@Sun.COM
8867917SReza.Sabdar@Sun.COM zfs_close(zhp);
8877917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
8887917SReza.Sabdar@Sun.COM return (0);
8897917SReza.Sabdar@Sun.COM }
8907917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
8917917SReza.Sabdar@Sun.COM
8927917SReza.Sabdar@Sun.COM (void) memset((void *)&ddhead, 0, sizeof (ddhead));
8937917SReza.Sabdar@Sun.COM if (initdumptimes(&ddhead) < 0) {
8947917SReza.Sabdar@Sun.COM dd_free(&ddhead);
8957917SReza.Sabdar@Sun.COM return (-1);
8967917SReza.Sabdar@Sun.COM }
8977917SReza.Sabdar@Sun.COM
8987917SReza.Sabdar@Sun.COM /*
8997917SReza.Sabdar@Sun.COM * Empty dumpdates file means level 0 for all paths.
9007917SReza.Sabdar@Sun.COM */
9017917SReza.Sabdar@Sun.COM if ((ddp = ddhead.dd_next) == 0) {
9027917SReza.Sabdar@Sun.COM if (!IS_LBR_BKTYPE(*level & 0xff))
9037917SReza.Sabdar@Sun.COM *level = 0;
9047917SReza.Sabdar@Sun.COM *ddate = 0;
9057917SReza.Sabdar@Sun.COM return (0);
9067917SReza.Sabdar@Sun.COM }
9077917SReza.Sabdar@Sun.COM
9087917SReza.Sabdar@Sun.COM /*
9097917SReza.Sabdar@Sun.COM * If it's not level backup, then find the exact record
9107917SReza.Sabdar@Sun.COM * type.
9117917SReza.Sabdar@Sun.COM */
9127917SReza.Sabdar@Sun.COM if (IS_LBR_BKTYPE(*level & 0xff)) {
9137917SReza.Sabdar@Sun.COM save = find_date(ddp, path, *level, *ddate);
9147917SReza.Sabdar@Sun.COM
9157917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
9167917SReza.Sabdar@Sun.COM "LBR_BKTYPE save 0x%p", save);
9177917SReza.Sabdar@Sun.COM
9187917SReza.Sabdar@Sun.COM *ddate = save ? save->dd_ddate : (time_t)0;
9197917SReza.Sabdar@Sun.COM } else {
9207917SReza.Sabdar@Sun.COM /*
9217917SReza.Sabdar@Sun.COM * Go find the entry with the same name for a maximum of a
9227917SReza.Sabdar@Sun.COM * lower increment and older date.
9237917SReza.Sabdar@Sun.COM */
9247917SReza.Sabdar@Sun.COM save = NULL;
9257917SReza.Sabdar@Sun.COM for (i = *level - 1; i >= 0; i--) {
9267917SReza.Sabdar@Sun.COM save = find_date(ddp, path, i, *ddate);
9277917SReza.Sabdar@Sun.COM if (save) {
9287917SReza.Sabdar@Sun.COM *level = save->dd_level;
9297917SReza.Sabdar@Sun.COM *ddate = save->dd_ddate;
9307917SReza.Sabdar@Sun.COM break;
9317917SReza.Sabdar@Sun.COM }
9327917SReza.Sabdar@Sun.COM }
9337917SReza.Sabdar@Sun.COM
9347917SReza.Sabdar@Sun.COM if (!save) {
9357917SReza.Sabdar@Sun.COM *level = 0;
9367917SReza.Sabdar@Sun.COM *ddate = (time_t)0;
9377917SReza.Sabdar@Sun.COM }
9387917SReza.Sabdar@Sun.COM }
9397917SReza.Sabdar@Sun.COM
9407917SReza.Sabdar@Sun.COM dd_free(&ddhead);
9417917SReza.Sabdar@Sun.COM
9427917SReza.Sabdar@Sun.COM return (0);
9437917SReza.Sabdar@Sun.COM }
9447917SReza.Sabdar@Sun.COM
9457917SReza.Sabdar@Sun.COM
9467917SReza.Sabdar@Sun.COM /*
9477917SReza.Sabdar@Sun.COM * Put the date and the level of the back up for the
9487917SReza.Sabdar@Sun.COM * specified path in the dumpdates file. If there is a line
9497917SReza.Sabdar@Sun.COM * for the same path and the same level, the date is updated.
9507917SReza.Sabdar@Sun.COM * Otherwise, a line is appended to the file.
9517917SReza.Sabdar@Sun.COM *
9527917SReza.Sabdar@Sun.COM * Returns:
9537917SReza.Sabdar@Sun.COM * 0 on success
9547917SReza.Sabdar@Sun.COM * < 0 on error
9557917SReza.Sabdar@Sun.COM */
9567917SReza.Sabdar@Sun.COM int
ndmpd_put_dumptime(char * path,int level,time_t ddate)9577917SReza.Sabdar@Sun.COM ndmpd_put_dumptime(char *path, int level, time_t ddate)
9587917SReza.Sabdar@Sun.COM {
9597917SReza.Sabdar@Sun.COM char vol[ZFS_MAXNAMELEN];
9607917SReza.Sabdar@Sun.COM zfs_handle_t *zhp;
9617917SReza.Sabdar@Sun.COM char tbuf[64];
9627917SReza.Sabdar@Sun.COM int rv;
9637917SReza.Sabdar@Sun.COM
9647917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "[%s][%d][%u]", path, level,
9657917SReza.Sabdar@Sun.COM ddate);
9667917SReza.Sabdar@Sun.COM
9677917SReza.Sabdar@Sun.COM /* Check if this is a ZFS dataset */
9687917SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx);
9697917SReza.Sabdar@Sun.COM if ((zlibh != NULL) &&
9707917SReza.Sabdar@Sun.COM (get_zfsvolname(vol, sizeof (vol), path) == 0) &&
9717917SReza.Sabdar@Sun.COM ((zhp = zfs_open(zlibh, vol, ZFS_TYPE_DATASET)) != NULL)) {
9727917SReza.Sabdar@Sun.COM
9737917SReza.Sabdar@Sun.COM (void) ctime_r(&ddate, tbuf, sizeof (tbuf));
9747917SReza.Sabdar@Sun.COM rv = zfs_prop_set(zhp, zfs_dumpdate_props[level], tbuf);
9757917SReza.Sabdar@Sun.COM zfs_close(zhp);
9767917SReza.Sabdar@Sun.COM
9777917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
9787917SReza.Sabdar@Sun.COM return (rv);
9797917SReza.Sabdar@Sun.COM }
9807917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
9817917SReza.Sabdar@Sun.COM
9827917SReza.Sabdar@Sun.COM (void) mutex_lock(&ndmp_dd_lock);
9837917SReza.Sabdar@Sun.COM rv = putdumptime(path, level, ddate);
9847917SReza.Sabdar@Sun.COM (void) mutex_unlock(&ndmp_dd_lock);
9857917SReza.Sabdar@Sun.COM
9867917SReza.Sabdar@Sun.COM return (rv);
9877917SReza.Sabdar@Sun.COM }
9887917SReza.Sabdar@Sun.COM
9897917SReza.Sabdar@Sun.COM
9907917SReza.Sabdar@Sun.COM /*
9917917SReza.Sabdar@Sun.COM * Append a backup date record to the specified file.
9927917SReza.Sabdar@Sun.COM */
9937917SReza.Sabdar@Sun.COM int
ndmpd_append_dumptime(char * fname,char * path,int level,time_t ddate)9947917SReza.Sabdar@Sun.COM ndmpd_append_dumptime(char *fname, char *path, int level, time_t ddate)
9957917SReza.Sabdar@Sun.COM {
9967917SReza.Sabdar@Sun.COM char vol[ZFS_MAXNAMELEN];
9977917SReza.Sabdar@Sun.COM zfs_handle_t *zhp;
9987917SReza.Sabdar@Sun.COM char tbuf[64];
9997917SReza.Sabdar@Sun.COM int rv;
10007917SReza.Sabdar@Sun.COM
10017917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "[%s][%s][%d][%u]", fname,
10027917SReza.Sabdar@Sun.COM path, level, ddate);
10037917SReza.Sabdar@Sun.COM
10047917SReza.Sabdar@Sun.COM /* Check if this is a ZFS dataset */
10057917SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx);
10067917SReza.Sabdar@Sun.COM if ((zlibh != NULL) &&
10077917SReza.Sabdar@Sun.COM (get_zfsvolname(vol, sizeof (vol), path) == 0) &&
10087917SReza.Sabdar@Sun.COM ((zhp = zfs_open(zlibh, vol, ZFS_TYPE_DATASET)) != NULL)) {
10097917SReza.Sabdar@Sun.COM
10107917SReza.Sabdar@Sun.COM (void) ctime_r(&ddate, tbuf, sizeof (tbuf));
10117917SReza.Sabdar@Sun.COM rv = zfs_prop_set(zhp, zfs_dumpdate_props[level], tbuf);
10127917SReza.Sabdar@Sun.COM zfs_close(zhp);
10137917SReza.Sabdar@Sun.COM
10147917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
10157917SReza.Sabdar@Sun.COM return (rv);
10167917SReza.Sabdar@Sun.COM }
10177917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
10187917SReza.Sabdar@Sun.COM
10197917SReza.Sabdar@Sun.COM (void) mutex_lock(&ndmp_dd_lock);
10207917SReza.Sabdar@Sun.COM rv = append_dumptime(fname, path, level, ddate);
10217917SReza.Sabdar@Sun.COM (void) mutex_unlock(&ndmp_dd_lock);
10227917SReza.Sabdar@Sun.COM
10237917SReza.Sabdar@Sun.COM return (rv);
10247917SReza.Sabdar@Sun.COM }
1025