fdupes  2.1.2
About: FDUPES finds duplicate files in a given set of directories.
  Fossies Dox: fdupes-2.1.2.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

log.c
Go to the documentation of this file.
1 /* Copyright (c) 2018 Adrian Lopez
2 
3  This software is provided 'as-is', without any express or implied
4  warranty. In no event will the authors be held liable for any damages
5  arising from the use of this software.
6 
7  Permission is granted to anyone to use this software for any purpose,
8  including commercial applications, and to alter it and redistribute it
9  freely, subject to the following restrictions:
10 
11  1. The origin of this software must not be misrepresented; you must not
12  claim that you wrote the original software. If you use this software
13  in a product, an acknowledgment in the product documentation would be
14  appreciated but is not required.
15  2. Altered source versions must be plainly marked as such, and must not be
16  misrepresented as being the original software.
17  3. This notice may not be removed or altered from any source distribution. */
18 
19 #include <stdlib.h>
20 #include <string.h>
21 #include <time.h>
22 #include "fmatch.h"
23 #include "dir.h"
24 #include "log.h"
25 
26 #define LOG_HEADER "[fdupes log]\n"
27 
28 /* Open log file in append mode. If file exists, make sure it is a valid fdupes log file.
29 */
30 struct log_info *log_open(char *filename, int *error)
31 {
32  struct log_info *info;
33  int is_match;
34  size_t read;
35 
36  info = (struct log_info*) malloc(sizeof(struct log_info));
37  if (info == 0)
38  {
39  if (error != 0)
40  *error = LOG_ERROR_OUT_OF_MEMORY;
41 
42  return 0;
43  }
44 
45  info->file = fopen(filename, "a+");
46  if (info->file == 0)
47  {
48  if (error != 0)
49  *error = LOG_ERROR_FOPEN_FAILED;
50 
51  free(info);
52  return 0;
53  }
54 
55  fmatch(info->file, LOG_HEADER, &is_match, &read);
56  if (!is_match && read > 0)
57  {
58  if (error != 0)
59  *error = LOG_ERROR_NOT_A_LOG_FILE;
60 
61  free(info);
62  return 0;
63  }
64 
65  info->append = read > 0;
66 
67  info->log_start = 1;
68  info->deleted = 0;
69  info->remaining = 0;
70 
71  if (error != 0)
72  *error = LOG_ERROR_NONE;
73 
74  return info;
75 }
76 
77 /* Free linked lists holding set of deleted and remaining files.
78 */
79 void log_free_set(struct log_info *info)
80 {
81  struct log_file *f;
82  struct log_file *next;
83 
84  f = info->deleted;
85  while (f != 0)
86  {
87  next = f->next;
88 
89  free(f);
90 
91  f = next;
92  }
93 
94  f = info->remaining;
95  while (f != 0)
96  {
97  next = f->next;
98 
99  free(f);
100 
101  f = next;
102  }
103 
104  info->deleted = 0;
105  info->remaining = 0;
106 }
107 
108 /* Signal beginning of duplicate set.
109 */
110 void log_begin_set(struct log_info *info)
111 {
112  log_free_set(info);
113 }
114 
115 /* Add deleted file to log.
116 */
117 int log_file_deleted(struct log_info *info, char *name)
118 {
119  struct log_file *file;
120 
121  file = (struct log_file*) malloc(sizeof(struct log_file));
122  if (file == 0)
123  return 0;
124 
125  file->next = info->deleted;
126  file->filename = name;
127 
128  info->deleted = file;
129 
130  return 1;
131 }
132 
133 /* Add remaining file to log.
134 */
135 int log_file_remaining(struct log_info *info, char *name)
136 {
137  struct log_file *file;
138 
139  file = (struct log_file*) malloc(sizeof(struct log_file));
140  if (file == 0)
141  return 0;
142 
143  file->next = info->remaining;
144  file->filename = name;
145 
146  info->remaining = file;
147 
148  return 1;
149 }
150 
151 /* Output log header.
152 */
153 void log_header(FILE *file)
154 {
155  fprintf(file, "%s\n", LOG_HEADER);
156 }
157 
158 /* Output log timestamp.
159 */
160 void log_timestamp(FILE *file)
161 {
162  time_t t = time(NULL);
163  struct tm tm = *localtime(&t);
164 
165  fprintf(file, "Log entry for %d-%02d-%02d %02d:%02d:%02d\n\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
166 }
167 
168 /* Output current working directory.
169 */
170 void log_cwd(FILE *file)
171 {
172  char *cwd = getworkingdirectory();
173 
174  fprintf(file, "working directory:\n %s\n\n", cwd);
175 
176  free(cwd);
177 }
178 
179 /* Signal the end of a duplicate set.
180 */
181 void log_end_set(struct log_info *info)
182 {
183  struct log_file *f;
184 
185  if (info->deleted == 0)
186  return;
187 
188  if (info->log_start)
189  {
190  if (info->append)
191  fprintf(info->file, "---\n\n");
192  else
193  log_header(info->file);
194 
195  log_timestamp(info->file);
196  log_cwd(info->file);
197 
198  info->log_start = 0;
199  }
200 
201  f = info->deleted;
202  do
203  {
204  fprintf(info->file, "deleted %s\n", f->filename);
205  f = f->next;
206  } while (f != 0);
207 
208  f = info->remaining;
209  while (f != 0)
210  {
211  fprintf(info->file, " left %s\n", f->filename);
212  f = f->next;
213  }
214 
215  fprintf(info->file, "\n");
216 
217  fflush(info->file);
218 }
219 
220 /* Close log and free all memory.
221 */
222 void log_close(struct log_info *info)
223 {
224  fclose(info->file);
225 
226  log_free_set(info);
227 
228  free(info);
229 }
LOG_ERROR_FOPEN_FAILED
#define LOG_ERROR_FOPEN_FAILED
Definition: log.h:26
log_close
void log_close(struct log_info *info)
Definition: log.c:222
log_end_set
void log_end_set(struct log_info *info)
Definition: log.c:181
LOG_ERROR_NOT_A_LOG_FILE
#define LOG_ERROR_NOT_A_LOG_FILE
Definition: log.h:27
log_cwd
void log_cwd(FILE *file)
Definition: log.c:170
fmatch.h
log_header
void log_header(FILE *file)
Definition: log.c:153
log_info
Definition: log.h:36
log_info::append
int append
Definition: log.h:38
log_open
struct log_info * log_open(char *filename, int *error)
Definition: log.c:30
log_begin_set
void log_begin_set(struct log_info *info)
Definition: log.c:110
getworkingdirectory
char * getworkingdirectory()
Definition: dir.c:24
log_timestamp
void log_timestamp(FILE *file)
Definition: log.c:160
log_free_set
void log_free_set(struct log_info *info)
Definition: log.c:79
log.h
log_file_remaining
int log_file_remaining(struct log_info *info, char *name)
Definition: log.c:135
log_file::filename
char * filename
Definition: log.h:31
fmatch
void fmatch(FILE *file, char *matchstring, int *is_match, size_t *chars_read)
Definition: fmatch.c:24
LOG_HEADER
#define LOG_HEADER
Definition: log.c:26
log_info::log_start
int log_start
Definition: log.h:39
LOG_ERROR_NONE
#define LOG_ERROR_NONE
Definition: log.h:24
LOG_ERROR_OUT_OF_MEMORY
#define LOG_ERROR_OUT_OF_MEMORY
Definition: log.h:25
log_info::remaining
struct log_file * remaining
Definition: log.h:41
log_info::file
FILE * file
Definition: log.h:37
log_file::next
struct log_file * next
Definition: log.h:32
log_file_deleted
int log_file_deleted(struct log_info *info, char *name)
Definition: log.c:117
dir.h
log_file
Definition: log.h:30
log_info::deleted
struct log_file * deleted
Definition: log.h:40