1#!/usr/local/bin/perl
2# backup.pl
3# Called by cron to backup a database, or all databases
4
5$no_acl_check++;
6require './mysql-lib.pl';
7
8if ($ARGV[0] eq "--all") {
9	$all = 1;
10	$cmode = $config{'backup_cmode_'};
11	}
12else {
13	$ARGV[0] || die "Missing database parameter";
14	$cmode = 0;
15	}
16$extra_prefix = "";
17if ($ARGV[1] eq "--prefix") {
18	$extra_prefix = $ARGV[2];
19	}
20
21$email = $config{'backup_email_'.($all ? '' : $ARGV[0])};
22$notify = $config{'backup_notify_'.($all ? '' : $ARGV[0])};
23
24# Check if MySQL is running
25$ex = 0;
26($r, $out) = &is_mysql_running();
27if ($r != 1) {
28	$failure = "MySQL does not appear to be running : $out\n".
29		   "Backups cannot be performed.\n";
30	$ex = 1;
31	goto EMAIL;
32	}
33
34# Get DBs
35if ($all) {
36	@dbs = grep { &supports_backup_db($_) } &list_databases();
37	}
38else {
39	@dbs = ( $ARGV[0] );
40	}
41
42if ($cmode) {
43	# Run and check before-backup command (for all DBs)
44	$bok = &execute_before(undef, STDOUT, 0, $config{'backup_'}, undef);
45	if (!$bok) {
46		$failure = "Before-backup command failed!\n";
47		$ex = 1;
48		goto EMAIL;
49		}
50	}
51
52foreach $db (@dbs) {
53	$sf = $all ? "" : $db;
54	if ($all) {
55		$dir = &date_subs($config{'backup_'});
56		$prefix = &date_subs($config{'backup_prefix_'});
57		&make_dir($dir, 0755) if ($config{'backup_mkdir_'});
58		$file = $dir."/".$extra_prefix.$prefix.$db.".sql".
59			($config{'backup_compress_'.$sf} == 1 ? ".gz" :
60			 $config{'backup_compress_'.$sf} == 2 ? ".bz2" : "");
61		}
62	else {
63		$file = &date_subs($config{'backup_'.$db});
64		}
65	if (!$file) {
66		push(@status, [ $db, $file, "No backup file set for $db" ]);
67		$ex = 1;
68		next;
69		}
70	@compat = $config{'backup_compatible_'.$sf} ?
71			( $config{'backup_compatible_'.$sf} ) : ( );
72	push(@compat, split(/\0/, $in{'backup_options_'.$sf}));
73	@tables = split(/\s+/, $config{'backup_tables_'.$sf});
74
75	if (!$cmode) {
76		# Run and check before-backup command (for one DB)
77		$temp = &transname();
78		&open_tempfile(TEMP, ">$temp");
79		$bok = &execute_before($db, TEMP, 0, $file, $all ? undef : $db);
80		&close_tempfile(TEMP);
81		$err = &read_file_contents($temp);
82		&unlink_file($temp);
83		if (!$bok) {
84			push(@status, [ $db, $file, "Before-backup command failed : $err" ]);
85			$ex = 1;
86			next;
87			}
88		}
89
90	# Do the backup
91	$err = &backup_database($db, $file,
92				$config{'backup_compress_'.$sf},
93				$config{'backup_drop_'.$sf},
94				$config{'backup_where_'.$sf},
95				$config{'backup_charset_'.$sf},
96				\@compat,
97				\@tables,
98				"root",
99				$config{'backup_single_'.$sf},
100				$config{'backup_quick_'.$sf},
101				undef,
102				$config{'backup_parameters_'.$sf}
103			       );
104	if ($err) {
105		$ex = 1;
106		}
107	@st = stat($file);
108	push(@status, [ $db, $file, $err, $st[7] ]);
109	if (!$cmode) {
110		&execute_after($db, undef, 0, $file, $all ? undef : $db);
111		}
112	}
113if ($cmode) {
114	&execute_after(undef, undef, 0, $config{'backup_'}, undef);
115	}
116
117# Send status email
118EMAIL:
119if ($email &&
120    ($notify == 0 || $notify == 1 && $ex || $notify == 2 && !$ex) &&
121    &foreign_check("mailboxes")) {
122	&foreign_require("mailboxes");
123	$host = &get_system_hostname();
124	$msg = $all ? 'backup_allsubject' : 'backup_subject';
125	$msg .= ($ex ? '_failed' : '_ok');
126	$subject = &text($msg, $dbs[0],
127			 scalar(@dbs) || $text{'backup_bodyall'},
128			 &get_display_hostname());
129	$data = &text('backup_body', $host,
130	              scalar(@dbs) || $text{'backup_bodyall'})."\n\n";
131	if ($failure) {
132		$data .= $failure."\n";
133		}
134	$total = 0;
135	foreach $s (@status) {
136		$data .= &text('backup_bodydoing', $s->[0], $s->[1])."\n";
137		if ($s->[2]) {
138			$data .= &text('backup_bodyfailed', $s->[2]);
139			}
140		else {
141			$data .= &text('backup_bodyok', &nice_size($s->[3]));
142			$total += $s->[3];
143			}
144		$data .= "\n\n";
145		}
146	if ($all && $total) {
147		$data .= &text('backup_bodytotal', &nice_size($total))."\n\n";
148		}
149	if (&foreign_check("mount")) {
150		&foreign_require("mount");
151		$dir = $status[0]->[1];
152		while($dir ne "/" && !$total_space) {
153			$dir =~ s/\/[^\/]*$//;
154			$dir = "/" if (!$dir);
155			($total_space, $free_space) =
156				&mount::disk_space(undef, $dir);
157			}
158		if ($total_space) {
159			$data .= &text('backup_bodyspace',
160					&nice_size($total_space*1024),
161					&nice_size($free_space*1024))."\n\n";
162			}
163		}
164	&mailboxes::send_text_mail(&mailboxes::get_from_address(),
165                                   $email, undef, $subject, $data);
166	}
167
168exit($ex);
169
170