2 * Create a squashfs filesystem. This is a highly compressed read only filesystem.
4 * Copyright (c) 2002, 2003, 2004, 2005
5 * Phillip Lougher <phillip@lougher.org.uk>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include <sys/types.h>
37 #include <squashfs_fs.h>
42 #define TRACE(s, args...) do { \
43 printf("mksquashfs: "s, ## args); \
46 #define TRACE(s, args...)
49 #define INFO(s, args...) do { \
50 if(!silent) printf("mksquashfs: "s, ## args); \
52 #define ERROR(s, args...) do { \
53 fprintf(stderr, s, ## args); \
55 #define EXIT_MKSQUASHFS() do { \
58 #define BAD_ERROR(s, args...) do {\
59 fprintf(stderr, "FATAL ERROR:" s, ##args);\
63 int mkisofs_style
= -1;
69 struct sort_info
*next
;
72 struct sort_info
*sort_info_list
[65536];
74 struct priority_entry
{
76 struct priority_entry
*next
;
79 struct priority_entry
*priority_list
[65536];
82 extern squashfs_inode
write_file(squashfs_inode
*inode
, struct dir_ent
*dir_ent
, long long size
, int *c_size
);
85 int add_priority_list(struct dir_ent
*dir
, int priority
)
87 struct priority_entry
*new_priority_entry
;
90 if((new_priority_entry
= malloc(sizeof(struct priority_entry
))) == NULL
) {
91 ERROR("Out of memory allocating priority entry\n");
95 new_priority_entry
->dir
= dir
;;
96 new_priority_entry
->next
= priority_list
[priority
];
97 priority_list
[priority
] = new_priority_entry
;
102 int get_priority(char *filename
, struct stat
*buf
, int priority
)
104 int hash
= buf
->st_ino
& 0xffff;
107 for(s
= sort_info_list
[hash
]; s
; s
= s
->next
)
108 if((s
->st_dev
== buf
->st_dev
) && (s
->st_ino
== buf
->st_ino
)) {
109 TRACE("returning priority %d (%s)\n", s
->priority
, filename
);
112 TRACE("returning priority %d (%s)\n", priority
, filename
);
117 #define ADD_ENTRY(buf, priority) {\
118 int hash = buf.st_ino & 0xffff;\
119 struct sort_info *s;\
120 if((s = malloc(sizeof(struct sort_info))) == NULL) {\
121 ERROR("Out of memory allocating sort list entry\n");\
124 s->st_dev = buf.st_dev;\
125 s->st_ino = buf.st_ino;\
126 s->priority = priority;\
127 s->next = sort_info_list[hash];\
128 sort_info_list[hash] = s;\
130 int add_sort_list(char *path
, int priority
, int source
, char *source_path
[])
136 TRACE("add_sort_list: filename %s, priority %d\n", path
, priority
);
137 if(strlen(path
) > 1 && strcmp(path
+ strlen(path
) - 2, "/*") == 0)
138 path
[strlen(path
) - 2] = '\0';
140 TRACE("add_sort_list: filename %s, priority %d\n", path
, priority
);
142 if(path
[0] == '/' || strncmp(path
, "./", 2) == 0 || strncmp(path
, "../", 3) == 0 || mkisofs_style
== 1) {
143 if(lstat(path
, &buf
) == -1)
145 TRACE("adding filename %s, priority %d, st_dev %llx, st_ino %llx\n", path
, priority
, buf
.st_dev
, buf
.st_ino
);
146 ADD_ENTRY(buf
, priority
);
150 for(i
= 0, n
= 0; i
< source
; i
++) {
151 strcat(strcat(strcpy(filename
, source_path
[i
]), "/"), path
);
152 if(lstat(filename
, &buf
) == -1) {
153 if(!(errno
== ENOENT
|| errno
== ENOTDIR
))
157 ADD_ENTRY(buf
, priority
);
161 if(n
== 0 && mkisofs_style
== -1 && lstat(path
, &buf
) != -1) {
162 ERROR("WARNING: Mkisofs style sortlist detected! This is supported but please\n");
163 ERROR("convert to mksquashfs style sortlist! A sortlist entry ");
164 ERROR("should be\neither absolute (starting with ");
165 ERROR("'/') start with './' or '../' (taken to be\nrelative to $PWD), otherwise it ");
166 ERROR("is assumed the entry is relative to one\nof the source directories, i.e. with ");
167 ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist ");
168 ERROR("entry \"file\" is assumed to be inside the directory test.\n\n");
178 BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more than one source entry! Please use an absolute path.\n", path
);
181 fprintf(stderr
, "Cannot stat sortlist entry \"%s\"\n", path
);
182 fprintf(stderr
, "This is probably because you're using the wrong file\n");
183 fprintf(stderr
, "path relative to the source directories\n");
188 void generate_file_priorities(struct dir_info
*dir
, int priority
, struct stat
*buf
)
190 priority
= get_priority(dir
->pathname
, buf
, priority
);
192 while(dir
->current_count
< dir
->count
) {
193 struct dir_ent
*dir_ent
= dir
->list
[dir
->current_count
++];
194 struct stat
*buf
= &dir_ent
->inode
->buf
;
198 switch(buf
->st_mode
& S_IFMT
) {
200 add_priority_list(dir_ent
, get_priority(dir_ent
->pathname
, buf
, priority
));
203 generate_file_priorities(dir_ent
->dir
, priority
, buf
);
207 dir
->current_count
= 0;
211 int read_sort_file(char *filename
, int source
, char *source_path
[])
214 char sort_filename
[16385];
217 if((fd
= fopen(filename
, "r")) == NULL
) {
218 perror("Could not open sort_list file...");
221 while(fscanf(fd
, "%s %d", sort_filename
, &priority
) != EOF
)
222 if(priority
>= -32768 && priority
<= 32767)
223 add_sort_list(sort_filename
, priority
, source
, source_path
);
225 ERROR("Sort file %s, priority %d outside range of -32767:32768 - skipping...\n", sort_filename
, priority
);
231 void sort_files_and_write(struct dir_info
*dir
)
234 struct priority_entry
*entry
;
235 squashfs_inode inode
;
238 generate_file_priorities(dir
, 0, &dir
->dir_ent
->inode
->buf
);
240 for(i
= 65535; i
>= 0; i
--)
241 for(entry
= priority_list
[i
]; entry
; entry
= entry
->next
) {
242 TRACE("%d: %s\n", i
- 32768, entry
->dir
->pathname
);
243 if(entry
->dir
->inode
->inode
== SQUASHFS_INVALID_BLK
) {
244 if(write_file(&inode
, entry
->dir
, entry
->dir
->inode
->buf
.st_size
,
246 INFO("file %s, uncompressed size %lld bytes %s\n",
247 entry
->dir
->pathname
,
248 entry
->dir
->inode
->buf
.st_size
,
249 duplicate_file
? "DUPLICATE" : "");
250 entry
->dir
->inode
->inode
= inode
;
251 entry
->dir
->inode
->type
= SQUASHFS_FILE_TYPE
;
254 INFO("file %s, uncompressed size %lld bytes LINK\n",
255 entry
->dir
->pathname
, entry
->dir
->inode
->buf
.st_size
);