source: MondoRescue/branches/2.2.10/mondo/src/common/libmondo-filelist.c@ 2508

Last change on this file since 2508 was 2508, checked in by Bruno Cornec, 14 years ago

r3287@localhost (orig r2285): bruno | 2009-07-20 11:36:47 +0200

r3285@localhost: bruno | 2009-07-20 11:17:35 +0200
Apply fix in 2.2.10 around multi USB device handling to 2.2.9 as well


r3291@localhost (orig r2288): bruno | 2009-07-21 16:48:31 +0200
Copy 2.2.10 test script in to 2.2.9 for memory problm analysis


r3293@localhost (orig r2290): bruno | 2009-07-22 14:03:44 +0200

  • Fix a printing error in mindi for the tar command
  • Fix all mr_asprintf which had no second param as a string


r3295@localhost (orig r2292): bruno | 2009-07-22 16:55:00 +0200

  • Fix #160 and #346 by rewriting the message.txt file with more valid information gathered in mindi


r3300@localhost (orig r2294): bruno | 2009-07-23 01:58:08 +0200

Man pages patch from Joe Ross (joe.ross_at_gmail.com)


r3303@localhost (orig r2297): bruno | 2009-07-23 17:43:49 +0200
Fix a remaining display error for 2.2.9. That version has been tested OK in a lab.


r3304@localhost (orig r2298): bruno | 2009-07-23 18:18:27 +0200

  • Remove memory leak for the last modification


r3308@localhost (orig r2302): bruno | 2009-07-24 21:18:50 +0200
Improve logging of mountlist.txt


r3310@localhost (orig r2304): bruno | 2009-07-27 19:45:10 +0200

  • popup_and_get_string needs an allocated buffer for the moment so fixing the calls with dyn. ones
  • Fix a bug in mem.c for mr_strcat, which wasn't modifying the right pointer level


r3311@localhost (orig r2305): bruno | 2009-07-27 19:49:35 +0200
Avoid a memory leak in the previous patch


r3314@localhost (orig r2308): bruno | 2009-07-27 20:59:06 +0200
Fix a bug in mr_strcat backported from 2.2.10. Should solve our seg faults.


r3315@localhost (orig r2309): bruno | 2009-07-28 02:14:23 +0200
Cosmetic changes to allow for quality to not giv false positive


r3343@localhost (orig r2311): bruno | 2009-08-18 02:13:43 +0200
Fix for initramfs detection with 2.6.30 (Hugo Vanwoerkom hvw59601_at_care2.com)


r3367@localhost (orig r2333): bruno | 2009-08-18 16:26:26 +0200
Adds a precision for -U option in man page on raw device usage and not partition name


r3373@localhost (orig r2336): bruno | 2009-08-20 17:37:41 +0200

  • Precise the combined usage of -E and -I in mondoarchive (Case 4601017223)


r3379@localhost (orig r2342): bruno | 2009-08-21 16:27:10 +0200


r3383@localhost (orig r2344): bruno | 2009-08-24 13:37:09 +0200

r3382@localhost: bruno | 2009-08-24 13:30:25 +0200
In NFS mode also propose access to expert, interactive, ... entry at boot prompt


r3388@localhost (orig r2346): bruno | 2009-08-27 11:41:16 +0200
Adds fdisk -l result in Log File at restore time


r3389@localhost (orig r2347): bruno | 2009-08-27 13:51:00 +0200

  • Solve tmp dir creation which sometimes was trying to create /%xx dirs. Should fix #293 for good


r3390@localhost (orig r2348): bruno | 2009-08-27 13:54:25 +0200
Improve logging (minor)


r3394@localhost (orig r2350): bruno | 2009-08-28 02:24:19 +0200
Change inerface of evaluate_mountlist and spread_flaws_across_three_lines in order to solve bugs linked to strings management in these functions. May fix a restoration crash seen by some customers


r3397@localhost (orig r2353): bruno | 2009-08-28 19:03:45 +0200

  • Addition of a nomd option to avoid starting mdadm
  • mpath is now already started if there was a mpath entry in mountlist


r3399@localhost (orig r2355): bruno | 2009-08-29 00:56:50 +0200
Remove function spread_flaws_across_three_lines and expand it at the single place where it was useful, and fix memory allocation issues in it.


r3402@localhost (orig r2358): bruno | 2009-09-01 19:02:35 +0200
P2V doc updated (Lester Wade lester.wade_at_hp.com)


r3404@localhost (orig r2360): bruno | 2009-09-01 19:26:53 +0200
Website update to refer to new P2V document


r3405@localhost (orig r2361): bruno | 2009-09-03 13:54:25 +0200

  • Fix a case where the NFS dir in restore mode was mounted rw (linked to bug #291 could create a huge problem)


r3407@localhost (orig r2363): bruno | 2009-09-03 14:46:46 +0200
More verbose at installation of additional tools


r3409@localhost (orig r2365): bruno | 2009-09-03 18:08:32 +0200

  • New update from Lester Wade (lester.wade_at_hp.com) for P2V doc


r3410@localhost (orig r2366): bruno | 2009-09-05 01:28:18 +0200
place the code of mondo_makefilelist before its call



r3411@localhost (orig r2367): bruno | 2009-09-06 01:51:26 +0200

  • Advertising for project-builder on the website added


r3412@localhost (orig r2368): bruno | 2009-09-07 15:36:23 +0200
Fix compilation issue


r3413@localhost (orig r2369): bruno | 2009-09-07 18:03:40 +0200
Another compilation issue fixed.


r3415@localhost (orig r2371): bruno | 2009-09-08 13:40:25 +0200

  • Fix a problem a error detection in evaluate_mountlist which casued nuke mode to abort. Error string should also be better now.


r3417@localhost (orig r2373): bruno | 2009-09-08 13:55:31 +0200
Avoid asking the Prefix name in NFS mode twice


r3418@localhost (orig r2374): bruno | 2009-09-08 20:04:07 +0200

  • Try to fix garbled screen progression in text mode based on 2.2.10 modifications which are working


r3424@localhost (orig r2380): bruno | 2009-09-09 20:30:47 +0200

  • Change NFS support into a NetFS support to allow for multiple protocol in addition to NFS (NEEDS TESTING)
  • Better logging to detect a potential nuke issue


r3425@localhost (orig r2381): bruno | 2009-09-10 02:05:55 +0200
Fix a missing param for sshfs call


r3428@localhost (orig r2384): bruno | 2009-09-10 13:02:56 +0200

  • Remove separate function look_for_duplicate_mountpoints used only once and whose interface created problems with caller


r3430@localhost (orig r2386): bruno | 2009-09-10 16:06:52 +0200
Be compatible on backup type by making old nfs recognized as netfs and proto forced


r3431@localhost (orig r2387): bruno | 2009-09-10 18:40:47 +0200
Fix a problem in netfs analysis in mondoarchive


r3432@localhost (orig r2388): bruno | 2009-09-10 20:25:13 +0200
Fix mondoarchive CLI analysis for NETFS type of requests


r3434@localhost (orig r2390): bruno | 2009-09-11 03:05:20 +0200

  • Adds ext3 initrd support for 2.6.30


r3437@localhost (orig r2393): bruno | 2009-09-11 11:56:52 +0200

  • Tries to add support for bzip2 and lzma initramfs (preliminary, not tested) for 2.6.30


r3438@localhost (orig r2394): bruno | 2009-09-12 02:53:02 +0200
Fix interface of evaluate_mountlist (remove 2nd param useless) and fix nuke mode which wasn't working.


r3441@localhost (orig r2397): bruno | 2009-09-14 18:54:34 +0200
Fix a format issue in text mode on percentage


r3452@localhost (orig r2398): bruno | 2009-09-15 16:00:13 +0200

  • Fix a bug where flaws_str could be NULL and wasn't tested correctly.


r3453@localhost (orig r2399): bruno | 2009-09-15 19:28:39 +0200

  • Use protocol name when displaying restore progress instead of netfs
  • Ask for network protocol name at restore time


r3455@localhost (orig r2401): bruno | 2009-09-15 19:34:19 +0200
Wrong structure member name was used


r3456@localhost (orig r2402): bruno | 2009-09-16 13:04:17 +0200
Use dir for shell related commands and dir1 for C related actions in open_and_list_dir to avoid missing some files with { in names e.g.


r3457@localhost (orig r2403): bruno | 2009-09-16 16:32:03 +0200

  • At restore time read the netfs protocol in the conf file


r3462@localhost (orig r2408): bruno | 2009-09-18 15:17:08 +0200
Remove useless script


r3463@localhost (orig r2409): bruno | 2009-09-18 15:25:35 +0200

  • Split deplist.txt into multiple conf files under deplist.d in the conf dir. This will allow to have a minimal.conf file for initrd content to analyze to improve support of new embedded feature in the future (sshfs, live install). The other conf files contain the additional commands to put in the all.tar.gz. For the moment, mindi is still working the same. THis infra will allow that support in a near future. deplist.txt is now reserved for the admin additional commands.


r3465@localhost (orig r2410): bruno | 2009-09-18 19:10:54 +0200

  • Better list of mandatory tools
  • Adds fuse and sshfs support in initrd


r3466@localhost (orig r2411): bruno | 2009-09-18 20:32:47 +0200
sshfs also needs ssh at restore time in initrd


r3478@localhost (orig r2418): bruno | 2009-09-23 23:22:39 +0200
Modify getfattr call to have all extended attributes, including non user ones. (patch from Kevin Ritzenthaler Kevin.Ritzenthaler_at_hp.com) and fix #357


r3479@localhost (orig r2419): bruno | 2009-09-23 23:50:34 +0200
star only supports ACL when used with exustar mode. Fix #356.


r3482@localhost (orig r2422): bruno | 2009-09-24 16:53:24 +0200

  • Adds support for bnx2x (BL 460 G6) and auth_rpcgss (Debian 2.6.31)


r3485@localhost (orig r2423): bruno | 2009-09-25 16:38:40 +0200
Fix an issue in is_this_device_mounted (string freed before last usage)


r3486@localhost (orig r2424): bruno | 2009-09-25 18:44:01 +0200

  • analyze-my-lvm now removes excluded devices from list coming from mondoarchive
  • new mr_make_devlist_from_pathlist which handle the new bkpinfo->exclude_devs field containing the excluded devices and remove corresponding code from libmondo-cli.c
  • Move DSF code into libmondo-devices.c for coherency, and only the previous function is made externally available
  • Remove dev_to_exclude in libmondo-archive.c which wasn't working correctly and replace it with bkpinfo->exclude_devs


r3487@localhost (orig r2425): bruno | 2009-09-25 18:58:23 +0200

  • Improving ssh support at restore time by providing a shadow file


r3489@localhost (orig r2426): bruno | 2009-09-25 19:42:09 +0200

  • Attempt to stay backward compatible without protocol for -n option


r3490@localhost (orig r2427): bruno | 2009-09-28 02:08:06 +0200
Avoids null param for excludes_devs for mindi call


r3492@localhost (orig r2429): bruno | 2009-09-28 11:46:16 +0200

  • Simplify GetInitrdFilesystemToUse which doesn't need to detect everything, but just know if it's initramfs (new mode) or a compressed FS ext2/3 (older mode) as initrd is anyway re-made by mindi. Should fix #353


r3494@localhost (orig r2431): bruno | 2009-09-28 13:16:18 +0200

  • Use only the AWK veriable everywhere and not the awk command


r3495@localhost (orig r2432): bruno | 2009-09-28 14:16:31 +0200
Warning emited in case of duplicate mountpoints or devices in fstab found


r3496@localhost (orig r2433): bruno | 2009-09-28 15:55:17 +0200
ssh in the restore env needs some dlopened libs (libnss_compat|files)


r3497@localhost (orig r2434): bruno | 2009-09-28 16:33:14 +0200
Compiler warning fixed


r3498@localhost (orig r2435): bruno | 2009-09-28 17:55:26 +0200
Improve user management for NetFS cases


r3499@localhost (orig r2436): bruno | 2009-09-29 01:48:32 +0200

  • Improve deplist.d/* files
  • adds libnss for ssh support in boot disk
  • Solve a memory management issue in DSF module (strtok => mr_strtok)
  • DSF now also supports partitions in addition to full disks
  • Adds debug in open_and_list_dir


r3500@localhost (orig r2437): bruno | 2009-09-29 10:41:56 +0200

  • Fix udev support in init for Mandriva 2009.1 (udevadm settle is blocking)


r3501@localhost (orig r2438): bruno | 2009-09-29 14:41:36 +0200

  • Improvements on sshfs/ssh management in restore mode
  • Include now all minimal requirements for sshfs


r3502@localhost (orig r2439): bruno | 2009-09-29 18:46:08 +0200

  • Avoids error message if some ssh conf files do not exist


r3503@localhost (orig r2440): bruno | 2009-09-29 18:57:13 +0200

  • Avoids comment analysis in the new code handling deplist.d


r3504@localhost (orig r2441): bruno | 2009-09-29 19:34:34 +0200

  • fuse device is needed at restore time for sshfs


r3505@localhost (orig r2442): bruno | 2009-09-29 20:02:36 +0200

  • Improves udev timeout handling


r3506@localhost (orig r2443): bruno | 2009-09-29 20:43:38 +0200

  • priority given to env var for tmpdir
  • fuse FS excluded from tmpdir computation


r3518@localhost (orig r2447): bruno | 2009-10-04 01:58:08 +0200

  • Iprove USB log in case of error by adding the conf file


r3519@localhost (orig r2448): bruno | 2009-10-05 11:06:13 +0200


r3520@localhost (orig r2449): bruno | 2009-10-06 01:10:35 +0200

  • Adds support for grub2 conf file grub.cfg in addition to menu.lst


r3521@localhost (orig r2450): bruno | 2009-10-06 01:24:02 +0200

  • Fix a mr_asprintf usage without & causing a seg fault.


r3523@localhost (orig r2452): bruno | 2009-10-06 12:47:56 +0200
CIFS mounts shouldn't be part of the mountlist analysis (should help solving #288)


r3524@localhost (orig r2453): bruno | 2009-10-07 10:17:03 +0200

  • Fix a bug in handling of -E option with real devices (bad report in function mr_make_devlist_from_pathlist of the test between -E and -I)


r3525@localhost (orig r2454): bruno | 2009-10-07 10:19:02 +0200

  • Fix an error in the test for grub conf files (or used instead of and)


r3526@localhost (orig r2455): bruno | 2009-10-07 16:14:59 +0200
afio is under /bin on Debian


r3527@localhost (orig r2456): bruno | 2009-10-07 17:31:26 +0200

  • Adds support for libcrc32c (needed by bnx2x)


r3532@localhost (orig r2457): bruno | 2009-10-09 13:33:44 +0200

  • Apply path from Matthew Cline (matt_at_nightrealms.com) in order to fix #359


r3533@localhost (orig r2458): bruno | 2009-10-09 13:41:02 +0200
Adds a conf file example for mindi and fix #360


r3535@localhost (orig r2459): bruno | 2009-10-09 15:13:01 +0200
MOde of conf file


r3546@localhost (orig r2461): bruno | 2009-10-14 01:12:24 +0200

  • umount freshly created VFAT partition on USB key as Ubunu has an automounter mounting it as soon as created (Steffen Neumann sneumann_at_ipb-halle.de)


r3566@localhost (orig r2463): bruno | 2009-10-26 01:34:16 +0100

  • Reset an error counter before blanking a DVD to avoid always returning an error (Vincent Raman vincent.raman_at_macqel.eu)


r3567@localhost (orig r2464): bruno | 2009-10-26 13:57:14 +0100
bzip2 is under /bin on Debian


r3568@localhost (orig r2465): bruno | 2009-10-28 01:46:30 +0100
some distro hold lvm commands under /usr/sbin


r3595@localhost (orig r2469): bruno | 2009-11-10 12:22:10 +0100
/dev/shm is now part of the default exclude list


r3596@localhost (orig r2470): bruno | 2009-11-10 12:32:40 +0100
Remove useless pb_log and MONDO_TRACEFILE


r3597@localhost (orig r2471): bruno | 2009-11-10 12:57:58 +0100
Improve analysis of kernel modules by printing whether it's a live or extra module which has not been found (Matthew Cline) as reported in #362


r3598@localhost (orig r2472): bruno | 2009-11-10 13:21:46 +0100

  • Default to DVD size when in iso or netfs mode


r3599@localhost (orig r2473): bruno | 2009-11-10 14:13:10 +0100

  • Fix #363 where exclude_paths was extended up to memory limit dumping core


r3600@localhost (orig r2474): bruno | 2009-11-10 14:31:14 +0100

  • Update deplist for Debian support


r3602@localhost (orig r2476): bruno | 2009-11-11 02:44:42 +0100

  • small improvement for loging in USB case


r3603@localhost (orig r2477): bruno | 2009-11-11 13:29:27 +0100

  • Adds a nolvm boot option at restore time


r3604@localhost (orig r2478): bruno | 2009-11-11 19:54:51 +0100

  • Fix #367 - the for loop doesn't make any test now, as it was computed before entering the loop, leading to an error, and was also made inside the loop anyway.


r3605@localhost (orig r2479): bruno | 2009-11-12 00:32:45 +0100

  • Add support for diskdumplib driver useful for RHEL 3 and IBM xseries 336


r3606@localhost (orig r2480): bruno | 2009-11-12 01:09:40 +0100

  • If using nolvm, mondorestore should also not nalyze and handle i-want-my-lvm


r3608@localhost (orig r2482): bruno | 2009-11-14 12:54:11 +0100
Fix bunzip2 on debian as well


r3610@localhost (orig r2484): bruno | 2009-11-15 00:44:19 +0100

  • Adds support for variable serial port console, with defalut to /dev/ttyS0, and a boot param to change it with serial=/dev/ttySx


r3615@localhost (orig r2485): bruno | 2009-11-15 01:34:33 +0100

r3614@localhost: bruno | 2009-11-15 01:34:12 +0100
Adds a space in exclude paths


r3623@localhost (orig r2487): bruno | 2009-11-18 20:41:40 +0100

r3620@localhost: bruno | 2009-11-18 10:31:36 +0100

  • Only link /dev/tty to serial port when there is indeed a serial port. If not breaks mondorestore on normal console


r3631@localhost (orig r2490): bruno | 2009-11-24 01:48:29 +0100
Put news below in the main page to make it more readable


r3648@localhost (orig r2492): bruno | 2009-11-25 23:50:13 +0100

r3647@localhost: bruno | 2009-11-25 23:49:11 +0100

  • Add warning for -f and SW Raid as in 2.2.10


r3650@localhost (orig r2493): bruno | 2009-11-26 00:19:52 +0100

r3649@localhost: bruno | 2009-11-26 00:18:27 +0100

  • Addition of the german translation made by Magnus Rasche (Magnus.rasche_at_gmx.de) and Website inclusion


r3652@localhost (orig r2495): bruno | 2009-11-27 15:55:55 +0100
cosmetic display fix
r3659@localhost (orig r2498): bruno | 2009-12-05 17:53:03 +0100
nfsopt restore boot time option added to support custom mount options for network restore


r3684@localhost (orig r2501): bruno | 2009-12-17 00:35:08 +0100
Fix #375 mondo will segfault if the partition in sensibly_set_tmpdir_and_scratchdir() is read-only (cylau)


r3685@localhost (orig r2502): bruno | 2009-12-17 01:02:47 +0100

  • Fix an issue in the function listing kernel modules when not found


r3686@localhost (orig r2503): bruno | 2009-12-17 01:15:01 +0100
Adds scsi_dump_register to mindi SCSI_MODS for RHEL3 + IBM servers


r3701@localhost (orig r2504): bruno | 2009-12-23 02:24:33 +0100

  • Addition of the Lab for Mondorescue


r3702@localhost (orig r2505): bruno | 2009-12-23 02:41:17 +0100
Web site update for Lab MondoRescue delivery


r3706@localhost (orig r2506): bruno | 2010-01-04 11:31:53 +0100

  • Fix a bug when isodir is / only when splitting it in iso_path and iso_mnt


r3707@localhost (orig r2507): bruno | 2010-01-04 13:22:49 +0100

  • Fix #377: Segfault in pause_and_ask_for_cdr() (ggeens)


  • Property svn:keywords set to Id
File size: 49.3 KB
Line 
1/*
2 $Id: libmondo-filelist.c 2508 2010-01-04 18:21:55Z bruno $
3*/
4
5/**
6 * @file
7 * Functions which create, chop, and edit the filelist.
8 */
9
10#include "my-stuff.h"
11#include "mondostructures.h"
12#include "lib-common-externs.h"
13#include "libmondo-filelist.h"
14#include "libmondo-string-EXT.h"
15#include "libmondo-files-EXT.h"
16#include "libmondo-fork-EXT.h"
17#include "libmondo-gui-EXT.h"
18#include "libmondo-tools-EXT.h"
19#include "mr_mem.h"
20#include "mr_str.h"
21
22#include <time.h>
23#include <stdio.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <dirent.h>
27#include <errno.h>
28#include <stdio.h>
29
30
31extern char *MONDO_LOGFILE;
32
33/* Reference to global bkpinfo */
34extern struct s_bkpinfo *bkpinfo;
35
36
37/*@unused@*/
38//static char cvsid[] = "$Id: libmondo-filelist.c 2508 2010-01-04 18:21:55Z bruno $";
39
40/**
41 * Number of lines in the filelist last loaded.
42 * @warning This implies that two filesets cannot be loaded at once.
43 * @ingroup globalGroup
44 */
45long g_original_noof_lines_in_filelist = 0;
46
47/**
48 * Number of filesets in the current backup.
49 * @ingroup globalGroup
50 */
51long g_noof_sets = 0;
52
53extern bool g_text_mode;
54extern newtComponent g_progressForm;
55extern int g_currentY;
56extern int g_noof_rows;
57
58extern char *g_getfacl;
59extern char *g_getfattr;
60
61
62
63/**
64 * @addtogroup filelistGroup
65 * @{
66 */
67/**
68 * Call chop_filelist() to chop the filelist into sets.
69 * @param bkpinfo The backup information structure. Fields used:
70 * - @c bkpinfo->image_devs
71 * - @c bkpinfo->optimal_set_size
72 * - @c bkpinfo->scratchdir
73 * - @c bkpinfo->tmpdir
74 * @see chop_filelist
75 */
76int call_filelist_chopper()
77{
78 /*@ buffers *********************** */
79 char *dev = NULL;
80 char *filelist = NULL;
81 char *tempfile = NULL;
82 long noof_sets;
83
84 /*@ pointers ********************** */
85 char *ptr = NULL;
86 FILE *fout;
87
88 /*@ int *************************** */
89 int i, retval = 0;
90
91 mvaddstr_and_log_it(g_currentY, 0, "Dividing filelist into sets");
92
93 log_to_screen("Dividing filelist into sets. Please wait.");
94 i = 0;
95 mr_asprintf(filelist, "%s/archives/filelist.full", bkpinfo->scratchdir);
96 if (!does_file_exist(filelist)) {
97 log_it("filelist %s not found", filelist);
98 mr_free(filelist);
99 fatal_error("call_filelist_chopper() -- filelist not found!");
100 }
101
102 noof_sets = chop_filelist(filelist, bkpinfo->optimal_set_size);
103 mr_free(filelist);
104 estimate_noof_media_required(noof_sets); // for cosmetic purposes
105
106 mr_asprintf(tempfile, "%s/biggielist.txt", bkpinfo->tmpdir);
107 if (!(fout = fopen(tempfile, "a"))) {
108 log_OS_error("Cannot append to biggielist");
109 retval++;
110 mr_free(tempfile);
111 return (retval);
112 }
113 mr_free(tempfile);
114
115 if (bkpinfo->image_devs) {
116 log_it("image_devs : %s", bkpinfo->image_devs);
117
118 ptr = bkpinfo->image_devs;
119
120 while (ptr && *ptr) {
121 mr_asprintf(dev, "%s", ptr);
122 log_it("Examining imagedev %s", dev);
123 for (i = 0; i < (int) strlen(dev) && dev[i] != ' '; i++);
124 dev[i] = '\0';
125 if (!strlen(dev)) {
126 mr_free(dev);
127 continue;
128 }
129 fprintf(fout, "%s\n", dev);
130 log_it("Adding '%s' to biggielist", dev);
131 if ((ptr = strchr(ptr, ' '))) {
132 ptr++;
133 }
134 mr_free(dev);
135 }
136 }
137 paranoid_fclose(fout);
138 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
139
140 return (retval);
141}
142
143
144int sort_file(char *orig_fname)
145{
146 char *tmp_fname = NULL;
147 char *command = NULL;
148 int retval = 0;
149
150 log_msg(5, "Sorting file %s", orig_fname);
151
152 if (!does_file_exist(orig_fname)) {
153 log_msg(2, "file %s empty", orig_fname);
154 return (0);
155 } // no sense in trying to sort an empty file
156
157 mr_asprintf(tmp_fname, "%s/sortfile", bkpinfo->tmpdir);
158 mr_asprintf(command, "sort %s > %s 2>> %s", orig_fname, tmp_fname, MONDO_LOGFILE);
159 retval = system(command);
160 mr_free(command);
161
162 if (retval) {
163 log_msg(2, "Failed to sort %s - oh dear", orig_fname);
164 } else {
165 log_msg(5, "Sorted %s --> %s OK. Copying it back to %s now", orig_fname, tmp_fname, orig_fname);
166 mr_asprintf(command, "mv -f %s %s", tmp_fname, orig_fname);
167 retval += run_program_and_log_output(command, 5);
168 mr_free(command);
169
170 if (retval) {
171 log_msg(2, "Failed to copy %s back to %s - oh dear", tmp_fname, orig_fname);
172 } else {
173 log_msg(5, "%s was sorted OK.", orig_fname);
174 }
175 }
176 mr_free(tmp_fname);
177 log_msg(5, "Finished sorting file %s", orig_fname);
178 return (retval);
179}
180
181
182
183/**
184 * Chop the filelist into sets.
185 * Each fileset is a list of files whose total (uncompressed) size is usually
186 * about X KB. Files bigger than 8X KB are placed in a "biggielist"; they will
187 * be sliced and compressed separately from the regular files.
188 *
189 * @param filelist The big filelist (filelist.full) to chop up.
190 * @param maxsetsizeK Optimal size of a fileset (X above).
191 * @return number of errors encountered (0 for success).
192 */
193int chop_filelist(char *filelist, long maxsetsizeK)
194{
195/*@ long ****************************************/
196 long lino = 0;
197 long max_sane_size_for_a_file;
198 long curr_set_size;
199 long noof_lines;
200 long siz;
201
202 /*@ int **************************************** */
203 int i;
204 long curr_set_no;
205
206 /*@ buffers ************************************* */
207 char *outfname = NULL;
208 char *biggie_fname = NULL;
209 char *incoming = NULL;
210 char *tmp = NULL;
211
212 /*@ pointers *********************************** */
213 FILE *fin;
214 FILE *fout;
215 FILE *fbig;
216
217 /*@ structures ********************************* */
218 struct stat buf;
219 int err = 0;
220
221 assert_string_is_neither_NULL_nor_zerolength(filelist);
222 assert(maxsetsizeK > 0);
223
224 max_sane_size_for_a_file = 64L * 1024L;
225// max_sane_size_for_a_file = maxsetsizeK*2;
226// if (max_sane_size_for_a_file > 32*1024)
227// { max_sane_size_for_a_file = 32*1024; }
228
229 log_it("filelist=%s;", filelist);
230 open_evalcall_form("Dividing filelist into sets");
231 noof_lines = count_lines_in_file(filelist);
232 if (!(fin = fopen(filelist, "r"))) {
233 log_OS_error("Cannot openin filelist");
234 return (0);
235 }
236 curr_set_no = 0;
237 curr_set_size = 0;
238 mr_asprintf(outfname, "%s/filelist.%ld", bkpinfo->tmpdir, curr_set_no);
239 mr_asprintf(biggie_fname, "%s/biggielist.txt", bkpinfo->tmpdir);
240 log_it("outfname=%s; biggie_fname=%s", outfname, biggie_fname);
241 if (!(fbig = fopen(biggie_fname, "w"))) {
242 log_OS_error("Cannot openout biggie_fname");
243 err++;
244 mr_free(outfname);
245 mr_free(biggie_fname);
246 return (curr_set_no + 1);
247 }
248 if (!(fout = fopen(outfname, "w"))) {
249 log_OS_error("Cannot openout outfname");
250 err++;
251 mr_free(outfname);
252 mr_free(biggie_fname);
253 return (curr_set_no + 1);
254 }
255
256 mr_getline(incoming, fin);
257 while (!feof(fin)) {
258 lino++;
259 i = strlen(incoming) - 1;
260 if (i < 0) {
261 i = 0;
262 }
263 /* Now that we dyn. alloc is truncating needed ?
264 if (i > MAX_STR_LEN - 1) {
265 incoming[MAX_STR_LEN - 30] = '\0';
266 log_msg(1, "Warning - truncating file %s's name", incoming);
267 err++;
268 }
269 */
270 if (incoming[i] < 32) {
271 incoming[i] = '\0';
272 }
273 if (!strncmp(incoming, "/dev/", 5)) {
274 siz = 1;
275 } else if (lstat(incoming, &buf) != 0) {
276 siz = 0;
277 } else {
278 siz = (long) (buf.st_size >> 10);
279 }
280 if (siz > max_sane_size_for_a_file) {
281 fprintf(fbig, "%s\n", incoming);
282 } else {
283 curr_set_size += siz;
284 fprintf(fout, "%s\n", incoming);
285 if (curr_set_size > maxsetsizeK) {
286 paranoid_fclose(fout);
287 sort_file(outfname);
288 mr_free(outfname);
289 curr_set_no++;
290 curr_set_size = 0;
291
292 mr_asprintf(outfname, "%s/filelist.%ld", bkpinfo->tmpdir, curr_set_no);
293 if (!(fout = fopen(outfname, "w"))) {
294 log_OS_error("Unable to openout outfname");
295 err++;
296 mr_free(outfname);
297 mr_free(biggie_fname);
298 mr_free(incoming);
299 return (curr_set_no + 1);
300 }
301 update_evalcall_form((int) (lino * 100 / noof_lines));
302 }
303 }
304 mr_free(incoming);
305 mr_getline(incoming, fin);
306 }
307 mr_free(incoming);
308
309 paranoid_fclose(fin);
310 paranoid_fclose(fout);
311 paranoid_fclose(fbig);
312
313 if (length_of_file(outfname) <= 2) {
314 unlink(outfname);
315 g_noof_sets--;
316 }
317 g_noof_sets = curr_set_no;
318 sort_file(outfname);
319 mr_free(outfname);
320
321 sort_file(biggie_fname);
322 mr_free(biggie_fname);
323
324 mr_asprintf(tmp, "echo 'last-filelist-number %ld' >> "MINDI_CACHE"/mondorestore.cfg", curr_set_no);
325 paranoid_system(tmp);
326 mr_free(tmp);
327
328 if (curr_set_no == 0) {
329 log_msg(1, "Only one fileset. Fine.");
330 } else {
331 log_msg(1, "Filelist divided into %ld sets", curr_set_no + 1);
332 }
333 close_evalcall_form();
334 /* This is to work around an obscure bug in Newt; open a form, close it,
335 carry on... I don't know why it works but it works. If you don't do this
336 then update_progress_form() won't show the "time taken / time remaining"
337 line. The bug only crops up AFTER the call to chop_filelist(). Weird. */
338 if (!g_text_mode) {
339 open_progress_form("", "", "", "", 100);
340 newtPopHelpLine();
341 newtFormDestroy(g_progressForm);
342 newtPopWindow();
343 }
344 return (err ? 0 : curr_set_no + 1);
345}
346
347
348
349
350
351/**
352 * Free all the memory used by a filelist structure.
353 * Since this may take a long time for large filelists, a progress bar will be displayed.
354 * @param filelist The filelist to free.
355 */
356void free_filelist(struct s_node *filelist)
357{
358 /*@ int's ******************************************************* */
359 static int depth = 0;
360 int percentage;
361
362 /*@ long's ****************************************************** */
363 static long i = 0;
364
365 /*@ end vars **************************************************** */
366
367 assert(filelist != NULL);
368 if (depth == 0) {
369 open_evalcall_form("Freeing memory");
370 log_to_screen("Freeing memory formerly occupied by filelist");
371 }
372 depth++;
373
374 if (filelist->ch == '\0') {
375 if (!(i++ % 1111)) {
376 percentage =
377 (int) (i * 100 / g_original_noof_lines_in_filelist);
378 update_evalcall_form(percentage);
379
380 }
381 }
382
383 if (filelist->right) {
384 free_filelist(filelist->right);
385 filelist->right = NULL;
386 }
387 if (filelist->down) {
388/* if (!(i++ %39999)) { update_evalcall_form(0); } */
389 free_filelist(filelist->down);
390 filelist->down = NULL;
391 }
392 filelist->ch = '\0';
393 paranoid_free(filelist);
394 depth--;
395 if (depth == 0) {
396 close_evalcall_form();
397 log_it("Finished freeing memory");
398 }
399}
400
401
402int call_exe_and_pipe_output_to_fd(char *syscall, FILE * pout)
403{
404 FILE *pattr = NULL;
405 char *tmp = NULL;
406
407 pattr = popen(syscall, "r");
408 if (!pattr) {
409 log_msg(1, "Failed to open fattr() %s", syscall);
410 return (1);
411 }
412 if (feof(pattr)) {
413 log_msg(1, "Failed to call fattr() %s", syscall);
414 paranoid_pclose(pattr);
415 return (2);
416 }
417 for (mr_getline(tmp, pattr); !feof(pattr); mr_getline(tmp, pattr)) {
418 fputs(tmp, pout);
419 mr_free(tmp);
420 }
421 mr_free(tmp);
422 paranoid_pclose(pattr);
423 return (0);
424}
425
426
427
428int gen_aux_list(char *filelist, char *syscall_sprintf,
429 char *auxlist_fname)
430{
431 FILE *fin = NULL;
432 FILE *pout = NULL;
433 char *pout_command = NULL;
434 char *syscall = NULL;
435 char *file_to_analyze = NULL;
436 char *strtmp = NULL;
437 char *tmp = NULL;
438 int i;
439
440 if (!(fin = fopen(filelist, "r"))) {
441 log_msg(1, "Cannot openin filelist %s", filelist);
442 return (1);
443 }
444 mr_asprintf(pout_command, "gzip -c1 > %s", auxlist_fname);
445 if (!(pout = popen(pout_command, "w"))) {
446 log_msg(1, "Cannot openout auxlist_fname %s", auxlist_fname);
447 fclose(fin);
448 mr_free(pout_command);
449 return (4);
450 }
451 mr_free(pout_command);
452
453 for (mr_getline(file_to_analyze, fin); !feof(fin); mr_getline(file_to_analyze, fin)) {
454 i = strlen(file_to_analyze);
455 if (i > 0 && file_to_analyze[i - 1] < 32) {
456 file_to_analyze[i - 1] = '\0';
457 }
458 log_msg(8, "Analyzing %s", file_to_analyze);
459 tmp = mr_stresc(file_to_analyze, "`$\\\"(){}[]'*?&|!#~", '\\');
460 mr_asprintf(strtmp, syscall_sprintf, tmp);
461 mr_free(tmp);
462
463 mr_asprintf(syscall, "%s 2>> /dev/null", strtmp); // " MONDO_LOGFILE);
464 mr_free(strtmp);
465
466 call_exe_and_pipe_output_to_fd(syscall, pout);
467 mr_free(syscall);
468 mr_free(file_to_analyze);
469 }
470 mr_free(file_to_analyze);
471 paranoid_fclose(fin);
472 paranoid_pclose(pout);
473 return (0);
474}
475
476
477int get_acl_list(char *filelist, char *facl_fname)
478{
479 char *command = NULL;
480 int retval = 0;
481
482 if (g_getfacl != NULL) {
483 mr_asprintf(command, "touch %s", facl_fname);
484 run_program_and_log_output(command, 8);
485 mr_free(command);
486
487 mr_asprintf(command, "getfacl --all-effective -P %s 2>> %s | gzip -c1 > %s 2>> %s", filelist, MONDO_LOGFILE, facl_fname, MONDO_LOGFILE);
488 log_it("%s",command);
489 retval = system(command);
490 mr_free(command);
491 }
492 return (retval);
493}
494
495
496int get_fattr_list(char *filelist, char *fattr_fname)
497{
498 char *command;
499 int retval = 0;
500
501 if (g_getfattr != NULL) {
502 mr_asprintf(command, "touch %s", fattr_fname);
503 run_program_and_log_output(command, 8);
504 mr_free(command);
505 retval =
506 gen_aux_list(filelist, "getfattr --en=hex -P -m - -d \"%s\"",
507 fattr_fname);
508 }
509 return (retval);
510}
511
512
513int set_EXAT_list(char *orig_msklist, char *original_exat_fname,
514 char *executable)
515{
516 const int my_depth = 8;
517 char *command = NULL;
518 char *syscall_pin = NULL;
519 char *syscall_pout = NULL;
520 char *incoming = NULL;
521 char *current_subset_file = NULL;
522 char *current_master_file = NULL;
523 char *masklist = NULL;
524 int retval = 0;
525 int i;
526 char *p, *q;
527 FILE *pin, *pout, *faclin;
528
529 log_msg(1, "set_EXAT_list(%s, %s, %s)", orig_msklist, original_exat_fname, executable);
530 if (!orig_msklist || !orig_msklist[0]
531 || !does_file_exist(orig_msklist)) {
532 log_msg(1, "No masklist provided. I shall therefore set ALL attributes.");
533 mr_asprintf(command, "gzip -dc %s | %s --restore - 2>> %s", original_exat_fname, executable, MONDO_LOGFILE);
534 log_msg(1, "command = %s", command);
535 retval = system(command);
536 mr_free(command);
537 log_msg(1, "Returning w/ retval=%d", retval);
538 return (retval);
539 }
540 if (length_of_file(original_exat_fname) <= 0) {
541 log_msg(1, "original_exat_fname %s is empty or missing, so no need to set EXAT list", original_exat_fname);
542 return (0);
543 }
544 mr_asprintf(masklist, "%s/masklist", bkpinfo->tmpdir);
545 mr_asprintf(command, "cp -f %s %s", orig_msklist, masklist);
546 run_program_and_log_output(command, 1);
547 mr_free(command);
548
549 sort_file(masklist);
550
551 mr_asprintf(syscall_pout, "%s --restore - 2>> %s", executable, MONDO_LOGFILE);
552 log_msg(1, "syscall_pout = %s", syscall_pout);
553 pout = popen(syscall_pout, "w");
554 mr_free(syscall_pout);
555
556 if (!pout) {
557 log_it("Unable to openout to syscall_pout");
558 mr_free(masklist);
559 return (1);
560 }
561
562 mr_asprintf(syscall_pin, "gzip -dc %s", original_exat_fname);
563 log_msg(1, "syscall_pin = %s", syscall_pin);
564 pin = popen(syscall_pin, "r");
565 mr_free(syscall_pin);
566
567 if (!pin) {
568 pclose(pout);
569 log_it("Unable to openin from syscall");
570 return (1);
571 }
572 faclin = fopen(masklist, "r");
573 if (!faclin) {
574 pclose(pin);
575 pclose(pout);
576 log_it("Unable to openin masklist");
577 mr_free(masklist);
578 return (1);
579 }
580// printf("Hi there. Starting the loop\n");
581
582 mr_getline(current_subset_file, faclin);
583 mr_getline(incoming, pin);
584 while (!feof(pin) && !feof(faclin)) {
585 mr_asprintf(current_master_file, "%s", incoming + 8);
586
587 p = current_subset_file;
588 if (*p == '/') {
589 p++;
590 }
591 i = strlen(p);
592 if (i > 0 && p[i - 1] < 32) {
593 p[i - 1] = '\0';
594 }
595
596
597 q = current_master_file;
598 if (*q == '/') {
599 q++;
600 }
601 i = strlen(q);
602 if (i > 0 && q[i - 1] < 32) {
603 q[i - 1] = '\0';
604 }
605
606 i = strcmp(p, q);
607 log_msg(my_depth, "'%s' v '%s' --> %d\n", p, q, i);
608
609// printf("%s v %s --> %d\n", p, q, i);
610
611 if (i < 0) { // read another subset file in.
612 log_msg(my_depth, "Reading next subset line in\n\n");
613 mr_free(current_subset_file);
614 mr_getline(current_subset_file, faclin);
615 continue;
616 }
617
618 if (!i) {
619 fputs(incoming, pout);
620 }
621 mr_free(incoming);
622 mr_getline(incoming, pin);
623 if (!i) {
624 log_msg(my_depth, "Copying master %s", q);
625 }
626
627 while (!feof(pin) && strncmp(incoming, "# file: ", 8)) {
628 if (!i) {
629 fputs(incoming, pout);
630 }
631 mr_free(incoming);
632 mr_getline(incoming, pin);
633 }
634 if (!i) {
635 mr_free(current_subset_file);
636 mr_getline(current_subset_file, faclin);
637 }
638 mr_free(current_master_file);
639 }
640 mr_free(current_subset_file);
641 mr_free(incoming);
642 fclose(faclin);
643 pclose(pin);
644 pclose(pout);
645
646 unlink(masklist);
647 mr_free(masklist);
648
649 return (retval);
650}
651
652
653int set_fattr_list(char *masklist, char *fattr_fname) {
654
655 char *tmp = NULL;
656
657 tmp = find_home_of_exe("setfattr");
658 if (tmp) {
659 mr_free(tmp);
660 return (set_EXAT_list(masklist, fattr_fname, "setfattr"));
661 } else {
662 mr_free(tmp);
663 log_msg(1, "ERROR: set_EXAT_list: setfattr doesn't exist");
664 return(0);
665 }
666}
667
668
669
670int set_acl_list(char *masklist, char *acl_fname) {
671
672 char *tmp = NULL;
673
674 tmp = find_home_of_exe("setfacl");
675 if (tmp) {
676 mr_free(tmp);
677 return (set_EXAT_list(masklist, acl_fname, "setfacl"));
678 } else {
679 mr_free(tmp);
680 log_msg(1, "ERROR: set_EXAT_list: setfacl doesn't exist");
681 return(0);
682 }
683}
684
685
686/**
687 * Get the number of the last fileset in the backup.
688 * @return The last filelist number.
689 * @note This function should only be called at restore-time.
690 */
691int get_last_filelist_number()
692{
693 /*@ buffers ***************************************************** */
694 char *val_sz = NULL;
695 char *cfg_fname = NULL;
696
697 /*@ long ******************************************************** */
698 int val_i;
699
700 /*@ end vars **************************************************** */
701
702 assert(bkpinfo != NULL);
703
704 mr_asprintf(cfg_fname, "%s/mondorestore.cfg", MINDI_CACHE);
705 val_sz = read_cfg_var(cfg_fname, "last-filelist-number");
706 mr_free(cfg_fname);
707
708 if (val_sz == NULL) {
709 mr_asprintf(val_sz, "");
710 }
711 val_i = atoi(val_sz);
712 mr_free(val_sz);
713
714 if (val_i <= 0) {
715 val_i = 500;
716 }
717 return (val_i);
718}
719
720
721/**
722 * Add a string at @p startnode.
723 * @param startnode The node to start at when searching for where to add the string.
724 * @param string_to_add The string to add.
725 * @return 0 for success, 1 for failure.
726 * @bug I don't understand this function. Would someone care to explain it?
727 */
728int add_string_at_node(struct s_node *startnode, char *string_to_add)
729{
730
731
732 /*@ int ******************************************************** */
733 int noof_chars;
734 int i;
735 int res;
736
737 /*@ sturctures ************************************************* */
738 struct s_node *node, *newnode;
739
740 /*@ char ****************************************************** */
741 char char_to_add;
742
743 /*@ bools ****************************************************** */
744
745 const bool sosodef = FALSE;
746
747 static int depth = 0;
748 static char original_string[MAX_STR_LEN];
749
750 assert(startnode != NULL);
751 assert(string_to_add != NULL);
752
753 if (!depth) {
754 strcpy(original_string, string_to_add);
755 }
756
757 noof_chars = strlen(string_to_add) + 1; /* we include the '\0' */
758
759 /* walk across tree if necessary */
760 node = startnode;
761 char_to_add = string_to_add[0];
762 if (node->right != NULL && node->ch < char_to_add) {
763 log_msg(7, "depth=%d --- going RIGHT ... %c-->%c", depth,
764 char_to_add, node->ch, (node->right)->ch);
765 return (add_string_at_node(node->right, string_to_add));
766 }
767
768 /* walk down tree if appropriate */
769 if (node->down != NULL && node->ch == char_to_add) {
770 log_msg(7, "depth=%d char=%c --- going DOWN", depth, char_to_add);
771 depth++;
772 res = add_string_at_node(node->down, string_to_add + 1);
773 depth--;
774 return (res);
775 }
776
777 if (char_to_add == '\0' && node->ch == '\0') {
778 log_msg(6, "%s already in tree", original_string);
779 return (1);
780 }
781
782 /* add here */
783 if (!(newnode = (struct s_node *) malloc(sizeof(struct s_node)))) {
784 log_to_screen("failed to malloc");
785 depth--;
786 return (1);
787 }
788 if (char_to_add < node->ch) // add to the left of node
789 {
790 log_msg(7, "depth=%d char=%c --- adding (left)", depth,
791 char_to_add);
792 memcpy((void *) newnode, (void *) node, sizeof(struct s_node));
793 node->right = newnode;
794 } else if (char_to_add > node->ch) // add to the right of node
795 {
796 log_msg(7, "depth=%d char=%c --- adding (right)", depth,
797 char_to_add);
798 newnode->right = node->right; // newnode is to the RIGHT of node
799 node->right = newnode;
800 node = newnode;
801 }
802 // from now on, we're working on 'node'
803 node->down = NULL;
804 node->ch = char_to_add;
805 node->expanded = node->selected = FALSE;
806 if (char_to_add == '\0') {
807 log_msg(6, "Added %s OK", original_string);
808 return (0);
809 }
810// add the rest
811 log_msg(6, "Adding remaining chars ('%s')", string_to_add + 1);
812 for (i = 1; i < noof_chars; i++) {
813 if (!
814 (node->down =
815 (struct s_node *) malloc(sizeof(struct s_node)))) {
816 log_to_screen("%s - failed to malloc", string_to_add);
817 return (1);
818 }
819 node = node->down;
820 char_to_add = string_to_add[i];
821 log_msg(6, "Adding '%c'", char_to_add);
822 node->ch = char_to_add;
823 node->right = node->down = NULL;
824 node->expanded = node->selected = FALSE;
825 if (!node->ch) {
826 node->selected = sosodef;
827 }
828 }
829 log_msg(6, "Finally - added %s OK", original_string);
830 return (0);
831}
832
833
834
835
836/**
837 * Load a filelist into a <tt>struct s_node</tt>.
838 * When you are done with the filelist, call free_filelist().
839 * @param filelist_fname The file to load the filelist from.
840 * @return A filelist tree structure.
841 */
842struct s_node *load_filelist(char *filelist_fname)
843{
844
845 /*@ structures ************************************************* */
846 struct s_node *filelist;
847
848 /*@ pointers *************************************************** */
849 FILE *pin;
850
851 /*@ buffers **************************************************** */
852 char *command_to_open_fname = NULL;
853 char *fname = NULL;
854 char *tmp = NULL;
855 char *tmp1 = NULL;
856 int pos_in_fname;
857 /*@ int ******************************************************** */
858 int percentage;
859
860 /*@ long ******************************************************* */
861 long lines_in_filelist;
862 long lino = 0;
863 /*@ end vars *************************************************** */
864
865 assert_string_is_neither_NULL_nor_zerolength(filelist_fname);
866
867 if (!does_file_exist(filelist_fname)) {
868 fatal_error("filelist does not exist -- cannot load it");
869 }
870 log_to_screen("Loading filelist");
871 mr_asprintf(tmp, "zcat %s | wc -l", filelist_fname);
872 log_msg(6, "tmp = %s", tmp);
873
874 tmp1 = call_program_and_get_last_line_of_output(tmp);
875 mr_free(tmp);
876
877 lines_in_filelist = atol(tmp1);
878 mr_free(tmp1);
879
880 if (lines_in_filelist < 3) {
881 log_to_screen("Warning - surprisingly short filelist.");
882 }
883 g_original_noof_lines_in_filelist = lines_in_filelist;
884 if (!(filelist = (struct s_node *) malloc(sizeof(struct s_node)))) {
885 return (NULL);
886 }
887 filelist->ch = '/';
888 filelist->right = NULL;
889 filelist->down = malloc(sizeof(struct s_node));
890 filelist->expanded = filelist->selected = FALSE;
891 (filelist->down)->ch = '\0';
892 (filelist->down)->right = (filelist->down)->down = FALSE;
893 (filelist->down)->expanded = (filelist->down)->selected = FALSE;
894
895 mr_asprintf(command_to_open_fname, "gzip -dc %s", filelist_fname);
896 if (!(pin = popen(command_to_open_fname, "r"))) {
897 log_OS_error("Unable to openin filelist_fname");
898 mr_free(command_to_open_fname);
899 return (NULL);
900 }
901 mr_free(command_to_open_fname);
902
903 open_evalcall_form("Loading filelist from disk");
904 for (mr_getline(fname, pin); !feof(pin); mr_getline(fname, pin)) {
905 if ((strlen(fname) > 0) && (fname[strlen(fname) - 1] == 13 || fname[strlen(fname) - 1] == 10)) {
906 fname[strlen(fname) - 1] = '\0';
907 }
908 if (!strlen(fname)) {
909 mr_free(fname);
910 continue;
911 }
912 for (pos_in_fname = 0; fname[pos_in_fname] != '\0'; pos_in_fname++) {
913 if (fname[pos_in_fname] != '/') {
914 continue;
915 }
916 mr_asprintf(tmp, "%s", fname);
917 tmp[pos_in_fname] = '\0';
918 if (strlen(tmp)) {
919 add_string_at_node(filelist, tmp);
920 }
921 mr_free(tmp);
922 }
923 add_string_at_node(filelist, fname);
924
925 if (!(++lino % 1111)) {
926 percentage = (int) (lino * 100 / lines_in_filelist);
927 update_evalcall_form(percentage);
928 }
929 mr_free(fname);
930 }
931 mr_free(fname);
932
933 paranoid_pclose(pin);
934 close_evalcall_form();
935 log_it("Finished loading filelist");
936 return (filelist);
937}
938
939
940/**
941 * Log a list of files in @p node.
942 * @param node The toplevel node to use.
943 */
944void show_filelist(struct s_node *node)
945{
946 static int depth = 0;
947 static char current_string[200];
948
949 if (depth == 0) {
950 log_msg(0, "----------------show filelist--------------");
951 }
952 current_string[depth] = node->ch;
953
954 log_msg(3, "depth=%d", depth);
955 if (node->down) {
956 log_msg(3, "moving down");
957 depth++;
958 show_filelist(node->down);
959 depth--;
960 }
961
962 if (!node->ch) {
963 log_msg(0, "%s\n", current_string);
964 }
965
966 if (node->right) {
967 log_msg(3, "moving right");
968 show_filelist(node->right);
969 }
970 if (depth == 0) {
971 log_msg(0, "----------------show filelist--------------");
972 }
973 return;
974}
975
976
977
978
979/**
980 * Reset the filelist to the state it was when it was loaded. This does not
981 * touch the file on disk.
982 * @param filelist The filelist tree structure.
983 */
984void reload_filelist(struct s_node *filelist)
985{
986 assert(filelist != NULL);
987 toggle_node_selection(filelist, FALSE);
988 toggle_path_expandability(filelist, "/", FALSE);
989 toggle_all_root_dirs_on(filelist);
990}
991
992
993
994/**
995 * Save a filelist tree structure to disk.
996 * @param filelist The filelist tree structure to save.
997 * @param outfname Where to save it.
998 */
999void save_filelist(struct s_node *filelist, char *outfname)
1000{
1001 /*@ int ********************************************************* */
1002 static int percentage;
1003 static int depth = 0;
1004
1005 /*@ buffers ***************************************************** */
1006 static char str[MAX_STR_LEN];
1007
1008 /*@ structures ************************************************** */
1009 struct s_node *node;
1010
1011 /*@ pointers **************************************************** */
1012 static FILE *fout = NULL;
1013
1014 /*@ long ******************************************************** */
1015 static long lines_in_filelist = 0;
1016 static long lino = 0;
1017
1018 /*@ end vars *************************************************** */
1019
1020 assert(filelist != NULL);
1021 assert(outfname != NULL); // will be zerolength if save_filelist() is called by itself
1022 if (depth == 0) {
1023 log_to_screen("Saving filelist");
1024 if (!(fout = fopen(outfname, "w"))) {
1025 fatal_error("Cannot openout/save filelist");
1026 }
1027 lines_in_filelist = g_original_noof_lines_in_filelist; /* set by load_filelist() */
1028 open_evalcall_form("Saving selection to disk");
1029 }
1030 for (node = filelist; node != NULL; node = node->right) {
1031 str[depth] = node->ch;
1032 log_msg(5, "depth=%d ch=%c", depth, node->ch);
1033 if (!node->ch) {
1034// if (node->selected)
1035// {
1036 fprintf(fout, "%s\n", str);
1037// }
1038 if (!(++lino % 1111)) {
1039 percentage = (int) (lino * 100 / lines_in_filelist);
1040 update_evalcall_form(percentage);
1041 }
1042 }
1043 if (node->down) {
1044 depth++;
1045 save_filelist(node->down, "");
1046 depth--;
1047 }
1048 }
1049 if (depth == 0) {
1050 paranoid_fclose(fout);
1051 close_evalcall_form();
1052 log_it("Finished saving filelist");
1053 }
1054}
1055
1056
1057
1058/**
1059 * Toggle all root dirs on.
1060 * @param filelist The filelist tree structure to operate on.
1061 * @bug I don't understand this function. Would someone care to explain it?
1062 */
1063void toggle_all_root_dirs_on(struct s_node *filelist)
1064{
1065 /*@ structures ************************************************** */
1066 struct s_node *node;
1067
1068 /*@ int ********************************************************* */
1069 static int depth = 0;
1070 static int root_dirs_expanded;
1071
1072 /*@ buffers ***************************************************** */
1073 static char filename[MAX_STR_LEN];
1074
1075 /*@ end vars *************************************************** */
1076
1077 assert(filelist != NULL);
1078 if (depth == 0) {
1079 log_it("Toggling all root dirs ON");
1080 root_dirs_expanded = 0;
1081 }
1082 for (node = filelist; node != NULL; node = node->right) {
1083 filename[depth] = node->ch;
1084 if (node->ch == '\0' && strlen(filename) > 1
1085 && (!strchr(filename + 1, '/'))) {
1086 node->selected = FALSE;
1087 node->expanded = TRUE;
1088// log_it (filename);
1089 root_dirs_expanded++;
1090 }
1091 if (node->down) {
1092 depth++;
1093 toggle_all_root_dirs_on(node->down);
1094 depth--;
1095 }
1096 }
1097 if (depth == 0) {
1098 log_it("Finished toggling all root dirs ON");
1099 }
1100}
1101
1102
1103/**
1104 * Toggle the expandability of a path.
1105 * @param filelist The filelist tree to operate on.
1106 * @param pathname The path to toggle expandability of.
1107 * @param on_or_off Whether to toggle it on or off.
1108 * @bug I don't understand this function. Would someone care to explain it?
1109 */
1110void
1111toggle_path_expandability(struct s_node *filelist, char *pathname,
1112 bool on_or_off)
1113{
1114
1115 /*@ int ******************************************************** */
1116 static int depth = 0;
1117 static int total_expanded;
1118 static int root_depth;
1119 int j;
1120 /*@ structures ************************************************* */
1121 struct s_node *node;
1122
1123 /*@ buffers **************************************************** */
1124 static char current_filename[MAX_STR_LEN];
1125
1126/* char tmp[MAX_STR_LEN+2]; */
1127
1128 /*@ end vars *************************************************** */
1129
1130 assert(filelist != NULL);
1131 assert_string_is_neither_NULL_nor_zerolength(pathname);
1132 if (depth == 0) {
1133 total_expanded = 0;
1134// log_it ("Toggling path's expandability");
1135 for (root_depth = (int) strlen(pathname);
1136 root_depth > 0 && pathname[root_depth - 1] != '/';
1137 root_depth--);
1138 if (root_depth < 2) {
1139 root_depth = (int) strlen(pathname);
1140 }
1141 }
1142 for (node = filelist; node != NULL; node = node->right) {
1143 current_filename[depth] = node->ch;
1144 if (node->down) {
1145 depth++;
1146 toggle_path_expandability(node->down, pathname, on_or_off);
1147 depth--;
1148 }
1149 if (node->ch == '\0') {
1150 if (!strncmp(pathname, current_filename, strlen(pathname))) {
1151 for (j = root_depth;
1152 current_filename[j] != '/'
1153 && current_filename[j] != '\0'; j++);
1154 if (current_filename[j] != '\0') {
1155 for (j++;
1156 current_filename[j] != '/'
1157 && current_filename[j] != '\0'; j++);
1158 }
1159 if (current_filename[j] == '\0') {
1160 node->expanded =
1161 (!strcmp(pathname, current_filename) ? TRUE :
1162 on_or_off);
1163 }
1164 }
1165 }
1166 if (node->expanded) {
1167 if (total_expanded < ARBITRARY_MAXIMUM - 32
1168 || !strrchr(current_filename + strlen(pathname), '/')) {
1169 total_expanded++;
1170 } else {
1171 node->expanded = FALSE;
1172 }
1173 }
1174 }
1175 if (depth == 0) {
1176// log_it ("Finished toggling expandability");
1177 }
1178}
1179
1180/**
1181 * Toggle whether a path is selected.
1182 * @param filelist The filelist tree to operate on.
1183 * @param pathname The path to toggle selection of.
1184 * @param on_or_off Whether to toggle it on or off.
1185 * @bug I don't understand this function. Would someone care to explain it?
1186 */
1187void
1188toggle_path_selection(struct s_node *filelist, char *pathname,
1189 bool on_or_off)
1190{
1191 /*@ int ********************************************************* */
1192 static int depth = 0;
1193 int j;
1194
1195 /*@ structures ************************************************** */
1196 struct s_node *node;
1197
1198 /*@ buffers ***************************************************** */
1199 static char current_filename[MAX_STR_LEN];
1200
1201 /*@ end vars *************************************************** */
1202 assert(filelist != NULL);
1203 assert_string_is_neither_NULL_nor_zerolength(pathname);
1204 if (depth == 0) {
1205 log_it("Toggling path's selection");
1206 }
1207 for (node = filelist; node != NULL; node = node->right) {
1208 current_filename[depth] = node->ch;
1209 if (node->down) {
1210 depth++;
1211 toggle_path_selection(node->down, pathname, on_or_off);
1212 depth--;
1213 }
1214 if (node->ch == '\0') {
1215 if (!strncmp(pathname, current_filename, strlen(pathname))) {
1216 for (j = 0;
1217 pathname[j] != '\0'
1218 && pathname[j] == current_filename[j]; j++);
1219 if (current_filename[j] == '/'
1220 || current_filename[j] == '\0') {
1221 node->selected = on_or_off;
1222 }
1223 }
1224 }
1225 }
1226 if (depth == 0) {
1227 log_it("Finished toggling selection");
1228 }
1229}
1230
1231
1232/**
1233 * Toggle node selection of a filelist tree.
1234 * @param filelist The filelist tree to operate on.
1235 * @param on_or_off Whether to toggle selection on or off.
1236 * @bug I don't understand this function. Would someone care to explain it?
1237 */
1238void toggle_node_selection(struct s_node *filelist, bool on_or_off)
1239{
1240 /*@ structure ************************************************** */
1241 struct s_node *node;
1242
1243 /*@ end vars *************************************************** */
1244 assert(filelist != NULL);
1245 for (node = filelist; node != NULL; node = node->right) {
1246 if (node->ch == '/') {
1247 continue;
1248 } /* don't go deep */
1249 if (node->ch == '\0') {
1250 node->selected = on_or_off;
1251 }
1252 if (node->down) {
1253 toggle_node_selection(node->down, on_or_off);
1254 }
1255 }
1256}
1257
1258
1259
1260/**
1261 * The pathname to the skeleton filelist, used to give better progress reporting for mondo_makefilelist().
1262 */
1263char *g_skeleton_filelist = NULL;
1264
1265
1266
1267/**
1268 * Get the next entry in the space-separated list in @p incoming.
1269 * So if @p incoming was '"one and two" three four', we would
1270 * return "one and two".
1271 * @param incoming The list to get the next entry from.
1272 * @return The first item in the list (respecting double quotes).
1273 * @note The returned string points to static data that will be overwritten with each call.
1274 */
1275char *next_entry(char *incoming)
1276{
1277 char *sz_res;
1278 char *p;
1279 bool in_quotes = FALSE;
1280
1281 mr_asprintf(sz_res, "%s", incoming);
1282 p = sz_res;
1283 while ((*p != ' ' || in_quotes) && *p != '\0') {
1284 if (*p == '\"') {
1285 in_quotes = !in_quotes;
1286 }
1287 p++;
1288 }
1289 *p = '\0';
1290 return (sz_res);
1291}
1292
1293
1294/**
1295 * Number of entries in the skeleton filelist.
1296 */
1297long g_skeleton_entries = 0;
1298
1299
1300/**
1301 * Recursively list all files in @p dir newer than @p time_of_last_full_backup to @p fout.
1302 * @param dir The directory to list to @p fout.
1303 * @param sth The directories to skip (exclude).
1304 * @param fout The file to write everything to.
1305 * @param time_of_last_full_backup Only backup files newer than this (0 to disable).
1306 * @return 0, always.
1307 * @bug Return value should be @c void.
1308 */
1309int open_and_list_dir(char *dir1, char *sth, FILE * fout, time_t time_of_last_full_backup) {
1310
1311 const char delims[] = " ";
1312
1313 DIR *dip;
1314 struct dirent *dit;
1315 struct stat statbuf;
1316 char *new;
1317 char *tmp = NULL;
1318 char *tmp1 = NULL;
1319 char *dir = NULL;
1320 static int percentage = 0;
1321 char *skip_these = NULL;
1322 char *new_with_spaces = NULL;
1323 char *strtmp;
1324 char *token;
1325 char *find_excludes = NULL;
1326 char *name_of_evalcall_form = NULL;
1327 char *find_skeleton_marker = NULL;
1328 int i;
1329 int lastpos = 0;
1330 static int depth = 0;
1331 char *p;
1332 static int counter = 0;
1333 static int uberctr = 0;
1334 static long skeleton_lino = 0L;
1335 static time_t last_time = (time_t)0;
1336 time_t this_time;
1337
1338 /* dir is needed when we pass it to the shell */
1339 dir = mr_stresc(dir1, "`$\\\"(){}'[]&*?|!#~", '\\');
1340 p = strrchr(dir1, '/');
1341 if (p) {
1342 if (!strcmp(p, "/.") || !strcmp(p, "/..")) {
1343 mr_free(dir);
1344 return (0);
1345 }
1346 }
1347
1348 if (!depth) {
1349 mr_asprintf(find_excludes, " ");
1350 if (sth != NULL) {
1351 while((token = mr_strtok(sth, delims, &lastpos))) {
1352 mr_strcat(find_excludes," -path %s -prune -o", token);
1353 mr_free(token);
1354 }
1355 }
1356#if linux
1357 // 2.6 has /sys as a proc-type thing -- must be excluded
1358 mr_asprintf(strtmp, "find '%s' -fstype mvfs -prune -o -fstype devpts -prune -o -fstype tmpfs -prune -o -fstype proc -prune -o -fstype sysfs -prune -o %s -type d -print > %s 2> /dev/null", dir, find_excludes, g_skeleton_filelist);
1359#else
1360 // On BSD, for example, /sys is the kernel sources -- don't exclude
1361 mr_asprintf(strtmp, "find '%s' -fstype mvfs -prune -o -path /proc -prune -o %s -type d -print > %s 2> /dev/null", dir, find_excludes, g_skeleton_filelist);
1362#endif
1363 mr_free(find_excludes);
1364
1365 log_msg(5, "find command = %s", strtmp);
1366 (void)system(strtmp);
1367 mr_free(strtmp);
1368
1369 mr_asprintf(tmp, "wc -l %s | awk '{print $1;}'", g_skeleton_filelist);
1370 tmp1 = call_program_and_get_last_line_of_output(tmp);
1371 mr_free(tmp);
1372
1373 g_skeleton_entries = 1 + atol(tmp1);
1374 mr_free(tmp1);
1375
1376 mr_asprintf(name_of_evalcall_form, "Making catalog of %s", dir1);
1377 open_evalcall_form(name_of_evalcall_form);
1378 mr_free(name_of_evalcall_form);
1379
1380 skeleton_lino = 1;
1381 log_msg(5, "entries = %ld", g_skeleton_entries);
1382 percentage = 0;
1383 } else // update evalcall form if appropriate
1384 {
1385 mr_asprintf(find_skeleton_marker, "grep -Fv '%s' %s > %s.new 2> /dev/null", dir, g_skeleton_filelist, g_skeleton_filelist);
1386 if (!system(find_skeleton_marker)) {
1387 percentage = (int) (skeleton_lino * 100 / g_skeleton_entries);
1388 skeleton_lino++;
1389 mr_free(find_skeleton_marker);
1390
1391 mr_asprintf(find_skeleton_marker, "mv -f %s.new %s", g_skeleton_filelist, g_skeleton_filelist);
1392 (void)system(find_skeleton_marker);
1393 time(&this_time);
1394 if (this_time != last_time) {
1395 last_time = this_time;
1396 if (!g_text_mode) {
1397 mr_asprintf(tmp, "Reading %-68s", dir1);
1398 newtDrawRootText(0, g_noof_rows - 3, tmp);
1399 mr_free(tmp);
1400 }
1401 update_evalcall_form(percentage);
1402 }
1403 }
1404 mr_free(find_skeleton_marker);
1405 }
1406
1407 depth++;
1408
1409// log_msg(0, "Cataloguing %s", dir);
1410 if (sth[0] == ' ') {
1411 mr_asprintf(skip_these, "%s", sth);
1412 } else {
1413 mr_asprintf(skip_these, " %s ", sth);
1414 }
1415 mr_asprintf(new_with_spaces, " %s ", dir1);
1416 if ((dip = opendir(dir1)) == NULL) {
1417 mr_asprintf(tmp,"opendir %s", dir1);
1418 log_OS_error(tmp);
1419 mr_free(tmp);
1420 } else if (strstr(skip_these, new_with_spaces)) {
1421 log_msg(10, "Found dir ***%s**** excluded", dir1);
1422 fprintf(fout, "%s\n", dir1); // if excluded dir then print dir ONLY
1423 } else {
1424 log_msg(10, "Found dir ***%s**** parsed", dir1);
1425 fprintf(fout, "%s\n", dir1);
1426 while ((dit = readdir(dip)) != NULL) {
1427 i++;
1428 if (strcmp(dir1, "/")) {
1429 mr_asprintf(new,"%s/%s",dir1,dit->d_name);
1430 } else {
1431 mr_asprintf(new,"%s%s",dir1,dit->d_name);
1432 }
1433 mr_free(new_with_spaces);
1434 mr_asprintf(new_with_spaces, " %s ", new);
1435 if (strstr(skip_these, new_with_spaces)) {
1436 fprintf(fout, "%s\n", new);
1437 log_msg(10, "Found child dir ***%s**** excluded", new);
1438 mr_free(new_with_spaces);
1439 } else {
1440 mr_free(new_with_spaces);
1441 if (!lstat(new, &statbuf)) {
1442 if (!S_ISLNK(statbuf.st_mode)
1443 && S_ISDIR(statbuf.st_mode)) {
1444 log_msg(10, "Found child dir ***%s**** parsed", new);
1445 open_and_list_dir(new, skip_these, fout, time_of_last_full_backup);
1446 } else {
1447 if (time_of_last_full_backup == 0 || time_of_last_full_backup < statbuf.st_ctime) {
1448 log_msg(10, "Found child file ***%s**** parsed", new);
1449 log_msg(10, "Found child file ***%s**** parsed", new);
1450 fprintf(fout, "%s\n", new);
1451 if ((counter++) > 128) {
1452 counter = 0;
1453 uberctr++;
1454 mr_asprintf(tmp, " %c ", special_dot_char(uberctr));
1455 if (!g_text_mode) {
1456 newtDrawRootText(77, g_noof_rows - 3, tmp);
1457 newtRefresh();
1458 }
1459 mr_free(tmp);
1460 }
1461 }
1462 }
1463 }
1464 }
1465 mr_free(new);
1466 }
1467 }
1468 mr_free(new_with_spaces);
1469 mr_free(skip_these);
1470 mr_free(dir);
1471
1472 if (dip) {
1473 if (closedir(dip) == -1) {
1474 log_OS_error("closedir");
1475 }
1476 }
1477 depth--;
1478 if (!depth) {
1479 close_evalcall_form();
1480 unlink(g_skeleton_filelist);
1481 log_msg(5, "g_skeleton_entries = %ld", g_skeleton_entries);
1482 }
1483 return (0);
1484}
1485
1486
1487
1488
1489/**
1490 * Create the filelist for the backup. It will be stored in [scratchdir]/archives/filelist.full.
1491 * @param logfile Unused.
1492 * @param include_paths The paths to back up, or NULL if you're using a user-defined filelist.
1493 * @param excp The paths to NOT back up.
1494 * @param differential The differential level (currently only 0 and 1 are supported).
1495 * @param userdef_filelist The user-defined filelist, or NULL if you're using @p include_paths.
1496 * @return 0, always.
1497 * @bug @p logfile is unused.
1498 * @bug Return value is meaningless.
1499 */
1500int mondo_makefilelist(char *logfile, char *include_paths, char *excp, int differential, char *userdef_filelist)
1501{
1502 char *p, *q;
1503 char *sz_datefile;
1504 char *sz_filelist;
1505 char *exclude_paths = NULL;
1506 int i;
1507 FILE *fout;
1508 char *command = NULL;
1509 time_t time_of_last_full_backup = 0;
1510 struct stat statbuf;
1511 char *tmp1 = NULL;
1512 char *tmp2 = NULL;
1513
1514 mr_asprintf(sz_datefile,MONDO_CACHE"/difflevel.%d" , 0);
1515 if (!include_paths && !userdef_filelist) {
1516 fatal_error("Please supply either include_paths or userdef_filelist");
1517 }
1518 // make hole for filelist
1519 mr_asprintf(command, "mkdir -p %s/archives", bkpinfo->scratchdir);
1520 paranoid_system(command);
1521 mr_free(command);
1522
1523 mr_asprintf(sz_filelist, "%s/tmpfs/filelist.full", bkpinfo->tmpdir);
1524 make_hole_for_file(sz_filelist);
1525
1526 if (differential == 0) {
1527 // restore last good datefile if it exists
1528 mr_asprintf(command, "cp -f %s.aborted %s", sz_datefile, sz_datefile);
1529 run_program_and_log_output(command, 3);
1530 mr_free(command);
1531
1532 // backup last known good datefile just in case :)
1533 if (does_file_exist(sz_datefile)) {
1534 mr_asprintf(command, "mv -f %s %s.aborted", sz_datefile, sz_datefile);
1535 paranoid_system(command);
1536 mr_free(command);
1537 }
1538 make_hole_for_file(sz_datefile);
1539 tmp1 = call_program_and_get_last_line_of_output("date +%s");
1540 write_one_liner_data_file(sz_datefile, tmp1);
1541 mr_free(tmp1);
1542 } else if (lstat(sz_datefile, &statbuf)) {
1543 log_msg(2, "Warning - unable to find date of previous backup. Full backup instead.");
1544 differential = 0;
1545 time_of_last_full_backup = 0;
1546 } else {
1547 time_of_last_full_backup = statbuf.st_mtime;
1548 log_msg(2, "Differential backup. Yay.");
1549 }
1550 paranoid_free(sz_datefile);
1551
1552// use user-specified filelist (if specified)
1553 if (userdef_filelist) {
1554 log_msg(1, "Using the user-specified filelist - %s - instead of calculating one", userdef_filelist);
1555 mr_asprintf(command, "cp -f %s %s", userdef_filelist, sz_filelist);
1556 if (run_program_and_log_output(command, 3)) {
1557 mr_free(command);
1558 fatal_error("Failed to copy user-specified filelist");
1559 }
1560 mr_free(command);
1561 } else {
1562 if (include_paths) {
1563 log_msg(2, "include_paths = '%s'", include_paths);
1564 }
1565 log_msg(1, "Calculating filelist");
1566 tmp2 = call_program_and_get_last_line_of_output("mount | grep -Ew 'ntfs|ntfs-3g|fat|vfat|dos' | awk '{print $3}'");
1567 if (strlen(tmp2) < 1) {
1568 mr_asprintf(tmp1," ");
1569 } else {
1570 log_msg(2, "Found windows FS: %s",tmp2);
1571 mr_asprintf(tmp1, "find %s -name '/win386.swp' -o -name '/hiberfil.sys' -o -name '/pagefile.sys' 2> /dev/null\n",tmp2);
1572 mr_free(tmp2);
1573 tmp2 = call_program_and_get_last_line_of_output(tmp1);
1574 log_msg(2, "Found windows files: %s",tmp2);
1575 }
1576 mr_free(tmp1);
1577
1578 mr_asprintf(exclude_paths, " %s %s %s %s %s . .. " MNT_CDROM " " MNT_FLOPPY " /media /tmp /proc /sys /dev/shm " MINDI_CACHE, MONDO_CACHE, (excp == NULL) ? "" : excp, tmp2, (bkpinfo->tmpdir[0] == '/' && bkpinfo->tmpdir[1] == '/') ? (bkpinfo->tmpdir + 1) : bkpinfo->tmpdir, (bkpinfo->scratchdir[0] == '/' && bkpinfo->scratchdir[1] == '/') ? (bkpinfo->scratchdir + 1) : bkpinfo->scratchdir);
1579 mr_free(tmp2);
1580
1581 log_msg(2, "Excluding paths = '%s'", exclude_paths);
1582 log_msg(2, "Generating skeleton filelist so that we can track our progress");
1583 mr_asprintf(g_skeleton_filelist, "%s/tmpfs/skeleton.txt", bkpinfo->tmpdir);
1584 make_hole_for_file(g_skeleton_filelist);
1585 log_msg(4, "g_skeleton_entries = %ld", g_skeleton_entries);
1586 log_msg(2, "Opening out filelist to %s", sz_filelist);
1587 if (!(fout = fopen(sz_filelist, "w"))) {
1588 fatal_error("Cannot openout to sz_filelist");
1589 }
1590 i = 0;
1591 if ((!include_paths) || (strlen(include_paths) == 0)) {
1592 log_msg(1, "Including only '/' in %s", sz_filelist);
1593 open_and_list_dir("/", exclude_paths, fout,
1594 time_of_last_full_backup);
1595 } else {
1596 p = include_paths;
1597 while (*p) {
1598 q = next_entry(p);
1599 log_msg(1, "Including %s in filelist %s", q, sz_filelist);
1600 open_and_list_dir(q, exclude_paths, fout,
1601 time_of_last_full_backup);
1602 p += strlen(q);
1603 paranoid_free(q);
1604 while (*p == ' ') {
1605 p++;
1606 }
1607 }
1608 }
1609 mr_free(exclude_paths);
1610 paranoid_fclose(fout);
1611 }
1612 log_msg(2, "Copying new filelist to scratchdir");
1613 mr_asprintf(command, "mkdir -p %s/archives", bkpinfo->scratchdir);
1614 paranoid_system(command);
1615 mr_free(command);
1616
1617 mr_asprintf(command, "cp -f %s %s/archives/", sz_filelist, bkpinfo->scratchdir);
1618 paranoid_system(command);
1619 mr_free(command);
1620
1621 mr_asprintf(command, "mv -f %s %s", sz_filelist, bkpinfo->tmpdir);
1622 paranoid_system(command);
1623 mr_free(command);
1624
1625 paranoid_free(sz_filelist);
1626 log_msg(2, "Freeing variables");
1627 mr_free(g_skeleton_filelist);
1628 log_msg(2, "Exiting");
1629 return (0);
1630}
1631
1632/**
1633 * Wrapper around mondo_makefilelist().
1634 * @param bkpinfo The backup information structure. Fields used:
1635 * - @c bkpinfo->differential
1636 * - @c bkpinfo->exclude_paths
1637 * - @c bkpinfo->include_paths
1638 * - @c bkpinfo->make_filelist
1639 * - @c bkpinfo->scratchdir
1640 * - @c bkpinfo->tmpdir
1641 * @return 0 for success, nonzero for failure.
1642 * @see mondo_makefilelist
1643 */
1644int prepare_filelist()
1645{
1646
1647 /*@ int **************************************************** */
1648 int res = 0;
1649
1650/**
1651 * Wrapper around mondo_makefilelist().
1652 * @param bkpinfo The backup information structure. Fields used:
1653 * - @c bkpinfo->differential
1654 * - @c bkpinfo->exclude_paths
1655 * - @c bkpinfo->include_paths
1656 * - @c bkpinfo->make_filelist
1657 * - @c bkpinfo->scratchdir
1658 * - @c bkpinfo->tmpdir
1659 * @return 0 for success, nonzero for failure.
1660 * @see mondo_makefilelist
1661 */
1662int prepare_filelist()
1663{
1664
1665 /*@ int **************************************************** */
1666 int res = 0;
1667
1668 assert(bkpinfo != NULL);
1669 log_it("tmpdir=%s; scratchdir=%s", bkpinfo->tmpdir, bkpinfo->scratchdir);
1670 if (bkpinfo->make_filelist) {
1671 mvaddstr_and_log_it(g_currentY, 0,
1672 "Making catalog of files to be backed up");
1673 } else {
1674 mvaddstr_and_log_it(g_currentY, 0,
1675 "Using supplied catalog of files to be backed up");
1676 }
1677
1678 if (bkpinfo->make_filelist) {
1679 res =
1680 mondo_makefilelist(MONDO_LOGFILE, bkpinfo->include_paths, bkpinfo->exclude_paths, bkpinfo->differential, NULL);
1681 } else {
1682 res =
1683 mondo_makefilelist(MONDO_LOGFILE, NULL, bkpinfo->exclude_paths, bkpinfo->differential, bkpinfo->include_paths);
1684 }
1685
1686 if (res) {
1687 log_OS_error("Call to mondo_makefilelist failed");
1688 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1689 } else {
1690 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1691 }
1692 return (res);
1693}
1694
1695
1696/**
1697 * Locate the string @p string_to_find in the tree rooted at @p startnode.
1698 * @param startnode The node containing the root of the directory tree.
1699 * @param string_to_find The string to look for at @p startnode.
1700 * @return The node containing the last element of @p string_to_find, or NULL if
1701 * it was not found.
1702 */
1703struct s_node *find_string_at_node(struct s_node *startnode,
1704 char *string_to_find)
1705{
1706 /*@ int ******************************************************** */
1707 int noof_chars;
1708 static int depth = 0;
1709 static char original_string[MAX_STR_LEN];
1710
1711 /*@ sturctures ************************************************* */
1712 struct s_node *node;
1713
1714 /*@ char ****************************************************** */
1715 char char_to_find;
1716
1717 /*@ bools ****************************************************** */
1718
1719 if (!depth) {
1720 strcpy(original_string, string_to_find);
1721 }
1722
1723 assert(startnode != NULL);
1724 assert(string_to_find != NULL);
1725
1726 noof_chars = strlen(string_to_find) + 1; /* we include the '\0' */
1727
1728 log_msg(7, "starting --- str=%s", string_to_find);
1729
1730/* walk across tree if necessary */
1731 node = startnode;
1732 char_to_find = string_to_find[0];
1733 if (node->right != NULL && node->ch < char_to_find) {
1734 log_msg(7, "depth=%d --- going RIGHT ... %c-->%c", depth,
1735 char_to_find, node->ch, (node->right)->ch);
1736 return (find_string_at_node(node->right, string_to_find));
1737 }
1738
1739/* walk down tree if appropriate */
1740 if (node->down != NULL && node->ch == char_to_find) {
1741 log_msg(7, "depth=%d char=%c --- going DOWN", depth, char_to_find);
1742 depth++;
1743 node = find_string_at_node(node->down, string_to_find + 1);
1744 depth--;
1745 return (node);
1746 }
1747
1748 if (char_to_find == '\0' && node->ch == '\0') {
1749 log_msg(7, "%s is in tree", original_string);
1750 return (node);
1751 } else {
1752 log_msg(7, "%s is NOT in tree", original_string);
1753 return (NULL);
1754 }
1755}
1756
1757
1758
1759/**
1760 * Write all entries in @p needles_list_fname which are also in
1761 * @p filelist to @p matches_list_fname.
1762 * @param needles_list_fname A file containing strings to look for, 1 per line.
1763 * @param filelist The node for the root of the directory structure to search in.
1764 * @param matches_list_fname The filename where we should put the matches.
1765 * @return The number of matches found.
1766 */
1767long save_filelist_entries_in_common(char *needles_list_fname,
1768 struct s_node *filelist,
1769 char *matches_list_fname,
1770 bool use_star)
1771{
1772 int retval = 0;
1773 struct s_node *found_node;
1774 FILE *fin;
1775 FILE *fout;
1776 char *fname = NULL;
1777 char *tmp = NULL;
1778
1779 log_msg(5, "starting");
1780 log_msg(5, "needles_list_fname = %s", needles_list_fname);
1781 log_msg(5, "matches_list_fname = %s", matches_list_fname);
1782 if (!(fin = fopen(needles_list_fname, "r"))) {
1783 fatal_error("Cannot openin needles_list_fname");
1784 }
1785 if (!(fout = fopen(matches_list_fname, "w"))) {
1786 fatal_error("Cannot openout matches_list_fname");
1787 }
1788 while (!feof(fin)) {
1789 mr_getline(fname, fin);
1790 if (!use_star) {
1791 if (fname[0] == '/') {
1792 mr_asprintf(tmp, "%s", fname);
1793 } else {
1794 mr_asprintf(tmp, "/%s", fname);
1795 }
1796 mr_free(fname);
1797 fname = tmp;
1798 }
1799 while (strlen(fname) > 0 && fname[strlen(fname) - 1] < 32) {
1800 fname[strlen(fname) - 1] = '\0';
1801 }
1802
1803 log_msg(5, "Looking for '%s'", fname);
1804 found_node = find_string_at_node(filelist, fname);
1805 if (found_node) {
1806 if (found_node->selected) {
1807 if (fname[0] == '/') {
1808 mr_asprintf(tmp, "%s", fname + 1);
1809 mr_free(fname);
1810 fname = tmp;
1811 }
1812 log_msg(5, "Found '%s'", fname);
1813 tmp = mr_stresc(fname, "[]*?", '\\');
1814 mr_free(fname);
1815 fname = tmp;
1816 fprintf(fout, "%s\n", fname);
1817 retval++;
1818 }
1819 }
1820 mr_free(fname);
1821 }
1822 paranoid_fclose(fout);
1823 paranoid_fclose(fin);
1824 return (retval);
1825}
1826
1827
1828
1829/**
1830 * Add all files listed in @p list_of_files_fname to the directory structure rooted at
1831 * @p filelist.
1832 * @param filelist The top node of the directory structure to add the files to.
1833 * @param list_of_files_fname The file containing the files to add, 1 per line.
1834 * @param flag_em If TRUE, then flag the added files for restoration.
1835 * @return 0 for success, nonzero for failure.
1836 */
1837int add_list_of_files_to_filelist(struct s_node *filelist,
1838 char *list_of_files_fname, bool flag_em)
1839{
1840 FILE *fin = NULL;
1841 char *tmp = NULL;
1842 struct s_node *nod = NULL;
1843
1844 log_msg(3, "Adding %s to filelist", list_of_files_fname);
1845 if (!(fin = fopen(list_of_files_fname, "r"))) {
1846 log_it("%s",list_of_files_fname);
1847 return (1);
1848 }
1849 for (mr_getline(tmp, fin); !feof(fin); mr_getline(tmp, fin)) {
1850 if (!tmp[0]) {
1851 mr_free(tmp);
1852 continue;
1853 }
1854 if ((strlen(tmp) > 0) && (tmp[strlen(tmp) - 1] == 13 || tmp[strlen(tmp) - 1] == 10)) {
1855 tmp[strlen(tmp) - 1] = '\0';
1856 }
1857 log_msg(2, "tmp = '%s'", tmp);
1858 if (!tmp[0]) {
1859 mr_free(tmp);
1860 continue;
1861 }
1862 if ((nod = find_string_at_node(filelist, tmp))) {
1863 log_msg(5, "Found '%s' in filelist already. Cool.", tmp);
1864 } else {
1865 add_string_at_node(filelist, tmp);
1866 nod = find_string_at_node(filelist, tmp);
1867 }
1868
1869 if (nod && flag_em) {
1870 toggle_path_selection(filelist, tmp, TRUE);
1871 log_msg(5, "Flagged '%s'", tmp);
1872 }
1873 mr_free(tmp);
1874 }
1875 mr_free(tmp);
1876 paranoid_fclose(fin);
1877 return (0);
1878}
1879
1880/* @} - end of filelistGroup */
Note: See TracBrowser for help on using the repository browser.