1 /* vim: set sw=4 ts=4 noexpandtab : */
2 /*
3  * Copyright (C) 2007-2019 Abel Cheung.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the project nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #ifndef _RIFIUTI_UTILS_H
32 #define _RIFIUTI_UTILS_H
33 
34 /*
35  * Rifiuti itself only need _POSIX_C_SOURCE == 1 for usage of
36  * localtime_r(); however glib2's usage of siginfo_t pushes
37  * the requirement further. It's undefined in some Unices.
38  */
39 #ifndef _POSIX_C_SOURCE
40 #define _POSIX_C_SOURCE 199309L
41 #endif
42 
43 #include <inttypes.h>
44 #include <time.h>
45 #include <stdio.h>
46 #include <glib.h>
47 
48 /* Error and exit status */
49 typedef enum
50 {
51 	R2_OK = 0, /* as synonym of EXIT_SUCCESS */
52 	R2_ERR_ARG,
53 	R2_ERR_OPEN_FILE,
54 	R2_ERR_BROKEN_FILE,  /* file format validation failure */
55 	R2_ERR_WRITE_FILE,
56 	R2_ERR_USER_ENCODING,
57 	R2_ERR_INTERNAL = 64
58 } r2status;
59 
60 typedef enum
61 {
62 	RECYCLE_BIN_TYPE_FILE,
63 	RECYCLE_BIN_TYPE_DIR,
64 } rbin_type;
65 
66 /* The first 4 or 8 bytes of recycle bin index files */
67 enum
68 {
69 	/* negative number means error when retrieving version info */
70 	VERSION_INCONSISTENT = -2,
71 	VERSION_NOT_FOUND,
72 
73 	/* $Recycle.bin */
74 	VERSION_VISTA = 1,
75 	VERSION_WIN10,
76 
77 	/* INFO / INFO2 */
78 	VERSION_WIN95 = 0,
79 	VERSION_NT4   = 2,
80 	VERSION_WIN98 = 4,
81 	VERSION_ME_03,
82 };
83 
84 /*
85  * The following enum is different from the versions above.
86  * This is more detailed breakdown, and for detection of exact
87  * Windows version from various recycle bin artifacts.
88  * WARNING: MUST match os_strings string array
89  */
90 typedef enum
91 {
92 	OS_GUESS_UNKNOWN = -1,
93 	OS_GUESS_95,
94 	OS_GUESS_NT4,
95 	OS_GUESS_98,
96 	OS_GUESS_ME,
97 	OS_GUESS_2K,
98 	OS_GUESS_XP_03,
99 	OS_GUESS_2K_03,   /* Empty recycle bin, full detection impossible */
100 	OS_GUESS_VISTA,   /* includes everything up to 8.1 */
101 	OS_GUESS_10
102 } _os_guess;
103 
104 enum
105 {
106 	OUTPUT_NONE,
107 	OUTPUT_CSV,
108 	OUTPUT_XML
109 };
110 
111 /*! \struct _rbin_meta
112  *  \brief Metadata for recycle bin
113  */
114 typedef struct _rbin_meta
115 {
116 	rbin_type       type;
117 	const char     *filename;
118 	_os_guess       os_guess;
119 	int64_t         version;
120 	uint32_t        recordsize;          /*!< INFO2 only */
121 	uint32_t        total_entry;         /*!< 95/NT4 only */
122 	gboolean        keep_deleted_entry;  /*!< 98-03 only, add extra output column */
123 	gboolean        is_empty;
124 	gboolean        has_unicode_path;
125 	gboolean        fill_junk;  /*!< TRUE for 98/ME/2000 only, some fields padded
126 	                                 with junk data instaed of zeroed */
127 } metarecord;
128 
129 /*! \struct _rbin_struct
130  *  \brief Struct for single recycle bin item
131  */
132 typedef struct _rbin_struct
133 {
134 	/*! For $Recycle.bin, version of each index file is kept here,
135 	 * while meta.version keeps the global status of whole dir */
136 	uint64_t          version;          /* $Recycle.bin only */
137 
138 	/*! Each record links to metadata for more convenient access */
139 	const metarecord *meta;
140 
141 	/*! \brief Number is for INFO2, file name for $Recycle.bin */
142 	union
143 	{
144 		uint32_t      index_n;          /* INFO2 only */
145 		char         *index_s;          /* $Recycle.bin only */
146 	};
147 
148 	/*! Item delection time */
149 	time_t            deltime;
150 
151 	/*! Can mean cluster size or actual file/folder size */
152 	uint64_t          filesize;
153 
154 	/* despite var names, all filenames are converted to UTF-8 upon parsing */
155 	char             *uni_path;
156 	char             *legacy_path;     /* INFO2 only */
157 
158 	gboolean          emptied;         /* INFO2 only */
159 	unsigned char     drive;           /* INFO2 only */
160 } rbin_struct;
161 
162 /* convenience macro */
163 #define copy_field(field, off1, off2) memcpy((field), \
164 		buf + off1 ## _OFFSET, off2 ## _OFFSET - off1 ## _OFFSET)
165 
166 /*! Every Windows use this GUID in recycle bin desktop.ini */
167 #define RECYCLE_BIN_CLSID "645FF040-5081-101B-9F08-00AA002F954E"
168 
169 /*
170  * Most versions of recycle bin use full PATH_MAX (260 char) to store file paths,
171  * in either ANSI or Unicode variations, except Windows 10 which uses variable size.
172  * However we don't want to use PATH_MAX directly since on Linux/Unix it's
173  * another thing.
174  */
175 #define WIN_PATH_MAX 260
176 
177 /* shared functions */
178 void          rifiuti_init                (const char       *progpath);
179 
180 void          rifiuti_setup_opt_ctx       (GOptionContext    **context,
181                                            rbin_type         type);
182 
183 r2status      rifiuti_parse_opt_ctx      (GOptionContext  **context,
184                                            int              *argc,
185                                            char           ***argv);
186 
187 time_t        win_filetime_to_epoch       (uint64_t          win_filetime);
188 
189 char *        utf16le_to_utf8             (const gunichar2  *str,
190                                            glong             len,
191                                            glong            *items_read,
192                                            glong            *items_written,
193                                            GError          **error)
194                                            G_GNUC_UNUSED;
195 
196 int           check_file_args             (const char       *path,
197                                            GSList          **list,
198                                            rbin_type         type);
199 
200 r2status      prepare_output_handle       (void);
201 
202 void          close_output_handle         (void);
203 
204 void          print_header                (metarecord        meta);
205 
206 void          print_record_cb             (rbin_struct      *record);
207 
208 void          print_footer                (void);
209 
210 r2status      move_temp_file              (void);
211 
212 void          print_version_and_exit      (void) G_GNUC_NORETURN;
213 
214 void          free_record_cb              (rbin_struct      *record);
215 
216 void          my_debug_handler            (const char       *log_domain,
217                                            GLogLevelFlags    log_level,
218                                            const char       *message,
219                                            gpointer          data);
220 
221 char *        conv_path_to_utf8_with_tmpl (const char      *str,
222                                            const char      *from_enc,
223                                            const char      *tmpl,
224                                            size_t          *read,
225                                            r2status        *st);
226 
227 void          free_vars                   (void);
228 
229 #endif
230