]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - SQUASHFS/squashfs-tools-4.4/squashfs-tools/sort.c
2 * Create a squashfs filesystem. This is a highly compressed read only
5 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012,
7 * Phillip Lougher <phillip@squashfs.org.uk>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2,
12 * or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 #define MAX_LINE 16384
32 #include <sys/types.h>
41 #include "squashfs_fs.h"
42 #include "mksquashfs.h"
45 #include "progressbar.h"
47 int mkisofs_style
= -1;
53 struct sort_info
*next
;
56 struct sort_info
*sort_info_list
[65536];
58 struct priority_entry
*priority_list
[65536];
61 extern void write_file(squashfs_inode
*inode
, struct dir_ent
*dir_ent
,
63 extern char *pathname(struct dir_ent
*dir_ent
);
66 void add_priority_list(struct dir_ent
*dir
, int priority
)
68 struct priority_entry
*new_priority_entry
;
71 new_priority_entry
= malloc(sizeof(struct priority_entry
));
72 if(new_priority_entry
== NULL
)
75 new_priority_entry
->dir
= dir
;;
76 new_priority_entry
->next
= priority_list
[priority
];
77 priority_list
[priority
] = new_priority_entry
;
81 int get_priority(char *filename
, struct stat
*buf
, int priority
)
83 int hash
= buf
->st_ino
& 0xffff;
86 for(s
= sort_info_list
[hash
]; s
; s
= s
->next
)
87 if((s
->st_dev
== buf
->st_dev
) && (s
->st_ino
== buf
->st_ino
)) {
88 TRACE("returning priority %d (%s)\n", s
->priority
,
92 TRACE("returning priority %d (%s)\n", priority
, filename
);
97 #define ADD_ENTRY(buf, priority) {\
98 int hash = buf.st_ino & 0xffff;\
100 if((s = malloc(sizeof(struct sort_info))) == NULL) \
102 s->st_dev = buf.st_dev;\
103 s->st_ino = buf.st_ino;\
104 s->priority = priority;\
105 s->next = sort_info_list[hash];\
106 sort_info_list[hash] = s;\
108 int add_sort_list(char *path
, int priority
, int source
, char *source_path
[])
113 TRACE("add_sort_list: filename %s, priority %d\n", path
, priority
);
114 if(strlen(path
) > 1 && strcmp(path
+ strlen(path
) - 2, "/*") == 0)
115 path
[strlen(path
) - 2] = '\0';
117 TRACE("add_sort_list: filename %s, priority %d\n", path
, priority
);
119 if(path
[0] == '/' || strncmp(path
, "./", 2) == 0 ||
120 strncmp(path
, "../", 3) == 0 || mkisofs_style
== 1) {
121 if(lstat(path
, &buf
) == -1)
123 TRACE("adding filename %s, priority %d, st_dev %d, st_ino "
124 "%lld\n", path
, priority
, (int) buf
.st_dev
,
125 (long long) buf
.st_ino
);
126 ADD_ENTRY(buf
, priority
);
130 for(i
= 0, n
= 0; i
< source
; i
++) {
132 int res
= asprintf(&filename
, "%s/%s", source_path
[i
], path
);
134 BAD_ERROR("asprintf failed in add_sort_list\n");
135 res
= lstat(filename
, &buf
);
138 if(!(errno
== ENOENT
|| errno
== ENOTDIR
))
142 ADD_ENTRY(buf
, priority
);
146 if(n
== 0 && mkisofs_style
== -1 && lstat(path
, &buf
) != -1) {
147 ERROR("WARNING: Mkisofs style sortlist detected! This is "
148 "supported but please\n");
149 ERROR("convert to mksquashfs style sortlist! A sortlist entry");
150 ERROR(" should be\neither absolute (starting with ");
151 ERROR("'/') start with './' or '../' (taken to be\nrelative to "
152 "$PWD), otherwise it ");
153 ERROR("is assumed the entry is relative to one\nof the source "
154 "directories, i.e. with ");
155 ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist ");
156 ERROR("entry \"file\" is assumed to be inside the directory "
167 ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more "
168 "than one source entry! Please use an absolute path."
174 ERROR_START("Cannot stat sortlist entry \"%s\"\n", path
);
175 ERROR("This is probably because you're using the wrong file\n");
176 ERROR("path relative to the source directories.");
177 ERROR_EXIT(" Ignoring");
180 * Failure to stat a sortlist entry is deliberately ignored, even
181 * though it is an error. Squashfs release 2.2 changed the behaviour
182 * to treat it as a fatal error, but it was changed back to
183 * the original behaviour to ignore it in release 2.2-r2 following
184 * feedback from users at the time.
190 void generate_file_priorities(struct dir_info
*dir
, int priority
,
193 struct dir_ent
*dir_ent
= dir
->list
;
195 priority
= get_priority(dir
->pathname
, buf
, priority
);
197 for(; dir_ent
; dir_ent
= dir_ent
->next
) {
198 struct stat
*buf
= &dir_ent
->inode
->buf
;
199 if(dir_ent
->inode
->root_entry
)
202 switch(buf
->st_mode
& S_IFMT
) {
204 add_priority_list(dir_ent
,
205 get_priority(pathname(dir_ent
), buf
,
209 generate_file_priorities(dir_ent
->dir
,
217 int read_sort_file(char *filename
, int source
, char *source_path
[])
220 char line_buffer
[MAX_LINE
+ 1]; /* overflow safe */
221 char sort_filename
[MAX_LINE
+ 1]; /* overflow safe */
223 int n
, priority
, res
;
225 if((fd
= fopen(filename
, "r")) == NULL
) {
226 ERROR("Failed to open sort file \"%s\" because %s\n",
227 filename
, strerror(errno
));
231 while(fgets(line
= line_buffer
, MAX_LINE
+ 1, fd
) != NULL
) {
232 int len
= strlen(line
);
234 if(len
== MAX_LINE
&& line
[len
- 1] != '\n') {
236 ERROR("Line too long when reading "
237 "sort file \"%s\", larger than %d "
238 "bytes\n", filename
, MAX_LINE
);
243 * Remove '\n' terminator if it exists (the last line
244 * in the file may not be '\n' terminated)
246 if(len
&& line
[len
- 1] == '\n')
247 line
[len
- 1] = '\0';
249 /* Skip any leading whitespace */
250 while(isspace(*line
))
253 /* if comment line, skip */
258 * Scan for filename, don't use sscanf() and "%s" because
259 * that can't handle filenames with spaces
261 for(name
= sort_filename
; !isspace(*line
) && *line
!= '\0';) {
272 * if filename empty, then line was empty of anything but
273 * whitespace or a backslash character. Skip empy lines
275 if(sort_filename
[0] == '\0')
279 * Scan the rest of the line, we expect a decimal number
280 * which is the filename priority
283 res
= sscanf(line
, "%d%n", &priority
, &n
);
285 if((res
< 1 || errno
) && errno
!= ERANGE
) {
287 /* No error, assume EOL or match failure */
288 ERROR("Sort file \"%s\", can't find priority "
289 "in entry \"%s\", EOL or match "
290 "failure\n", filename
, line_buffer
);
292 /* Some other failure not ERANGE */
293 ERROR("Sscanf failed reading sort file \"%s\" "
294 "because %s\n", filename
,
297 } else if((errno
== ERANGE
) ||
298 (priority
< -32768 || priority
> 32767)) {
299 ERROR("Sort file \"%s\", entry \"%s\" has priority "
300 "outside range of -32768:32767.\n", filename
,
305 /* Skip any trailing whitespace */
307 while(isspace(*line
))
311 ERROR("Sort file \"%s\", trailing characters after "
312 "priority in entry \"%s\"\n", filename
,
317 res
= add_sort_list(sort_filename
, priority
, source
,
324 ERROR("Reading sort file \"%s\" failed because %s\n", filename
,
338 void sort_files_and_write(struct dir_info
*dir
)
341 struct priority_entry
*entry
;
342 squashfs_inode inode
;
345 for(i
= 65535; i
>= 0; i
--)
346 for(entry
= priority_list
[i
]; entry
; entry
= entry
->next
) {
347 TRACE("%d: %s\n", i
- 32768, pathname(entry
->dir
));
348 if(entry
->dir
->inode
->inode
== SQUASHFS_INVALID_BLK
) {
349 write_file(&inode
, entry
->dir
, &duplicate_file
);
350 INFO("file %s, uncompressed size %lld bytes %s"
351 "\n", pathname(entry
->dir
),
353 entry
->dir
->inode
->buf
.st_size
,
354 duplicate_file
? "DUPLICATE" : "");
355 entry
->dir
->inode
->inode
= inode
;
356 entry
->dir
->inode
->type
= SQUASHFS_FILE_TYPE
;
358 INFO("file %s, uncompressed size %lld bytes "
359 "LINK\n", pathname(entry
->dir
),
361 entry
->dir
->inode
->buf
.st_size
);