fstests: Replace all __[u]intNN_t types with standard [u]intNN_t
[xfstests-dev.git] / common / dump
1 ##/bin/bash
2 #
3 # Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.  All Rights Reserved.
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License as
7 # published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it would be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write the Free Software Foundation,
16 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 #
18 #
19 # Functions useful for xfsdump/xfsrestore tests
20 #
21
22 # --- initializations ---
23 rm -f $seqres.full
24
25 if [ -n "$DEBUGDUMP" ]; then
26         _dump_debug=-v4
27         _restore_debug=-v4
28         _invutil_debug=-d
29
30         # Use dump/restore in qa directory (copy them here) for debugging
31         export PATH="$here:$PATH"
32         export __XFSDUMP_PROG="`set_prog_path xfsdump`"
33         export XFSDUMP_PROG="$__XFSDUMP_PROG -e"
34         export XFSRESTORE_PROG="`set_prog_path xfsrestore`"
35         export XFSINVUTIL_PROG="`set_prog_path xfsinvutil`"
36         [ -x $here/xfsdump ]    && echo "Using xfstests' xfsdump for debug"
37         [ -x $here/xfsrestore ] && echo "Using xfstests' xfsrestore for debug"
38         [ -x $here/xfsinvutil ] && echo "Using xfstests' xfsinvutil for debug"
39 fi
40
41 [ "$XFSDUMP_PROG" = "" ]    && _notrun "xfsdump not found"
42 [ "$XFSRESTORE_PROG" = "" ] && _notrun "xfsrestore not found"
43 [ "$XFSINVUTIL_PROG" = "" ] && _notrun "xfsinvutil not found"
44
45 # status returned for not run tests
46 NOTRUNSTS=2
47
48 # name those directories
49 dump_file=$tmp.dumpfile
50 # dump_file=$here/dumpfile #TEMP OVERRIDE DUMP FILE
51 dump_sdir=dumpdir
52 dump_dir=$SCRATCH_MNT/$dump_sdir
53 restore_sdir=restoredir
54 restore_dir=$SCRATCH_MNT/$restore_sdir
55 multi=3
56 dumptape=$TAPE_DEV
57 media_label="stress_tape_media"
58 session_label="stress_$seq"
59
60 nobody=4 # define this uid/gid as a number
61 do_quota_check=true # do quota check if quotas enabled
62
63 # install our cleaner
64 trap "_cleanup; exit \$status" 0 1 2 3 15
65
66 # start inventory from a known base - move it aside for test
67 for dir in /var/xfsdump/inventory /var/lib/xfsdump/inventory; do
68     if [ -d $dir ]; then
69         [ -d $dir.$seq ] && rm -rf $dir.$seq
70         mv $dir $dir.$seq
71     fi
72 done
73
74 have_mtvariable=false
75 [ `uname` = "Linux" ] && have_mtvariable=true
76
77
78 _require_multi_stream()
79 {
80     $XFSDUMP_PROG -JF -f /dev/null -f /dev/null 2> /dev/null |
81     grep -q "too many -f arguments" &&
82     _notrun "xfsdump multi-stream support required"
83 }
84
85 _require_legacy_v2_format()
86 {
87     $XFSDUMP_PROG 2>&1 |
88     grep -q "generate format 2 dump" ||
89     _notrun "xfsdump -K option required"
90
91     $XFSRESTORE_PROG 2>&1 |
92     grep -q "force use of format 2 generation" ||
93     _notrun "xfsrestore -K option required"
94 }
95
96 #
97 # do a remote/local mt
98 #
99 _mt()
100 {
101     op=$1
102     if _isrmt; then
103         # REMOTE
104         _rmtdev=`echo $dumptape | $AWK_PROG -F: '{print $2}'`
105
106         if echo $dumptape | grep '@' >/dev/null; then
107             _spec=`echo $dumptape | $AWK_PROG -F: '{print $1}'`
108             _rmtuser=`echo $_spec | $AWK_PROG -F@ '{print $1}'`
109             _rmthost=`echo $_spec | $AWK_PROG -F@ '{print $2}'`
110             rsh -n -l $_rmtuser $_rmthost "mt -t $_rmtdev $op"
111         else
112             _rmthost=`echo $dumptape | $AWK_PROG -F: '{print $1}'`
113             rsh -n $_rmthost "mt -t $_rmtdev $op"
114         fi
115     else
116         #LOCAL
117         mt -t $dumptape $op
118     fi
119 }
120
121 _check_onl()
122 {
123     _limit=10
124     i=0
125     while [ $i -lt $_limit ]; do
126         echo "Checking online..." >>$seqres.full
127         if _mt status >$tmp.status 2>&1; then
128             break;
129         else
130             sleep 1
131         fi
132         let i=$i+1
133     done
134
135
136     if [ $i -eq $_limit ]; then
137         echo "ERROR: mt -f $dumptape failed"
138         cat $tmp.status
139
140         _notrun "mt -f $dumptape failed"
141     fi
142
143
144     if egrep -i 'onl|ready' $tmp.status | grep -iv 'not ready' >/dev/null; then
145         :
146     else
147         echo "ERROR: $dumptape is not online"
148         cat $tmp.status
149
150         _notrun "dumptape, $dumptape, is not online"
151     fi
152 }
153
154 _wait_tape()
155 {
156     echo "Wait for tape, $dumptape, ..." >>$seqres.full
157
158     i=0
159     while [ $i -lt 20 ]; do
160         echo "Checking status..." >>$seqres.full
161         if _mt status 2>&1 | tee -a $seqres.full | egrep -i "onl|ready" >/dev/null; then
162             break;
163         else
164             sleep 1
165         fi
166         let i=$i+1
167     done
168 }
169
170 #
171 # Keep trying so we know we really have rewound
172 #
173 _rewind()
174 {
175     echo "Initiate rewind..." >>$seqres.full
176     _wait_tape
177     _mt rewind >/dev/null
178     _wait_tape
179 }
180
181 #
182 # Do a custom erase because:
183 # (i) some machines don't support it
184 # (ii) some machines take forever to do it
185 #
186 _erase_soft()
187 {
188     echo "Erasing tape" | tee -a $seqres.full
189     _rewind
190     _mt weof 3
191     _rewind
192 }
193
194 _erase_hard()
195 {
196     echo "Erasing tape" | tee -a $seqres.full
197     _mt erase
198 }
199
200 _isrmt()
201 {
202     echo $dumptape | grep ':' >/dev/null
203 }
204
205 #
206 # Get tape ready
207 #
208 _set_variable()
209 {
210     $have_mtvariable || return
211
212     if _isrmt; then
213         :
214     else
215         # LOCAL
216         echo "Put scsi tape driver into variable block size mode"
217         mt -f $dumptape setblk 0
218     fi
219 }
220
221 _require_tape()
222 {
223     dumptape=$1
224
225     if [ -z "$dumptape" -o "@" == "$dumptape" ]; then
226         _notrun "No dump tape specified"
227     fi
228
229     _check_onl
230     _set_variable
231 }
232
233 _wipe_fs()
234 {
235     _require_scratch
236
237     _scratch_mkfs_xfs >>$seqres.full || _fail "mkfs failed"
238     _scratch_mount >>$seqres.full || _fail "mount failed"
239 }
240
241 #
242 # Cleanup created dirs and files
243 # Called by trap
244 #
245 _cleanup()
246 {
247     # Some tests include this before checking _supported_fs xfs
248     # and the sleeps & checks here get annoying
249     if [ "$FSTYP" != "xfs" ]; then
250        return
251     fi
252
253     cd $here
254     rm -f $tmp.*
255
256     if [ -n "$DEBUGDUMP" ]; then
257         # save it for inspection
258         for dir in /var/xfsdump/inventory /var/lib/xfsdump/inventory; do
259             [ -d $dir ] || continue
260             tar -cvf $seqres.inventory.tar $dir
261             ls -nR $dir >$seqres.inventory.ls
262         done
263     fi
264
265     # put inventory dir back
266     for dir in /var/xfsdump/inventory /var/lib/xfsdump/inventory; do
267         [ -d $dir.$seq ] || continue
268         rm -rf $dir             # get rid of new one
269         mv $dir.$seq $dir
270     done
271
272     if [ $status -ne $NOTRUNSTS ]; then
273         # Sleep added to stop _check_scratch_fs from complaining that the
274         # scratch_dev is still busy
275         sleep 10
276
277         _check_scratch_fs
278     fi
279 }
280
281 #
282 # ensure that bulkstat data will
283 # match with incore data
284 # by forcing disk data to be written out
285 #
286 _stable_fs()
287 {
288     _saveddir=`pwd`; cd /
289     _scratch_unmount >>$seqres.full || _fail "unmount failed"
290     _scratch_mount >>$seqres.full || _fail "mount failed"
291     cd $_saveddir
292 }
293
294 #
295 # Run fsstress to create a mixture of
296 # files,dirs,links,symlinks
297 #
298 # Pinched from test 013.
299 # Takes one argument, the number of ops to perform
300 #
301 _create_dumpdir_stress_num()
302 {
303     echo "Creating directory system to dump using fsstress."
304
305     _count=$1
306     _wipe_fs
307
308     _param="-f link=10 -f creat=10 -f mkdir=10 -f truncate=5 -f symlink=10"
309     rm -rf $dump_dir
310     if ! mkdir $dump_dir; then
311         echo "    failed to mkdir $dump_dir"
312         status=1
313         exit
314     fi
315
316     # Remove fsstress commands that aren't supported on all xfs configs so that
317     # we always execute exactly the same sequence of operations no matter how
318     # the filesystem is configured
319     if $FSSTRESS_PROG | grep -q clonerange; then
320         FSSTRESS_AVOID="-f clonerange=0 $FSSTRESS_AVOID"
321     fi
322     if $FSSTRESS_PROG | grep -q deduperange; then
323         FSSTRESS_AVOID="-f deduperange=0 $FSSTRESS_AVOID"
324     fi
325
326     echo ""
327     echo "-----------------------------------------------"
328     echo "fsstress : $_param"
329     echo "-----------------------------------------------"
330     if ! $here/ltp/fsstress $_param -s 1 $FSSTRESS_AVOID -n $_count -d $dump_dir >$tmp.out 2>&1
331     then
332         echo "    fsstress (count=$_count) returned $? - see $seqres.full"
333
334         echo "--------------------------------------"       >>$seqres.full
335         echo "output from fsstress:"                        >>$seqres.full
336         echo "--------------------------------------"       >>$seqres.full
337         cat $tmp.out                                        >>$seqres.full
338         status=1
339     fi
340
341     _stable_fs
342 }
343
344 _create_dumpdir_stress() {
345         _create_dumpdir_stress_num 240
346 }
347
348 _mk_fillconfig1()
349 {
350     cat <<End-of-File >$tmp.config
351 # pathname      size in bytes   owner   group
352 #
353 small           10      $nobody $nobody
354 big             102400  daemon  sys
355 sub/small       10      bin     bin
356 sub/big         102400  $nobody sys
357 #
358 sub/a           1       $nobody $nobody
359 sub/b           2       $nobody $nobody
360 sub/c           4       $nobody $nobody
361 sub/d           8       $nobody $nobody
362 sub/e           16      $nobody $nobody
363 sub/f           32      $nobody $nobody
364 sub/g           64      $nobody $nobody
365 sub/h           128     $nobody $nobody
366 sub/i           256     $nobody $nobody
367 sub/j           512     $nobody $nobody
368 sub/k           1024    $nobody $nobody
369 sub/l           2048    $nobody $nobody
370 sub/m           4096    $nobody $nobody
371 sub/n           8192    $nobody $nobody
372 #
373 sub/a00         100     $nobody $nobody
374 sub/b00         200     $nobody $nobody
375 sub/c00         400     $nobody $nobody
376 sub/d00         800     $nobody $nobody
377 sub/e00         1600    $nobody $nobody
378 sub/f00         3200    $nobody $nobody
379 sub/g00         6400    $nobody $nobody
380 sub/h00         12800   $nobody $nobody
381 sub/i00         25600   $nobody $nobody
382 sub/j00         51200   $nobody $nobody
383 sub/k00         102400  $nobody $nobody
384 sub/l00         204800  $nobody $nobody
385 sub/m00         409600  $nobody $nobody
386 sub/n00         819200  $nobody $nobody
387 #
388 sub/a000        1000    $nobody $nobody
389 sub/e000        16000   $nobody $nobody
390 sub/h000        128000  $nobody $nobody
391 sub/k000        1024000 $nobody $nobody
392 End-of-File
393 }
394
395 _mk_fillconfig2()
396 {
397     cat <<End-of-File >$tmp.config
398 # pathname      size in bytes
399 #
400 smalll          10      $nobody $nobody
401 biggg           102400  $nobody $nobody
402 sub/smalll      10      $nobody $nobody
403 sub/biggg       102400  $nobody $nobody
404 End-of-File
405 }
406
407 _mk_fillconfig_perm()
408 {
409     cat <<End-of-File >$tmp.config
410 # pathname      size/dir  user group mode
411 #
412 file_suid       10      $nobody $nobody 04777
413 file_guid       10      $nobody $nobody 02777
414 file_sticky     10      $nobody $nobody 01777
415 file_mix1       10      $nobody $nobody 761
416 file_mix2       10      $nobody $nobody 642
417 dir_suid        d       $nobody $nobody 04777
418 dir_guid        d       $nobody $nobody 02777
419 dir_sticky      d       $nobody $nobody 01777
420 dir_mix1        d       $nobody $nobody 761
421 dir_mix2        d       $nobody $nobody 642
422 End-of-File
423 }
424
425 _mk_fillconfig_ea()
426 {
427     cat <<End-of-File >$tmp.config
428 # pathname      size    user    group    perm   name value namespace
429 #
430 smalll          10      $nobody $nobody  777    attr1 some_text   user
431 biggg           102400  $nobody $nobody  777    attr2 some_text2  root
432 sub/smalll      10      $nobody $nobody  777    attr3 some_text3  user
433 sub/biggg       102400  $nobody $nobody  777    attr4 some_text4  root
434 dir             d       $nobody $nobody  777    attr5 dir_text    user
435 #
436 # Add more files so that there are more than the number
437 # of streams.
438 # There are bugs in dump/restore for # non-dir files < # streams
439 # It can be tested in another configuration.
440 # It is a pathalogical case.
441 #
442 sub/a           1       $nobody $nobody
443 sub/b           2       $nobody $nobody
444 sub/c           4       $nobody $nobody
445 sub/d           8       $nobody $nobody
446 sub/e           16      $nobody $nobody
447 sub/f           32      $nobody $nobody
448 sub/g           64      $nobody $nobody
449 sub/h           128     $nobody $nobody
450 sub/i           256     $nobody $nobody
451 sub/j           512     $nobody $nobody
452 sub/k           1024    $nobody $nobody
453 sub/l           2048    $nobody $nobody
454 sub/m           4096    $nobody $nobody
455 sub/n           8192    $nobody $nobody
456 End-of-File
457 }
458
459 #
460 # extended file attribute flags
461 #
462 _mk_fillconfig_xattr()
463 {
464     cat <<End-of-File >$tmp.config
465 # pathname      size    user    group    perm   name
466 #
467 xflag_realtime  10      $nobody $nobody  777    XFS_XFLAG_REALTIME
468 xflag_prealloc  10      $nobody $nobody  777    XFS_XFLAG_PREALLOC
469 xflag_immutable 10      $nobody $nobody  777    XFS_XFLAG_IMMUTABLE
470 xflag_append    10      $nobody $nobody  777    XFS_XFLAG_APPEND
471 xflag_sync      10      $nobody $nobody  777    XFS_XFLAG_SYNC
472 xflag_noatime   10      $nobody $nobody  777    XFS_XFLAG_NOATIME
473 xflag_nodump    10      $nobody $nobody  777    XFS_XFLAG_NODUMP
474 xflag_hasattr   10      $nobody $nobody  777    XFS_XFLAG_HASATTR
475 End-of-File
476 }
477
478 #
479 # Create a bunch of directories/files of different sizes
480 # filled with data.
481 #
482 # Pinched from test 001.
483 #
484 _do_create_dumpdir_fill()
485 {
486     echo "Creating directory system to dump using src/fill."
487
488     mkdir -p $dump_dir || _fail "cannot mkdir \"$dump_dir\""
489     cd $dump_dir
490
491     $verbose && echo -n "Setup "
492     sed -e '/^#/d' $tmp.config \
493     | while read file nbytes owner group perms ea_name ea_value namespace
494     do
495         if [ $nbytes = "d" ]; then
496             # create a directory
497             dir=$file
498             if [ ! -d $dir ]
499             then
500                 if mkdir $dir
501                 then
502                     :
503                 else
504                     $verbose && echo
505                     echo "Error: cannot mkdir \"$dir\""
506                     exit 1
507                 fi
508             fi
509         else
510             # create a directory/file
511             dir=`dirname $file`
512             if [ "$dir" != "." ]
513             then
514                 if [ ! -d $dir ]
515                 then
516                     if mkdir $dir
517                     then
518                         :
519                     else
520                         $verbose && echo
521                         echo "Error: cannot mkdir \"$dir\""
522                         exit 1
523                     fi
524                 fi
525             fi
526             rm -f $file
527             if $here/src/fill $file $file $nbytes
528             then
529                 :
530             else
531                 $verbose && echo
532                 echo "Error: cannot create \"$file\""
533                 exit 1
534             fi
535         fi
536         if [ -n "$owner" -a -n "$group" ]; then
537             chown $owner.$group $file
538         fi
539         if [ -n "$perms" ]; then
540             chmod $perms $file
541         fi
542
543         # extended attributes (EA)
544         if [ -n "$ea_name" -a -n "$ea_value" ]; then
545             if [ "X$namespace" = "Xroot" ]; then
546                 attr -R -s $ea_name -V $ea_value $file
547             else
548                 attr -s $ea_name -V $ea_value $file
549             fi
550         # extended file attribute flags - no value - NOT EAs
551         elif [ -n "$ea_name" -a -z "$ea_value" ]; then
552             # set the flag
553             # TODO XXX
554             # use xfs_io to send the ioctl
555             :
556         fi
557         $verbose && echo -n "."
558     done
559     $verbose && echo
560
561     cd $here
562 }
563
564 _mk_fillconfig_multi()
565 {
566     _mk_fillconfig1
567     cat <<End-of-File >>$tmp.config
568 # pathname      size in bytes
569 #
570 large000        8874368 $nobody $nobody
571 large111        2582912 $nobody $nobody
572 large222        7825792 $nobody $nobody
573 End-of-File
574 }
575
576 _create_dumpdir_largefile()
577 {
578     _wipe_fs
579     mkdir -p $dump_dir || _fail "cannot mkdir \"$dump_dir\""
580     _largesize=4294967297
581     _largefile=$dump_dir/largefile
582     echo "dd a largefile at offset $_largesize"
583     POSIXLY_CORRECT=yes \
584     dd if=/dev/zero of=$_largefile bs=1 seek=$_largesize count=10 2>&1
585     _stable_fs
586 }
587
588 _create_dumpdir_fill()
589 {
590     _wipe_fs
591     _mk_fillconfig1
592     _do_create_dumpdir_fill
593     _stable_fs
594 }
595
596 _create_dumpdir_fill2()
597 {
598     _wipe_fs
599     _mk_fillconfig2
600     _do_create_dumpdir_fill
601     _stable_fs
602 }
603
604 _create_dumpdir_fill_perm()
605 {
606     _wipe_fs
607     _mk_fillconfig_perm
608     _do_create_dumpdir_fill
609     _stable_fs
610 }
611
612 _create_dumpdir_fill_ea()
613 {
614     _wipe_fs
615     _mk_fillconfig_ea
616     _do_create_dumpdir_fill
617     _stable_fs
618 }
619
620 #
621 # Create enough files, and a few large enough files, so that
622 # some files are likely to be split across streams.
623 #
624 _create_dumpdir_fill_multi()
625 {
626     _wipe_fs
627     _mk_fillconfig_multi
628     _do_create_dumpdir_fill
629     _stable_fs
630 }
631
632 #
633 # Append a subset of the fill'ed files
634 # So we can see if just these get dumped on an incremental
635 #
636 _append_dumpdir_fill()
637 {
638     cd $dump_dir
639     cat <<End-of-File >$tmp.config
640 # pathname
641 #
642 small
643 sub/big
644 #
645 sub/a
646 sub/c
647 sub/e
648 End-of-File
649     sed -e '/^#/d' $tmp.config \
650     | while read file
651     do
652         echo 'Extra text' >>$file
653     done
654
655     cd $here
656     _stable_fs
657 }
658
659 _do_create_dump_symlinks()
660 {
661     echo "Creating directory system of symlinks to dump."
662
663     mkdir -p $dump_dir || _fail "cannot mkdir \"$dump_dir\""
664     cd $dump_dir
665
666     $verbose && echo -n "Setup "
667     sed -e '/^#/d' $tmp.config \
668     | while read file nbytes owner group owner2 group2 perms perms2
669     do
670         dir=`dirname $file`
671         if [ "$dir" != "." ]
672         then
673             if [ ! -d $dir ]
674             then
675                 if mkdir $dir
676                 then
677                     :
678                 else
679                     $verbose && echo
680                     echo "Error: cannot mkdir \"$dir\""
681                     exit 1
682                 fi
683             fi
684         fi
685         rm -f $file
686         touch $file
687
688         # Do chmod on symlink using umask.
689         # This won't do the right thing as it subtracts permissions.
690         # However, I don't care, as long as I get some different perms
691         # for testing.
692         if [ -n "$perms2" ]; then
693             omask=`umask`
694             umask $perms2
695         fi
696         ln -s $file $file-link
697         if [ -n "$perms2" ]; then
698             umask $omask
699         fi
700
701         if [ -n "$owner" -a -n "$group" ]; then
702             chown $owner.$group $file
703         fi
704         if [ -n "$owner" -a -n "$group" ]; then
705             chown -h $owner.$group $file-link
706         fi
707         if [ -n "$perms" ]; then
708             chmod $perms $file
709         fi
710         $verbose && echo -n "."
711     done
712     $verbose && echo
713
714     cd $here
715 }
716
717 _mk_symlink_config()
718 {
719     cat <<End-of-File >$tmp.config
720 # path  size    owner1  group1  owner2  group2  perm1   perm2
721 #
722 a       0       $nobody $nobody daemon  sys     124     421
723 b       0       daemon  sys     bin     bin     347     743
724 sub/a   0       bin     bin     $nobody sys     777     777
725 sub/b   0       $nobody sys     $nobody $nobody 367     763
726 End-of-File
727 }
728
729 _create_dumpdir_symlinks()
730 {
731     _wipe_fs
732     _mk_symlink_config
733     _do_create_dump_symlinks
734     _stable_fs
735 }
736
737 #
738 # create hardlinks of form $_fname, $_fname_h1 $_fname_h2 ...
739 #
740 _create_hardlinks()
741 {
742     _fname=$1
743     _numlinks=$2
744
745     touch $_fname
746     _j=1
747     while [ $_j -le $_numlinks ]; do
748         _suffix=_h$_j
749         _hardlink=$_fname$_suffix
750         echo "creating hardlink $_hardlink to $_fname"
751         ln $_fname $_hardlink
752         let _j=$_j+1
753     done
754 }
755
756 #
757 # create a set of hardlinks
758 # create hardlinks of form file1, file1_h1 file1_h2 ...
759 # create hardlinks of form file2, file2_h1 file2_h2 ...
760 # create hardlinks of form file3, file3_h1 file3_h2 ...
761 #
762 _create_hardset()
763 {
764     _numsets=$1
765     _i=1
766     while [ $_i -le $_numsets ]; do
767         _create_hardlinks file$_i 5
768         let _i=$_i+1
769     done
770 }
771
772
773 _modify_level()
774 {
775     _level=$1
776     echo "mod level $_level" >$dump_dir/file$_level
777 }
778
779 _create_dumpdir_hardlinks()
780 {
781     _numsets=$1
782     _wipe_fs
783     echo "Creating directory system of hardlinks to incrementally dump."
784
785     mkdir -p $dump_dir || _fail "cannot mkdir \"$dump_dir\""
786     cd $dump_dir
787
788     _create_hardset $_numsets
789
790     cd $here
791     _stable_fs
792 }
793
794 #
795 # Filter for ls
796 # Filter out times and dates on symlinks and char devices.
797 # Filter out size on directories because this can differ
798 # when transitioning to long inode numbers (ie. 64 bits).
799 #
800 _ls_filter()
801 {
802   $AWK_PROG '
803         /^l/ { date = $8; time = $7; sub(date,"DATE"); sub(time,"TIME"); print}
804         /^c/ { date = $9; time = $7; sub(date,"DATE"); sub(time,"TIME"); print}
805         /^d/ { size = $5; sub(size,"SIZE"); print}
806         {print}' \
807   | sed -e 's/total [0-9][0-9]*/total TOTAL/'
808 }
809
810 #
811 # Filtering of Irix character hwgraph device names
812 # e.g.
813 # chardev: /hw/node/xtalk/15/pci/0/scsi_ctlr/0/target/1/lun/0/disk/partition/4/char
814 # blkdev:  /dev/dsk/dks0d1s4
815 #
816 _filter_devchar()
817 {
818     $AWK_PROG '
819         /\/hw\/node/ {
820             sub(/\/hw.*scsi_ctlr\//,"/dev/dsk/dks")  # blah blah /dev/dsk/dks0/target/1/....
821             sub(/\/target\//,"d")                    # blah blah /dev/dsk/dks0d1/lun/0/disk.....
822             sub(/\/lun.*partition\//,"s")            # blah blah /dev/dsk/dks0d1s4/char
823             sub(/\/char/,"")                         # blah blah /dev/dsk/dks0d1s4
824         }
825         { print }
826     '
827 }
828
829
830 #
831 # Filter out the non-deterministic dump msgs from
832 # xfsdump and xfsrestore
833 #
834 _dump_filter_main()
835 {
836   _filter_devchar |\
837   sed \
838       -e "s#$__XFSDUMP_PROG#xfsdump#"                   \
839       -e "s#$XFSRESTORE_PROG#xfsrestore#"               \
840       -e "s#$XFSINVUTIL_PROG#xfsinvutil#"               \
841       -e "s/`hostname`/HOSTNAME/"                       \
842       -e "s#$SCRATCH_DEV#SCRATCH_DEV#"                  \
843       -e "s#$SCRATCH_RAWDEV#SCRATCH_DEV#"               \
844       -e "s#$dumptape#TAPE_DEV#"                        \
845       -e "s#$SCRATCH_MNT#SCRATCH_MNT#"                  \
846       -e "s#$dump_file#DUMP_FILE#"                      \
847       -e 's#/var/lib/xfsdump#/var/xfsdump#'             \
848       -e 's/session id:[        ]*[0-9a-f-]*/session id: ID/'  \
849       -e '/filesystem id:[      ]*[0-9a-f-]*/d'         \
850       -e 's/time:[      ].*/time: TIME/'                \
851       -e 's/date:[      ].*/date: DATE/'                \
852       -e 's/dump begun .*/dump begun DATE/'             \
853       -e 's/previously begun .*/previously begun DATE/' \
854       -e 's/[0-9][0-9]* seconds/SECS seconds/'          \
855       -e 's/restore.[0-9][0-9]*/restore.PID/'           \
856       -e 's/ino [0-9][0-9]*/ino INO/g'                  \
857       -e '/stream [0-9]:/s/offset [0-9][0-9]*/offset NUM/g'     \
858       -e '/: dump size/s/[0-9][0-9]*/NUM/'              \
859       -e '/dump size:/s/[0-9][0-9]*/NUM/'               \
860       -e '/dump size per stream:/s/[0-9][0-9]*/NUM/'    \
861       -e 's/\(media file size[   ]*\)[0-9][0-9]*/\1NUM/' \
862       -e 's/\(mfile size:[       ]*\)[0-9][0-9]*/\1NUM/' \
863       -e '/drive[        ]*[0-9][0-9]*:/d'              \
864       -e '/\/dev\/tty/d'                                \
865       -e '/inventory session uuid/d'                    \
866       -e '/ - Running single-threaded/d'                \
867       -e '/Mount point match/d'                         \
868       -e '/^.*I\/O metrics: .*$/d'                      \
869       -e 's/1048576/BLOCKSZ/'                           \
870       -e 's/2097152/BLOCKSZ/'                           \
871       -e 's/(pid[        ]*[1-9][0-9]*)/\(pid PID\)/'   \
872       -e '/version [3-9]\.[0-9]/d'                      \
873       -e 's/\/hw\/module.*$/SCRATCH_DEV/'               \
874       -e 's/xfsdump: ino map phase 1: .*/xfsdump: ino map <PHASES>/' \
875       -e '/xfsdump: ino map phase [2]/,1d'              \
876       -e '/xfsdump: ino map phase [3]/,1d'              \
877       -e '/xfsdump: ino map phase [4]/,1d'              \
878       -e '/xfsdump: ino map phase [5]/,1d'              \
879       -e 's/id:[[:space:]]*[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}/ID: ID/'                                              \
880       -e 's/\[y\/n\][- ]----------------------*/\[y\/n\]/'              \
881       -e '/skip attribute set/d'                                \
882   | perl -ne '
883         # filter out all the output between the lines "Dump Summary:"
884         # and "Dump Status:"
885         if ($_ =~ /(?:Dump|Restore) Summary/) {
886                 $skip = 1;
887         } elsif ($_ =~ /(?:Dump|Restore) Status/) {
888                 $skip = 0;
889         }
890         print if (! $skip);' \
891   | perl -ne '
892         # correct the file count if large scratch devices are being used
893         $skip = 0;
894         if ($_ =~ /(\S+) directories and (\S+) entries/) {
895                 $foo = $2;
896                 if ($ENV{'LARGE_SCRATCH_DEV'} && $foo > 0) {
897                         $foo -= 1;
898                 }
899                 printf("xfsrestore: %u directories and %u entries processed\n",
900                                                 $1, $foo);
901                 $skip = 1;
902         }
903         print if (! $skip);'
904 }
905
906 _dump_filter()
907 {
908    if $do_quota_check
909    then
910        _dump_filter_main | _check_quota_dumprestore | _check_quota_entries
911    else
912        _dump_filter_main
913    fi
914 }
915
916 _invutil_filter()
917 {
918   _dump_filter_main \
919   | sed \
920         -e 's/UUID[     ]*:[    ][0-9a-f-]*/UUID                :       ID/' \
921         -e 's/TIME OF DUMP[     ]*:.*/TIME OF DUMP      :       TIME/' \
922         -e 's/HOSTNAME:SCRATCH_MNT.*/HOSTNAME:SCRATCH_MNT/' \
923         -e 's#inventory/[0-9a-f-]*#inventory/UUID#' \
924
925 }
926
927
928 _dir_filter()
929 {
930   sed \
931     -e "s#$dump_file#DUMP_FILE#g"      \
932     -e "s#$SCRATCH_DEV#SCRATCH_DEV#"        \
933     -e "s#$SCRATCH_RAWDEV#SCRATCH_DEV#"    \
934     -e "s#$dumptape#TAPE_DEV#"         \
935     -e "s#$dump_dir#DUMP_DIR#g"       \
936     -e "s#$restore_dir#RESTORE_DIR#g" \
937     -e "s#$SCRATCH_MNT#SCRATCH_MNT#g"       \
938     -e "s#$dump_sdir#DUMP_SUBDIR#g"   \
939     -e "s#$restore_sdir#RESTORE_SUBDIR#g" \
940     -e "s#$$#PID#g" \
941     -e "/Only in SCRATCH_MNT: .use_space/d" \
942     -e "s#$RESULT_DIR/##g" \
943
944 }
945
946 #
947 # Parse xfsdump arguments.
948 # Note: requires a space between option letter and argument
949 #
950 _parse_dump_args()
951 {
952     OPTIND=0
953     dump_args=""
954     while [ $# -gt 0 ]
955     do
956         case $1
957         in
958         -f)
959             [ -z "$2" ] && _fail "missing argument for -f"
960             dumptape=$2
961             dump_file=$2
962             shift
963             ;;
964         -L)
965             [ -z "$2" ] && _fail "missing argument for -L"
966             session_label=$2
967             shift
968             ;;
969         --multi)
970             [ -z "$2" ] && _fail "missing argument for --multi"
971             multi=$2
972             shift
973             ;;
974         --check-quota)
975             do_quota_check=true
976             ;;
977         --no-check-quota)
978             do_quota_check=false
979             ;;
980         -o|-D|-F|-K)
981             dump_args="$dump_args $1"
982             ;;
983         -l|-d)
984             [ -z "$2" ] && _fail "missing argument for $1"
985             dump_args="$dump_args $1$2"
986             shift
987             ;;
988         *)
989             _fail "invalid argument to common/dump function: $1"
990             ;;
991         esac
992         shift
993     done
994 }
995
996 #
997 # Parse xfsrestore arguments.
998 # Note: requires a space between option letter and argument
999 #
1000 _parse_restore_args()
1001 {
1002     OPTIND=0
1003     restore_args=""
1004     while [ $# -gt 0 ]
1005     do
1006         case $1
1007         in
1008         -f)
1009             [ -z "$2" ] && _fail "missing argument for -f"
1010             dumptape=$2
1011             dump_file=$2
1012             shift
1013             ;;
1014         -L)
1015             [ -z "$2" ] && _fail "missing argument for -L"
1016             session_label=$2
1017             shift
1018             ;;
1019         --multi)
1020             [ -z "$2" ] && _fail "missing argument for --multi"
1021             multi=$2
1022             shift
1023             ;;
1024         --check-quota)
1025             do_quota_check=true
1026             ;;
1027         --no-check-quota)
1028             do_quota_check=false
1029             ;;
1030         -K|-R)
1031             restore_args="$restore_args $1"
1032             ;;
1033         *)
1034             _fail "invalid argument to common/dump function: $1"
1035             ;;
1036         esac
1037         shift
1038     done
1039 }
1040
1041
1042 #
1043 # Dump a subdir
1044 #
1045 _do_dump_sub()
1046 {
1047     _parse_dump_args $*
1048
1049     echo "Dumping to tape..."
1050     opts="$_dump_debug$dump_args -s $dump_sdir -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
1051     echo "xfsdump $opts" | _dir_filter
1052     $XFSDUMP_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1053 }
1054
1055 #
1056 # Do dump to tape
1057 #
1058 _do_dump()
1059 {
1060     _parse_dump_args $*
1061
1062     echo "Dumping to tape..."
1063     opts="$_dump_debug$dump_args -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
1064     echo "xfsdump $opts" | _dir_filter
1065     $XFSDUMP_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1066 }
1067
1068
1069 #
1070 # Do full dump with -m
1071 #
1072 _do_dump_min()
1073 {
1074     _parse_dump_args $*
1075
1076     echo "Dumping to tape..."
1077     onemeg=1048576
1078     opts="$_dump_debug$dump_args -m -b $onemeg -l0 -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
1079     echo "xfsdump $opts" | _dir_filter
1080     $XFSDUMP_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1081 }
1082
1083
1084 #
1085 # Do full dump to file
1086 #
1087 _do_dump_file()
1088 {
1089     _parse_dump_args $*
1090
1091     echo "Dumping to file..."
1092     opts="$_dump_debug$dump_args -f $dump_file -M $media_label -L $session_label $SCRATCH_MNT"
1093     echo "xfsdump $opts" | _dir_filter
1094     $XFSDUMP_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1095 }
1096
1097 #
1098 # Do full dump to multiple files
1099 #
1100 _do_dump_multi_file()
1101 {
1102     _parse_dump_args $*
1103
1104     multi_args=""
1105
1106     i=0
1107     while [ $i -lt $multi ]
1108     do
1109         multi_args="$multi_args -f $dump_file.$i -M $media_label.$i"
1110         let i=$i+1
1111     done
1112
1113     echo "Dumping to files..."
1114     opts="$_dump_debug$dump_args $multi_args -L $session_label $SCRATCH_MNT"
1115     echo "xfsdump $opts" | _dir_filter
1116     $XFSDUMP_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1117 }
1118
1119
1120 _prepare_restore_dir()
1121 {
1122     rm -rf $restore_dir
1123     mkdir $restore_dir || _fail "failed to mkdir $restore_dir"
1124 }
1125
1126
1127 #
1128 # Get tape ready and restore dir
1129 #
1130 _prepare_restore()
1131 {
1132     _prepare_restore_dir
1133
1134     echo "Rewinding tape"
1135     _rewind
1136 }
1137
1138 #
1139 # Restore the tape into $restore_dir
1140 #
1141 _do_restore()
1142 {
1143     _parse_restore_args $*
1144     _prepare_restore
1145
1146     echo "Restoring from tape..."
1147     opts="$_restore_debug$restore_args -f $dumptape  -L $session_label $restore_dir"
1148     echo "xfsrestore $opts" | _dir_filter
1149     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1150 }
1151
1152 #
1153 # Restore the tape into $restore_dir using -m
1154 #
1155 _do_restore_min()
1156 {
1157     _parse_restore_args $*
1158     _prepare_restore
1159
1160     echo "Restoring from tape..."
1161     onemeg=1048576
1162     opts="$_restore_debug$restore_args -m -b $onemeg -f $dumptape  -L $session_label $restore_dir"
1163     echo "xfsrestore $opts" | _dir_filter
1164     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1165 }
1166
1167 #
1168 # Restore the tape from a dump file
1169 #
1170 _do_restore_file()
1171 {
1172     _parse_restore_args $*
1173     _prepare_restore_dir
1174
1175     echo "Restoring from file..."
1176     opts="$_restore_debug$restore_args -f $dump_file  -L $session_label $restore_dir"
1177     echo "xfsrestore $opts" | _dir_filter
1178     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1179 }
1180
1181 #
1182 # Cumulative restore from a file
1183 # Must call _prepare_restore_dir before the first
1184 # (and only the first) call to this function.
1185 #
1186 _do_restore_file_cum()
1187 {
1188     _parse_restore_args $*
1189
1190     echo "Restoring cumumlative from file..."
1191     opts="$_restore_debug$restore_args -f $dump_file -r $restore_dir"
1192     echo "xfsrestore $opts" | _dir_filter
1193     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1194 }
1195
1196 _do_restore_toc()
1197 {
1198     _parse_restore_args $*
1199
1200     echo "Contents of dump ..."
1201     opts="$_restore_debug$restore_args -f $dump_file -t"
1202     echo "xfsrestore $opts" | _dir_filter
1203     cd $SCRATCH_MNT
1204     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter_main |\
1205     _check_quota_file |\
1206     _check_quota_entries |\
1207     $AWK_PROG 'NF != 1 { print; next }
1208                {files = sprintf("%s\n%s", files, $1)}
1209                 END { print files | "sort" } '
1210     # the above awk code is to alpha sort only the output
1211     # of files (and not the verbose restore msgs)
1212     cd $here # put back
1213 }
1214
1215 #
1216 # Restore the tape from multiple dump files
1217 #
1218 _do_restore_multi_file()
1219 {
1220     _parse_restore_args $*
1221     _prepare_restore_dir
1222
1223     multi_args=""
1224
1225     i=0
1226     while [ $i -lt $multi ]
1227     do
1228         multi_args="$multi_args -f $dump_file.$i"
1229         let i=$i+1
1230     done
1231
1232     echo "Restoring from file..."
1233     opts="$_restore_debug$restore_args $multi_args -L $session_label $restore_dir"
1234     echo "xfsrestore $opts" | _dir_filter
1235     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1236 }
1237
1238 #
1239 # Do xfsdump piped into xfsrestore - xfsdump | xfsrestore
1240 # Pass dump options in $1 and restore options in $2, if required. e.g.:
1241 #     _do_dump_restore "-o -F" "-R"
1242 #     _do_dump_restore "" "-R"
1243 #
1244 # Use -s as we want to dump and restore to the same xfs partition
1245 #
1246 _do_dump_restore()
1247 {
1248     _parse_dump_args $1
1249     _parse_restore_args $2
1250     _prepare_restore_dir
1251     echo "xfsdump|xfsrestore ..."
1252     restore_opts="$_restore_debug$restore_args - $restore_dir"
1253     dump_opts="$_dump_debug$dump_args -s $dump_sdir - $SCRATCH_MNT"
1254     echo "xfsdump $dump_opts | xfsrestore $restore_opts" | _dir_filter
1255     $XFSDUMP_PROG $dump_opts 2>$tmp.dump.mlog | $XFSRESTORE_PROG $restore_opts 2>&1 | tee -a $seqres.full | _dump_filter
1256     _dump_filter <$tmp.dump.mlog
1257 }
1258
1259 #
1260 # Compare dumped subdirectory with restored dir
1261 # using ls -nR.
1262 # Thus no contents are compared but permissions, sizes,
1263 # owners, etc... are.
1264 #
1265 _ls_compare_sub()
1266 {
1267     #
1268     # verify we got back what we dumped
1269     #
1270     echo "Comparing listing of dump directory with restore directory"
1271     ls -nR $dump_dir | tee -a $seqres.full | _ls_filter >$tmp.dump_dir
1272     ls -nR $restore_dir/$dump_sdir | tee -a $seqres.full | _ls_filter \
1273     | sed -e "s#$restore_sdir\/##" >$tmp.restore_dir
1274
1275     diff -bcs $tmp.dump_dir $tmp.restore_dir | sed -e "s#$tmp#TMP#g"
1276 }
1277
1278 #
1279 # filter out the date fields
1280 #
1281 _ls_nodate_filter()
1282 {
1283     $AWK_PROG 'NF == 9 { print $1, $2, $3, $4, $9 }'
1284 }
1285
1286 #
1287 # _ls_compare_sub but don't compare dates
1288 _ls_nodate_compare_sub()
1289 {
1290     #
1291     # verify we got back what we dumped
1292     #
1293     echo "Comparing listing of dump directory with restore directory"
1294     ls -nR $dump_dir | tee -a $seqres.full | _ls_filter | _ls_nodate_filter >$tmp.dump_dir
1295     ls -nR $restore_dir/$dump_sdir | tee -a $seqres.full | _ls_filter \
1296     | _ls_nodate_filter | sed -e "s#$restore_sdir\/##" >$tmp.restore_dir
1297
1298     diff -bcs $tmp.dump_dir $tmp.restore_dir | sed -e "s#$tmp#TMP#g"
1299 }
1300
1301 #
1302 # Compare using recursive diff the files of the dumped
1303 # subdirectory.
1304 # This one will compare the contents.
1305 #
1306 _diff_compare_sub()
1307 {
1308     echo "Comparing dump directory with restore directory"
1309     diff -rs $dump_dir $restore_dir/$dump_sdir | _dir_filter
1310 }
1311
1312 _get_eas_on_path()
1313 {
1314     _path=$1
1315
1316 # Tim - this is the IRIX way...
1317     # find $_path -exec attr -l {} \; |\
1318     # awk '{print $9, $2}' |\
1319     # sed 's/["]//g' |\
1320     # sort |\
1321 # and this is now the Linux way...
1322     echo "User names"
1323     getfattr --absolute-names -Rh -m user $_path |\
1324     perl -wn -e '
1325         if (m/^# file: (\S+)/) { $file = $1 }
1326         elsif (m/^user\.(\w+)/) { print $file, " ",$1,"\n" }' |\
1327     sort |\
1328     while read file ea_name; do
1329         attr -g $ea_name $file
1330     done
1331
1332     if [ "$USE_ATTR_SECURE" = yes ]; then
1333         echo "Security names"
1334         getfattr --absolute-names -Rh -m security $_path |\
1335         perl -wn -e '
1336             if (m/^# file: (\S+)/) { $file = $1 }
1337             elsif (m/^security\.(\w+)/) { print $file, " ",$1,"\n" }' |\
1338         sort |\
1339         while read file ea_name; do
1340             attr -g $ea_name $file
1341         done
1342     fi
1343
1344     echo "Root names"
1345     getfattr --absolute-names -Rh -m trusted $_path |\
1346     perl -wn -e '
1347         if (m/^# file: (\S+)/) { $file = $1 }
1348         elsif (m/^trusted\.(\w+)/) { print $file, " ",$1,"\n" }' |\
1349     sort |\
1350     while read file ea_name; do
1351         attr -R -g $ea_name $file
1352     done
1353 }
1354
1355 #
1356 # Compare the extended attributes of the files/dirs
1357 # b/w the dumped and restore dirs.
1358 #
1359 #
1360 # Attribute "attr5" had a 8 byte value for /spare1/dump.5460/dir:
1361 # Attribute "attr5" had a 8 byte value for /spare1/restore.5460/dump.5460/dir:
1362 #
1363 _diff_compare_eas()
1364 {
1365     echo "Comparing dump directory with restore directory"
1366     echo "Looking at the extended attributes (EAs)"
1367     echo "EAs on dump"
1368     _get_eas_on_path $dump_dir | tee $seqres.ea1 | _dir_filter
1369     echo "EAs on restore"
1370     _get_eas_on_path $restore_dir/$dump_sdir \
1371     | sed -e "s#$restore_sdir\/##" \
1372     | tee $seqres.ea2 \
1373     | _dir_filter
1374     diff -s $seqres.ea1 $seqres.ea2 | _dir_filter
1375 }
1376
1377
1378 #
1379 # Compare using recursive diff the files of the dumped
1380 # filesystem
1381 #
1382 _diff_compare()
1383 {
1384     echo "Comparing dump directory with restore directory"
1385     diff -rs $SCRATCH_MNT $restore_dir | _dir_filter | _check_quota_diff
1386 }
1387
1388 #
1389 # Check out the dump inventory
1390 #
1391 _dump_inventory()
1392 {
1393     $XFSDUMP_PROG $_dump_debug -I | tee -a $seqres.full | _dump_filter_main
1394 }
1395
1396 #
1397 # Do the xfsinvutil cmd with debug and filters
1398 # Need to set variable: "$middate" to the invutil date
1399 #
1400 _do_invutil()
1401 {
1402     host=`hostname`
1403     echo "xfsinvutil $_invutil_debug -M $host:$SCRATCH_MNT \"$middate\" $*" >$seqres.full
1404     $XFSINVUTIL_PROG $_invutil_debug $* -M $host:$SCRATCH_MNT "$middate" \
1405     | tee -a $seqres.full | _invutil_filter
1406 }
1407
1408 #
1409 # ensure we can find the user quota msg if user quotas are on
1410 # ensure we can find the group quota msg if group quotas are on
1411 #
1412 _check_quota()
1413 {
1414     usermsg=$1
1415     groupmsg=$2
1416     projectmsg=$3
1417     uquota=0
1418     gquota=0
1419     pquota=0
1420     $here/src/feature -U $SCRATCH_DEV && uquota=1
1421     $here/src/feature -G $SCRATCH_DEV && gquota=1
1422     $here/src/feature -P $SCRATCH_DEV && pquota=1
1423
1424     $AWK_PROG -v uquota=$uquota -v gquota=$gquota -v pquota=$pquota \
1425               -v full=$seqres.full -v usermsg="$usermsg" \
1426               -v groupmsg="$groupmsg" -v projectmsg="$projectmsg" '
1427         $0 ~ projectmsg {
1428                         print "Found project quota:", $0 >>full
1429                         found_pquota = 1
1430                         if (!pquota) {
1431                             print "Found extra:", $0
1432                         }
1433                         next
1434         }
1435         $0 ~ groupmsg {
1436                         print "Found group quota:", $0 >>full
1437                         found_gquota = 1
1438                         if (!gquota) {
1439                             print "Found extra:", $0
1440                         }
1441                         next
1442         }
1443         $0 ~ usermsg {
1444                         print "Found user quota:", $0 >>full
1445                         found_uquota = 1
1446                         if (!uquota) {
1447                             print "Found extra:", $0
1448                         }
1449                         next
1450         }
1451                         { print }
1452         END {
1453                 if (uquota && !found_uquota) {
1454                     print "Missing user quota msg:", usermsg
1455                 }
1456                 if (gquota && !found_gquota) {
1457                     print "Missing group quota msg:", groupmsg
1458                 }
1459                 if (pquota && !found_pquota) {
1460                     print "Missing project quota msg:", projectmsg
1461                 }
1462         }
1463     '
1464 }
1465
1466 #
1467 # xfsrestore: 3 directories and 40 entries processed
1468 #   $5 = 40
1469 #   num entries needs to be reduced by num quota file(s)
1470 #
1471 _check_quota_entries()
1472 {
1473     uquota=0
1474     gquota=0
1475     pquota=0
1476     $here/src/feature -U $SCRATCH_DEV && uquota=1
1477     $here/src/feature -G $SCRATCH_DEV && gquota=1
1478     $here/src/feature -P $SCRATCH_DEV && pquota=1
1479     $AWK_PROG -v uquota=$uquota -v gquota=$gquota -v pquota=$pquota '
1480         /entries processed/ {
1481                 if (uquota) $5--
1482                 if (gquota) $5--
1483                 if (pquota) $5--
1484         }
1485         {print}'
1486 }
1487
1488 #
1489 # Look for:
1490 # xfsdump: saving user quota information for: SCRATCH_MNT
1491 # xfsdump: saving group quota information for: SCRATCH_MNT
1492 # xfsdump: saving project quota information for: SCRATCH_MNT
1493 # xfsrestore: user quota information written to ...'
1494 # xfsrestore: group quota information written to ...'
1495 # xfsrestore: project quota information written to ...'
1496 # xfsrestore: use 'xfs_quota' to restore quotas
1497 #
1498 _check_quota_dumprestore()
1499 {
1500         _check_quota 'user quota information' \
1501                      'group quota information' \
1502                      'project quota information' | \
1503                 sed "/xfsrestore:.*use 'xfs_quota' to restore quotas/d"
1504 }
1505
1506 #
1507 # Look for:
1508 # Only in RESTORE_DIR: xfsdump_quotas
1509 # Only in RESTORE_DIR: xfsdump_quotas_group
1510 # Only in RESTORE_DIR: xfsdump_quotas_project
1511 #
1512 _check_quota_diff()
1513 {
1514    _check_quota 'Only in RESTORE_DIR: xfsdump_quotas' \
1515         'Only in RESTORE_DIR: xfsdump_quotas_group' \
1516         'Only in RESTORE_DIR: xfsdump_quotas_proj'
1517 }
1518
1519 #
1520 # Look for the quota file in the output
1521 # Ensure that it is there if it should be
1522 # Filter it out so that the output is always the same
1523 # even with no quotas
1524 #
1525 _check_quota_file()
1526 {
1527    _check_quota 'xfsdump_quotas' 'xfsdump_quotas_group' 'xfsdump_quotas_proj'
1528 }
1529
1530
1531 # make sure this script returns success
1532 /bin/true