aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE4
-rw-r--r--README6
-rw-r--r--applets/busybox.c8
-rw-r--r--archival/gzip.c18
-rw-r--r--archival/tar.c17
-rw-r--r--busybox.c8
-rw-r--r--busybox.def.h1
-rw-r--r--cat.c2
-rw-r--r--chmod_chown_chgrp.c168
-rw-r--r--console-tools/loadfont.c4
-rw-r--r--console-tools/loadkmap.c4
-rw-r--r--coreutils/cat.c2
-rw-r--r--coreutils/cp.c2
-rw-r--r--coreutils/date.c2
-rw-r--r--coreutils/dd.c2
-rw-r--r--coreutils/df.c2
-rw-r--r--coreutils/ls.c19
-rw-r--r--coreutils/mkdir.c2
-rw-r--r--coreutils/mknod.c2
-rw-r--r--coreutils/printf.c2
-rw-r--r--coreutils/touch.c2
-rw-r--r--cp.c2
-rw-r--r--date.c2
-rw-r--r--dd.c2
-rw-r--r--df.c2
-rw-r--r--dmesg.c128
-rw-r--r--dutmp.c4
-rw-r--r--findutils/grep.c2
-rw-r--r--grep.c2
-rw-r--r--gzip.c18
-rw-r--r--init.c2
-rw-r--r--init/init.c2
-rw-r--r--internal.h6
-rw-r--r--kill.c8
-rw-r--r--loadfont.c4
-rw-r--r--loadkmap.c4
-rw-r--r--ls.c19
-rw-r--r--makedevs.c5
-rw-r--r--math.c2
-rw-r--r--miscutils/dutmp.c4
-rw-r--r--miscutils/makedevs.c5
-rw-r--r--miscutils/mt.c2
-rw-r--r--mkdir.c2
-rw-r--r--mknod.c2
-rw-r--r--mkswap.c448
-rw-r--r--mnc.c2
-rw-r--r--more.c2
-rw-r--r--mount.c2
-rw-r--r--mt.c2
-rw-r--r--printf.c2
-rw-r--r--procps/kill.c8
-rw-r--r--sfdisk.c2880
-rw-r--r--tar.c17
-rw-r--r--touch.c2
-rw-r--r--umount.c2
-rw-r--r--util-linux/dmesg.c128
-rw-r--r--util-linux/mkswap.c448
-rw-r--r--util-linux/more.c2
-rw-r--r--util-linux/mount.c2
-rw-r--r--util-linux/umount.c2
-rw-r--r--zcat.c14
61 files changed, 3997 insertions, 472 deletions
diff --git a/LICENSE b/LICENSE
index cf73b2c33..e8f4a0930 100644
--- a/LICENSE
+++ b/LICENSE
@@ -22,3 +22,7 @@ Please see the top of the source files for more precise indivigual
22copyright and license info. 22copyright and license info.
23 23
24This program suite may be distributed under the GNU General Public License. 24This program suite may be distributed under the GNU General Public License.
25
26
27Please send patches, suggestions, insults, and bribes to <andersee@debian.org>.
28
diff --git a/README b/README
index 7d4e0f304..86175ee93 100644
--- a/README
+++ b/README
@@ -17,11 +17,15 @@ using C++ comments (//)
17After the build is complete a busybox.links file is generated to allow 17After the build is complete a busybox.links file is generated to allow
18you to easily make the sym/hard links to the busybox binary. 18you to easily make the sym/hard links to the busybox binary.
19 19
20Note the modular system is Makefile based, and purposly very 20Note the modular system is Makefile based, and purposely very
21simplistic. It does no dependency checking. That is left for you 21simplistic. It does no dependency checking. That is left for you
22to figure out by trial and error. 22to figure out by trial and error.
23 23
24Please feed patches back to: 24Please feed patches back to:
25 Erik Andersen <andersee@deban.org>
26and
27 Bruce Perens <bruce@perens.com>
28and
25 Dave Cinege <dcinege@psychosis.com> 29 Dave Cinege <dcinege@psychosis.com>
26and: 30and:
27 Enrique Zanardi <ezanardi@ull.es> 31 Enrique Zanardi <ezanardi@ull.es>
diff --git a/applets/busybox.c b/applets/busybox.c
index 3af98407d..6bcb65297 100644
--- a/applets/busybox.c
+++ b/applets/busybox.c
@@ -14,7 +14,7 @@ static const struct Applet applets[] = {
14 {"block_device", block_device_main}, 14 {"block_device", block_device_main},
15#endif 15#endif
16#ifdef BB_CAT //bin 16#ifdef BB_CAT //bin
17 {"cat", cat_more_main}, 17 {"cat", cat_main},
18#endif 18#endif
19#ifdef BB_CHMOD_CHOWN_CHGRP //bin 19#ifdef BB_CHMOD_CHOWN_CHGRP //bin
20 {"chmod", chmod_chown_chgrp_main}, 20 {"chmod", chmod_chown_chgrp_main},
@@ -43,7 +43,7 @@ static const struct Applet applets[] = {
43 {"dmesg", dmesg_main}, 43 {"dmesg", dmesg_main},
44#endif 44#endif
45#ifdef BB_DUTMP //usr/sbin 45#ifdef BB_DUTMP //usr/sbin
46 {"dutmp", cat_more_main}, 46 {"dutmp", dutmp_main},
47#endif 47#endif
48#ifdef BB_FDFLUSH //bin 48#ifdef BB_FDFLUSH //bin
49 {"fdflush", fdflush_main}, 49 {"fdflush", fdflush_main},
@@ -123,6 +123,10 @@ static const struct Applet applets[] = {
123#ifdef BB_RMDIR //bin 123#ifdef BB_RMDIR //bin
124 {"rmdir", rmdir_main}, 124 {"rmdir", rmdir_main},
125#endif 125#endif
126#ifdef BB_SFDISK //sbin
127 {"fdisk", sfdisk_main},
128 {"sfdisk", sfdisk_main},
129#endif
126#ifdef BB_SLEEP //bin 130#ifdef BB_SLEEP //bin
127 {"sleep", sleep_main}, 131 {"sleep", sleep_main},
128#endif 132#endif
diff --git a/archival/gzip.c b/archival/gzip.c
index c7fb25ed0..0ed20b61a 100644
--- a/archival/gzip.c
+++ b/archival/gzip.c
@@ -11,7 +11,7 @@
11#error you need zcat to have gzip support! 11#error you need zcat to have gzip support!
12#endif 12#endif
13 13
14const char gzip_usage[] = "gzip\nignores all command line arguments\ncompress stdin to stdout with -9 compression\n"; 14static const char gzip_usage[] = "gzip\nignores all command line arguments\ncompress stdin to stdout with -9 compression\n";
15 15
16/* gzip.h -- common declarations for all gzip modules 16/* gzip.h -- common declarations for all gzip modules
17 * Copyright (C) 1992-1993 Jean-loup Gailly. 17 * Copyright (C) 1992-1993 Jean-loup Gailly.
@@ -380,7 +380,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
380# undef LZW 380# undef LZW
381#endif 381#endif
382 382
383/* $Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $ */ 383/* $Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $ */
384/* tailor.h -- target dependent definitions 384/* tailor.h -- target dependent definitions
385 * Copyright (C) 1992-1993 Jean-loup Gailly. 385 * Copyright (C) 1992-1993 Jean-loup Gailly.
386 * This is free software; you can redistribute it and/or modify it under the 386 * This is free software; you can redistribute it and/or modify it under the
@@ -391,7 +391,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
391 * The target dependent functions should be defined in tailor.c. 391 * The target dependent functions should be defined in tailor.c.
392 */ 392 */
393 393
394/* $Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $ */ 394/* $Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $ */
395 395
396#if defined(__MSDOS__) && !defined(MSDOS) 396#if defined(__MSDOS__) && !defined(MSDOS)
397# define MSDOS 397# define MSDOS
@@ -767,7 +767,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
767#endif 767#endif
768 768
769#ifdef RCSID 769#ifdef RCSID
770static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; 770static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $";
771#endif 771#endif
772 772
773/* =========================================================================== 773/* ===========================================================================
@@ -976,7 +976,7 @@ void copy_block(buf, len, header)
976#include <stdio.h> 976#include <stdio.h>
977 977
978#ifdef RCSID 978#ifdef RCSID
979static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; 979static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $";
980#endif 980#endif
981 981
982/* =========================================================================== 982/* ===========================================================================
@@ -1592,7 +1592,7 @@ ulg deflate()
1592 */ 1592 */
1593 1593
1594#ifdef RCSID 1594#ifdef RCSID
1595static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; 1595static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $";
1596#endif 1596#endif
1597 1597
1598#include <ctype.h> 1598#include <ctype.h>
@@ -1925,7 +1925,7 @@ local void do_exit(int exitcode)
1925#include <ctype.h> 1925#include <ctype.h>
1926 1926
1927#ifdef RCSID 1927#ifdef RCSID
1928static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; 1928static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $";
1929#endif 1929#endif
1930 1930
1931/* =========================================================================== 1931/* ===========================================================================
@@ -2943,7 +2943,7 @@ local void set_file_type()
2943 */ 2943 */
2944 2944
2945#ifdef RCSID 2945#ifdef RCSID
2946static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; 2946static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $";
2947#endif 2947#endif
2948 2948
2949#include <ctype.h> 2949#include <ctype.h>
@@ -3142,7 +3142,7 @@ void display_ratio(num, den, file)
3142 */ 3142 */
3143 3143
3144#ifdef RCSID 3144#ifdef RCSID
3145static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; 3145static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $";
3146#endif 3146#endif
3147 3147
3148#include <ctype.h> 3148#include <ctype.h>
diff --git a/archival/tar.c b/archival/tar.c
index f222c3c9d..b404ab025 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -12,10 +12,15 @@
12 12
13 13
14#include "internal.h" 14#include "internal.h"
15#include <stdio.h>
16#include <dirent.h>
17#include <errno.h>
18#include <fcntl.h>
19#include <signal.h>
20#include <time.h>
15 21
16#ifdef BB_TAR
17 22
18const char tar_usage[] = 23static const char tar_usage[] =
19 "Create, extract, or list files from a TAR file\n\n" 24 "Create, extract, or list files from a TAR file\n\n"
20 "usage: tar -[cxtvOf] [tarFileName] [FILE] ...\n" 25 "usage: tar -[cxtvOf] [tarFileName] [FILE] ...\n"
21 "\tc=create, x=extract, t=list contents, v=verbose,\n" 26 "\tc=create, x=extract, t=list contents, v=verbose,\n"
@@ -23,13 +28,6 @@ const char tar_usage[] =
23 28
24 29
25 30
26#include <stdio.h>
27#include <dirent.h>
28#include <errno.h>
29#include <fcntl.h>
30#include <signal.h>
31#include <time.h>
32
33/* 31/*
34 * Tar file constants. 32 * Tar file constants.
35 */ 33 */
@@ -1151,5 +1149,4 @@ wantFileName (const char *fileName, int fileCount, char **fileTable)
1151 1149
1152 1150
1153 1151
1154#endif
1155/* END CODE */ 1152/* END CODE */
diff --git a/busybox.c b/busybox.c
index 3af98407d..6bcb65297 100644
--- a/busybox.c
+++ b/busybox.c
@@ -14,7 +14,7 @@ static const struct Applet applets[] = {
14 {"block_device", block_device_main}, 14 {"block_device", block_device_main},
15#endif 15#endif
16#ifdef BB_CAT //bin 16#ifdef BB_CAT //bin
17 {"cat", cat_more_main}, 17 {"cat", cat_main},
18#endif 18#endif
19#ifdef BB_CHMOD_CHOWN_CHGRP //bin 19#ifdef BB_CHMOD_CHOWN_CHGRP //bin
20 {"chmod", chmod_chown_chgrp_main}, 20 {"chmod", chmod_chown_chgrp_main},
@@ -43,7 +43,7 @@ static const struct Applet applets[] = {
43 {"dmesg", dmesg_main}, 43 {"dmesg", dmesg_main},
44#endif 44#endif
45#ifdef BB_DUTMP //usr/sbin 45#ifdef BB_DUTMP //usr/sbin
46 {"dutmp", cat_more_main}, 46 {"dutmp", dutmp_main},
47#endif 47#endif
48#ifdef BB_FDFLUSH //bin 48#ifdef BB_FDFLUSH //bin
49 {"fdflush", fdflush_main}, 49 {"fdflush", fdflush_main},
@@ -123,6 +123,10 @@ static const struct Applet applets[] = {
123#ifdef BB_RMDIR //bin 123#ifdef BB_RMDIR //bin
124 {"rmdir", rmdir_main}, 124 {"rmdir", rmdir_main},
125#endif 125#endif
126#ifdef BB_SFDISK //sbin
127 {"fdisk", sfdisk_main},
128 {"sfdisk", sfdisk_main},
129#endif
126#ifdef BB_SLEEP //bin 130#ifdef BB_SLEEP //bin
127 {"sleep", sleep_main}, 131 {"sleep", sleep_main},
128#endif 132#endif
diff --git a/busybox.def.h b/busybox.def.h
index 68d1ec021..c90297aa2 100644
--- a/busybox.def.h
+++ b/busybox.def.h
@@ -40,6 +40,7 @@
40#define BB_REBOOT 40#define BB_REBOOT
41#define BB_RM 41#define BB_RM
42#define BB_RMDIR 42#define BB_RMDIR
43#define BB_SFDISK
43#define BB_SLEEP 44#define BB_SLEEP
44#define BB_SWAPONOFF 45#define BB_SWAPONOFF
45#define BB_SYNC 46#define BB_SYNC
diff --git a/cat.c b/cat.c
index 38078d505..3aae6d78e 100644
--- a/cat.c
+++ b/cat.c
@@ -32,7 +32,7 @@ static void print_file( FILE *file)
32 fflush(stdout); 32 fflush(stdout);
33} 33}
34 34
35extern int cat_more_main(int argc, char **argv) 35extern int cat_main(int argc, char **argv)
36{ 36{
37 FILE *file; 37 FILE *file;
38 38
diff --git a/chmod_chown_chgrp.c b/chmod_chown_chgrp.c
index cac09e71d..e76050022 100644
--- a/chmod_chown_chgrp.c
+++ b/chmod_chown_chgrp.c
@@ -144,3 +144,171 @@ int chmod_chown_chgrp_main(int argc, char **argv)
144 exit(TRUE); 144 exit(TRUE);
145} 145}
146 146
147
148
149
150
151
152
153
154
155
156
157
158#ifdef fooo
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174#include "internal.h"
175#include <pwd.h>
176#include <grp.h>
177#include <string.h>
178#include <stdio.h>
179
180int my_getid(const char *filename, const char *name, uid_t *id)
181{
182 FILE *stream;
183 uid_t rid;
184 char *rname, *start, *end, buf[128];
185
186 stream=fopen(filename,"r");
187
188 while (fgets (buf, 128, stream) != NULL) {
189 if (buf[0] == '#')
190 continue;
191
192 start = buf;
193 end = strchr (start, ':');
194 if (end == NULL)
195 continue;
196 *end = '\0';
197 rname = start;
198
199 start = end + 1;
200 end = strchr (start, ':');
201 if (end == NULL)
202 continue;
203
204 start = end + 1;
205 rid = (uid_t) strtol (start, &end, 10);
206 if (end == start)
207 continue;
208
209 if (name) {
210 if (0 == strcmp(rname, name)) {
211 *id=rid;
212 return 0;
213 }
214 } else {
215 if ( *id == rid )
216 return 0;
217 }
218 }
219 fclose(stream);
220 return -1;
221}
222
223int
224my_getpwuid(uid_t *uid)
225{
226 return my_getid("/etc/passwd", NULL, uid);
227}
228
229int
230my_getpwnam(char *name, uid_t *uid)
231{
232 return my_getid("/etc/passwd", name, uid);
233}
234
235int
236my_getgrgid(gid_t *gid)
237{
238 return my_getid("/etc/group", NULL, gid);
239}
240
241int
242my_getgrnam(char *name, gid_t *gid)
243{
244 return my_getid("/etc/group", name, gid);
245}
246
247const char chown_usage[] = "chown [-R] user-name file [file ...]\n"
248"\n\tThe group list is kept in the file /etc/groups.\n\n"
249"\t-R:\tRecursively change the mode of all files and directories\n"
250"\t\tunder the argument directory.";
251
252int
253parse_user_name(const char * s, struct FileInfo * i)
254{
255 char * dot = strchr(s, '.');
256 char * end = NULL;
257 uid_t id = 0;
258
259 if (! dot )
260 dot = strchr(s, ':');
261
262 if ( dot )
263 *dot = '\0';
264
265 if ( my_getpwnam(s,&id) == -1 ) {
266 id = strtol(s,&end,10);
267 if ((*end != '\0') || ( my_getpwuid(&id) == -1 )) {
268 fprintf(stderr, "%s: no such user.\n", s);
269 return 1;
270 }
271 }
272 i->userID = id;
273
274 if ( dot ) {
275 if ( my_getgrnam(++dot,&id) == -1 ) {
276 id = strtol(dot,&end,10);
277 if ((*end != '\0') || ( my_getgrgid(&id) == -1 )) {
278 fprintf(stderr, "%s: no such group.\n", dot);
279 return 1;
280 }
281 }
282 i->groupID = id;
283 i->changeGroupID = 1;
284 }
285 return 0;
286}
287
288extern int
289chown_main(struct FileInfo * i, int argc, char * * argv)
290{
291 int status;
292
293 while ( argc >= 3 && strcmp("-R", argv[1]) == 0 ) {
294 i->recursive = 1;
295 argc--;
296 argv++;
297 }
298
299 if ( (status = parse_user_name(argv[1], i)) != 0 )
300 return status;
301
302 argv++;
303 argc--;
304
305 i->changeUserID = 1;
306 i->complainInPostProcess = 1;
307
308 return monadic_main(i, argc, argv);
309}
310
311
312
313
314#endif
diff --git a/console-tools/loadfont.c b/console-tools/loadfont.c
index a10fa8a69..e44525d9c 100644
--- a/console-tools/loadfont.c
+++ b/console-tools/loadfont.c
@@ -75,7 +75,7 @@ do_loadfont(int fd, char *inbuf, int unit, int fontsize) {
75 for (i = 0; i < fontsize; i++) 75 for (i = 0; i < fontsize; i++)
76 memcpy(buf+(32*i), inbuf+(unit*i), unit); 76 memcpy(buf+(32*i), inbuf+(unit*i), unit);
77 77
78#if defined( PIO_FONTX ) && !defined( sparc ) 78#if defined( PIO_FONTX ) && !defined( __sparc__ )
79 { 79 {
80 struct consolefontdesc cfd; 80 struct consolefontdesc cfd;
81 81
@@ -196,7 +196,7 @@ loadnewfont(int fd) {
196 exit(1); 196 exit(1);
197 } 197 }
198 fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256); 198 fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256);
199#if !defined( PIO_FONTX ) || defined( sparc ) 199#if !defined( PIO_FONTX ) || defined( __sparc__ )
200 if (fontsize != 256) { 200 if (fontsize != 256) {
201 fprintf(stderr, "Only fontsize 256 supported\n"); 201 fprintf(stderr, "Only fontsize 256 supported\n");
202 exit(1); 202 exit(1);
diff --git a/console-tools/loadkmap.c b/console-tools/loadkmap.c
index eb5a5dd4a..27865d58e 100644
--- a/console-tools/loadkmap.c
+++ b/console-tools/loadkmap.c
@@ -7,7 +7,7 @@
7#include <sys/ioctl.h> 7#include <sys/ioctl.h>
8 8
9 9
10const char loadkmap_usage[] = "loadkmap\n" 10static const char loadkmap_usage[] = "loadkmap\n"
11"\n" 11"\n"
12"\tLoad a binary keyboard translation table from standard input.\n" 12"\tLoad a binary keyboard translation table from standard input.\n"
13"\n"; 13"\n";
@@ -48,7 +48,7 @@ loadkmap_main(int argc, char * * argv)
48 if (flags[i]==1){ 48 if (flags[i]==1){
49 pos=0; 49 pos=0;
50 while (pos < ibuffsz) { 50 while (pos < ibuffsz) {
51 if ( (readsz = read(0,ibuff+pos,ibuffsz-pos)) < 0 ) { 51 if ( (readsz = read(0,(char *)ibuff+pos,ibuffsz-pos)) < 0 ) {
52 fprintf(stderr, "Error reading keymap: %s\n", 52 fprintf(stderr, "Error reading keymap: %s\n",
53 strerror(errno)); 53 strerror(errno));
54 return 1; 54 return 1;
diff --git a/coreutils/cat.c b/coreutils/cat.c
index 38078d505..3aae6d78e 100644
--- a/coreutils/cat.c
+++ b/coreutils/cat.c
@@ -32,7 +32,7 @@ static void print_file( FILE *file)
32 fflush(stdout); 32 fflush(stdout);
33} 33}
34 34
35extern int cat_more_main(int argc, char **argv) 35extern int cat_main(int argc, char **argv)
36{ 36{
37 FILE *file; 37 FILE *file;
38 38
diff --git a/coreutils/cp.c b/coreutils/cp.c
index 11c76825c..34c12922d 100644
--- a/coreutils/cp.c
+++ b/coreutils/cp.c
@@ -25,7 +25,7 @@
25#include <utime.h> 25#include <utime.h>
26#include <dirent.h> 26#include <dirent.h>
27 27
28const char cp_usage[] = "cp [OPTION]... SOURCE DEST\n" 28static const char cp_usage[] = "cp [OPTION]... SOURCE DEST\n"
29 " or: cp [OPTION]... SOURCE... DIRECTORY\n" 29 " or: cp [OPTION]... SOURCE... DIRECTORY\n"
30 "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n" 30 "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n"
31 "\n" 31 "\n"
diff --git a/coreutils/date.c b/coreutils/date.c
index 70d5dd5c6..51194848b 100644
--- a/coreutils/date.c
+++ b/coreutils/date.c
@@ -34,7 +34,7 @@
34 an RFC 822 complient date output for shell scripting 34 an RFC 822 complient date output for shell scripting
35 mail commands */ 35 mail commands */
36 36
37const char date_usage[] = "date [OPTION]... [+FORMAT]\n" 37static const char date_usage[] = "date [OPTION]... [+FORMAT]\n"
38" or: date [OPTION] [MMDDhhmm[[CC]YY][.ss]]\n" 38" or: date [OPTION] [MMDDhhmm[[CC]YY][.ss]]\n"
39"Display the current time in the given FORMAT, or set the system date.\n" 39"Display the current time in the given FORMAT, or set the system date.\n"
40"\nOptions:\n\t-R\t\toutput RFC-822 compliant date string\n" 40"\nOptions:\n\t-R\t\toutput RFC-822 compliant date string\n"
diff --git a/coreutils/dd.c b/coreutils/dd.c
index ecf7e3a3d..1cf731664 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -14,7 +14,7 @@
14#include <fcntl.h> 14#include <fcntl.h>
15#include <errno.h> 15#include <errno.h>
16 16
17const char dd_usage[] = 17static const char dd_usage[] =
18 "Copy a file, converting and formatting according to options\n\ 18 "Copy a file, converting and formatting according to options\n\
19\n\ 19\n\
20usage: [if=name] [of=name] [bs=n] [count=n]\n\ 20usage: [if=name] [of=name] [bs=n] [count=n]\n\
diff --git a/coreutils/df.c b/coreutils/df.c
index a777d70f4..7a72bf8fd 100644
--- a/coreutils/df.c
+++ b/coreutils/df.c
@@ -5,7 +5,7 @@
5#include <sys/vfs.h> 5#include <sys/vfs.h>
6#include <fstab.h> 6#include <fstab.h>
7 7
8const char df_usage[] = "df [filesystem ...]\n" 8static const char df_usage[] = "df [filesystem ...]\n"
9"\n" 9"\n"
10"\tPrint the filesystem space used and space available.\n"; 10"\tPrint the filesystem space used and space available.\n";
11 11
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 0adc35de1..a8e7e048a 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -132,7 +132,6 @@ int ls_main(int argc, char **argv)
132#else 132#else
133 133
134 134
135#include "internal.h"
136/* 135/*
137 * tiny-ls.c version 0.1.0: A minimalist 'ls' 136 * tiny-ls.c version 0.1.0: A minimalist 'ls'
138 * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com> 137 * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com>
@@ -175,7 +174,7 @@ int ls_main(int argc, char **argv)
175 * 1. requires lstat (BSD) - how do you do it without? 174 * 1. requires lstat (BSD) - how do you do it without?
176 */ 175 */
177 176
178#define FEATURE_USERNAME /* show username/groupnames (libc6 uses NSS) */ 177//#define FEATURE_USERNAME /* show username/groupnames (libc6 uses NSS) */
179#define FEATURE_TIMESTAMPS /* show file timestamps */ 178#define FEATURE_TIMESTAMPS /* show file timestamps */
180#define FEATURE_AUTOWIDTH /* calculate terminal & column widths */ 179#define FEATURE_AUTOWIDTH /* calculate terminal & column widths */
181#define FEATURE_FILETYPECHAR /* enable -p and -F */ 180#define FEATURE_FILETYPECHAR /* enable -p and -F */
@@ -187,8 +186,8 @@ int ls_main(int argc, char **argv)
187 186
188/************************************************************************/ 187/************************************************************************/
189 188
190 189#include "internal.h"
191#if 1 /* FIXME libc 6 */ 190#if !defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
192# include <linux/types.h> 191# include <linux/types.h>
193#else 192#else
194# include <sys/types.h> 193# include <sys/types.h>
@@ -225,7 +224,7 @@ int ls_main(int argc, char **argv)
225 224
226/* The 9 mode bits to test */ 225/* The 9 mode bits to test */
227 226
228static const umode_t MBIT[] = { 227static const mode_t MBIT[] = {
229 S_IRUSR, S_IWUSR, S_IXUSR, 228 S_IRUSR, S_IWUSR, S_IXUSR,
230 S_IRGRP, S_IWGRP, S_IXGRP, 229 S_IRGRP, S_IWGRP, S_IXGRP,
231 S_IROTH, S_IWOTH, S_IXOTH 230 S_IROTH, S_IWOTH, S_IXOTH
@@ -233,7 +232,7 @@ static const umode_t MBIT[] = {
233 232
234/* The special bits. If set, display SMODE0/1 instead of MODE0/1 */ 233/* The special bits. If set, display SMODE0/1 instead of MODE0/1 */
235 234
236static const umode_t SBIT[] = { 235static const mode_t SBIT[] = {
237 0, 0, S_ISUID, 236 0, 0, S_ISUID,
238 0, 0, S_ISGID, 237 0, 0, S_ISGID,
239 0, 0, S_ISVTX 238 0, 0, S_ISVTX
@@ -278,7 +277,7 @@ static unsigned char time_fmt = TIME_MOD;
278 277
279static void writenum(long val, short minwidth) 278static void writenum(long val, short minwidth)
280{ 279{
281 char scratch[20]; 280 char scratch[128];
282 281
283 char *p = scratch + sizeof(scratch); 282 char *p = scratch + sizeof(scratch);
284 short len = 0; 283 short len = 0;
@@ -324,7 +323,7 @@ static void tab(short col)
324} 323}
325 324
326#ifdef FEATURE_FILETYPECHAR 325#ifdef FEATURE_FILETYPECHAR
327static char append_char(umode_t mode) 326static char append_char(mode_t mode)
328{ 327{
329 if (!(opts & DISP_FTYPE)) 328 if (!(opts & DISP_FTYPE))
330 return '\0'; 329 return '\0';
@@ -343,14 +342,14 @@ static char append_char(umode_t mode)
343 342
344static void list_single(const char *name, struct stat *info) 343static void list_single(const char *name, struct stat *info)
345{ 344{
346 char scratch[20]; 345 char scratch[PATH_MAX];
347 short len = strlen(name); 346 short len = strlen(name);
348#ifdef FEATURE_FILETYPECHAR 347#ifdef FEATURE_FILETYPECHAR
349 char append = append_char(info->st_mode); 348 char append = append_char(info->st_mode);
350#endif 349#endif
351 350
352 if (display_fmt == FMT_LONG) { 351 if (display_fmt == FMT_LONG) {
353 umode_t mode = info->st_mode; 352 mode_t mode = info->st_mode;
354 int i; 353 int i;
355 354
356 scratch[0] = TYPECHAR(mode); 355 scratch[0] = TYPECHAR(mode);
diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c
index b42899a4a..cf65f272f 100644
--- a/coreutils/mkdir.c
+++ b/coreutils/mkdir.c
@@ -24,7 +24,7 @@
24#include <errno.h> 24#include <errno.h>
25#include <sys/param.h> 25#include <sys/param.h>
26 26
27const char mkdir_usage[] = "Usage: mkdir [OPTION] DIRECTORY...\n" 27static const char mkdir_usage[] = "Usage: mkdir [OPTION] DIRECTORY...\n"
28"Create the DIRECTORY(ies), if they do not already exist\n\n" 28"Create the DIRECTORY(ies), if they do not already exist\n\n"
29"-m\tset permission mode (as in chmod), not rwxrwxrwx - umask\n" 29"-m\tset permission mode (as in chmod), not rwxrwxrwx - umask\n"
30"-p\tno error if existing, make parent directories as needed\n"; 30"-p\tno error if existing, make parent directories as needed\n";
diff --git a/coreutils/mknod.c b/coreutils/mknod.c
index 95d7de360..ea2331fa3 100644
--- a/coreutils/mknod.c
+++ b/coreutils/mknod.c
@@ -6,7 +6,7 @@
6#include <fcntl.h> 6#include <fcntl.h>
7#include <unistd.h> 7#include <unistd.h>
8 8
9const char mknod_usage[] = "mknod file b|c|u|p major minor\n" 9static const char mknod_usage[] = "mknod file b|c|u|p major minor\n"
10"\tMake special files.\n" 10"\tMake special files.\n"
11"\n" 11"\n"
12"\tb:\tMake a block (buffered) device.\n" 12"\tb:\tMake a block (buffered) device.\n"
diff --git a/coreutils/printf.c b/coreutils/printf.c
index 4d4465943..02d08118b 100644
--- a/coreutils/printf.c
+++ b/coreutils/printf.c
@@ -136,7 +136,7 @@ static void verify __P ((char *s, char *end));
136/* The value to return to the calling program. */ 136/* The value to return to the calling program. */
137static int exit_status; 137static int exit_status;
138 138
139const char printf_usage[] = "printf format [argument...]\n"; 139static const char printf_usage[] = "printf format [argument...]\n";
140 140
141int 141int
142printf_main(int argc, char** argv) 142printf_main(int argc, char** argv)
diff --git a/coreutils/touch.c b/coreutils/touch.c
index c36ffca90..d882a6319 100644
--- a/coreutils/touch.c
+++ b/coreutils/touch.c
@@ -28,7 +28,7 @@
28#include <errno.h> 28#include <errno.h>
29 29
30 30
31const char touch_usage[] = "touch [-c] file [file ...]\n\n" 31static const char touch_usage[] = "touch [-c] file [file ...]\n\n"
32"\tUpdate the last-modified date on the given file[s].\n"; 32"\tUpdate the last-modified date on the given file[s].\n";
33 33
34 34
diff --git a/cp.c b/cp.c
index 11c76825c..34c12922d 100644
--- a/cp.c
+++ b/cp.c
@@ -25,7 +25,7 @@
25#include <utime.h> 25#include <utime.h>
26#include <dirent.h> 26#include <dirent.h>
27 27
28const char cp_usage[] = "cp [OPTION]... SOURCE DEST\n" 28static const char cp_usage[] = "cp [OPTION]... SOURCE DEST\n"
29 " or: cp [OPTION]... SOURCE... DIRECTORY\n" 29 " or: cp [OPTION]... SOURCE... DIRECTORY\n"
30 "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n" 30 "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n"
31 "\n" 31 "\n"
diff --git a/date.c b/date.c
index 70d5dd5c6..51194848b 100644
--- a/date.c
+++ b/date.c
@@ -34,7 +34,7 @@
34 an RFC 822 complient date output for shell scripting 34 an RFC 822 complient date output for shell scripting
35 mail commands */ 35 mail commands */
36 36
37const char date_usage[] = "date [OPTION]... [+FORMAT]\n" 37static const char date_usage[] = "date [OPTION]... [+FORMAT]\n"
38" or: date [OPTION] [MMDDhhmm[[CC]YY][.ss]]\n" 38" or: date [OPTION] [MMDDhhmm[[CC]YY][.ss]]\n"
39"Display the current time in the given FORMAT, or set the system date.\n" 39"Display the current time in the given FORMAT, or set the system date.\n"
40"\nOptions:\n\t-R\t\toutput RFC-822 compliant date string\n" 40"\nOptions:\n\t-R\t\toutput RFC-822 compliant date string\n"
diff --git a/dd.c b/dd.c
index ecf7e3a3d..1cf731664 100644
--- a/dd.c
+++ b/dd.c
@@ -14,7 +14,7 @@
14#include <fcntl.h> 14#include <fcntl.h>
15#include <errno.h> 15#include <errno.h>
16 16
17const char dd_usage[] = 17static const char dd_usage[] =
18 "Copy a file, converting and formatting according to options\n\ 18 "Copy a file, converting and formatting according to options\n\
19\n\ 19\n\
20usage: [if=name] [of=name] [bs=n] [count=n]\n\ 20usage: [if=name] [of=name] [bs=n] [count=n]\n\
diff --git a/df.c b/df.c
index a777d70f4..7a72bf8fd 100644
--- a/df.c
+++ b/df.c
@@ -5,7 +5,7 @@
5#include <sys/vfs.h> 5#include <sys/vfs.h>
6#include <fstab.h> 6#include <fstab.h>
7 7
8const char df_usage[] = "df [filesystem ...]\n" 8static const char df_usage[] = "df [filesystem ...]\n"
9"\n" 9"\n"
10"\tPrint the filesystem space used and space available.\n"; 10"\tPrint the filesystem space used and space available.\n";
11 11
diff --git a/dmesg.c b/dmesg.c
index e5d403f7a..aa26f5836 100644
--- a/dmesg.c
+++ b/dmesg.c
@@ -1,45 +1,49 @@
1#include "internal.h"
2#include <stdlib.h>
3#include <unistd.h>
4#include <time.h>
5
6/* dmesg.c -- Print out the contents of the kernel ring buffer 1/* dmesg.c -- Print out the contents of the kernel ring buffer
7 * Created: Sat Oct 9 16:19:47 1993 2 * Created: Sat Oct 9 16:19:47 1993
8 * Revised: Thu Oct 28 21:52:17 1993 by faith@cs.unc.edu 3 * Revised: Thu Oct 28 21:52:17 1993 by faith@cs.unc.edu
9 * Copyright 1993 Theodore Ts'o (tytso@athena.mit.edu) 4 * Copyright 1993 Theodore Ts'o (tytso@athena.mit.edu)
10 * This program comes with ABSOLUTELY NO WARRANTY. 5 * This program comes with ABSOLUTELY NO WARRANTY.
11 * Modifications by Rick Sladkey (jrs@world.std.com) 6 * Modifications by Rick Sladkey (jrs@world.std.com)
12 * from util-linux; adapted for busybox 7 * Larger buffersize 3 June 1998 by Nicolai Langfeldt, based on a patch
8 * by Peeter Joot. This was also suggested by John Hudson.
9 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
10 * - added Native Language Support
11 *
12 * from util-linux -- adapted for busybox by
13 * Erik Andersen <andersee@debian.org>. I ripped out Native Language
14 * Support, replaced getopt, added some gotos for redundant stuff.
13 */ 15 */
14 16
17#include "internal.h"
15#include <linux/unistd.h> 18#include <linux/unistd.h>
16#include <stdio.h> 19#include <stdio.h>
20#include <getopt.h>
21#include <stdlib.h>
17 22
18#define __NR_klog __NR_syslog 23#if __GNU_LIBRARY__ < 5
19
20#if defined(__GLIBC__)
21#include <sys/klog.h>
22#define klog klogctl
23#else
24static inline _syscall3 (int, klog, int, type, char *, b, int, len)
25#endif /* __GLIBC__ */
26 24
25#ifndef __alpha__
26# define __NR_klogctl __NR_syslog
27 static inline _syscall3(int, klogctl, int, type, char *, b, int, len);
28#else /* __alpha__ */
29#define klogctl syslog
30#endif
27 31
32#else
33# include <sys/klog.h>
34#endif
28 35
29static const char dmesg_usage[] = "dmesg [-c] [-n level]\n"; 36static const char dmesg_usage[] = "dmesg [-c] [-n level] [-s bufsize]\n";
30 37
31int dmesg_main (int argc, char **argv) 38int dmesg_main( int argc, char** argv )
32{ 39{
33 40 char *buf;
34 char buf[4096]; 41 int bufsize=8196;
35 int i; 42 int i;
36 int n; 43 int n;
37 int level = 0; 44 int level = 0;
38 int lastc; 45 int lastc;
39 int cmd = 3; 46 int cmd = 3;
40
41 argc--;
42 argv++;
43 47
44 /* Parse any options */ 48 /* Parse any options */
45 while (argc && **argv == '-') { 49 while (argc && **argv == '-') {
@@ -56,43 +60,57 @@ int dmesg_main (int argc, char **argv)
56 --argc; 60 --argc;
57 ++argv; 61 ++argv;
58 break; 62 break;
63 case 's':
64 if (--argc == 0)
65 goto end;
66 bufsize = atoi (*(++argv));
67 --argc;
68 ++argv;
69 break;
59 default: 70 default:
60 goto end; 71 goto end;
61 } 72 }
62 } 73 }
74
75 if (argc > 1) {
76 goto end;
77 }
63 78
64 if (cmd == 8) { 79 if (cmd == 8) {
65 n = klog (cmd, NULL, level); 80 n = klogctl( cmd, NULL, level );
66 if (n < 0) { 81 if (n < 0) {
67 perror ("klog"); 82 goto klogctl_error;
68 exit (FALSE); 83 }
69 } 84 exit( TRUE );
70 exit (TRUE); 85 }
71 }
72 86
73 n = klog (cmd, buf, sizeof (buf)); 87 if (bufsize < 4096) bufsize = 4096;
74 if (n < 0) { 88 buf = (char*)malloc(bufsize);
75 perror ("klog"); 89 n = klogctl( cmd, buf, bufsize );
76 exit (FALSE); 90 if (n < 0) {
77 } 91 goto klogctl_error;
92 }
78 93
79 lastc = '\n'; 94 lastc = '\n';
80 for (i = 0; i < n; i++) { 95 for (i = 0; i < n; i++) {
81 if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') { 96 if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') {
97 i++;
98 while (buf[i] >= '0' && buf[i] <= '9')
82 i++; 99 i++;
83 while (buf[i] >= '0' && buf[i] <= '9') 100 if (buf[i] == '>')
84 i++; 101 i++;
85 if (buf[i] == '>') 102 }
86 i++; 103 lastc = buf[i];
87 } 104 putchar( lastc );
88 lastc = buf[i]; 105 }
89 putchar (lastc); 106 if (lastc != '\n')
90 } 107 putchar( '\n' );
91 if (lastc != '\n') 108 exit( TRUE);
92 putchar ('\n'); 109end:
93 exit (TRUE);
94
95 end:
96 usage( dmesg_usage); 110 usage( dmesg_usage);
97 exit (FALSE); 111 exit (FALSE);
112klogctl_error:
113 perror( "klogctl" );
114 exit( FALSE );
115
98} 116}
diff --git a/dutmp.c b/dutmp.c
index 7dd5b91fa..c5307b638 100644
--- a/dutmp.c
+++ b/dutmp.c
@@ -14,12 +14,12 @@
14#include <stdio.h> 14#include <stdio.h>
15#include <utmp.h> 15#include <utmp.h>
16 16
17const char dutmp_usage[] = "dutmp\n" 17static const char dutmp_usage[] = "dutmp\n"
18 "\n" 18 "\n"
19 "\tDump file or stdin utmp file format to stdout, pipe delimited.\n" 19 "\tDump file or stdin utmp file format to stdout, pipe delimited.\n"
20 "\tdutmp /var/run/utmp\n"; 20 "\tdutmp /var/run/utmp\n";
21 21
22extern int dutmp_fn (int argc, char **argv) 22static int dutmp_main (int argc, char **argv)
23{ 23{
24 24
25 FILE *f = stdin; 25 FILE *f = stdin;
diff --git a/findutils/grep.c b/findutils/grep.c
index de1c820a0..108c879af 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -29,7 +29,7 @@
29#include <ctype.h> 29#include <ctype.h>
30 30
31 31
32const char grep_usage[] = 32static const char grep_usage[] =
33"grep [-ihn]... PATTERN [FILE]...\n" 33"grep [-ihn]... PATTERN [FILE]...\n"
34"Search for PATTERN in each FILE or standard input.\n\n" 34"Search for PATTERN in each FILE or standard input.\n\n"
35"\t-h\tsuppress the prefixing filename on output\n" 35"\t-h\tsuppress the prefixing filename on output\n"
diff --git a/grep.c b/grep.c
index de1c820a0..108c879af 100644
--- a/grep.c
+++ b/grep.c
@@ -29,7 +29,7 @@
29#include <ctype.h> 29#include <ctype.h>
30 30
31 31
32const char grep_usage[] = 32static const char grep_usage[] =
33"grep [-ihn]... PATTERN [FILE]...\n" 33"grep [-ihn]... PATTERN [FILE]...\n"
34"Search for PATTERN in each FILE or standard input.\n\n" 34"Search for PATTERN in each FILE or standard input.\n\n"
35"\t-h\tsuppress the prefixing filename on output\n" 35"\t-h\tsuppress the prefixing filename on output\n"
diff --git a/gzip.c b/gzip.c
index c7fb25ed0..0ed20b61a 100644
--- a/gzip.c
+++ b/gzip.c
@@ -11,7 +11,7 @@
11#error you need zcat to have gzip support! 11#error you need zcat to have gzip support!
12#endif 12#endif
13 13
14const char gzip_usage[] = "gzip\nignores all command line arguments\ncompress stdin to stdout with -9 compression\n"; 14static const char gzip_usage[] = "gzip\nignores all command line arguments\ncompress stdin to stdout with -9 compression\n";
15 15
16/* gzip.h -- common declarations for all gzip modules 16/* gzip.h -- common declarations for all gzip modules
17 * Copyright (C) 1992-1993 Jean-loup Gailly. 17 * Copyright (C) 1992-1993 Jean-loup Gailly.
@@ -380,7 +380,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
380# undef LZW 380# undef LZW
381#endif 381#endif
382 382
383/* $Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $ */ 383/* $Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $ */
384/* tailor.h -- target dependent definitions 384/* tailor.h -- target dependent definitions
385 * Copyright (C) 1992-1993 Jean-loup Gailly. 385 * Copyright (C) 1992-1993 Jean-loup Gailly.
386 * This is free software; you can redistribute it and/or modify it under the 386 * This is free software; you can redistribute it and/or modify it under the
@@ -391,7 +391,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
391 * The target dependent functions should be defined in tailor.c. 391 * The target dependent functions should be defined in tailor.c.
392 */ 392 */
393 393
394/* $Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $ */ 394/* $Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $ */
395 395
396#if defined(__MSDOS__) && !defined(MSDOS) 396#if defined(__MSDOS__) && !defined(MSDOS)
397# define MSDOS 397# define MSDOS
@@ -767,7 +767,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */
767#endif 767#endif
768 768
769#ifdef RCSID 769#ifdef RCSID
770static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; 770static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $";
771#endif 771#endif
772 772
773/* =========================================================================== 773/* ===========================================================================
@@ -976,7 +976,7 @@ void copy_block(buf, len, header)
976#include <stdio.h> 976#include <stdio.h>
977 977
978#ifdef RCSID 978#ifdef RCSID
979static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; 979static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $";
980#endif 980#endif
981 981
982/* =========================================================================== 982/* ===========================================================================
@@ -1592,7 +1592,7 @@ ulg deflate()
1592 */ 1592 */
1593 1593
1594#ifdef RCSID 1594#ifdef RCSID
1595static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; 1595static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $";
1596#endif 1596#endif
1597 1597
1598#include <ctype.h> 1598#include <ctype.h>
@@ -1925,7 +1925,7 @@ local void do_exit(int exitcode)
1925#include <ctype.h> 1925#include <ctype.h>
1926 1926
1927#ifdef RCSID 1927#ifdef RCSID
1928static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; 1928static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $";
1929#endif 1929#endif
1930 1930
1931/* =========================================================================== 1931/* ===========================================================================
@@ -2943,7 +2943,7 @@ local void set_file_type()
2943 */ 2943 */
2944 2944
2945#ifdef RCSID 2945#ifdef RCSID
2946static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; 2946static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $";
2947#endif 2947#endif
2948 2948
2949#include <ctype.h> 2949#include <ctype.h>
@@ -3142,7 +3142,7 @@ void display_ratio(num, den, file)
3142 */ 3142 */
3143 3143
3144#ifdef RCSID 3144#ifdef RCSID
3145static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; 3145static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $";
3146#endif 3146#endif
3147 3147
3148#include <ctype.h> 3148#include <ctype.h>
diff --git a/init.c b/init.c
index ca194dd35..6c44cce15 100644
--- a/init.c
+++ b/init.c
@@ -300,7 +300,7 @@ configure_terminals( int serial_cons, int single_user_mode )
300 } 300 }
301 if (!first_terminal) 301 if (!first_terminal)
302 first_terminal = console; 302 first_terminal = console;
303#if #cpu (sparc) 303#if defined (__sparc__)
304 if (serial_cons > 0 && !strncmp(term_ptr,"TERM=linux",10)) 304 if (serial_cons > 0 && !strncmp(term_ptr,"TERM=linux",10))
305 term_ptr = "TERM=vt100"; 305 term_ptr = "TERM=vt100";
306#endif 306#endif
diff --git a/init/init.c b/init/init.c
index ca194dd35..6c44cce15 100644
--- a/init/init.c
+++ b/init/init.c
@@ -300,7 +300,7 @@ configure_terminals( int serial_cons, int single_user_mode )
300 } 300 }
301 if (!first_terminal) 301 if (!first_terminal)
302 first_terminal = console; 302 first_terminal = console;
303#if #cpu (sparc) 303#if defined (__sparc__)
304 if (serial_cons > 0 && !strncmp(term_ptr,"TERM=linux",10)) 304 if (serial_cons > 0 && !strncmp(term_ptr,"TERM=linux",10))
305 term_ptr = "TERM=vt100"; 305 term_ptr = "TERM=vt100";
306#endif 306#endif
diff --git a/internal.h b/internal.h
index 8bf9c3eb4..dedb9f193 100644
--- a/internal.h
+++ b/internal.h
@@ -56,7 +56,7 @@ struct Applet {
56 56
57extern int busybox_main(int argc, char** argv); 57extern int busybox_main(int argc, char** argv);
58extern int block_device_main(int argc, char** argv); 58extern int block_device_main(int argc, char** argv);
59extern int cat_more_main(int argc, char** argv); 59extern int cat_main(int argc, char** argv);
60extern int more_main(int argc, char** argv); 60extern int more_main(int argc, char** argv);
61extern int cp_main(int argc, char** argv); 61extern int cp_main(int argc, char** argv);
62extern int chmod_chown_chgrp_main(int argc, char** argv); 62extern int chmod_chown_chgrp_main(int argc, char** argv);
@@ -66,6 +66,7 @@ extern int date_main(int argc, char** argv);
66extern int dd_main(int argc, char** argv); 66extern int dd_main(int argc, char** argv);
67extern int df_main(int argc, char** argv); 67extern int df_main(int argc, char** argv);
68extern int dmesg_main(int argc, char** argv); 68extern int dmesg_main(int argc, char** argv);
69extern int dutmp_main(int argc, char** argv);
69extern int false_main(int argc, char** argv); 70extern int false_main(int argc, char** argv);
70extern int fdisk_main(int argc, char** argv); 71extern int fdisk_main(int argc, char** argv);
71extern int fdflush_main(int argc, char **argv); 72extern int fdflush_main(int argc, char **argv);
@@ -96,11 +97,12 @@ extern int rmdir_main(int argc, char **argv);
96extern int rm_main(int argc, char** argv); 97extern int rm_main(int argc, char** argv);
97extern int scan_partitions_main(int argc, char** argv); 98extern int scan_partitions_main(int argc, char** argv);
98extern int sh_main(int argc, char** argv); 99extern int sh_main(int argc, char** argv);
100extern int sfdisk_main(int argc, char** argv);
99extern int sleep_main(int argc, char** argv); 101extern int sleep_main(int argc, char** argv);
100extern int swap_on_off_main(int argc, char** argv); 102extern int swap_on_off_main(int argc, char** argv);
103extern int sync_main(int argc, char** argv);
101extern int tar_main(int argc, char** argv); 104extern int tar_main(int argc, char** argv);
102extern int touch_main(int argc, char** argv); 105extern int touch_main(int argc, char** argv);
103extern int sync_main(int argc, char** argv);
104extern int tput_main(int argc, char** argv); 106extern int tput_main(int argc, char** argv);
105extern int true_main(int argc, char** argv); 107extern int true_main(int argc, char** argv);
106extern int tryopen_main(int argc, char** argv); 108extern int tryopen_main(int argc, char** argv);
diff --git a/kill.c b/kill.c
index 00f10f91f..e89f913d0 100644
--- a/kill.c
+++ b/kill.c
@@ -21,20 +21,20 @@ const struct signal_name signames[] = {
21#ifndef __alpha__ 21#ifndef __alpha__
22 {"IOT", SIGIOT}, 22 {"IOT", SIGIOT},
23#endif 23#endif
24#if defined(sparc) || defined(__alpha__) 24#if defined(__sparc__) || defined(__alpha__)
25 {"EMT", SIGEMT}, 25 {"EMT", SIGEMT},
26#else 26#else
27 {"BUS", SIGBUS}, 27 {"BUS", SIGBUS},
28#endif 28#endif
29 {"FPE", SIGFPE}, 29 {"FPE", SIGFPE},
30 {"KILL", SIGKILL}, 30 {"KILL", SIGKILL},
31#if defined(sparc) || defined(__alpha__) 31#if defined(__sparc__) || defined(__alpha__)
32 {"BUS", SIGBUS}, 32 {"BUS", SIGBUS},
33#else 33#else
34 {"USR1", SIGUSR1}, 34 {"USR1", SIGUSR1},
35#endif 35#endif
36 {"SEGV", SIGSEGV}, 36 {"SEGV", SIGSEGV},
37#if defined(sparc) || defined(__alpha__) 37#if defined(__sparc__) || defined(__alpha__)
38 {"SYS", SIGSYS}, 38 {"SYS", SIGSYS},
39#else 39#else
40 {"USR2", SIGUSR2}, 40 {"USR2", SIGUSR2},
@@ -42,7 +42,7 @@ const struct signal_name signames[] = {
42 {"PIPE", SIGPIPE}, 42 {"PIPE", SIGPIPE},
43 {"ALRM", SIGALRM}, 43 {"ALRM", SIGALRM},
44 {"TERM", SIGTERM}, 44 {"TERM", SIGTERM},
45#if defined(sparc) || defined(__alpha__) 45#if defined(__sparc__) || defined(__alpha__)
46 {"URG", SIGURG}, 46 {"URG", SIGURG},
47 {"STOP", SIGSTOP}, 47 {"STOP", SIGSTOP},
48 {"TSTP", SIGTSTP}, 48 {"TSTP", SIGTSTP},
diff --git a/loadfont.c b/loadfont.c
index a10fa8a69..e44525d9c 100644
--- a/loadfont.c
+++ b/loadfont.c
@@ -75,7 +75,7 @@ do_loadfont(int fd, char *inbuf, int unit, int fontsize) {
75 for (i = 0; i < fontsize; i++) 75 for (i = 0; i < fontsize; i++)
76 memcpy(buf+(32*i), inbuf+(unit*i), unit); 76 memcpy(buf+(32*i), inbuf+(unit*i), unit);
77 77
78#if defined( PIO_FONTX ) && !defined( sparc ) 78#if defined( PIO_FONTX ) && !defined( __sparc__ )
79 { 79 {
80 struct consolefontdesc cfd; 80 struct consolefontdesc cfd;
81 81
@@ -196,7 +196,7 @@ loadnewfont(int fd) {
196 exit(1); 196 exit(1);
197 } 197 }
198 fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256); 198 fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256);
199#if !defined( PIO_FONTX ) || defined( sparc ) 199#if !defined( PIO_FONTX ) || defined( __sparc__ )
200 if (fontsize != 256) { 200 if (fontsize != 256) {
201 fprintf(stderr, "Only fontsize 256 supported\n"); 201 fprintf(stderr, "Only fontsize 256 supported\n");
202 exit(1); 202 exit(1);
diff --git a/loadkmap.c b/loadkmap.c
index eb5a5dd4a..27865d58e 100644
--- a/loadkmap.c
+++ b/loadkmap.c
@@ -7,7 +7,7 @@
7#include <sys/ioctl.h> 7#include <sys/ioctl.h>
8 8
9 9
10const char loadkmap_usage[] = "loadkmap\n" 10static const char loadkmap_usage[] = "loadkmap\n"
11"\n" 11"\n"
12"\tLoad a binary keyboard translation table from standard input.\n" 12"\tLoad a binary keyboard translation table from standard input.\n"
13"\n"; 13"\n";
@@ -48,7 +48,7 @@ loadkmap_main(int argc, char * * argv)
48 if (flags[i]==1){ 48 if (flags[i]==1){
49 pos=0; 49 pos=0;
50 while (pos < ibuffsz) { 50 while (pos < ibuffsz) {
51 if ( (readsz = read(0,ibuff+pos,ibuffsz-pos)) < 0 ) { 51 if ( (readsz = read(0,(char *)ibuff+pos,ibuffsz-pos)) < 0 ) {
52 fprintf(stderr, "Error reading keymap: %s\n", 52 fprintf(stderr, "Error reading keymap: %s\n",
53 strerror(errno)); 53 strerror(errno));
54 return 1; 54 return 1;
diff --git a/ls.c b/ls.c
index 0adc35de1..a8e7e048a 100644
--- a/ls.c
+++ b/ls.c
@@ -132,7 +132,6 @@ int ls_main(int argc, char **argv)
132#else 132#else
133 133
134 134
135#include "internal.h"
136/* 135/*
137 * tiny-ls.c version 0.1.0: A minimalist 'ls' 136 * tiny-ls.c version 0.1.0: A minimalist 'ls'
138 * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com> 137 * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com>
@@ -175,7 +174,7 @@ int ls_main(int argc, char **argv)
175 * 1. requires lstat (BSD) - how do you do it without? 174 * 1. requires lstat (BSD) - how do you do it without?
176 */ 175 */
177 176
178#define FEATURE_USERNAME /* show username/groupnames (libc6 uses NSS) */ 177//#define FEATURE_USERNAME /* show username/groupnames (libc6 uses NSS) */
179#define FEATURE_TIMESTAMPS /* show file timestamps */ 178#define FEATURE_TIMESTAMPS /* show file timestamps */
180#define FEATURE_AUTOWIDTH /* calculate terminal & column widths */ 179#define FEATURE_AUTOWIDTH /* calculate terminal & column widths */
181#define FEATURE_FILETYPECHAR /* enable -p and -F */ 180#define FEATURE_FILETYPECHAR /* enable -p and -F */
@@ -187,8 +186,8 @@ int ls_main(int argc, char **argv)
187 186
188/************************************************************************/ 187/************************************************************************/
189 188
190 189#include "internal.h"
191#if 1 /* FIXME libc 6 */ 190#if !defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
192# include <linux/types.h> 191# include <linux/types.h>
193#else 192#else
194# include <sys/types.h> 193# include <sys/types.h>
@@ -225,7 +224,7 @@ int ls_main(int argc, char **argv)
225 224
226/* The 9 mode bits to test */ 225/* The 9 mode bits to test */
227 226
228static const umode_t MBIT[] = { 227static const mode_t MBIT[] = {
229 S_IRUSR, S_IWUSR, S_IXUSR, 228 S_IRUSR, S_IWUSR, S_IXUSR,
230 S_IRGRP, S_IWGRP, S_IXGRP, 229 S_IRGRP, S_IWGRP, S_IXGRP,
231 S_IROTH, S_IWOTH, S_IXOTH 230 S_IROTH, S_IWOTH, S_IXOTH
@@ -233,7 +232,7 @@ static const umode_t MBIT[] = {
233 232
234/* The special bits. If set, display SMODE0/1 instead of MODE0/1 */ 233/* The special bits. If set, display SMODE0/1 instead of MODE0/1 */
235 234
236static const umode_t SBIT[] = { 235static const mode_t SBIT[] = {
237 0, 0, S_ISUID, 236 0, 0, S_ISUID,
238 0, 0, S_ISGID, 237 0, 0, S_ISGID,
239 0, 0, S_ISVTX 238 0, 0, S_ISVTX
@@ -278,7 +277,7 @@ static unsigned char time_fmt = TIME_MOD;
278 277
279static void writenum(long val, short minwidth) 278static void writenum(long val, short minwidth)
280{ 279{
281 char scratch[20]; 280 char scratch[128];
282 281
283 char *p = scratch + sizeof(scratch); 282 char *p = scratch + sizeof(scratch);
284 short len = 0; 283 short len = 0;
@@ -324,7 +323,7 @@ static void tab(short col)
324} 323}
325 324
326#ifdef FEATURE_FILETYPECHAR 325#ifdef FEATURE_FILETYPECHAR
327static char append_char(umode_t mode) 326static char append_char(mode_t mode)
328{ 327{
329 if (!(opts & DISP_FTYPE)) 328 if (!(opts & DISP_FTYPE))
330 return '\0'; 329 return '\0';
@@ -343,14 +342,14 @@ static char append_char(umode_t mode)
343 342
344static void list_single(const char *name, struct stat *info) 343static void list_single(const char *name, struct stat *info)
345{ 344{
346 char scratch[20]; 345 char scratch[PATH_MAX];
347 short len = strlen(name); 346 short len = strlen(name);
348#ifdef FEATURE_FILETYPECHAR 347#ifdef FEATURE_FILETYPECHAR
349 char append = append_char(info->st_mode); 348 char append = append_char(info->st_mode);
350#endif 349#endif
351 350
352 if (display_fmt == FMT_LONG) { 351 if (display_fmt == FMT_LONG) {
353 umode_t mode = info->st_mode; 352 mode_t mode = info->st_mode;
354 int i; 353 int i;
355 354
356 scratch[0] = TYPECHAR(mode); 355 scratch[0] = TYPECHAR(mode);
diff --git a/makedevs.c b/makedevs.c
index 00f0066ff..f7fbeb2fe 100644
--- a/makedevs.c
+++ b/makedevs.c
@@ -15,7 +15,7 @@
15#include <sys/types.h> 15#include <sys/types.h>
16#include <sys/stat.h> 16#include <sys/stat.h>
17 17
18const char makedevs_usage[] = 18static const char makedevs_usage[] =
19"makedevs 0.01 -- Create an entire range of device files\n\n" 19"makedevs 0.01 -- Create an entire range of device files\n\n"
20"\tmakedevs /dev/ttyS c 4 64 0 63 (ttyS0-ttyS63)\n" 20"\tmakedevs /dev/ttyS c 4 64 0 63 (ttyS0-ttyS63)\n"
21"\tmakedevs /dev/hda b 3 0 0 8 s (hda,hda1-hda8)\n"; 21"\tmakedevs /dev/hda b 3 0 0 8 s (hda,hda1-hda8)\n";
@@ -45,8 +45,7 @@ char buf[255];
45 case 'f': 45 case 'f':
46 mode = S_IFIFO; break; 46 mode = S_IFIFO; break;
47 default: 47 default:
48 fprintf(stderr, "Usage: %s\n", makedevs_usage); 48 usage( makedevs_usage);
49 return 2;
50 } 49 }
51 mode |= 0660; 50 mode |= 0660;
52 51
diff --git a/math.c b/math.c
index 29962a873..1f6d093b9 100644
--- a/math.c
+++ b/math.c
@@ -6,7 +6,7 @@
6 6
7/* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */ 7/* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */
8 8
9const char math_usage[] = "math expression ..."; 9static const char math_usage[] = "math expression ...";
10 10
11static double stack[100]; 11static double stack[100];
12static unsigned int pointer; 12static unsigned int pointer;
diff --git a/miscutils/dutmp.c b/miscutils/dutmp.c
index 7dd5b91fa..c5307b638 100644
--- a/miscutils/dutmp.c
+++ b/miscutils/dutmp.c
@@ -14,12 +14,12 @@
14#include <stdio.h> 14#include <stdio.h>
15#include <utmp.h> 15#include <utmp.h>
16 16
17const char dutmp_usage[] = "dutmp\n" 17static const char dutmp_usage[] = "dutmp\n"
18 "\n" 18 "\n"
19 "\tDump file or stdin utmp file format to stdout, pipe delimited.\n" 19 "\tDump file or stdin utmp file format to stdout, pipe delimited.\n"
20 "\tdutmp /var/run/utmp\n"; 20 "\tdutmp /var/run/utmp\n";
21 21
22extern int dutmp_fn (int argc, char **argv) 22static int dutmp_main (int argc, char **argv)
23{ 23{
24 24
25 FILE *f = stdin; 25 FILE *f = stdin;
diff --git a/miscutils/makedevs.c b/miscutils/makedevs.c
index 00f0066ff..f7fbeb2fe 100644
--- a/miscutils/makedevs.c
+++ b/miscutils/makedevs.c
@@ -15,7 +15,7 @@
15#include <sys/types.h> 15#include <sys/types.h>
16#include <sys/stat.h> 16#include <sys/stat.h>
17 17
18const char makedevs_usage[] = 18static const char makedevs_usage[] =
19"makedevs 0.01 -- Create an entire range of device files\n\n" 19"makedevs 0.01 -- Create an entire range of device files\n\n"
20"\tmakedevs /dev/ttyS c 4 64 0 63 (ttyS0-ttyS63)\n" 20"\tmakedevs /dev/ttyS c 4 64 0 63 (ttyS0-ttyS63)\n"
21"\tmakedevs /dev/hda b 3 0 0 8 s (hda,hda1-hda8)\n"; 21"\tmakedevs /dev/hda b 3 0 0 8 s (hda,hda1-hda8)\n";
@@ -45,8 +45,7 @@ char buf[255];
45 case 'f': 45 case 'f':
46 mode = S_IFIFO; break; 46 mode = S_IFIFO; break;
47 default: 47 default:
48 fprintf(stderr, "Usage: %s\n", makedevs_usage); 48 usage( makedevs_usage);
49 return 2;
50 } 49 }
51 mode |= 0660; 50 mode |= 0660;
52 51
diff --git a/miscutils/mt.c b/miscutils/mt.c
index a61ad5a40..7168ef7ac 100644
--- a/miscutils/mt.c
+++ b/miscutils/mt.c
@@ -3,7 +3,7 @@
3#include <sys/mtio.h> 3#include <sys/mtio.h>
4#include <sys/fcntl.h> 4#include <sys/fcntl.h>
5 5
6const char mt_usage[] = "mt [-f device] opcode value\n"; 6static const char mt_usage[] = "mt [-f device] opcode value\n";
7 7
8struct mt_opcodes { 8struct mt_opcodes {
9 char * name; 9 char * name;
diff --git a/mkdir.c b/mkdir.c
index b42899a4a..cf65f272f 100644
--- a/mkdir.c
+++ b/mkdir.c
@@ -24,7 +24,7 @@
24#include <errno.h> 24#include <errno.h>
25#include <sys/param.h> 25#include <sys/param.h>
26 26
27const char mkdir_usage[] = "Usage: mkdir [OPTION] DIRECTORY...\n" 27static const char mkdir_usage[] = "Usage: mkdir [OPTION] DIRECTORY...\n"
28"Create the DIRECTORY(ies), if they do not already exist\n\n" 28"Create the DIRECTORY(ies), if they do not already exist\n\n"
29"-m\tset permission mode (as in chmod), not rwxrwxrwx - umask\n" 29"-m\tset permission mode (as in chmod), not rwxrwxrwx - umask\n"
30"-p\tno error if existing, make parent directories as needed\n"; 30"-p\tno error if existing, make parent directories as needed\n";
diff --git a/mknod.c b/mknod.c
index 95d7de360..ea2331fa3 100644
--- a/mknod.c
+++ b/mknod.c
@@ -6,7 +6,7 @@
6#include <fcntl.h> 6#include <fcntl.h>
7#include <unistd.h> 7#include <unistd.h>
8 8
9const char mknod_usage[] = "mknod file b|c|u|p major minor\n" 9static const char mknod_usage[] = "mknod file b|c|u|p major minor\n"
10"\tMake special files.\n" 10"\tMake special files.\n"
11"\n" 11"\n"
12"\tb:\tMake a block (buffered) device.\n" 12"\tb:\tMake a block (buffered) device.\n"
diff --git a/mkswap.c b/mkswap.c
index 8c0c4dec7..fceeb28dd 100644
--- a/mkswap.c
+++ b/mkswap.c
@@ -1,4 +1,3 @@
1#include "internal.h"
2/* 1/*
3 * mkswap.c - set up a linux swap device 2 * mkswap.c - set up a linux swap device
4 * 3 *
@@ -9,51 +8,170 @@
9/* 8/*
10 * 20.12.91 - time began. Got VM working yesterday by doing this by hand. 9 * 20.12.91 - time began. Got VM working yesterday by doing this by hand.
11 * 10 *
12 * Usage: mkswap [-c] device [size-in-blocks] 11 * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks]
13 * 12 *
14 * -c for readablility checking (use it unless you are SURE!) 13 * -c for readability checking. (Use it unless you are SURE!)
14 * -vN for swap areas version N. (Only N=0,1 known today.)
15 * -f for forcing swap creation even if it would smash partition table.
15 * 16 *
16 * The device may be a block device or a image of one, but this isn't 17 * The device may be a block device or an image of one, but this isn't
17 * enforced (but it's not much fun on a character device :-). 18 * enforced (but it's not much fun on a character device :-).
18 * 19 *
19 * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the 20 * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the
20 * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995. 21 * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995.
22 *
23 * Version 1 swap area code (for kernel 2.1.117), aeb, 981010.
24 *
25 * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb.
26 * V1_MAX_PAGES fixes, jj, 990325.
27 *
28 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
29 * - added Native Language Support
30 *
31 * from util-linux -- adapted for busybox by
32 * Erik Andersen <andersee@debian.org>. I ripped out Native Language
33 * Support, made some stuff smaller, and fitted for life in busybox.
34 *
21 */ 35 */
22 36
37#include "internal.h"
23#include <stdio.h> 38#include <stdio.h>
24#include <unistd.h> 39#include <unistd.h>
25#include <string.h> 40#include <string.h>
26#include <fcntl.h> 41#include <fcntl.h>
27#include <stdlib.h> 42#include <stdlib.h>
43#include <sys/ioctl.h> /* for _IO */
44#include <sys/utsname.h>
28#include <sys/stat.h> 45#include <sys/stat.h>
29#include <sys/ioctl.h> 46#include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
47 /* we also get PAGE_SIZE via getpagesize() */
30 48
31#include <asm/page.h>
32#include <linux/fs.h>
33 49
34#ifndef __linux__ 50static const char mkswap_usage[] = "mkswap [-c] [-v0|-v1] device [block-count]\n"
35# define volatile 51"Prepare a disk partition to be used as a swap partition.\n\n"
36#endif 52"\t-c\tCheck for read-ability.\n"
53"\t-v0\tMake version 0 swap [max 128 Megs].\n"
54"\t-v1\tMake version 1 swap [big!] (default for kernels > 2.1.117).\n"
55"\tblock-count\tNumber of block to use (default is entire partition).\n";
37 56
38#define TEST_BUFFER_PAGES 8
39 57
40const char mkswap_usage[] = "mkswap [-c] partition [block-count]\n" 58#ifndef _IO
41"\n" 59/* pre-1.3.45 */
42"\tPrepare a disk partition to be used as a swap partition.\n" 60#define BLKGETSIZE 0x1260
43"\tThe default block count is the size of the entire partition.\n" 61#else
44"\n" 62/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
45"\t-c:\tCheck for read-ability.\n" 63#define BLKGETSIZE _IO(0x12,96)
46"\tblock-count\tUse only this many blocks.\n"; 64#endif
47 65
48static const char * program_name = "mkswap"; 66static char * program_name = "mkswap";
49static const char * device_name = NULL; 67static char * device_name = NULL;
50static int DEV = -1; 68static int DEV = -1;
51static long PAGES = 0; 69static long PAGES = 0;
52static int do_check = 0; 70static int check = 0;
53static int badpages = 0; 71static int badpages = 0;
72static int version = -1;
73
74#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
75
76static int
77linux_version_code(void) {
78 struct utsname my_utsname;
79 int p, q, r;
80
81 if (uname(&my_utsname) == 0) {
82 p = atoi(strtok(my_utsname.release, "."));
83 q = atoi(strtok(NULL, "."));
84 r = atoi(strtok(NULL, "."));
85 return MAKE_VERSION(p,q,r);
86 }
87 return 0;
88}
89
90/*
91 * The definition of the union swap_header uses the constant PAGE_SIZE.
92 * Unfortunately, on some architectures this depends on the hardware model,
93 * and can only be found at run time -- we use getpagesize().
94 */
95
96static int pagesize;
97static int *signature_page;
98
99struct swap_header_v1 {
100 char bootbits[1024]; /* Space for disklabel etc. */
101 unsigned int version;
102 unsigned int last_page;
103 unsigned int nr_badpages;
104 unsigned int padding[125];
105 unsigned int badpages[1];
106} *p;
107
108static void
109init_signature_page() {
110 pagesize = getpagesize();
111
112#ifdef PAGE_SIZE
113 if (pagesize != PAGE_SIZE)
114 fprintf(stderr, "Assuming pages of size %d\n", pagesize);
115#endif
116 signature_page = (int *) malloc(pagesize);
117 memset(signature_page,0,pagesize);
118 p = (struct swap_header_v1 *) signature_page;
119}
54 120
121static void
122write_signature(char *sig) {
123 char *sp = (char *) signature_page;
55 124
56static long bit_test_and_set (unsigned int *addr, unsigned int nr) 125 strncpy(sp+pagesize-10, sig, 10);
126}
127
128#define V0_MAX_PAGES (8 * (pagesize - 10))
129/* Before 2.2.0pre9 */
130#define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
131/* Since 2.2.0pre9:
132 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
133 with variations on
134 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
135 #define SWP_OFFSET(entry) ((entry) >> 8)
136 on the various architectures. Below the result - yuk.
137
138 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
139 i386 2^12 o<<8 e>>8 1<<24 1<<19
140 mips 2^12 o<<15 e>>15 1<<17 1<<19
141 alpha 2^13 o<<40 e>>40 1<<24 1<<18
142 m68k 2^12 o<<12 e>>12 1<<20 1<<19
143 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
144 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
145 ppc 2^12 o<<8 e>>8 1<<24 1<<19
146 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
147 armv 2^12 o<<9 e>>9 1<<23 1<<19
148
149 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
150
151 The bad part is that we need to know this since the kernel will
152 refuse a swap space if it is too large.
153*/
154/* patch from jj - why does this differ from the above? */
155#if defined(__alpha__)
156#define V1_MAX_PAGES ((1 << 24) - 1)
157#elif defined(__mips__)
158#define V1_MAX_PAGES ((1 << 17) - 1)
159#elif defined(__sparc_v9__)
160#define V1_MAX_PAGES ((3 << 29) - 1)
161#elif defined(__sparc__)
162#define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
163#else
164#define V1_MAX_PAGES V1_OLD_MAX_PAGES
165#endif
166/* man page now says:
167The maximum useful size of a swap area now depends on the architecture.
168It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
169128GB on alpha and 3TB on sparc64.
170*/
171
172#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
173
174static void bit_set (unsigned int *addr, unsigned int nr)
57{ 175{
58 unsigned int r, m; 176 unsigned int r, m;
59 177
@@ -61,7 +179,6 @@ static long bit_test_and_set (unsigned int *addr, unsigned int nr)
61 r = *addr; 179 r = *addr;
62 m = 1 << (nr & (8 * sizeof(int) - 1)); 180 m = 1 << (nr & (8 * sizeof(int) - 1));
63 *addr = r | m; 181 *addr = r | m;
64 return (r & m) != 0;
65} 182}
66 183
67static int bit_test_and_clear (unsigned int *addr, unsigned int nr) 184static int bit_test_and_clear (unsigned int *addr, unsigned int nr)
@@ -75,47 +192,59 @@ static int bit_test_and_clear (unsigned int *addr, unsigned int nr)
75 return (r & m) != 0; 192 return (r & m) != 0;
76} 193}
77 194
78/* 195
79 * Volatile to let gcc know that this doesn't return. When trying 196void
80 * to compile this under minix, volatile gives a warning, as 197die(const char *str) {
81 * exit() isn't defined as volatile under minix. 198 fprintf(stderr, "%s: %s\n", program_name, str);
82 */ 199 exit( FALSE);
83volatile void fatal_error(const char * fmt_string)
84{
85 fprintf(stderr,fmt_string,program_name,device_name);
86 exit(FALSE);
87} 200}
88 201
89#define die(str) fatal_error("%s: " str "\n") 202void
203page_ok(int page) {
204 if (version==0)
205 bit_set(signature_page, page);
206}
90 207
91static void check_blocks(int * signature_page) 208void
92{ 209page_bad(int page) {
210 if (version == 0)
211 bit_test_and_clear(signature_page, page);
212 else {
213 if (badpages == MAX_BADPAGES)
214 die("too many bad pages");
215 p->badpages[badpages] = page;
216 }
217 badpages++;
218}
219
220void
221check_blocks(void) {
93 unsigned int current_page; 222 unsigned int current_page;
94 int do_seek = 1; 223 int do_seek = 1;
95 char buffer[PAGE_SIZE]; 224 char *buffer;
96 225
226 buffer = malloc(pagesize);
227 if (!buffer)
228 die("Out of memory");
97 current_page = 0; 229 current_page = 0;
98 while (current_page < PAGES) { 230 while (current_page < PAGES) {
99 if (!do_check) { 231 if (!check) {
100 bit_test_and_set(signature_page,current_page++); 232 page_ok(current_page++);
101 continue; 233 continue;
102 } else {
103 printf("\r%d", current_page);
104 } 234 }
105 if (do_seek && lseek(DEV,current_page*PAGE_SIZE,SEEK_SET) != 235 if (do_seek && lseek(DEV,current_page*pagesize,SEEK_SET) !=
106 current_page*PAGE_SIZE) 236 current_page*pagesize)
107 die("seek failed in check_blocks"); 237 die("seek failed in check_blocks");
108 if ( (do_seek = (PAGE_SIZE != read(DEV, buffer, PAGE_SIZE))) ) { 238 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
109 bit_test_and_clear(signature_page,current_page++); 239 page_bad(current_page++);
110 badpages++;
111 continue; 240 continue;
112 } 241 }
113 bit_test_and_set(signature_page,current_page++); 242 page_ok(current_page++);
114 } 243 }
115 if (do_check) 244 if (badpages == 1)
116 printf("\n"); 245 printf("one bad page\n");
117 if (badpages) 246 else if (badpages > 1)
118 printf("%d bad page%s\n",badpages,(badpages>1)?"s":""); 247 printf("%d bad pages\n", badpages);
119} 248}
120 249
121static long valid_offset (int fd, int offset) 250static long valid_offset (int fd, int offset)
@@ -129,12 +258,13 @@ static long valid_offset (int fd, int offset)
129 return 1; 258 return 1;
130} 259}
131 260
132static int count_blocks (int fd) 261static int
262find_size (int fd)
133{ 263{
134 int high, low; 264 unsigned int high, low;
135 265
136 low = 0; 266 low = 0;
137 for (high = 1; valid_offset (fd, high); high *= 2) 267 for (high = 1; high > 0 && valid_offset (fd, high); high *= 2)
138 low = high; 268 low = high;
139 while (low < high - 1) 269 while (low < high - 1)
140 { 270 {
@@ -145,108 +275,194 @@ static int count_blocks (int fd)
145 else 275 else
146 high = mid; 276 high = mid;
147 } 277 }
148 valid_offset (fd, 0);
149 return (low + 1); 278 return (low + 1);
150} 279}
151 280
152static int get_size(const char *file) 281/* return size in pages, to avoid integer overflow */
282static long
283get_size(const char *file)
153{ 284{
154 int fd; 285 int fd;
155 int size; 286 long size;
156 287
157 fd = open(file, O_RDWR); 288 fd = open(file, O_RDONLY);
158 if (fd < 0) { 289 if (fd < 0) {
159 perror(file); 290 perror(file);
160 exit(1); 291 exit(1);
161 } 292 }
162 if (ioctl(fd, BLKGETSIZE, &size) >= 0) { 293 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
163 close(fd); 294 int sectors_per_page = pagesize/512;
164 return (size * 512); 295 size /= sectors_per_page;
296 } else {
297 size = find_size(fd) / pagesize;
165 } 298 }
166
167 size = count_blocks(fd);
168 close(fd); 299 close(fd);
169 return size; 300 return size;
170} 301}
171 302
172int 303int mkswap_main(int argc, char ** argv)
173mkswap(const char *device_name, int pages, int check) 304{
174 { 305 char * tmp;
175 struct stat statbuf; 306 struct stat statbuf;
307 int sz;
308 int maxpages;
176 int goodpages; 309 int goodpages;
177 int signature_page[PAGE_SIZE/sizeof(int)]; 310 int offset;
311 int force = 0;
178 312
179 PAGES = pages; 313 if (argc && *argv)
180 do_check = check; 314 program_name = *argv;
181 315
182 memset(signature_page,0,PAGE_SIZE); 316 init_signature_page(); /* get pagesize */
183 317
184 if (device_name && !PAGES) { 318 while (argc-- > 1) {
185 PAGES = get_size(device_name) / PAGE_SIZE; 319 argv++;
320 if (argv[0][0] != '-') {
321 if (device_name) {
322 int blocks_per_page = pagesize/1024;
323 PAGES = strtol(argv[0],&tmp,0)/blocks_per_page;
324 if (*tmp)
325 usage( mkswap_usage);
326 } else
327 device_name = argv[0];
328 } else {
329 switch (argv[0][1]) {
330 case 'c':
331 check=1;
332 break;
333 case 'f':
334 force=1;
335 break;
336 case 'v':
337 version=atoi(argv[0]+2);
338 break;
339 default:
340 usage( mkswap_usage);
341 }
342 }
343 }
344 if (!device_name) {
345 fprintf(stderr,
346 "%s: error: Nowhere to set up swap on?\n",
347 program_name);
348 usage( mkswap_usage);
186 } 349 }
187 if (!device_name || PAGES<10) { 350 sz = get_size(device_name);
351 if (!PAGES) {
352 PAGES = sz;
353 } else if (PAGES > sz && !force) {
354 fprintf(stderr,
355 "%s: error: "
356 "size %ld is larger than device size %d\n",
357 program_name,
358 PAGES*(pagesize/1024), sz*(pagesize/1024));
359 exit( FALSE);
360 }
361
362 if (version == -1) {
363 if (PAGES <= V0_MAX_PAGES)
364 version = 0;
365 else if (linux_version_code() < MAKE_VERSION(2,1,117))
366 version = 0;
367 else if (pagesize < 2048)
368 version = 0;
369 else
370 version = 1;
371 }
372 if (version != 0 && version != 1) {
373 fprintf(stderr, "%s: error: unknown version %d\n",
374 program_name, version);
375 usage( mkswap_usage);
376 }
377 if (PAGES < 10) {
188 fprintf(stderr, 378 fprintf(stderr,
189 "%s: error: swap area needs to be at least %ldkB\n", 379 "%s: error: swap area needs to be at least %ldkB\n",
190 program_name, 10 * PAGE_SIZE / 1024); 380 program_name, (long)(10 * pagesize / 1024));
191 /* usage(mkswap_usage); */ 381 usage( mkswap_usage);
192 exit(1); 382 }
383#if 0
384 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
385#else
386 if (!version)
387 maxpages = V0_MAX_PAGES;
388 else if (linux_version_code() >= MAKE_VERSION(2,2,1))
389 maxpages = V1_MAX_PAGES;
390 else {
391 maxpages = V1_OLD_MAX_PAGES;
392 if (maxpages > V1_MAX_PAGES)
393 maxpages = V1_MAX_PAGES;
193 } 394 }
194 if (PAGES > 8 * (PAGE_SIZE - 10)) { 395#endif
195 PAGES = 8 * (PAGE_SIZE - 10); 396 if (PAGES > maxpages) {
397 PAGES = maxpages;
196 fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n", 398 fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n",
197 program_name, PAGES * PAGE_SIZE / 1024); 399 program_name, PAGES * pagesize / 1024);
198 } 400 }
401
199 DEV = open(device_name,O_RDWR); 402 DEV = open(device_name,O_RDWR);
200 if (DEV < 0 || fstat(DEV, &statbuf) < 0) { 403 if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
201 perror(device_name); 404 perror(device_name);
202 exit(1); 405 exit( FALSE);
203 } 406 }
204 if (!S_ISBLK(statbuf.st_mode)) 407 if (!S_ISBLK(statbuf.st_mode))
205 do_check=0; 408 check=0;
206 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) 409 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
207 die("Will not try to make swapdevice on '%s'"); 410 die("Will not try to make swapdevice on '%s'");
208 check_blocks(signature_page); 411
209 if (!bit_test_and_clear(signature_page,0)) 412#ifdef __sparc__
413 if (!force && version == 0) {
414 /* Don't overwrite partition table unless forced */
415 unsigned char *buffer = (unsigned char *)signature_page;
416 unsigned short *q, sum;
417
418 if (read(DEV, buffer, 512) != 512)
419 die("fatal: first page unreadable");
420 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
421 q = (unsigned short *)(buffer + 510);
422 for (sum = 0; q >= (unsigned short *) buffer;)
423 sum ^= *q--;
424 if (!sum) {
425 fprintf(stderr, "\
426%s: Device '%s' contains a valid Sun disklabel.\n\
427This probably means creating v0 swap would destroy your partition table\n\
428No swap created. If you really want to create swap v0 on that device, use\n\
429the -f option to force it.\n",
430 program_name, device_name);
431 exit( FALSE);
432 }
433 }
434 }
435#endif
436
437 if (version == 0 || check)
438 check_blocks();
439 if (version == 0 && !bit_test_and_clear(signature_page,0))
210 die("fatal: first page unreadable"); 440 die("fatal: first page unreadable");
441 if (version == 1) {
442 p->version = version;
443 p->last_page = PAGES-1;
444 p->nr_badpages = badpages;
445 }
446
211 goodpages = PAGES - badpages - 1; 447 goodpages = PAGES - badpages - 1;
212 if (goodpages <= 0) 448 if (goodpages <= 0)
213 die("Unable to set up swap-space: unreadable"); 449 die("Unable to set up swap-space: unreadable");
214 printf("Setting up swapspace, size = %ld bytes\n",goodpages*PAGE_SIZE); 450 printf("Setting up swapspace version %d, size = %ld bytes\n",
215 strncpy((char*)signature_page+PAGE_SIZE-10,"SWAP-SPACE",10); 451 version, (long)(goodpages*pagesize));
216 if (lseek(DEV, 0, SEEK_SET)) 452 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
453
454 offset = ((version == 0) ? 0 : 1024);
455 if (lseek(DEV, offset, SEEK_SET) != offset)
217 die("unable to rewind swap-device"); 456 die("unable to rewind swap-device");
218 if (PAGE_SIZE != write(DEV, signature_page, PAGE_SIZE)) 457 if (write(DEV,(char*)signature_page+offset, pagesize-offset)
458 != pagesize-offset)
219 die("unable to write signature page"); 459 die("unable to write signature page");
220 460
221 close(DEV); 461 /*
222 return (TRUE); 462 * A subsequent swapon() will fail if the signature
223} 463 * is not actually on disk. (This is a kernel bug.)
224 464 */
225int mkswap_main(int argc, char ** argv) 465 if (fsync(DEV))
226{ 466 die("fsync failed");
227 char * tmp; 467 exit ( TRUE);
228 long int pages=0;
229 int check=0;
230
231 if (argc && *argv)
232 program_name = *argv;
233 while (argc > 1) {
234 argv++;
235 argc--;
236 if (argv[0][0] != '-')
237 if (device_name) {
238 pages = strtol(argv[0],&tmp,0)>>(PAGE_SHIFT-10);
239 if (*tmp) {
240 usage (mkswap_usage);
241 }
242 } else
243 device_name = argv[0];
244 else while (*++argv[0])
245 switch (argv[0][0]) {
246 case 'c': check=1; break;
247 default: usage (mkswap_usage);
248 exit( TRUE);
249 }
250 }
251 exit( mkswap(device_name, pages, check));
252} 468}
diff --git a/mnc.c b/mnc.c
index 124ea0345..a9e66bebf 100644
--- a/mnc.c
+++ b/mnc.c
@@ -39,7 +39,7 @@
39 39
40#define BUFSIZE 100 40#define BUFSIZE 100
41 41
42const char mnc_usage[] = 42static const char mnc_usage[] =
43"mini-netcat 0.0.3 -- Open pipe to IP:port\n" 43"mini-netcat 0.0.3 -- Open pipe to IP:port\n"
44"\tmnc [IP] [port]\n"; 44"\tmnc [IP] [port]\n";
45 45
diff --git a/more.c b/more.c
index 53437ed58..772d51b18 100644
--- a/more.c
+++ b/more.c
@@ -30,7 +30,7 @@
30#include <signal.h> 30#include <signal.h>
31 31
32 32
33const char more_usage[] = "[file ...]"; 33static const char more_usage[] = "[file ...]";
34 34
35 35
36#ifdef BB_MORE_TERM 36#ifdef BB_MORE_TERM
diff --git a/mount.c b/mount.c
index 26d4693d0..a7d5aed2d 100644
--- a/mount.c
+++ b/mount.c
@@ -37,7 +37,7 @@
37#include <ctype.h> 37#include <ctype.h>
38#include <fstab.h> 38#include <fstab.h>
39 39
40const char mount_usage[] = "Usage:\tmount [flags]\n" 40static const char mount_usage[] = "Usage:\tmount [flags]\n"
41 "\tmount [flags] device directory [-o options,more-options]\n" 41 "\tmount [flags] device directory [-o options,more-options]\n"
42 "\n" 42 "\n"
43 "Flags:\n" 43 "Flags:\n"
diff --git a/mt.c b/mt.c
index a61ad5a40..7168ef7ac 100644
--- a/mt.c
+++ b/mt.c
@@ -3,7 +3,7 @@
3#include <sys/mtio.h> 3#include <sys/mtio.h>
4#include <sys/fcntl.h> 4#include <sys/fcntl.h>
5 5
6const char mt_usage[] = "mt [-f device] opcode value\n"; 6static const char mt_usage[] = "mt [-f device] opcode value\n";
7 7
8struct mt_opcodes { 8struct mt_opcodes {
9 char * name; 9 char * name;
diff --git a/printf.c b/printf.c
index 4d4465943..02d08118b 100644
--- a/printf.c
+++ b/printf.c
@@ -136,7 +136,7 @@ static void verify __P ((char *s, char *end));
136/* The value to return to the calling program. */ 136/* The value to return to the calling program. */
137static int exit_status; 137static int exit_status;
138 138
139const char printf_usage[] = "printf format [argument...]\n"; 139static const char printf_usage[] = "printf format [argument...]\n";
140 140
141int 141int
142printf_main(int argc, char** argv) 142printf_main(int argc, char** argv)
diff --git a/procps/kill.c b/procps/kill.c
index 00f10f91f..e89f913d0 100644
--- a/procps/kill.c
+++ b/procps/kill.c
@@ -21,20 +21,20 @@ const struct signal_name signames[] = {
21#ifndef __alpha__ 21#ifndef __alpha__
22 {"IOT", SIGIOT}, 22 {"IOT", SIGIOT},
23#endif 23#endif
24#if defined(sparc) || defined(__alpha__) 24#if defined(__sparc__) || defined(__alpha__)
25 {"EMT", SIGEMT}, 25 {"EMT", SIGEMT},
26#else 26#else
27 {"BUS", SIGBUS}, 27 {"BUS", SIGBUS},
28#endif 28#endif
29 {"FPE", SIGFPE}, 29 {"FPE", SIGFPE},
30 {"KILL", SIGKILL}, 30 {"KILL", SIGKILL},
31#if defined(sparc) || defined(__alpha__) 31#if defined(__sparc__) || defined(__alpha__)
32 {"BUS", SIGBUS}, 32 {"BUS", SIGBUS},
33#else 33#else
34 {"USR1", SIGUSR1}, 34 {"USR1", SIGUSR1},
35#endif 35#endif
36 {"SEGV", SIGSEGV}, 36 {"SEGV", SIGSEGV},
37#if defined(sparc) || defined(__alpha__) 37#if defined(__sparc__) || defined(__alpha__)
38 {"SYS", SIGSYS}, 38 {"SYS", SIGSYS},
39#else 39#else
40 {"USR2", SIGUSR2}, 40 {"USR2", SIGUSR2},
@@ -42,7 +42,7 @@ const struct signal_name signames[] = {
42 {"PIPE", SIGPIPE}, 42 {"PIPE", SIGPIPE},
43 {"ALRM", SIGALRM}, 43 {"ALRM", SIGALRM},
44 {"TERM", SIGTERM}, 44 {"TERM", SIGTERM},
45#if defined(sparc) || defined(__alpha__) 45#if defined(__sparc__) || defined(__alpha__)
46 {"URG", SIGURG}, 46 {"URG", SIGURG},
47 {"STOP", SIGSTOP}, 47 {"STOP", SIGSTOP},
48 {"TSTP", SIGTSTP}, 48 {"TSTP", SIGTSTP},
diff --git a/sfdisk.c b/sfdisk.c
new file mode 100644
index 000000000..5b67e69ab
--- /dev/null
+++ b/sfdisk.c
@@ -0,0 +1,2880 @@
1/*
2 * sfdisk version 3.0 - aeb - 950813
3 *
4 * Copyright (C) 1995 Andries E. Brouwer (aeb@cwi.nl)
5 *
6 * This program is free software. You can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation: either Version 1
9 * or (at your option) any later version.
10 *
11 * A.V. Le Blanc (LeBlanc@mcc.ac.uk) wrote Linux fdisk 1992-1994,
12 * patched by various people (faith@cs.unc.edu, martin@cs.unc.edu,
13 * leisner@sdsp.mc.xerox.com, esr@snark.thyrsus.com, aeb@cwi.nl)
14 * 1993-1995, with version numbers (as far as I have seen) 0.93 - 2.0e.
15 * This program had (head,sector,cylinder) as basic unit, and was
16 * (therefore) broken in several ways for the use on larger disks -
17 * for example, my last patch (from 2.0d to 2.0e) was required
18 * to allow a partition to cross cylinder 8064, and to write an
19 * extended partition past the 4GB mark.
20 *
21 * The current program is a rewrite from scratch, and I started a
22 * version numbering at 3.0.
23 * Andries Brouwer, aeb@cwi.nl, 950813
24 *
25 * Well, a good user interface is still lacking. On the other hand,
26 * many configurations cannot be handled by any other fdisk.
27 * I changed the name to sfdisk to prevent confusion. - aeb, 970501
28 *
29 * Changes:
30 * 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n
31 *
32 * busyboxed by Erik Andersen <andersee@debian.org> -- I stipped out
33 * all the NLS, pulled in some includes, and made stuff smaller...
34 */
35
36#define PROGNAME "sfdisk"
37#define VERSION "3.07"
38#define DATE "990908"
39
40#include "internal.h"
41#include <stdio.h>
42#include <stdlib.h> /* atoi, free */
43#include <stdarg.h> /* varargs */
44#include <unistd.h> /* read, write */
45#include <fcntl.h> /* O_RDWR */
46#include <errno.h> /* ERANGE */
47#include <string.h> /* index() */
48#include <ctype.h>
49#include <getopt.h>
50#include <sys/ioctl.h>
51#include <sys/stat.h>
52#include <linux/unistd.h> /* _syscall */
53#include <linux/hdreg.h> /* HDIO_GETGEO */
54#include <linux/fs.h> /* BLKGETSIZE */
55
56
57static const char sfdisk_usage[] =
58"Usage: sfdisk [options] device ...\n"
59"device: something like /dev/hda or /dev/sda\n"
60"useful options:\n"
61" -s [or --show-size]: list size of a partition\n"
62" -c [or --id]: print or change partition Id\n"
63" -l [or --list]: list partitions of each device\n"
64" -d [or --dump]: idem, but in a format suitable for later input\n"
65" -i [or --increment]: number cylinders etc. from 1 instead of from 0\n"
66" -uS, -uB, -uC, -uM: accept/report in units of sectors/blocks/cylinders/MB\n"
67" -T [or --list-types]:list the known partition types\n"
68" -D [or --DOS]: for DOS-compatibility: waste a little space\n"
69" -R [or --re-read]: make kernel reread partition table\n"
70" -N# : change only the partition with number #\n"
71" -n : do not actually write to disk\n"
72" -O file : save the sectors that will be overwritten to file\n"
73" -I file : restore these sectors again\n"
74" -v [or --version]: print version\n"
75" -? [or --help]: print this message\n"
76"dangerous options:\n"
77" -g [or --show-geometry]: print the kernel's idea of the geometry\n"
78" -x [or --show-extended]: also list extended partitions on output\n\n"
79" or expect descriptors for them on input\n"
80" -L [or --Linux]: do not complain about things irrelevant for Linux\n"
81" -q [or --quiet]: suppress warning messages\n"
82" You can override the detected geometry using:\n"
83" -C# [or --cylinders #]:set the number of cylinders to use\n"
84" -H# [or --heads #]: set the number of heads to use\n"
85" -S# [or --sectors #]: set the number of sectors to use\n"
86"You can disable all consistency checking with:\n"
87" -f [or --force]: do what I say, even if it is stupid\n";
88
89
90
91/* common stuff for fdisk, cfdisk, sfdisk */
92struct systypes {
93 unsigned char type;
94 char *name;
95};
96
97static struct systypes i386_sys_types[] = {
98 {0x00, "Empty"},
99 {0x01, "FAT12"},
100 {0x02, "XENIX root"},
101 {0x03, "XENIX usr"},
102 {0x04, "FAT16 <32M"},
103 {0x05, "Extended"}, /* DOS 3.3+ extended partition */
104 {0x06, "FAT16"}, /* DOS 16-bit >=32M */
105 {0x07, "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
106 {0x08, "AIX"}, /* AIX boot (AIX -- PS/2 port or SplitDrive) */
107 {0x09, "AIX bootable"}, /* AIX data or Coherent */
108 {0x0a, "OS/2 Boot Manager"},/* OS/2 Boot Manager */
109 {0x0b, "Win95 FAT32"},
110 {0x0c, "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
111 {0x0e, "Win95 FAT16 (LBA)"},
112 {0x0f, "Win95 Ext'd (LBA)"},
113 {0x10, "OPUS"},
114 {0x11, "Hidden FAT12"},
115 {0x12, "Compaq diagnostics"},
116 {0x14, "Hidden FAT16 <32M"},
117 {0x16, "Hidden FAT16"},
118 {0x17, "Hidden HPFS/NTFS"},
119 {0x18, "AST Windows swapfile"},
120 {0x1b, "Hidden Win95 FAT32"},
121 {0x1c, "Hidden Win95 FAT32 (LBA)"},
122 {0x1e, "Hidden Win95 FAT16 (LBA)"},
123 {0x24, "NEC DOS"},
124 {0x3c, "PartitionMagic recovery"},
125 {0x40, "Venix 80286"},
126 {0x41, "PPC PReP Boot"},
127 {0x42, "SFS"},
128 {0x4d, "QNX4.x"},
129 {0x4e, "QNX4.x 2nd part"},
130 {0x4f, "QNX4.x 3rd part"},
131 {0x50, "OnTrack DM"},
132 {0x51, "OnTrack DM6 Aux1"}, /* (or Novell) */
133 {0x52, "CP/M"}, /* CP/M or Microport SysV/AT */
134 {0x53, "OnTrack DM6 Aux3"},
135 {0x54, "OnTrackDM6"},
136 {0x55, "EZ-Drive"},
137 {0x56, "Golden Bow"},
138 {0x5c, "Priam Edisk"},
139 {0x61, "SpeedStor"},
140 {0x63, "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
141 {0x64, "Novell Netware 286"},
142 {0x65, "Novell Netware 386"},
143 {0x70, "DiskSecure Multi-Boot"},
144 {0x75, "PC/IX"},
145 {0x80, "Old Minix"}, /* Minix 1.4a and earlier */
146 {0x81, "Minix / old Linux"},/* Minix 1.4b and later */
147 {0x82, "Linux swap"}, /* also Solaris */
148 {0x83, "Linux"},
149 {0x84, "OS/2 hidden C: drive"},
150 {0x85, "Linux extended"},
151 {0x86, "NTFS volume set"},
152 {0x87, "NTFS volume set"},
153 {0x93, "Amoeba"},
154 {0x94, "Amoeba BBT"}, /* (bad block table) */
155 {0xa0, "IBM Thinkpad hibernation"},
156 {0xa5, "BSD/386"},
157 {0xa6, "OpenBSD"},
158 {0xa7, "NeXTSTEP"},
159 {0xb7, "BSDI fs"},
160 {0xb8, "BSDI swap"},
161 {0xc1, "DRDOS/sec (FAT-12)"},
162 {0xc4, "DRDOS/sec (FAT-16 < 32M)"},
163 {0xc6, "DRDOS/sec (FAT-16)"},
164 {0xc7, "Syrinx"},
165 {0xdb, "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or Concurrent DOS or CTOS */
166 {0xe1, "DOS access"}, /* DOS access or SpeedStor 12-bit FAT extended partition */
167 {0xe3, "DOS R/O"}, /* DOS R/O or SpeedStor */
168 {0xe4, "SpeedStor"}, /* SpeedStor 16-bit FAT extended partition < 1024 cyl. */
169 {0xeb, "BeOS fs"},
170 {0xf1, "SpeedStor"},
171 {0xf4, "SpeedStor"}, /* SpeedStor large partition */
172 {0xf2, "DOS secondary"}, /* DOS 3.3+ secondary */
173 {0xfd, "Linux raid autodetect"},/* New (2.2.x) raid partition with autodetect
174 using persistent superblock */
175 {0xfe, "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
176 {0xff, "BBT"}, /* Xenix Bad Block Table */
177 { 0, 0 }
178};
179
180#define SIZE(a) (sizeof(a)/sizeof(a[0]))
181
182/*
183 * Table of contents:
184 * A. About seeking
185 * B. About sectors
186 * C. About heads, sectors and cylinders
187 * D. About system Ids
188 * E. About partitions
189 * F. The standard input
190 * G. The command line
191 * H. Listing the current situation
192 * I. Writing the new situation
193 */
194static int exit_status = 0;
195
196static int force = 0; /* 1: do what I say, even if it is stupid ... */
197static int quiet = 0; /* 1: suppress all warnings */
198static int Linux = 0; /* 1: suppress warnings irrelevant for Linux */
199static int DOS = 0; /* 1: shift extended partitions by #sectors, not 1 */
200static int dump = 0; /* 1: list in a format suitable for later input */
201static int verify = 0; /* 1: check that listed partition is reasonable */
202static int no_write = 0; /* 1: do not actually write to disk */
203static int no_reread = 0; /* 1: skip the BLKRRPART ioctl test at startup */
204static int leave_last = 0; /* 1: don't allocate the last cylinder */
205static int opt_list = 0;
206static char *save_sector_file = NULL;
207static char *restore_sector_file = NULL;
208
209static void
210warn(char *s, ...) {
211 va_list p;
212
213 va_start(p, s);
214 fflush(stdout);
215 if (!quiet)
216 vfprintf (stderr, s, p);
217 va_end(p);
218}
219
220static void
221error(char *s, ...) {
222 va_list p;
223
224 va_start(p, s);
225 fflush(stdout);
226 fprintf(stderr, "\n" PROGNAME ": ");
227 vfprintf(stderr, s, p);
228 va_end(p);
229}
230
231static void
232fatal(char *s, ...) {
233 va_list p;
234
235 va_start(p, s);
236 fflush(stdout);
237 fprintf(stderr, "\n" PROGNAME ": ");
238 vfprintf(stderr, s, p);
239 va_end(p);
240 exit(1);
241}
242
243/*
244 * A. About seeking
245 */
246
247/*
248 * sseek: seek to specified sector - return 0 on failure
249 *
250 * For >4GB disks lseek needs a > 32bit arg, and we have to use llseek.
251 * On the other hand, a 32 bit sector number is OK until 2TB.
252 * The routines _llseek and sseek below are the only ones that
253 * know about the loff_t type.
254 */
255#ifndef __alpha__
256static
257_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
258 loff_t *, res, uint, wh);
259#endif
260
261static int
262sseek(char *dev, unsigned int fd, unsigned long s) {
263 loff_t in, out;
264 in = ((loff_t) s << 9);
265 out = 1;
266
267#ifndef __alpha__
268 if (_llseek (fd, in>>32, in & 0xffffffff, &out, SEEK_SET) != 0) {
269#else
270 if ((out = lseek(fd, in, SEEK_SET)) != in) {
271#endif
272 perror("llseek");
273 error("seek error on %s - cannot seek to %lu\n", dev, s);
274 return 0;
275 }
276
277 if (in != out) {
278 error("seek error: wanted 0x%08x%08x, got 0x%08x%08x\n",
279 (uint)(in>>32), (uint)(in & 0xffffffff),
280 (uint)(out>>32), (uint)(out & 0xffffffff));
281 return 0;
282 }
283 return 1;
284}
285
286/*
287 * B. About sectors
288 */
289
290/*
291 * We preserve all sectors read in a chain - some of these will
292 * have to be modified and written back.
293 */
294struct sector {
295 struct sector *next;
296 unsigned long sectornumber;
297 int to_be_written;
298 char data[512];
299} *sectorhead;
300
301static void
302free_sectors(void) {
303 struct sector *s;
304
305 while (sectorhead) {
306 s = sectorhead;
307 sectorhead = s->next;
308 free(s);
309 }
310}
311
312static struct sector *
313get_sector(char *dev, int fd, unsigned long sno) {
314 struct sector *s;
315
316 for(s = sectorhead; s; s = s->next)
317 if(s->sectornumber == sno)
318 return s;
319
320 if (!sseek(dev, fd, sno))
321 return 0;
322
323 if (!(s = (struct sector *) malloc(sizeof(struct sector))))
324 fatal("out of memory - giving up\n");
325
326 if (read(fd, s->data, sizeof(s->data)) != sizeof(s->data)) {
327 perror("read");
328 error("read error on %s - cannot read sector %lu\n", dev, sno);
329 free(s);
330 return 0;
331 }
332
333 s->next = sectorhead;
334 sectorhead = s;
335 s->sectornumber = sno;
336 s->to_be_written = 0;
337
338 return s;
339}
340
341static int
342msdos_signature (struct sector *s) {
343 if (*(unsigned short *) (s->data + 0x1fe) != 0xaa55) {
344 error("ERROR: sector %lu does not have an msdos signature\n",
345 s->sectornumber);
346 return 0;
347 }
348 return 1;
349}
350
351static int
352write_sectors(char *dev, int fd) {
353 struct sector *s;
354
355 for (s = sectorhead; s; s = s->next)
356 if (s->to_be_written) {
357 if (!sseek(dev, fd, s->sectornumber))
358 return 0;
359 if (write(fd, s->data, sizeof(s->data)) != sizeof(s->data)) {
360 perror("write");
361 error("write error on %s - cannot write sector %lu\n",
362 dev, s->sectornumber);
363 return 0;
364 }
365 s->to_be_written = 0;
366 }
367 return 1;
368}
369
370static void
371ulong_to_chars(unsigned long u, char *uu) {
372 int i;
373
374 for(i=0; i<4; i++) {
375 uu[i] = (u & 0xff);
376 u >>= 8;
377 }
378}
379
380static unsigned long
381chars_to_ulong(unsigned char *uu) {
382 int i;
383 unsigned long u = 0;
384
385 for(i=3; i>=0; i--)
386 u = (u << 8) | uu[i];
387 return u;
388}
389
390static int
391save_sectors(char *dev, int fdin) {
392 struct sector *s;
393 char ss[516];
394 int fdout;
395
396 fdout = open(save_sector_file, O_WRONLY | O_CREAT, 0444);
397 if (fdout < 0) {
398 perror(save_sector_file);
399 error("cannot open partition sector save file (%s)\n",
400 save_sector_file);
401 return 0;
402 }
403
404 for (s = sectorhead; s; s = s->next)
405 if (s->to_be_written) {
406 ulong_to_chars(s->sectornumber, ss);
407 if (!sseek(dev, fdin, s->sectornumber))
408 return 0;
409 if (read(fdin, ss+4, 512) != 512) {
410 perror("read");
411 error("read error on %s - cannot read sector %lu\n",
412 dev, s->sectornumber);
413 return 0;
414 }
415 if (write(fdout, ss, sizeof(ss)) != sizeof(ss)) {
416 perror("write");
417 error("write error on %s\n"), save_sector_file;
418 return 0;
419 }
420 }
421 return 1;
422}
423
424static void reread_disk_partition(char *dev, int fd);
425
426static int
427restore_sectors(char *dev) {
428 int fdin, fdout, ct;
429 struct stat statbuf;
430 char *ss0, *ss;
431 unsigned long sno;
432
433 if (stat(restore_sector_file, &statbuf) < 0) {
434 perror(restore_sector_file);
435 error("cannot stat partition restore file (%s)\n",
436 restore_sector_file);
437 return 0;
438 }
439 if (statbuf.st_size % 516) {
440 error("partition restore file has wrong size - not restoring\n");
441 return 0;
442 }
443 if (!(ss = (char *) malloc(statbuf.st_size))) {
444 error("out of memory?\n");
445 return 0;
446 }
447 fdin = open(restore_sector_file, O_RDONLY);
448 if (fdin < 0) {
449 perror(restore_sector_file);
450 error("cannot open partition restore file (%s)\n",
451 restore_sector_file);
452 return 0;
453 }
454 if (read(fdin, ss, statbuf.st_size) != statbuf.st_size) {
455 perror("read");
456 error("error reading %s\n"), restore_sector_file;
457 return 0;
458 }
459
460 fdout = open(dev, O_WRONLY);
461 if (fdout < 0) {
462 perror(dev);
463 error("cannot open device %s for writing\n"), dev;
464 return 0;
465 }
466
467 ss0 = ss;
468 ct = statbuf.st_size/516;
469 while(ct--) {
470 sno = chars_to_ulong(ss);
471 if (!sseek(dev, fdout, sno))
472 return 0;
473 if (write(fdout, ss+4, 512) != 512) {
474 perror(dev);
475 error("error writing sector %lu on %s\n", sno, dev);
476 return 0;
477 }
478 ss += 516;
479 }
480 free(ss0);
481
482 reread_disk_partition(dev, fdout);
483
484 return 1;
485}
486
487/*
488 * C. About heads, sectors and cylinders
489 */
490
491/*
492 * <linux/hdreg.h> defines HDIO_GETGEO and
493 * struct hd_geometry {
494 * unsigned char heads;
495 * unsigned char sectors;
496 * unsigned short cylinders;
497 * unsigned long start;
498 * };
499 */
500
501/*
502 * We consider several geometries for a disk:
503 * B - the BIOS geometry, gotten from the kernel via HDIO_GETGEO
504 * F - the fdisk geometry
505 * U - the user-specified geometry
506 *
507 * 0 means unspecified / unknown
508 */
509struct geometry {
510 unsigned long cylindersize;
511 unsigned long heads, sectors, cylinders;
512} B, F, U;
513
514static void
515get_cylindersize(char *dev, int fd, int silent) {
516 struct hd_geometry g;
517 int ioctl_ok = 0;
518
519 B.heads = B.sectors = B.cylinders = 0;
520
521 if (!ioctl(fd, HDIO_GETGEO, &g)) {
522 ioctl_ok = 1;
523
524 B.heads = g.heads;
525 B.sectors = g.sectors;
526 B.cylinders = g.cylinders;
527 }
528
529 if (U.heads)
530 B.heads = U.heads;
531 if (U.sectors)
532 B.sectors = U.sectors;
533 if (U.cylinders)
534 B.cylinders = U.cylinders;
535
536 B.cylindersize = B.heads * B.sectors;
537
538 if (ioctl_ok) {
539 if (g.start && !force) {
540 warn(
541 "Warning: start=%d - this looks like a partition rather than\n"
542 "the entire disk. Using fdisk on it is probably meaningless.\n"
543 "[Use the --force option if you really want this]\n", g.start);
544 exit(1);
545 }
546 if (B.heads != g.heads)
547 warn("Warning: HDIO_GETGEO says that there are %d heads\n",
548 g.heads);
549 if (B.sectors != g.sectors)
550 warn("Warning: HDIO_GETGEO says that there are %d sectors\n",
551 g.sectors);
552 if (B.cylinders != g.cylinders)
553 warn("Warning: HDIO_GETGEO says that there are %d cylinders\n",
554 g.cylinders);
555 } else if (!silent)
556 if (!B.heads || !B.sectors || !B.cylinders)
557 printf("Disk %s: cannot get geometry\n", dev);
558 if (B.sectors > 63)
559 warn("Warning: unlikely number of sectors (%d - usually at most 63\n"
560 "This will give problems with all software that uses C/H/S addressing.\n",
561 B.sectors);
562 if (!silent)
563 printf("\nDisk %s: %lu cylinders, %lu heads, %lu sectors/track\n",
564 dev, B.cylinders, B.heads, B.sectors);
565}
566
567typedef struct { unsigned char h,s,c; } chs; /* has some c bits in s */
568static chs zero_chs = { 0,0,0 };
569
570typedef struct { unsigned long h,s,c; } longchs;
571static longchs zero_longchs;
572
573static chs
574longchs_to_chs (longchs aa, struct geometry G) {
575 chs a;
576
577 if (aa.h < 256 && aa.s < 64 && aa.c < 1024) {
578 a.h = aa.h;
579 a.s = aa.s | ((aa.c >> 2) & 0xc0);
580 a.c = (aa.c & 0xff);
581 } else if (G.heads && G.sectors) {
582 a.h = G.heads - 1;
583 a.s = G.sectors | 0xc0;
584 a.c = 0xff;
585 } else
586 a = zero_chs;
587 return a;
588}
589
590static longchs
591chs_to_longchs (chs a) {
592 longchs aa;
593
594 aa.h = a.h;
595 aa.s = (a.s & 0x3f);
596 aa.c = (a.s & 0xc0);
597 aa.c = (aa.c << 2) + a.c;
598 return aa;
599}
600
601static longchs
602ulong_to_longchs (unsigned long sno, struct geometry G) {
603 longchs aa;
604
605 if (G.heads && G.sectors && G.cylindersize) {
606 aa.s = 1 + sno % G.sectors;
607 aa.h = (sno / G.sectors) % G.heads;
608 aa.c = sno / G.cylindersize;
609 return aa;
610 } else {
611 return zero_longchs;
612 }
613}
614
615//static unsigned long
616//longchs_to_ulong (longchs aa, struct geometry G) {
617// return (aa.c*G.cylindersize + aa.h*G.sectors + aa.s - 1);
618//}
619
620static chs
621ulong_to_chs (unsigned long sno, struct geometry G) {
622 return longchs_to_chs(ulong_to_longchs(sno, G), G);
623}
624
625//static unsigned long
626//chs_to_ulong (chs a, struct geometry G) {
627// return longchs_to_ulong(chs_to_longchs(a), G);
628//}
629
630static int
631is_equal_chs (chs a, chs b) {
632 return (a.h == b.h && a.s == b.s && a.c == b.c);
633}
634
635static int
636chs_ok (chs a, char *v, char *w) {
637 longchs aa = chs_to_longchs(a);
638 int ret = 1;
639
640 if (is_equal_chs(a, zero_chs))
641 return 1;
642 if (B.heads && aa.h >= B.heads) {
643 warn("%s of partition %s has impossible value for head: "
644 "%d (should be in 0-%d)\n", w, v, aa.h, B.heads-1);
645 ret = 0;
646 }
647 if (B.sectors && (aa.s == 0 || aa.s > B.sectors)) {
648 warn("%s of partition %s has impossible value for sector: "
649 "%d (should be in 1-%d)\n", w, v, aa.s, B.sectors);
650 ret = 0;
651 }
652 if (B.cylinders && aa.c >= B.cylinders) {
653 warn("%s of partition %s has impossible value for cylinders: "
654 "%d (should be in 0-%d)\n", w, v, aa.c, B.cylinders-1);
655 ret = 0;
656 }
657 return ret;
658}
659
660/*
661 * D. About system Ids
662 */
663
664#define EMPTY_PARTITION 0
665#define EXTENDED_PARTITION 5
666#define WIN98_EXTENDED 0x0f
667#define DM6_AUX1PARTITION 0x51
668#define DM6_AUX3PARTITION 0x53
669#define DM6_PARTITION 0x54
670#define EZD_PARTITION 0x55
671#define LINUX_SWAP 0x82
672#define LINUX_NATIVE 0x83
673#define LINUX_EXTENDED 0x85
674#define BSD_PARTITION 0xa5
675
676/* List of partition types now in i386_sys_types.c */
677
678static const char *
679sysname(unsigned char type) {
680 struct systypes *s;
681
682 for (s = i386_sys_types; s->name; s++)
683 if (s->type == type)
684 return s->name;
685 return "Unknown";
686}
687
688static void
689list_types(void) {
690 struct systypes *s;
691
692 printf("Id Name\n\n");
693 for (s = i386_sys_types; s->name; s++)
694 printf("%2x %s\n", s->type, s->name);
695}
696
697static int
698is_extended(unsigned char type) {
699 return (type == EXTENDED_PARTITION
700 || type == LINUX_EXTENDED
701 || type == WIN98_EXTENDED);
702}
703
704static int
705is_bsd(unsigned char type) {
706 return (type == BSD_PARTITION);
707}
708
709/*
710 * E. About partitions
711 */
712
713/* MS/DOS partition */
714
715struct partition {
716 unsigned char bootable; /* 0 or 0x80 */
717 chs begin_chs;
718 unsigned char sys_type;
719 chs end_chs;
720 unsigned int start_sect; /* starting sector counting from 0 */
721 unsigned int nr_sects; /* nr of sectors in partition */
722};
723
724/* Unfortunately, partitions are not aligned, and non-Intel machines
725 are unhappy with non-aligned integers. So, we need a copy by hand. */
726static int
727copy_to_int(unsigned char *cp) {
728 unsigned int m;
729
730 m = *cp++;
731 m += (*cp++ << 8);
732 m += (*cp++ << 16);
733 m += (*cp++ << 24);
734 return m;
735}
736
737static void
738copy_from_int(int m, char *cp) {
739 *cp++ = (m & 0xff); m >>= 8;
740 *cp++ = (m & 0xff); m >>= 8;
741 *cp++ = (m & 0xff); m >>= 8;
742 *cp++ = (m & 0xff);
743}
744
745static void
746copy_to_part(char *cp, struct partition *p) {
747 p->bootable = *cp++;
748 p->begin_chs.h = *cp++;
749 p->begin_chs.s = *cp++;
750 p->begin_chs.c = *cp++;
751 p->sys_type = *cp++;
752 p->end_chs.h = *cp++;
753 p->end_chs.s = *cp++;
754 p->end_chs.c = *cp++;
755 p->start_sect = copy_to_int(cp);
756 p->nr_sects = copy_to_int(cp+4);
757}
758
759static void
760copy_from_part(struct partition *p, char *cp) {
761 *cp++ = p->bootable;
762 *cp++ = p->begin_chs.h;
763 *cp++ = p->begin_chs.s;
764 *cp++ = p->begin_chs.c;
765 *cp++ = p->sys_type;
766 *cp++ = p->end_chs.h;
767 *cp++ = p->end_chs.s;
768 *cp++ = p->end_chs.c;
769 copy_from_int(p->start_sect, cp);
770 copy_from_int(p->nr_sects, cp+4);
771}
772
773/* Roughly speaking, Linux doesn't use any of the above fields except
774 for partition type, start sector and number of sectors. (However,
775 see also linux/drivers/scsi/fdomain.c.)
776 The only way partition type is used (in the kernel) is the comparison
777 for equality with EXTENDED_PARTITION (and these Disk Manager types). */
778
779struct part_desc {
780 unsigned long start;
781 unsigned long size;
782 unsigned long sector, offset; /* disk location of this info */
783 struct partition p;
784 struct part_desc *ep; /* extended partition containing this one */
785 int ptype;
786#define DOS_TYPE 0
787#define BSD_TYPE 1
788} zero_part_desc;
789
790struct part_desc *
791outer_extended_partition(struct part_desc *p) {
792 while (p->ep)
793 p = p->ep;
794 return p;
795}
796
797static int
798is_parent(struct part_desc *pp, struct part_desc *p) {
799 while (p) {
800 if (pp == p)
801 return 1;
802 p = p->ep;
803 }
804 return 0;
805}
806
807struct disk_desc {
808 struct part_desc partitions[128];
809 int partno;
810} oldp, newp;
811
812/* determine where on the disk this information goes */
813static void
814add_sector_and_offset(struct disk_desc *z) {
815 int pno;
816 struct part_desc *p;
817
818 for (pno = 0; pno < z->partno; pno++) {
819 p = &(z->partitions[pno]);
820 p->offset = 0x1be + (pno%4)*sizeof(struct partition);
821 p->sector = (p->ep ? p->ep->start : 0);
822 }
823}
824
825/* tell the kernel to reread the partition tables */
826static int
827reread_ioctl(int fd) {
828 if(ioctl(fd, BLKRRPART)) {
829 perror("BLKRRPART");
830 return -1;
831 }
832 return 0;
833}
834
835static int
836is_blockdev(int fd) {
837 struct stat statbuf;
838
839 return(fstat(fd, &statbuf) == 0 && S_ISBLK(statbuf.st_mode));
840}
841
842/* reread after writing */
843static void
844reread_disk_partition(char *dev, int fd) {
845 printf("Re-reading the partition table ...\n");
846 fflush(stdout);
847 sync();
848 sleep(3); /* superfluous since 1.3.20 */
849
850 if(reread_ioctl(fd) && is_blockdev(fd))
851 printf("The command to re-read the partition table failed\n"
852 "Reboot your system now, before using mkfs\n");
853
854 if (close(fd)) {
855 perror(dev);
856 printf("Error closing %s\n", dev);
857 }
858 printf("\n");
859}
860
861/* find Linux name of this partition, assuming that it will have a name */
862static int
863index_to_linux(int pno, struct disk_desc *z) {
864 int i, ct = 1;
865 struct part_desc *p = &(z->partitions[0]);
866 for (i=0; i<pno; i++,p++)
867 if(i < 4 || (p->size > 0 && !is_extended(p->p.sys_type)))
868 ct++;
869 return ct;
870}
871
872static int
873linux_to_index(int lpno, struct disk_desc *z) {
874 int i, ct = 0;
875 struct part_desc *p = &(z->partitions[0]);
876 for (i=0; i<z->partno && ct < lpno; i++,p++)
877 if((i < 4 || (p->size > 0 && !is_extended(p->p.sys_type)))
878 && ++ct == lpno)
879 return i;
880 return -1;
881}
882
883static int
884asc_to_index(char *pnam, struct disk_desc *z) {
885 int pnum, pno;
886
887 if (*pnam == '#') {
888 pno = atoi(pnam+1);
889 } else {
890 pnum = atoi(pnam);
891 pno = linux_to_index(pnum, z);
892 }
893 if (!(pno >= 0 && pno < z->partno))
894 fatal("%s: no such partition\n"), pnam;
895 return pno;
896}
897
898/*
899 * List partitions - in terms of sectors, blocks or cylinders
900 */
901#define F_SECTOR 1
902#define F_BLOCK 2
903#define F_CYLINDER 3
904#define F_MEGABYTE 4
905
906static int default_format = F_MEGABYTE;
907static int specified_format = 0;
908static int show_extended = 0;
909static int one_only = 0;
910static int one_only_pno;
911static int increment = 0;
912
913static void
914set_format(char c) {
915 switch(c) {
916 default:
917 printf("unrecognized format - using sectors\n");
918 case 'S': specified_format = F_SECTOR; break;
919 case 'B': specified_format = F_BLOCK; break;
920 case 'C': specified_format = F_CYLINDER; break;
921 case 'M': specified_format = F_MEGABYTE; break;
922 }
923}
924
925static unsigned long
926unitsize(int format) {
927 default_format = (B.cylindersize ? F_CYLINDER : F_MEGABYTE);
928 if (!format && !(format = specified_format))
929 format = default_format;
930
931 switch(format) {
932 default:
933 case F_CYLINDER:
934 if(B.cylindersize)
935 return B.cylindersize;
936 case F_SECTOR:
937 return 1;
938 case F_BLOCK:
939 return 2;
940 case F_MEGABYTE:
941 return 2048;
942 }
943}
944
945static unsigned long
946get_disksize(int format) {
947 unsigned long cs = B.cylinders;
948 if (cs && leave_last)
949 cs--;
950 return (cs * B.cylindersize) / unitsize(format);
951}
952
953static void
954out_partition_header(char *dev, int format, struct geometry G) {
955 if (dump) {
956 printf("# partition table of %s\n", dev);
957 printf("unit: sectors\n\n");
958 return;
959 }
960
961 default_format = (G.cylindersize ? F_CYLINDER : F_MEGABYTE);
962 if (!format && !(format = specified_format))
963 format = default_format;
964
965 switch(format) {
966 default:
967 printf("unimplemented format - using %s\n",
968 G.cylindersize ? "cylinders" : "sectors");
969 case F_CYLINDER:
970 if (G.cylindersize) {
971 printf("Units = cylinders of %lu bytes, blocks of 1024 bytes"
972 ", counting from %d\n\n",
973 G.cylindersize<<9, increment);
974 printf(" Device Boot Start End #cyls #blocks Id System\n");
975 break;
976 }
977 /* fall through */
978 case F_SECTOR:
979 printf("Units = sectors of 512 bytes, counting from %d\n\n",
980 increment);
981 printf(" Device Boot Start End #sectors Id System\n");
982 break;
983 case F_BLOCK:
984 printf("Units = blocks of 1024 bytes, counting from %d\n\n",
985 increment);
986 printf(" Device Boot Start End #blocks Id System\n");
987 break;
988 case F_MEGABYTE:
989 printf("Units = megabytes of 1048576 bytes, blocks of 1024 bytes"
990 ", counting from %d\n\n", increment);
991 printf(" Device Boot Start End MB #blocks Id System\n");
992 break;
993 }
994}
995
996static void
997out_rounddown(int width, unsigned long n, unsigned long unit, int inc) {
998 printf("%*lu", width, inc + n/unit);
999 if (unit != 1)
1000 putchar((n % unit) ? '+' : ' ');
1001 putchar(' ');
1002}
1003
1004static void
1005out_roundup(int width, unsigned long n, unsigned long unit, int inc) {
1006 if (n == (unsigned long)(-1))
1007 printf("%*s", width, "-");
1008 else
1009 printf("%*lu", width, inc + n/unit);
1010 if (unit != 1)
1011 putchar(((n+1) % unit) ? '-' : ' ');
1012 putchar(' ');
1013}
1014
1015static void
1016out_roundup_size(int width, unsigned long n, unsigned long unit) {
1017 printf("%*lu", width, (n+unit-1)/unit);
1018 if (unit != 1)
1019 putchar((n % unit) ? '-' : ' ');
1020 putchar(' ');
1021}
1022
1023static int
1024get_fdisk_geometry(struct part_desc *p) {
1025 chs b = p->p.end_chs;
1026 longchs bb = chs_to_longchs(b);
1027 F.heads = bb.h+1;
1028 F.sectors = bb.s;
1029 F.cylindersize = F.heads*F.sectors;
1030 return (F.sectors != B.sectors || F.heads != B.heads);
1031}
1032
1033static void
1034out_partition(char *dev, int format, struct part_desc *p,
1035 struct disk_desc *z, struct geometry G) {
1036 unsigned long start, end, size;
1037 int pno, lpno;
1038
1039 if (!format && !(format = specified_format))
1040 format = default_format;
1041
1042 pno = p - &(z->partitions[0]); /* our index */
1043 lpno = index_to_linux(pno, z); /* name of next one that has a name */
1044 if(pno == linux_to_index(lpno, z)) /* was that us? */
1045 printf("%8s%-2u", dev, lpno); /* yes */
1046 else if(show_extended)
1047 printf(" - ");
1048 else
1049 return;
1050 putchar(dump ? ':' : ' ');
1051
1052 start = p->start;
1053 end = p->start + p->size - 1;
1054 size = p->size;
1055
1056 if (dump) {
1057 printf(" start=%9lu", start);
1058 printf(", size=%8lu", size);
1059 if (p->ptype == DOS_TYPE) {
1060 printf(", Id=%2x", p->p.sys_type);
1061 if (p->p.bootable == 0x80)
1062 printf(", bootable");
1063 }
1064 printf("\n");
1065 return;
1066 }
1067
1068 if(p->ptype != DOS_TYPE || p->p.bootable == 0)
1069 printf(" ");
1070 else if(p->p.bootable == 0x80)
1071 printf(" * ");
1072 else
1073 printf(" ? "); /* garbage */
1074
1075 switch(format) {
1076 case F_CYLINDER:
1077 if (G.cylindersize) {
1078 out_rounddown(6, start, G.cylindersize, increment);
1079 out_roundup(6, end, G.cylindersize, increment);
1080 out_roundup_size(6, size, G.cylindersize);
1081 out_rounddown(8, size, 2, 0);
1082 break;
1083 }
1084 /* fall through */
1085 default:
1086 case F_SECTOR:
1087 out_rounddown(9, start, 1, increment);
1088 out_roundup(9, end, 1, increment);
1089 out_rounddown(9, size, 1, 0);
1090 break;
1091 case F_BLOCK:
1092#if 0
1093 printf("%8lu,%3lu ",
1094 p->sector/2, ((p->sector & 1) ? 512 : 0) + p->offset);
1095#endif
1096 out_rounddown(8, start, 2, increment);
1097 out_roundup(8, end, 2, increment);
1098 out_rounddown(8, size, 2, 0);
1099 break;
1100 case F_MEGABYTE:
1101 out_rounddown(5, start, 2048, increment);
1102 out_roundup(5, end, 2048, increment);
1103 out_roundup_size(5, size, 2048);
1104 out_rounddown(8, size, 2, 0);
1105 break;
1106 }
1107 if (p->ptype == DOS_TYPE) {
1108 printf(" %2x %s\n",
1109 p->p.sys_type, sysname(p->p.sys_type));
1110 } else {
1111 printf("\n");
1112 }
1113
1114 /* Is chs as we expect? */
1115 if (!quiet && p->ptype == DOS_TYPE) {
1116 chs a, b;
1117 longchs aa, bb;
1118 a = (size ? ulong_to_chs(start,G) : zero_chs);
1119 b = p->p.begin_chs;
1120 aa = chs_to_longchs(a);
1121 bb = chs_to_longchs(b);
1122 if(a.s && !is_equal_chs(a, b))
1123 printf("\t\tstart: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n",
1124 aa.c, aa.h, aa.s, bb.c, bb.h, bb.s);
1125 a = (size ? ulong_to_chs(end,G) : zero_chs);
1126 b = p->p.end_chs;
1127 aa = chs_to_longchs(a);
1128 bb = chs_to_longchs(b);
1129 if(a.s && !is_equal_chs(a, b))
1130 printf("\t\tend: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n",
1131 aa.c, aa.h, aa.s, bb.c, bb.h, bb.s);
1132 if(G.cylinders && G.cylinders < 1024 && bb.c > G.cylinders)
1133 printf("partition ends on cylinder %ld, beyond the end of the disk\n",
1134 bb.c);
1135 }
1136}
1137
1138static void
1139out_partitions(char *dev, struct disk_desc *z) {
1140 struct part_desc *p;
1141 int pno, format = 0;
1142
1143 if (z->partno == 0)
1144 printf("No partitions found\n");
1145 else {
1146 for (pno=0; pno < z->partno; pno++) {
1147 p = &(z->partitions[pno]);
1148 if (p->size != 0 && p->p.sys_type != 0) {
1149 if (get_fdisk_geometry(p))
1150 printf(
1151 "Warning: The first partition looks like it was made\n"
1152 " for C/H/S=*/%ld/%ld (instead of %ld/%ld/%ld).\n"
1153 "For this listing I'll assume that geometry.\n",
1154 F.heads, F.sectors, B.cylinders, B.heads, B.sectors);
1155 break;
1156 }
1157 }
1158 out_partition_header(dev, format, F);
1159 for(pno=0; pno < z->partno; pno++) {
1160 out_partition(dev, format, &(z->partitions[pno]), z, F);
1161 if(show_extended && pno%4==3)
1162 printf("\n");
1163 }
1164 }
1165}
1166
1167static int
1168disj(struct part_desc *p, struct part_desc *q) {
1169 return
1170 ((p->start + p->size <= q->start)
1171 || (is_extended(p->p.sys_type)
1172 && q->start + q->size <= p->start + p->size));
1173}
1174
1175static char *
1176pnumber(struct part_desc *p, struct disk_desc *z) {
1177 static char buf[20];
1178 int this, next;
1179 struct part_desc *p0 = &(z->partitions[0]);
1180
1181 this = index_to_linux(p-p0, z);
1182 next = index_to_linux(p-p0+1, z);
1183
1184 if (next > this)
1185 sprintf(buf, "%d", this);
1186 else
1187 sprintf(buf, "[%d]", this);
1188 return buf;
1189}
1190
1191static int
1192partitions_ok(struct disk_desc *z) {
1193 struct part_desc *partitions = &(z->partitions[0]), *p, *q;
1194 int partno = z->partno;
1195
1196#define PNO(p) pnumber(p, z)
1197
1198 /* Have at least 4 partitions been defined? */
1199 if (partno < 4) {
1200 if (!partno)
1201 fatal("no partition table present.\n");
1202 else
1203 fatal("strange, only %d partitions defined.\n"), partno;
1204 return 0;
1205 }
1206
1207 /* Are the partitions of size 0 marked empty?
1208 And do they have start = 0? And bootable = 0? */
1209 for (p = partitions; p - partitions < partno; p++)
1210 if (p->size == 0) {
1211 if(p->p.sys_type != EMPTY_PARTITION)
1212 warn("Warning: partition %s has size 0 but is not marked Empty\n",
1213 PNO(p));
1214 else if(p->p.bootable != 0)
1215 warn("Warning: partition %s has size 0 and is bootable\n",
1216 PNO(p));
1217 else if(p->p.start_sect != 0)
1218 warn("Warning: partition %s has size 0 and nonzero start\n",
1219 PNO(p));
1220 /* all this is probably harmless, no error return */
1221 }
1222
1223 /* Are the logical partitions contained in their extended partitions? */
1224 for (p = partitions+4; p < partitions+partno; p++)
1225 if (p->ptype == DOS_TYPE)
1226 if (p->size && !is_extended(p->p.sys_type)) {
1227 q = p->ep;
1228 if (p->start < q->start || p->start + p->size > q->start + q->size) {
1229 warn("Warning: partition %s "), PNO(p);
1230 warn("is not contained in partition %s\n"), PNO(q);
1231 return 0;
1232 }
1233 }
1234
1235 /* Are the data partitions mutually disjoint? */
1236 for (p = partitions; p < partitions+partno; p++)
1237 if (p->size && !is_extended(p->p.sys_type))
1238 for (q = p+1; q < partitions+partno; q++)
1239 if (q->size && !is_extended(q->p.sys_type))
1240 if(!((p->start > q-> start) ? disj(q,p) : disj(p,q))) {
1241 warn("Warning: partitions %s "), PNO(p);
1242 warn("and %s overlap\n"), PNO(q);
1243 return 0;
1244 }
1245
1246 /* Are the data partitions and the extended partition
1247 table sectors disjoint? */
1248 for (p = partitions; p < partitions+partno; p++)
1249 if (p->size && !is_extended(p->p.sys_type))
1250 for (q = partitions; q < partitions+partno; q++)
1251 if (is_extended(q->p.sys_type))
1252 if (p->start <= q->start && p->start + p->size > q->start) {
1253 warn("Warning: partition %s contains part of ", PNO(p));
1254 warn("the partition table (sector %lu),\n", q->start);
1255 warn("and will destroy it when filled\n");
1256 return 0;
1257 }
1258
1259 /* Do they start past zero and end before end-of-disk? */
1260 { unsigned long ds = get_disksize(F_SECTOR);
1261 for (p = partitions; p < partitions+partno; p++)
1262 if (p->size) {
1263 if(p->start == 0) {
1264 warn("Warning: partition %s starts at sector 0\n", PNO(p));
1265 return 0;
1266 }
1267 if (p->size && p->start + p->size > ds) {
1268 warn("Warning: partition %s extends past end of disk\n", PNO(p));
1269 return 0;
1270 }
1271 }
1272 }
1273
1274 /* At most one chain of DOS extended partitions ? */
1275 /* It seems that the OS/2 fdisk has the additional requirement
1276 that the extended partition must be the fourth one */
1277 { int ect = 0;
1278 for (p = partitions; p < partitions+4; p++)
1279 if (p->p.sys_type == EXTENDED_PARTITION)
1280 ect++;
1281 if (ect > 1 && !Linux) {
1282 warn("Among the primary partitions, at most one can be extended\n");
1283 warn(" (although this is not a problem under Linux)\n");
1284 return 0;
1285 }
1286 }
1287
1288 /*
1289 * Do all partitions start at a cylinder boundary ?
1290 * (this is not required for Linux)
1291 * The first partition starts after MBR.
1292 * Logical partitions start slightly after the containing extended partn.
1293 */
1294 if (B.cylindersize) {
1295 for(p = partitions; p < partitions+partno; p++)
1296 if (p->size) {
1297 if(p->start % B.cylindersize != 0
1298 && (!p->ep || p->start / B.cylindersize != p->ep->start / B.cylindersize)
1299 && (p->p.start_sect >= B.cylindersize)) {
1300 warn("Warning: partition %s does not start "
1301 "at a cylinder boundary\n", PNO(p));
1302 if (!Linux)
1303 return 0;
1304 }
1305 if((p->start + p->size) % B.cylindersize) {
1306 warn("Warning: partition %s does not end "
1307 "at a cylinder boundary\n", PNO(p));
1308 if (!Linux)
1309 return 0;
1310 }
1311 }
1312 }
1313
1314 /* Usually, one can boot only from primary partitions. */
1315 /* In fact, from a unique one only. */
1316 /* do not warn about bootable extended partitions -
1317 often LILO is there */
1318 { int pno = -1;
1319 for(p = partitions; p < partitions+partno; p++)
1320 if (p->p.bootable) {
1321 if (pno == -1)
1322 pno = p - partitions;
1323 else if (p - partitions < 4) {
1324 warn("Warning: more than one primary partition is marked "
1325 "bootable (active)\n"
1326 "This does not matter for LILO, but the DOS MBR will "
1327 "not boot this disk.\n");
1328 break;
1329 }
1330 if (p - partitions >= 4) {
1331 warn("Warning: usually one can boot from primary partitions "
1332 "only\nLILO disregards the `bootable' flag.\n");
1333 break;
1334 }
1335 }
1336 if (pno == -1 || pno >= 4)
1337 warn("Warning: no primary partition is marked bootable (active)\n"
1338 "This does not matter for LILO, but the DOS MBR will "
1339 "not boot this disk.\n");
1340 }
1341
1342 /* Is chs as we expect? */
1343 for(p = partitions; p < partitions+partno; p++)
1344 if(p->ptype == DOS_TYPE) {
1345 chs a, b;
1346 longchs aa, bb;
1347 a = p->size ? ulong_to_chs(p->start,B) : zero_chs;
1348 b = p->p.begin_chs;
1349 aa = chs_to_longchs(a);
1350 bb = chs_to_longchs(b);
1351 if (!chs_ok(b, PNO(p), "start"))
1352 return 0;
1353 if(a.s && !is_equal_chs(a, b))
1354 warn("partition %s: start: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n",
1355 PNO(p), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s);
1356 a = p->size ? ulong_to_chs(p->start + p->size - 1, B) : zero_chs;
1357 b = p->p.end_chs;
1358 aa = chs_to_longchs(a);
1359 bb = chs_to_longchs(b);
1360 if (!chs_ok(b, PNO(p), "end"))
1361 return 0;
1362 if(a.s && !is_equal_chs(a, b))
1363 warn("partition %s: end: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n",
1364 PNO(p), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s);
1365 if(B.cylinders && B.cylinders < 1024 && bb.c > B.cylinders)
1366 warn("partition %s ends on cylinder %ld, beyond the end of the disk\n",
1367 PNO(p), bb.c);
1368 }
1369
1370 return 1;
1371
1372#undef PNO
1373}
1374
1375static void
1376extended_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) {
1377 char *cp;
1378 struct sector *s;
1379 unsigned long start, here, next;
1380 int i, moretodo = 1;
1381 struct partition p;
1382 struct part_desc *partitions = &(z->partitions[0]);
1383 int pno = z->partno;
1384
1385 here = start = ep->start;
1386
1387 while (moretodo) {
1388 moretodo = 0;
1389
1390 if (!(s = get_sector(dev, fd, here)))
1391 break;
1392
1393 if (!msdos_signature(s))
1394 break;
1395
1396 cp = s->data + 0x1be;
1397
1398 if (pno+4 >= SIZE(z->partitions)) {
1399 printf("too many partitions - ignoring those past nr (%d)\n",
1400 pno-1);
1401 break;
1402 }
1403
1404 next = 0;
1405
1406 for (i=0; i<4; i++,cp += sizeof(struct partition)) {
1407 partitions[pno].sector = here;
1408 partitions[pno].offset = cp - s->data;
1409 partitions[pno].ep = ep;
1410 copy_to_part(cp,&p);
1411 if (is_extended(p.sys_type)) {
1412 partitions[pno].start = start + p.start_sect;
1413 if (next)
1414 printf("tree of partitions?\n");
1415 else
1416 next = partitions[pno].start; /* follow `upper' branch */
1417 moretodo = 1;
1418 } else {
1419 partitions[pno].start = here + p.start_sect;
1420 }
1421 partitions[pno].size = p.nr_sects;
1422 partitions[pno].ptype = DOS_TYPE;
1423 partitions[pno].p = p;
1424 pno++;
1425 }
1426 here = next;
1427 }
1428
1429 z->partno = pno;
1430}
1431
1432#define BSD_DISKMAGIC (0x82564557UL)
1433#define BSD_MAXPARTITIONS 8
1434#define BSD_FS_UNUSED 0
1435typedef unsigned char u8;
1436typedef unsigned short u16;
1437typedef unsigned int u32;
1438struct bsd_disklabel {
1439 u32 d_magic;
1440 char d_junk1[4];
1441 char d_typename[16];
1442 char d_packname[16];
1443 char d_junk2[92];
1444 u32 d_magic2;
1445 char d_junk3[2];
1446 u16 d_npartitions; /* number of partitions in following */
1447 char d_junk4[8];
1448 struct bsd_partition { /* the partition table */
1449 u32 p_size; /* number of sectors in partition */
1450 u32 p_offset; /* starting sector */
1451 u32 p_fsize; /* filesystem basic fragment size */
1452 u8 p_fstype; /* filesystem type, see below */
1453 u8 p_frag; /* filesystem fragments per block */
1454 u16 p_cpg; /* filesystem cylinders per group */
1455 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
1456};
1457
1458static void
1459bsd_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) {
1460 struct bsd_disklabel *l;
1461 struct bsd_partition *bp, *bp0;
1462 unsigned long start = ep->start;
1463 struct sector *s;
1464 struct part_desc *partitions = &(z->partitions[0]);
1465 int pno = z->partno;
1466
1467 if (!(s = get_sector(dev,fd,start+1)))
1468 return;
1469 l = (struct bsd_disklabel *) (s->data);
1470 if (l->d_magic != BSD_DISKMAGIC)
1471 return;
1472
1473 bp = bp0 = &l->d_partitions[0];
1474 while (bp - bp0 <= BSD_MAXPARTITIONS) {
1475 if (pno+1 >= SIZE(z->partitions)) {
1476 printf("too many partitions - ignoring those "
1477 "past nr (%d)\n", pno-1);
1478 break;
1479 }
1480 if (bp->p_fstype != BSD_FS_UNUSED) {
1481 partitions[pno].start = bp->p_offset;
1482 partitions[pno].size = bp->p_size;
1483 partitions[pno].sector = start+1;
1484 partitions[pno].offset = (char *)bp - (char *)bp0;
1485 partitions[pno].ep = 0;
1486 partitions[pno].ptype = BSD_TYPE;
1487 pno++;
1488 }
1489 bp++;
1490 }
1491 z->partno = pno;
1492}
1493
1494static int
1495msdos_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) {
1496 int i;
1497 char *cp;
1498 struct partition pt;
1499 struct sector *s;
1500 struct part_desc *partitions = &(z->partitions[0]);
1501 int pno = z->partno;
1502
1503 if (!(s = get_sector(dev, fd, start)))
1504 return 0;
1505
1506 if (!msdos_signature(s))
1507 return 0;
1508
1509 cp = s->data + 0x1be;
1510 copy_to_part(cp,&pt);
1511
1512 /* If I am not mistaken, recent kernels will hide this from us,
1513 so we will never actually see traces of a Disk Manager */
1514 if (pt.sys_type == DM6_PARTITION
1515 || pt.sys_type == EZD_PARTITION
1516 || pt.sys_type == DM6_AUX1PARTITION
1517 || pt.sys_type == DM6_AUX3PARTITION) {
1518 printf("detected Disk Manager - unable to handle that\n");
1519 return 0;
1520 }
1521 { unsigned int sig = *(unsigned short *)(s->data + 2);
1522 if (sig <= 0x1ae
1523 && *(unsigned short *)(s->data + sig) == 0x55aa
1524 && (1 & *(unsigned char *)(s->data + sig + 2))) {
1525 printf("DM6 signature found - giving up\n");
1526 return 0;
1527 }
1528 }
1529
1530 for (pno=0; pno<4; pno++,cp += sizeof(struct partition)) {
1531 partitions[pno].sector = start;
1532 partitions[pno].offset = cp - s->data;
1533 copy_to_part(cp,&pt);
1534 partitions[pno].start = start + pt.start_sect;
1535 partitions[pno].size = pt.nr_sects;
1536 partitions[pno].ep = 0;
1537 partitions[pno].p = pt;
1538 }
1539
1540 z->partno = pno;
1541
1542 for (i=0; i<4; i++) {
1543 if (is_extended(partitions[i].p.sys_type)) {
1544 if (!partitions[i].size) {
1545 printf("strange..., an extended partition of size 0?\n");
1546 continue;
1547 }
1548 extended_partition(dev, fd, &partitions[i], z);
1549 }
1550 if (is_bsd(partitions[i].p.sys_type)) {
1551 if (!partitions[i].size) {
1552 printf("strange..., a BSD partition of size 0?\n");
1553 continue;
1554 }
1555 bsd_partition(dev, fd, &partitions[i], z);
1556 }
1557 }
1558 return 1;
1559}
1560
1561static int
1562osf_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) {
1563 return 0;
1564}
1565
1566static int
1567sun_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) {
1568 return 0;
1569}
1570
1571static int
1572amiga_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) {
1573 return 0;
1574}
1575
1576static void
1577get_partitions(char *dev, int fd, struct disk_desc *z) {
1578 z->partno = 0;
1579
1580 if (!msdos_partition(dev, fd, 0, z)
1581 && !osf_partition(dev, fd, 0, z)
1582 && !sun_partition(dev, fd, 0, z)
1583 && !amiga_partition(dev, fd, 0, z)) {
1584 printf(" %s: unrecognized partition\n", dev);
1585 return;
1586 }
1587}
1588
1589static int
1590write_partitions(char *dev, int fd, struct disk_desc *z) {
1591 struct sector *s;
1592 struct part_desc *partitions = &(z->partitions[0]), *p;
1593 int pno = z->partno;
1594
1595 if (no_write) {
1596 printf("-n flag was given: Nothing changed\n");
1597 exit(0);
1598 }
1599
1600 for (p = partitions; p < partitions+pno; p++) {
1601 s = get_sector(dev, fd, p->sector);
1602 if (!s) return 0;
1603 s->to_be_written = 1;
1604 copy_from_part(&(p->p), s->data + p->offset);
1605 *(unsigned short *)(&(s->data[0x1fe])) = 0xaa55;
1606 }
1607 if (save_sector_file) {
1608 if (!save_sectors(dev, fd)) {
1609 fatal("Failed saving the old sectors - aborting\n");
1610 return 0;
1611 }
1612 }
1613 if (!write_sectors(dev, fd)) {
1614 error("Failed writing the partition on %s\n"), dev;
1615 return 0;
1616 }
1617 return 1;
1618}
1619
1620/*
1621 * F. The standard input
1622 */
1623
1624/*
1625 * Input format:
1626 * <start> <size> <type> <bootable> <c,h,s> <c,h,s>
1627 * Fields are separated by whitespace or comma or semicolon possibly
1628 * followed by whitespace; initial and trailing whitespace is ignored.
1629 * Numbers can be octal, decimal or hexadecimal, decimal is default
1630 * The <c,h,s> parts can (and probably should) be omitted.
1631 * Bootable is specified as [*|-], with as default not-bootable.
1632 * Type is given in hex, without the 0x prefix, or is [E|S|L|X], where
1633 * L (LINUX_NATIVE (83)) is the default, S is LINUX_SWAP (82), and E
1634 * is EXTENDED_PARTITION (5), X is LINUX_EXTENDED (85).
1635 * The default value of start is the first nonassigned sector/cylinder/...
1636 * The default value of size is as much as possible (until next
1637 * partition or end-of-disk).
1638 * .: end of chain of extended partitions.
1639 *
1640 * On interactive input an empty line means: all defaults.
1641 * Otherwise empty lines are ignored.
1642 */
1643
1644static int eof, eob;
1645
1646struct dumpfld {
1647 int fldno;
1648 char *fldname;
1649 int is_bool;
1650} dumpflds[] = {
1651 { 0, "start", 0 },
1652 { 1, "size", 0 },
1653 { 2, "Id", 0 },
1654 { 3, "bootable", 1 },
1655 { 4, "bh", 0 },
1656 { 5, "bs", 0 },
1657 { 6, "bc", 0 },
1658 { 7, "eh", 0 },
1659 { 8, "es", 0 },
1660 { 9, "ec", 0 }
1661};
1662
1663/*
1664 * Read a line, split it into fields
1665 *
1666 * (some primitive handwork, but a more elaborate parser seems
1667 * unnecessary)
1668 */
1669#define RD_EOF (-1)
1670#define RD_CMD (-2)
1671
1672static int
1673read_stdin(unsigned char **fields, unsigned char *line, int fieldssize, int linesize) {
1674 unsigned char *lp, *ip;
1675 int c, fno;
1676
1677 /* boolean true and empty string at start */
1678 line[0] = '*';
1679 line[1] = 0;
1680 for (fno=0; fno < fieldssize; fno++)
1681 fields[fno] = line + 1;
1682 fno = 0;
1683
1684 /* read a line from stdin */
1685 lp = fgets(line+2, linesize, stdin);
1686 if (lp == NULL) {
1687 eof = 1;
1688 return RD_EOF;
1689 }
1690 if (!(lp = index(lp, '\n')))
1691 fatal("long or incomplete input line - quitting\n");
1692 *lp = 0;
1693
1694 /* remove comments, if any */
1695 if ((lp = index(line+2, '#')) != 0)
1696 *lp = 0;
1697
1698 /* recognize a few commands - to be expanded */
1699 if (!strcmp(line+2, "unit: sectors")) {
1700 specified_format = F_SECTOR;
1701 return RD_CMD;
1702 }
1703
1704 /* dump style? - then bad input is fatal */
1705 if ((ip = index(line+2, ':')) != 0) {
1706 struct dumpfld *d;
1707
1708 nxtfld:
1709 ip++;
1710 while(isspace(*ip))
1711 ip++;
1712 if (*ip == 0)
1713 return fno;
1714 for(d = dumpflds; d-dumpflds < SIZE(dumpflds); d++) {
1715 if(!strncmp(ip, d->fldname, strlen(d->fldname))) {
1716 ip += strlen(d->fldname);
1717 while(isspace(*ip))
1718 ip++;
1719 if (d->is_bool)
1720 fields[d->fldno] = line;
1721 else if (*ip == '=') {
1722 while(isspace(*++ip)) ;
1723 fields[d->fldno] = ip;
1724 while(isalnum(*ip)) /* 0x07FF */
1725 ip++;
1726 } else
1727 fatal("input error: `=' expected after %s field\n",
1728 d->fldname);
1729 if (fno <= d->fldno)
1730 fno = d->fldno + 1;
1731 if(*ip == 0)
1732 return fno;
1733 if(*ip != ',' && *ip != ';')
1734 fatal("input error: unexpected character %c after %s field\n",
1735 *ip, d->fldname);
1736 *ip = 0;
1737 goto nxtfld;
1738 }
1739 }
1740 fatal("unrecognized input: %s\n"), ip;
1741 }
1742
1743 /* split line into fields */
1744 lp = ip = line+2;
1745 fields[fno++] = lp;
1746 while((c = *ip++) != 0) {
1747 if (!lp[-1] && (c == '\t' || c == ' '))
1748 ;
1749 else if (c == '\t' || c == ' ' || c == ',' || c == ';') {
1750 *lp++ = 0;
1751 if (fno < fieldssize)
1752 fields[fno++] = lp;
1753 continue;
1754 } else
1755 *lp++ = c;
1756 }
1757
1758 if (lp == fields[fno-1])
1759 fno--;
1760 return fno;
1761}
1762
1763/* read a number, use default if absent */
1764static int
1765get_ul(char *u, unsigned long *up, unsigned long def, int base) {
1766 char *nu;
1767
1768 if (*u) {
1769 errno = 0;
1770 *up = strtoul(u, &nu, base);
1771 if (errno == ERANGE) {
1772 printf("number too big\n");
1773 return -1;
1774 }
1775 if (*nu) {
1776 printf("trailing junk after number\n");
1777 return -1;
1778 }
1779 } else
1780 *up = def;
1781 return 0;
1782}
1783
1784/* There are two common ways to structure extended partitions:
1785 as nested boxes, and as a chain. Sometimes the partitions
1786 must be given in order. Sometimes all logical partitions
1787 must lie inside the outermost extended partition.
1788NESTED: every partition is contained in the surrounding partitions
1789 and is disjoint from all others.
1790CHAINED: every data partition is contained in the surrounding partitions
1791 and disjoint from all others, but extended partitions may lie outside
1792 (insofar as allowed by all_logicals_inside_outermost_extended).
1793ONESECTOR: all data partitions are mutually disjoint; extended partitions
1794 each use one sector only (except perhaps for the outermost one).
1795*/
1796static int partitions_in_order = 0;
1797static int all_logicals_inside_outermost_extended = 1;
1798static enum { NESTED, CHAINED, ONESECTOR } boxes = NESTED;
1799
1800/* find the default value for <start> - assuming entire units */
1801static unsigned long
1802first_free(int pno, int is_extended, struct part_desc *ep, int format,
1803 unsigned long mid, struct disk_desc *z) {
1804 unsigned long ff, fff;
1805 unsigned long unit = unitsize(format);
1806 struct part_desc *partitions = &(z->partitions[0]), *pp = 0;
1807
1808 /* if containing ep undefined, look at its container */
1809 if (ep && ep->p.sys_type == EMPTY_PARTITION)
1810 ep = ep->ep;
1811
1812 if (ep) {
1813 if (boxes == NESTED || (boxes == CHAINED && !is_extended))
1814 pp = ep;
1815 else if (all_logicals_inside_outermost_extended)
1816 pp = outer_extended_partition(ep);
1817 }
1818#if 0
1819 ff = pp ? (pp->start + unit - 1) / unit : 0;
1820#else
1821 /* rounding up wastes almost an entire cylinder - round down
1822 and leave it to compute_start_sect() to fix the difference */
1823 ff = pp ? pp->start / unit : 0;
1824#endif
1825 /* MBR and 1st sector of an extended partition are never free */
1826 if (unit == 1)
1827 ff++;
1828
1829 again:
1830 for(pp = partitions; pp < partitions+pno; pp++) {
1831 if (!is_parent(pp, ep) && pp->size > 0) {
1832 if ((partitions_in_order || pp->start / unit <= ff
1833 || (mid && pp->start / unit <= mid))
1834 && (fff = (pp->start + pp->size + unit - 1) / unit) > ff) {
1835 ff = fff;
1836 goto again;
1837 }
1838 }
1839 }
1840
1841 return ff;
1842}
1843
1844/* find the default value for <size> - assuming entire units */
1845static unsigned long
1846max_length(int pno, int is_extended, struct part_desc *ep, int format,
1847 unsigned long start, struct disk_desc *z) {
1848 unsigned long fu;
1849 unsigned long unit = unitsize(format);
1850 struct part_desc *partitions = &(z->partitions[0]), *pp = 0;
1851
1852 /* if containing ep undefined, look at its container */
1853 if (ep && ep->p.sys_type == EMPTY_PARTITION)
1854 ep = ep->ep;
1855
1856 if (ep) {
1857 if (boxes == NESTED || (boxes == CHAINED && !is_extended))
1858 pp = ep;
1859 else if (all_logicals_inside_outermost_extended)
1860 pp = outer_extended_partition(ep);
1861 }
1862 fu = pp ? (pp->start + pp->size) / unit : get_disksize(format);
1863
1864 for(pp = partitions; pp < partitions+pno; pp++)
1865 if (!is_parent(pp, ep) && pp->size > 0
1866 && pp->start / unit >= start && pp->start / unit < fu)
1867 fu = pp->start / unit;
1868
1869 return (fu > start) ? fu - start : 0;
1870}
1871
1872/* compute starting sector of a partition inside an extended one */
1873/* ep is 0 or points to surrounding extended partition */
1874static int
1875compute_start_sect(struct part_desc *p, struct part_desc *ep) {
1876 unsigned long base;
1877 int inc = (DOS && B.sectors) ? B.sectors : 1;
1878 int delta;
1879
1880 if (ep && p->start + p->size >= ep->start + 1)
1881 delta = p->start - ep->start - inc;
1882 else if (p->start == 0 && p->size > 0)
1883 delta = -inc;
1884 else
1885 delta = 0;
1886 if (delta < 0) {
1887 p->start -= delta;
1888 p->size += delta;
1889 if (is_extended(p->p.sys_type) && boxes == ONESECTOR)
1890 p->size = inc;
1891 else if ((int)(p->size) <= 0) {
1892 warn("no room for partition descriptor\n");
1893 return 0;
1894 }
1895 }
1896 base = (!ep ? 0
1897 : (is_extended(p->p.sys_type) ?
1898 outer_extended_partition(ep) : ep)->start);
1899 p->ep = ep;
1900 if (p->p.sys_type == EMPTY_PARTITION && p->size == 0) {
1901 p->p.start_sect = 0;
1902 p->p.begin_chs = zero_chs;
1903 p->p.end_chs = zero_chs;
1904 } else {
1905 p->p.start_sect = p->start - base;
1906 p->p.begin_chs = ulong_to_chs(p->start,B);
1907 p->p.end_chs = ulong_to_chs(p->start + p->size - 1,B);
1908 }
1909 p->p.nr_sects = p->size;
1910 return 1;
1911}
1912
1913/* build the extended partition surrounding a given logical partition */
1914static int
1915build_surrounding_extended(struct part_desc *p, struct part_desc *ep,
1916 struct disk_desc *z) {
1917 int inc = (DOS && B.sectors) ? B.sectors : 1;
1918 int format = F_SECTOR;
1919 struct part_desc *p0 = &(z->partitions[0]), *eep = ep->ep;
1920
1921 if (boxes == NESTED) {
1922 ep->start = first_free(ep-p0, 1, eep, format, p->start, z);
1923 ep->size = max_length(ep-p0, 1, eep, format, ep->start, z);
1924 if (ep->start > p->start || ep->start + ep->size < p->start + p->size) {
1925 warn("cannot build surrounding extended partition\n");
1926 return 0;
1927 }
1928 } else {
1929 ep->start = p->start;
1930 if(boxes == CHAINED)
1931 ep->size = p->size;
1932 else
1933 ep->size = inc;
1934 }
1935
1936 ep->p.nr_sects = ep->size;
1937 ep->p.bootable = 0;
1938 ep->p.sys_type = EXTENDED_PARTITION;
1939 if (!compute_start_sect(ep, eep) || !compute_start_sect(p, ep)) {
1940 ep->p.sys_type = EMPTY_PARTITION;
1941 ep->size = 0;
1942 return 0;
1943 }
1944
1945 return 1;
1946}
1947
1948static int
1949read_line(int pno, struct part_desc *ep, char *dev, int interactive,
1950 struct disk_desc *z) {
1951 unsigned char line[1000];
1952 unsigned char *fields[11];
1953 int fno, pct = pno%4;
1954 struct part_desc p, *orig;
1955 unsigned long ff, ff1, ul, ml, ml1, def;
1956 int format, lpno, is_extd;
1957
1958 if (eof || eob)
1959 return -1;
1960
1961 lpno = index_to_linux(pno, z);
1962
1963 if (interactive) {
1964 if (pct == 0 && (show_extended || pno == 0))
1965 warn("\n");
1966 warn("%8s%d: ", dev, lpno);
1967 }
1968
1969 /* read input line - skip blank lines when reading from a file */
1970 do {
1971 fno = read_stdin(fields, line, SIZE(fields), SIZE(line));
1972 } while(fno == RD_CMD || (fno == 0 && !interactive));
1973 if (fno == RD_EOF) {
1974 return -1;
1975 } else if (fno > 10 && *(fields[10]) != 0) {
1976 printf("too many input fields\n");
1977 return 0;
1978 }
1979
1980 if (fno == 1 && !strcmp(fields[0], ".")) {
1981 eob = 1;
1982 return -1;
1983 }
1984
1985 /* use specified format, but round to cylinders if F_MEGABYTE specified */
1986 format = 0;
1987 if (B.cylindersize && specified_format == F_MEGABYTE)
1988 format = F_CYLINDER;
1989
1990 orig = (one_only ? &(oldp.partitions[pno]) : 0);
1991
1992 p = zero_part_desc;
1993 p.ep = ep;
1994
1995 /* first read the type - we need to know whether it is extended */
1996 /* stop reading when input blank (defaults) and all is full */
1997 is_extd = 0;
1998 if (fno == 0) { /* empty line */
1999 if (orig && is_extended(orig->p.sys_type))
2000 is_extd = 1;
2001 ff = first_free(pno, is_extd, ep, format, 0, z);
2002 ml = max_length(pno, is_extd, ep, format, ff, z);
2003 if (ml == 0 && is_extd == 0) {
2004 is_extd = 1;
2005 ff = first_free(pno, is_extd, ep, format, 0, z);
2006 ml = max_length(pno, is_extd, ep, format, ff, z);
2007 }
2008 if (ml == 0 && pno >= 4) {
2009 /* no free blocks left - don't read any further */
2010 warn("No room for more\n");
2011 return -1;
2012 }
2013 }
2014 if (fno < 3 || !*(fields[2]))
2015 ul = orig ? orig->p.sys_type :
2016 (is_extd || (pno > 3 && pct == 1 && show_extended))
2017 ? EXTENDED_PARTITION : LINUX_NATIVE;
2018 else if(!strcmp(fields[2], "L"))
2019 ul = LINUX_NATIVE;
2020 else if(!strcmp(fields[2], "S"))
2021 ul = LINUX_SWAP;
2022 else if(!strcmp(fields[2], "E"))
2023 ul = EXTENDED_PARTITION;
2024 else if(!strcmp(fields[2], "X"))
2025 ul = LINUX_EXTENDED;
2026 else if (get_ul(fields[2], &ul, LINUX_NATIVE, 16))
2027 return 0;
2028 if (ul > 255) {
2029 warn("Illegal type\n");
2030 return 0;
2031 }
2032 p.p.sys_type = ul;
2033 is_extd = is_extended(ul);
2034
2035 /* find start */
2036 ff = first_free(pno, is_extd, ep, format, 0, z);
2037 ff1 = ff * unitsize(format);
2038 def = orig ? orig->start : (pno > 4 && pct > 1) ? 0 : ff1;
2039 if (fno < 1 || !*(fields[0]))
2040 p.start = def;
2041 else {
2042 if (get_ul(fields[0], &ul, def / unitsize(0), 0))
2043 return 0;
2044 p.start = ul * unitsize(0);
2045 p.start -= (p.start % unitsize(format));
2046 }
2047
2048 /* find length */
2049 ml = max_length(pno, is_extd, ep, format, p.start / unitsize(format), z);
2050 ml1 = ml * unitsize(format);
2051 def = orig ? orig->size : (pno > 4 && pct > 1) ? 0 : ml1;
2052 if (fno < 2 || !*(fields[1]))
2053 p.size = def;
2054 else {
2055 if (get_ul(fields[1], &ul, def / unitsize(0), 0))
2056 return 0;
2057 p.size = ul * unitsize(0) + unitsize(format) - 1;
2058 p.size -= (p.size % unitsize(format));
2059 }
2060 if (p.size > ml1) {
2061 warn("Warning: exceeds max allowable size (%lu)\n", ml1 / unitsize(0));
2062 if (!force)
2063 return 0;
2064 }
2065 if (p.size == 0 && pno >= 4 && (fno < 2 || !*(fields[1]))) {
2066 warn("Warning: empty partition\n");
2067 if (!force)
2068 return 0;
2069 }
2070 p.p.nr_sects = p.size;
2071
2072 if (p.size == 0 && !orig) {
2073 if(fno < 1 || !*(fields[0]))
2074 p.start = 0;
2075 if(fno < 3 || !*(fields[2]))
2076 p.p.sys_type = EMPTY_PARTITION;
2077 }
2078
2079 if (p.start < ff1 && p.size > 0) {
2080 warn("Warning: bad partition start (earliest %lu)\n",
2081 (ff1 + unitsize(0) - 1) / unitsize(0));
2082 if (!force)
2083 return 0;
2084 }
2085
2086 if (fno < 4 || !*(fields[3]))
2087 ul = (orig ? orig->p.bootable : 0);
2088 else if (!strcmp(fields[3], "-"))
2089 ul = 0;
2090 else if (!strcmp(fields[3], "*") || !strcmp(fields[3], "+"))
2091 ul = 0x80;
2092 else {
2093 warn("unrecognized bootable flag - choose - or *\n");
2094 return 0;
2095 }
2096 p.p.bootable = ul;
2097
2098 if (ep && ep->p.sys_type == EMPTY_PARTITION) {
2099 if(!build_surrounding_extended(&p, ep, z))
2100 return 0;
2101 } else
2102 if(!compute_start_sect(&p, ep))
2103 return 0;
2104
2105 { longchs aa = chs_to_longchs(p.p.begin_chs), bb;
2106
2107 if (fno < 5) {
2108 bb = aa;
2109 } else if (fno < 7) {
2110 warn("partial c,h,s specification?\n");
2111 return 0;
2112 } else if(get_ul(fields[4], &bb.c, aa.c, 0) ||
2113 get_ul(fields[5], &bb.h, aa.h, 0) ||
2114 get_ul(fields[6], &bb.s, aa.s, 0))
2115 return 0;
2116 p.p.begin_chs = longchs_to_chs(bb,B);
2117 }
2118 { longchs aa = chs_to_longchs(p.p.end_chs), bb;
2119
2120 if (fno < 8) {
2121 bb = aa;
2122 } else if (fno < 10) {
2123 warn("partial c,h,s specification?\n");
2124 return 0;
2125 } else if(get_ul(fields[7], &bb.c, aa.c, 0) ||
2126 get_ul(fields[8], &bb.h, aa.h, 0) ||
2127 get_ul(fields[9], &bb.s, aa.s, 0))
2128 return 0;
2129 p.p.end_chs = longchs_to_chs(bb, B);
2130 }
2131
2132 if (pno > 3 && p.size && show_extended && p.p.sys_type != EMPTY_PARTITION
2133 && (is_extended(p.p.sys_type) != (pct == 1))) {
2134 warn("Extended partition not where expected\n");
2135 if (!force)
2136 return 0;
2137 }
2138
2139 z->partitions[pno] = p;
2140 if (pno >= z->partno)
2141 z->partno += 4; /* reqd for out_partition() */
2142
2143 if (interactive)
2144 out_partition(dev, 0, &(z->partitions[pno]), z, B);
2145
2146 return 1;
2147}
2148
2149/* ep either points to the extended partition to contain this one,
2150 or to the empty partition that may become extended or is 0 */
2151static int
2152read_partition(char *dev, int interactive, int pno, struct part_desc *ep,
2153 struct disk_desc *z) {
2154 struct part_desc *p = &(z->partitions[pno]);
2155 int i;
2156
2157 if (one_only) {
2158 *p = oldp.partitions[pno];
2159 if (one_only_pno != pno)
2160 goto ret;
2161 } else if (!show_extended && pno > 4 && pno%4)
2162 goto ret;
2163
2164 while (!(i = read_line(pno, ep, dev, interactive, z)))
2165 if (!interactive)
2166 fatal("bad input\n");
2167 if (i < 0) {
2168 p->ep = ep;
2169 return 0;
2170 }
2171
2172 ret:
2173 p->ep = ep;
2174 if (pno >= z->partno)
2175 z->partno += 4;
2176 return 1;
2177}
2178
2179static void
2180read_partition_chain(char *dev, int interactive, struct part_desc *ep,
2181 struct disk_desc *z) {
2182 int i, base;
2183
2184 eob = 0;
2185 while (1) {
2186 base = z->partno;
2187 if (base+4 > SIZE(z->partitions)) {
2188 printf("too many partitions\n");
2189 break;
2190 }
2191 for (i=0; i<4; i++)
2192 if (!read_partition(dev, interactive, base+i, ep, z))
2193 return;
2194 for (i=0; i<4; i++) {
2195 ep = &(z->partitions[base+i]);
2196 if (is_extended(ep->p.sys_type) && ep->size)
2197 break;
2198 }
2199 if (i == 4) {
2200 /* nothing found - maybe an empty partition is going
2201 to be extended */
2202 if (one_only || show_extended)
2203 break;
2204 ep = &(z->partitions[base+1]);
2205 if (ep->size || ep->p.sys_type != EMPTY_PARTITION)
2206 break;
2207 }
2208 }
2209}
2210
2211static void
2212read_input(char *dev, int interactive, struct disk_desc *z) {
2213 int i;
2214 struct part_desc *partitions = &(z->partitions[0]), *ep;
2215
2216 for (i=0; i < SIZE(z->partitions); i++)
2217 partitions[i] = zero_part_desc;
2218 z->partno = 0;
2219
2220 if (interactive)
2221 warn("Input in the following format; absent fields get a default value.\n"
2222 "<start> <size> <type [E,S,L,X,hex]> <bootable [-,*]> <c,h,s> <c,h,s>\n"
2223 "Usually you only need to specify <start> and <size> (and perhaps <type>).\n");
2224 eof = 0;
2225
2226 for (i=0; i<4; i++)
2227 read_partition(dev, interactive, i, 0, z);
2228 for (i=0; i<4; i++) {
2229 ep = partitions+i;
2230 if (is_extended(ep->p.sys_type) && ep->size)
2231 read_partition_chain(dev, interactive, ep, z);
2232 }
2233 add_sector_and_offset(z);
2234}
2235
2236/*
2237 * G. The command line
2238 */
2239
2240static void version(void) {
2241 printf("%s %s %s (aeb@cwi.nl, %s)\n", PROGNAME, "version", VERSION, DATE);
2242}
2243
2244static char short_opts[] = "cdfgilnqsu:vx?1A::C:DH:I:LN:O:RS:TU::V";
2245
2246#define PRINT_ID 0400
2247#define CHANGE_ID 01000
2248
2249static const struct option long_opts[] = {
2250 { "change-id", no_argument, NULL, 'c' + CHANGE_ID },
2251 { "print-id", no_argument, NULL, 'c' + PRINT_ID },
2252 { "id", no_argument, NULL, 'c' },
2253 { "dump", no_argument, NULL, 'd' },
2254 { "force", no_argument, NULL, 'f' },
2255 { "show-geometry", no_argument, NULL, 'g' },
2256 { "increment", no_argument, NULL, 'i' },
2257 { "list", no_argument, NULL, 'l' },
2258 { "quiet", no_argument, NULL, 'q' },
2259 { "show-size", no_argument, NULL, 's' },
2260 { "unit", required_argument, NULL, 'u' },
2261 { "version", no_argument, NULL, 'v' },
2262 { "show-extended", no_argument, NULL, 'x' },
2263 { "help", no_argument, NULL, '?' },
2264 { "one-only", no_argument, NULL, '1' },
2265 { "cylinders", required_argument, NULL, 'C' },
2266 { "heads", required_argument, NULL, 'H' },
2267 { "sectors", required_argument, NULL, 'S' },
2268 { "activate", optional_argument, NULL, 'A' },
2269 { "DOS", no_argument, NULL, 'D' },
2270 { "Linux", no_argument, NULL, 'L' },
2271 { "re-read", no_argument, NULL, 'R' },
2272 { "list-types", no_argument, NULL, 'T' },
2273 { "unhide", optional_argument, NULL, 'U' },
2274 { "no-reread", no_argument, NULL, 160 },
2275 { "IBM", no_argument, NULL, 161 },
2276 { "leave-last", no_argument, NULL, 161 },
2277/* undocumented flags - not all completely implemented */
2278 { "in-order", no_argument, NULL, 128 },
2279 { "not-in-order", no_argument, NULL, 129 },
2280 { "inside-outer", no_argument, NULL, 130 },
2281 { "not-inside-outer", no_argument, NULL, 131 },
2282 { "nested", no_argument, NULL, 132 },
2283 { "chained", no_argument, NULL, 133 },
2284 { "onesector", no_argument, NULL, 134 },
2285 { NULL, 0, NULL, 0 }
2286};
2287
2288/* default devices to list */
2289static struct devd {
2290 char *pref, *letters;
2291} defdevs[] = {
2292 { "hd", "abcdefgh" },
2293 { "sd", "abcde" },
2294 { "xd", "ab" },
2295 { "ed", "abcd" }
2296};
2297
2298static int
2299is_ide_cdrom(char *device) {
2300 /* No device was given explicitly, and we are trying some
2301 likely things. But opening /dev/hdc may produce errors like
2302 "hdc: tray open or drive not ready"
2303 if it happens to be a CD-ROM drive. So try to be careful.
2304 This only works since 2.1.73. */
2305
2306 FILE *procf;
2307 char buf[100];
2308 struct stat statbuf;
2309
2310 sprintf(buf, "/proc/ide/%s/media", device+5);
2311 procf = fopen(buf, "r");
2312 if (procf != NULL && fgets(buf, sizeof(buf), procf))
2313 return !strncmp(buf, "cdrom", 5);
2314
2315 /* Now when this proc file does not exist, skip the
2316 device when it is read-only. */
2317 if (stat(device, &statbuf) == 0)
2318 return (statbuf.st_mode & 0222) == 0;
2319
2320 return 0;
2321}
2322
2323static void do_list(char *dev, int silent);
2324static void do_size(char *dev, int silent);
2325static void do_geom(char *dev, int silent);
2326static void do_fdisk(char *dev);
2327static void do_reread(char *dev);
2328static void do_change_id(char *dev, char *part, char *id);
2329static void do_unhide(char **av, int ac, char *arg);
2330static void do_activate(char **av, int ac, char *arg);
2331
2332static int total_size;
2333
2334extern int
2335sfdisk_main(int argc, char **argv) {
2336 int c;
2337 char *dev;
2338 int opt_size = 0;
2339 int opt_out_geom = 0;
2340 int opt_reread = 0;
2341 int activate = 0;
2342 int do_id = 0;
2343 int unhide = 0;
2344 char *activatearg = 0;
2345 char *unhidearg = 0;
2346
2347 if (argc < 1)
2348 usage( sfdisk_usage);
2349
2350 while ((c = getopt_long (argc, argv, short_opts, long_opts, NULL)) != -1) {
2351 switch (c) {
2352 case 'f':
2353 force = 1; break; /* does not imply quiet */
2354 case 'g':
2355 opt_out_geom = 1; break;
2356 case 'i':
2357 increment = 1; break;
2358 case 'c':
2359 case 'c' + PRINT_ID:
2360 case 'c' + CHANGE_ID:
2361 do_id = c; break;
2362 case 'd':
2363 dump = 1; /* fall through */
2364 case 'l':
2365 opt_list = 1; break;
2366 case 'n':
2367 no_write = 1; break;
2368 case 'q':
2369 quiet = 1; break;
2370 case 's':
2371 opt_size = 1; break;
2372 case 'u':
2373 set_format(*optarg); break;
2374 case 'v':
2375 version();
2376 exit(0);
2377 case 'x':
2378 show_extended = 1; break;
2379 case 'A':
2380 activatearg = optarg;
2381 activate = 1; break;
2382 case 'C':
2383 U.cylinders = atoi(optarg); break;
2384 case 'D':
2385 DOS = 1; break;
2386 case 'H':
2387 U.heads = atoi(optarg); break;
2388 case 'L':
2389 Linux = 1; break;
2390 case 'N':
2391 one_only = atoi(optarg); break;
2392 case 'I':
2393 restore_sector_file = optarg; break;
2394 case 'O':
2395 save_sector_file = optarg; break;
2396 case 'R':
2397 opt_reread = 1; break;
2398 case 'S':
2399 U.sectors = atoi(optarg); break;
2400 case 'T':
2401 list_types();
2402 exit(0);
2403 case 'U':
2404 unhidearg = optarg;
2405 unhide = 1; break;
2406 case 'V':
2407 verify = 1; break;
2408 case '?':
2409 default:
2410 usage( sfdisk_usage);
2411
2412 /* undocumented flags */
2413 case 128:
2414 partitions_in_order = 1; break;
2415 case 129:
2416 partitions_in_order = 0; break;
2417 case 130:
2418 all_logicals_inside_outermost_extended = 1; break;
2419 case 131:
2420 all_logicals_inside_outermost_extended = 0; break;
2421 case 132:
2422 boxes = NESTED; break;
2423 case 133:
2424 boxes = CHAINED; break;
2425 case 134:
2426 boxes = ONESECTOR; break;
2427
2428 /* more flags */
2429 case 160:
2430 no_reread = 1; break;
2431 case 161:
2432 leave_last = 1; break;
2433 }
2434 }
2435
2436 if (optind == argc && (opt_list || opt_out_geom || opt_size || verify)) {
2437 struct devd *dp;
2438 char *lp;
2439 char device[10];
2440
2441 total_size = 0;
2442
2443 for(dp = defdevs; dp-defdevs < SIZE(defdevs); dp++) {
2444 lp = dp->letters;
2445 while(*lp) {
2446 sprintf(device, "/dev/%s%c", dp->pref, *lp++);
2447 if (!strcmp(dp->pref, "hd") && is_ide_cdrom(device))
2448 continue;
2449 if (opt_out_geom)
2450 do_geom(device, 1);
2451 if (opt_size)
2452 do_size(device, 1);
2453 if (opt_list || verify)
2454 do_list(device, 1);
2455 }
2456 }
2457
2458 if (opt_size)
2459 printf("total: %d blocks\n", total_size);
2460
2461 exit(exit_status);
2462 }
2463
2464 if (optind == argc) usage( sfdisk_usage);
2465
2466 if (opt_list || opt_out_geom || opt_size || verify) {
2467 while (optind < argc) {
2468 if (opt_out_geom)
2469 do_geom(argv[optind], 0);
2470 if (opt_size)
2471 do_size(argv[optind], 0);
2472 if (opt_list || verify)
2473 do_list(argv[optind], 0);
2474 optind++;
2475 }
2476 exit(exit_status);
2477 }
2478
2479 if (activate) {
2480 do_activate(argv+optind, argc-optind, activatearg);
2481 exit(exit_status);
2482 }
2483 if (unhide) {
2484 do_unhide(argv+optind, argc-optind, unhidearg);
2485 exit(exit_status);
2486 }
2487 if (do_id) {
2488 if ((do_id & PRINT_ID) != 0 && optind != argc-2)
2489 fatal("usage: sfdisk --print-id device partition-number\n");
2490 else if ((do_id & CHANGE_ID) != 0 && optind != argc-3)
2491 fatal("usage: sfdisk --change-id device partition-number Id\n");
2492 else if (optind != argc-3 && optind != argc-2)
2493 fatal("usage: sfdisk --id device partition-number [Id]\n");
2494 do_change_id(argv[optind], argv[optind+1],
2495 (optind == argc-2) ? 0 : argv[optind+2]);
2496 exit(exit_status);
2497 }
2498
2499 if (optind != argc-1)
2500 fatal("can specify only one device (except with -l or -s)\n");
2501 dev = argv[optind];
2502
2503 if (opt_reread)
2504 do_reread(dev);
2505 else if (restore_sector_file)
2506 restore_sectors(dev);
2507 else
2508 do_fdisk(dev);
2509
2510 return ( TRUE);
2511}
2512
2513/*
2514 * H. Listing the current situation
2515 */
2516
2517static int
2518my_open (char *dev, int rw, int silent) {
2519 int fd, mode;
2520
2521 mode = (rw ? O_RDWR : O_RDONLY);
2522 fd = open(dev, mode);
2523 if (fd < 0 && !silent) {
2524 perror(dev);
2525 fatal("cannot open %s %s\n", dev, rw ? "read-write" : "for reading");
2526 }
2527 return fd;
2528}
2529
2530static void
2531do_list (char *dev, int silent) {
2532 int fd;
2533 struct disk_desc *z;
2534
2535 fd = my_open(dev, 0, silent);
2536 if (fd < 0)
2537 return;
2538
2539 z = &oldp;
2540
2541 free_sectors();
2542 get_cylindersize(dev, fd, dump ? 1 : opt_list ? 0 : 1);
2543 get_partitions(dev, fd, z);
2544
2545 if (opt_list)
2546 out_partitions(dev, z);
2547
2548 if (verify) {
2549 if (partitions_ok(z))
2550 warn("%s: OK\n"), dev;
2551 else
2552 exit_status = 1;
2553 }
2554}
2555
2556static void
2557do_geom (char *dev, int silent) {
2558 int fd;
2559 struct hd_geometry g;
2560
2561 fd = my_open(dev, 0, silent);
2562 if (fd < 0)
2563 return;
2564
2565 /* get_cylindersize(dev, fd, silent); */
2566 if (!ioctl(fd, HDIO_GETGEO, &g))
2567 printf("%s: %d cylinders, %d heads, %d sectors/track\n",
2568 dev, g.cylinders, g.heads, g.sectors);
2569 else
2570 printf("%s: unknown geometry\n", dev);
2571}
2572
2573/* for compatibility with earlier fdisk: provide option -s */
2574static void
2575do_size (char *dev, int silent) {
2576 int fd;
2577 long size;
2578
2579 fd = my_open(dev, 0, silent);
2580 if (fd < 0)
2581 return;
2582
2583 if(ioctl(fd, BLKGETSIZE, &size)) {
2584 if(!silent) {
2585 perror(dev);
2586 fatal("BLKGETSIZE ioctl failed for %s\n"), dev;
2587 }
2588 return;
2589 }
2590
2591 size /= 2; /* convert sectors to blocks */
2592
2593 /* a CDROM drive without mounted CD yields MAXINT */
2594 if (silent && size == ((1<<30)-1))
2595 return;
2596
2597 if (silent)
2598 printf("%s: %9ld\n", dev, size);
2599 else
2600 printf("%ld\n", size);
2601
2602 total_size += size;
2603}
2604
2605/*
2606 * Activate: usually one wants to have a single primary partition
2607 * to be active. OS/2 fdisk makes non-bootable logical partitions
2608 * active - I don't know what that means to OS/2 Boot Manager.
2609 *
2610 * Call: activate /dev/hda 2 5 7 make these partitions active
2611 * and the remaining ones inactive
2612 * Or: sfdisk -A /dev/hda 2 5 7
2613 *
2614 * If only a single partition must be active, one may also use the form
2615 * sfdisk -A2 /dev/hda
2616 *
2617 * With "activate /dev/hda" or "sfdisk -A /dev/hda" the active partitions
2618 * are listed but not changed. To get zero active partitions, use
2619 * "activate /dev/hda none" or "sfdisk -A /dev/hda none".
2620 * Use something like `echo ",,,*" | sfdisk -N2 /dev/hda' to only make
2621 * /dev/hda2 active, without changing other partitions.
2622 *
2623 * A warning will be given if after the change not precisely one primary
2624 * partition is active.
2625 *
2626 * The present syntax was chosen to be (somewhat) compatible with the
2627 * activate from the LILO package.
2628 */
2629static void
2630set_active (struct disk_desc *z, char *pnam) {
2631 int pno;
2632
2633 pno = asc_to_index(pnam, z);
2634 z->partitions[pno].p.bootable = 0x80;
2635}
2636
2637static void
2638do_activate (char **av, int ac, char *arg) {
2639 char *dev = av[0];
2640 int fd;
2641 int rw, i, pno, lpno;
2642 struct disk_desc *z;
2643
2644 z = &oldp;
2645
2646 rw = (!no_write && (arg || ac > 1));
2647 fd = my_open(dev, rw, 0);
2648
2649 free_sectors();
2650 get_cylindersize(dev, fd, 1);
2651 get_partitions(dev, fd, z);
2652
2653 if (!arg && ac == 1) {
2654 /* list active partitions */
2655 for (pno=0; pno < z->partno; pno++) {
2656 if (z->partitions[pno].p.bootable) {
2657 lpno = index_to_linux(pno, z);
2658 if (pno == linux_to_index(lpno, z))
2659 printf("%s%d\n", dev, lpno);
2660 else
2661 printf("%s#%d\n", dev, pno);
2662 if (z->partitions[pno].p.bootable != 0x80)
2663 warn("bad active byte: 0x%x instead of 0x80\n",
2664 z->partitions[pno].p.bootable);
2665 }
2666 }
2667 } else {
2668 /* clear `active byte' everywhere */
2669 for (pno=0; pno < z->partno; pno++)
2670 z->partitions[pno].p.bootable = 0;
2671
2672 /* then set where desired */
2673 if (ac == 1)
2674 set_active(z, arg);
2675 else for(i=1; i<ac; i++)
2676 set_active(z, av[i]);
2677
2678 /* then write to disk */
2679 if(write_partitions(dev, fd, z))
2680 warn("Done\n\n");
2681 else
2682 exit_status = 1;
2683 }
2684 i = 0;
2685 for (pno=0; pno < z->partno && pno < 4; pno++)
2686 if (z->partitions[pno].p.bootable)
2687 i++;
2688 if (i != 1)
2689 warn("You have %d active primary partitions. This does not matter for LILO,\n"
2690 "but the DOS MBR will only boot a disk with 1 active partition.\n", i);
2691}
2692
2693static void
2694set_unhidden (struct disk_desc *z, char *pnam) {
2695 int pno;
2696 unsigned char id;
2697
2698 pno = asc_to_index(pnam, z);
2699 id = z->partitions[pno].p.sys_type;
2700 if (id == 0x11 || id == 0x14 || id == 0x16 || id == 0x17)
2701 id -= 0x10;
2702 else
2703 fatal("partition %s has id %x and is not hidden\n", pnam, id);
2704 z->partitions[pno].p.sys_type = id;
2705}
2706
2707/*
2708 * maybe remove and make part of --change-id
2709 */
2710static void
2711do_unhide (char **av, int ac, char *arg) {
2712 char *dev = av[0];
2713 int fd, rw, i;
2714 struct disk_desc *z;
2715
2716 z = &oldp;
2717
2718 rw = !no_write;
2719 fd = my_open(dev, rw, 0);
2720
2721 free_sectors();
2722 get_cylindersize(dev, fd, 1);
2723 get_partitions(dev, fd, z);
2724
2725 /* unhide where desired */
2726 if (ac == 1)
2727 set_unhidden(z, arg);
2728 else for(i=1; i<ac; i++)
2729 set_unhidden(z, av[i]);
2730
2731 /* then write to disk */
2732 if(write_partitions(dev, fd, z))
2733 warn("Done\n\n");
2734 else
2735 exit_status = 1;
2736}
2737
2738static void do_change_id(char *dev, char *pnam, char *id) {
2739 int fd, rw, pno;
2740 struct disk_desc *z;
2741 unsigned long i;
2742
2743 z = &oldp;
2744
2745 rw = !no_write;
2746 fd = my_open(dev, rw, 0);
2747
2748 free_sectors();
2749 get_cylindersize(dev, fd, 1);
2750 get_partitions(dev, fd, z);
2751
2752 pno = asc_to_index(pnam, z);
2753 if (id == 0) {
2754 printf("%x\n", z->partitions[pno].p.sys_type);
2755 return;
2756 }
2757 i = strtoul(id, NULL, 16);
2758 if (i > 255)
2759 fatal("Bad Id %x\n"), i;
2760 z->partitions[pno].p.sys_type = i;
2761
2762 if(write_partitions(dev, fd, z))
2763 warn("Done\n\n");
2764 else
2765 exit_status = 1;
2766}
2767
2768static void
2769do_reread(char *dev) {
2770 int fd;
2771
2772 fd = my_open(dev, 0, 0);
2773 if(reread_ioctl(fd))
2774 printf("This disk is currently in use.\n");
2775}
2776
2777/*
2778 * I. Writing the new situation
2779 */
2780
2781static void
2782do_fdisk(char *dev){
2783 int fd;
2784 int c, answer;
2785 struct stat statbuf;
2786 int interactive = isatty(0);
2787 struct disk_desc *z;
2788
2789 if (stat(dev, &statbuf) < 0) {
2790 perror(dev);
2791 fatal("Fatal error: cannot find %s\n"), dev;
2792 }
2793 if (!S_ISBLK(statbuf.st_mode)) {
2794 warn("Warning: %s is not a block device\n"), dev;
2795 no_reread = 1;
2796 }
2797 fd = my_open(dev, !no_write, 0);
2798
2799 if(!no_write && !no_reread) {
2800 warn("Checking that no-one is using this disk right now ...\n");
2801 if(reread_ioctl(fd)) {
2802 printf("\nThis disk is currently in use - repartitioning is probably a bad idea."
2803 "Umount all file systems, and swapoff all swap partitions on this disk."
2804 "Use the --no-reread flag to suppress this check.\n");
2805 if (!force) {
2806 printf("Use the --force flag to overrule all checks.\n");
2807 exit(1);
2808 }
2809 } else
2810 warn("OK");
2811 }
2812
2813 z = &oldp;
2814
2815 free_sectors();
2816 get_cylindersize(dev, fd, 0);
2817 get_partitions(dev, fd, z);
2818
2819 printf("Old situation:\n");
2820 out_partitions(dev, z);
2821
2822 if (one_only && (one_only_pno = linux_to_index(one_only, z)) < 0)
2823 fatal("Partition %d does not exist, cannot change it\n"), one_only;
2824
2825 z = &newp;
2826
2827 while(1) {
2828
2829 read_input(dev, interactive, z);
2830
2831 printf("New situation:\n");
2832 out_partitions(dev, z);
2833
2834 if (!partitions_ok(z) && !force) {
2835 if(!interactive)
2836 fatal("I don't like these partitions - nothing changed.\n"
2837 "(If you really want this, use the --force option.)\n");
2838 else
2839 printf("I don't like this - probably you should answer No\n");
2840 }
2841 ask:
2842 if (interactive) {
2843 if (no_write)
2844 printf("Are you satisfied with this? [ynq] ");
2845 else
2846 printf("Do you want to write this to disk? [ynq] ");
2847 answer = c = getchar();
2848 while (c != '\n' && c != EOF)
2849 c = getchar();
2850 if (c == EOF)
2851 printf("\nsfdisk: premature end of input\n");
2852 if (c == EOF || answer == 'q' || answer == 'Q') {
2853 fatal("Quitting - nothing changed\n");
2854 } else if (answer == 'n' || answer == 'N') {
2855 continue;
2856 } else if (answer == 'y' || answer == 'Y') {
2857 break;
2858 } else {
2859 printf("Please answer one of y,n,q\n");
2860 goto ask;
2861 }
2862 } else
2863 break;
2864 }
2865
2866 if(write_partitions(dev, fd, z))
2867 printf("Successfully wrote the new partition table\n\n");
2868 else
2869 exit_status = 1;
2870
2871 reread_disk_partition(dev, fd);
2872
2873 warn("If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)\n"
2874 "to zero the first 512 bytes: dd if=/dev/zero of=/dev/foo7 bs=512 count=1\n"
2875 "(See fdisk(8).)\n");
2876
2877 sync(); /* superstition */
2878 sleep(3);
2879 exit(exit_status);
2880}
diff --git a/tar.c b/tar.c
index f222c3c9d..b404ab025 100644
--- a/tar.c
+++ b/tar.c
@@ -12,10 +12,15 @@
12 12
13 13
14#include "internal.h" 14#include "internal.h"
15#include <stdio.h>
16#include <dirent.h>
17#include <errno.h>
18#include <fcntl.h>
19#include <signal.h>
20#include <time.h>
15 21
16#ifdef BB_TAR
17 22
18const char tar_usage[] = 23static const char tar_usage[] =
19 "Create, extract, or list files from a TAR file\n\n" 24 "Create, extract, or list files from a TAR file\n\n"
20 "usage: tar -[cxtvOf] [tarFileName] [FILE] ...\n" 25 "usage: tar -[cxtvOf] [tarFileName] [FILE] ...\n"
21 "\tc=create, x=extract, t=list contents, v=verbose,\n" 26 "\tc=create, x=extract, t=list contents, v=verbose,\n"
@@ -23,13 +28,6 @@ const char tar_usage[] =
23 28
24 29
25 30
26#include <stdio.h>
27#include <dirent.h>
28#include <errno.h>
29#include <fcntl.h>
30#include <signal.h>
31#include <time.h>
32
33/* 31/*
34 * Tar file constants. 32 * Tar file constants.
35 */ 33 */
@@ -1151,5 +1149,4 @@ wantFileName (const char *fileName, int fileCount, char **fileTable)
1151 1149
1152 1150
1153 1151
1154#endif
1155/* END CODE */ 1152/* END CODE */
diff --git a/touch.c b/touch.c
index c36ffca90..d882a6319 100644
--- a/touch.c
+++ b/touch.c
@@ -28,7 +28,7 @@
28#include <errno.h> 28#include <errno.h>
29 29
30 30
31const char touch_usage[] = "touch [-c] file [file ...]\n\n" 31static const char touch_usage[] = "touch [-c] file [file ...]\n\n"
32"\tUpdate the last-modified date on the given file[s].\n"; 32"\tUpdate the last-modified date on the given file[s].\n";
33 33
34 34
diff --git a/umount.c b/umount.c
index 625fcfab9..48efbd349 100644
--- a/umount.c
+++ b/umount.c
@@ -26,7 +26,7 @@
26#include <fstab.h> 26#include <fstab.h>
27#include <errno.h> 27#include <errno.h>
28 28
29const char umount_usage[] = 29static const char umount_usage[] =
30"Usage: umount filesystem\n" 30"Usage: umount filesystem\n"
31" or: umount directory\n" 31" or: umount directory\n"
32" or: umount -a" 32" or: umount -a"
diff --git a/util-linux/dmesg.c b/util-linux/dmesg.c
index e5d403f7a..aa26f5836 100644
--- a/util-linux/dmesg.c
+++ b/util-linux/dmesg.c
@@ -1,45 +1,49 @@
1#include "internal.h"
2#include <stdlib.h>
3#include <unistd.h>
4#include <time.h>
5
6/* dmesg.c -- Print out the contents of the kernel ring buffer 1/* dmesg.c -- Print out the contents of the kernel ring buffer
7 * Created: Sat Oct 9 16:19:47 1993 2 * Created: Sat Oct 9 16:19:47 1993
8 * Revised: Thu Oct 28 21:52:17 1993 by faith@cs.unc.edu 3 * Revised: Thu Oct 28 21:52:17 1993 by faith@cs.unc.edu
9 * Copyright 1993 Theodore Ts'o (tytso@athena.mit.edu) 4 * Copyright 1993 Theodore Ts'o (tytso@athena.mit.edu)
10 * This program comes with ABSOLUTELY NO WARRANTY. 5 * This program comes with ABSOLUTELY NO WARRANTY.
11 * Modifications by Rick Sladkey (jrs@world.std.com) 6 * Modifications by Rick Sladkey (jrs@world.std.com)
12 * from util-linux; adapted for busybox 7 * Larger buffersize 3 June 1998 by Nicolai Langfeldt, based on a patch
8 * by Peeter Joot. This was also suggested by John Hudson.
9 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
10 * - added Native Language Support
11 *
12 * from util-linux -- adapted for busybox by
13 * Erik Andersen <andersee@debian.org>. I ripped out Native Language
14 * Support, replaced getopt, added some gotos for redundant stuff.
13 */ 15 */
14 16
17#include "internal.h"
15#include <linux/unistd.h> 18#include <linux/unistd.h>
16#include <stdio.h> 19#include <stdio.h>
20#include <getopt.h>
21#include <stdlib.h>
17 22
18#define __NR_klog __NR_syslog 23#if __GNU_LIBRARY__ < 5
19
20#if defined(__GLIBC__)
21#include <sys/klog.h>
22#define klog klogctl
23#else
24static inline _syscall3 (int, klog, int, type, char *, b, int, len)
25#endif /* __GLIBC__ */
26 24
25#ifndef __alpha__
26# define __NR_klogctl __NR_syslog
27 static inline _syscall3(int, klogctl, int, type, char *, b, int, len);
28#else /* __alpha__ */
29#define klogctl syslog
30#endif
27 31
32#else
33# include <sys/klog.h>
34#endif
28 35
29static const char dmesg_usage[] = "dmesg [-c] [-n level]\n"; 36static const char dmesg_usage[] = "dmesg [-c] [-n level] [-s bufsize]\n";
30 37
31int dmesg_main (int argc, char **argv) 38int dmesg_main( int argc, char** argv )
32{ 39{
33 40 char *buf;
34 char buf[4096]; 41 int bufsize=8196;
35 int i; 42 int i;
36 int n; 43 int n;
37 int level = 0; 44 int level = 0;
38 int lastc; 45 int lastc;
39 int cmd = 3; 46 int cmd = 3;
40
41 argc--;
42 argv++;
43 47
44 /* Parse any options */ 48 /* Parse any options */
45 while (argc && **argv == '-') { 49 while (argc && **argv == '-') {
@@ -56,43 +60,57 @@ int dmesg_main (int argc, char **argv)
56 --argc; 60 --argc;
57 ++argv; 61 ++argv;
58 break; 62 break;
63 case 's':
64 if (--argc == 0)
65 goto end;
66 bufsize = atoi (*(++argv));
67 --argc;
68 ++argv;
69 break;
59 default: 70 default:
60 goto end; 71 goto end;
61 } 72 }
62 } 73 }
74
75 if (argc > 1) {
76 goto end;
77 }
63 78
64 if (cmd == 8) { 79 if (cmd == 8) {
65 n = klog (cmd, NULL, level); 80 n = klogctl( cmd, NULL, level );
66 if (n < 0) { 81 if (n < 0) {
67 perror ("klog"); 82 goto klogctl_error;
68 exit (FALSE); 83 }
69 } 84 exit( TRUE );
70 exit (TRUE); 85 }
71 }
72 86
73 n = klog (cmd, buf, sizeof (buf)); 87 if (bufsize < 4096) bufsize = 4096;
74 if (n < 0) { 88 buf = (char*)malloc(bufsize);
75 perror ("klog"); 89 n = klogctl( cmd, buf, bufsize );
76 exit (FALSE); 90 if (n < 0) {
77 } 91 goto klogctl_error;
92 }
78 93
79 lastc = '\n'; 94 lastc = '\n';
80 for (i = 0; i < n; i++) { 95 for (i = 0; i < n; i++) {
81 if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') { 96 if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') {
97 i++;
98 while (buf[i] >= '0' && buf[i] <= '9')
82 i++; 99 i++;
83 while (buf[i] >= '0' && buf[i] <= '9') 100 if (buf[i] == '>')
84 i++; 101 i++;
85 if (buf[i] == '>') 102 }
86 i++; 103 lastc = buf[i];
87 } 104 putchar( lastc );
88 lastc = buf[i]; 105 }
89 putchar (lastc); 106 if (lastc != '\n')
90 } 107 putchar( '\n' );
91 if (lastc != '\n') 108 exit( TRUE);
92 putchar ('\n'); 109end:
93 exit (TRUE);
94
95 end:
96 usage( dmesg_usage); 110 usage( dmesg_usage);
97 exit (FALSE); 111 exit (FALSE);
112klogctl_error:
113 perror( "klogctl" );
114 exit( FALSE );
115
98} 116}
diff --git a/util-linux/mkswap.c b/util-linux/mkswap.c
index 8c0c4dec7..fceeb28dd 100644
--- a/util-linux/mkswap.c
+++ b/util-linux/mkswap.c
@@ -1,4 +1,3 @@
1#include "internal.h"
2/* 1/*
3 * mkswap.c - set up a linux swap device 2 * mkswap.c - set up a linux swap device
4 * 3 *
@@ -9,51 +8,170 @@
9/* 8/*
10 * 20.12.91 - time began. Got VM working yesterday by doing this by hand. 9 * 20.12.91 - time began. Got VM working yesterday by doing this by hand.
11 * 10 *
12 * Usage: mkswap [-c] device [size-in-blocks] 11 * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks]
13 * 12 *
14 * -c for readablility checking (use it unless you are SURE!) 13 * -c for readability checking. (Use it unless you are SURE!)
14 * -vN for swap areas version N. (Only N=0,1 known today.)
15 * -f for forcing swap creation even if it would smash partition table.
15 * 16 *
16 * The device may be a block device or a image of one, but this isn't 17 * The device may be a block device or an image of one, but this isn't
17 * enforced (but it's not much fun on a character device :-). 18 * enforced (but it's not much fun on a character device :-).
18 * 19 *
19 * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the 20 * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the
20 * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995. 21 * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995.
22 *
23 * Version 1 swap area code (for kernel 2.1.117), aeb, 981010.
24 *
25 * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb.
26 * V1_MAX_PAGES fixes, jj, 990325.
27 *
28 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
29 * - added Native Language Support
30 *
31 * from util-linux -- adapted for busybox by
32 * Erik Andersen <andersee@debian.org>. I ripped out Native Language
33 * Support, made some stuff smaller, and fitted for life in busybox.
34 *
21 */ 35 */
22 36
37#include "internal.h"
23#include <stdio.h> 38#include <stdio.h>
24#include <unistd.h> 39#include <unistd.h>
25#include <string.h> 40#include <string.h>
26#include <fcntl.h> 41#include <fcntl.h>
27#include <stdlib.h> 42#include <stdlib.h>
43#include <sys/ioctl.h> /* for _IO */
44#include <sys/utsname.h>
28#include <sys/stat.h> 45#include <sys/stat.h>
29#include <sys/ioctl.h> 46#include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
47 /* we also get PAGE_SIZE via getpagesize() */
30 48
31#include <asm/page.h>
32#include <linux/fs.h>
33 49
34#ifndef __linux__ 50static const char mkswap_usage[] = "mkswap [-c] [-v0|-v1] device [block-count]\n"
35# define volatile 51"Prepare a disk partition to be used as a swap partition.\n\n"
36#endif 52"\t-c\tCheck for read-ability.\n"
53"\t-v0\tMake version 0 swap [max 128 Megs].\n"
54"\t-v1\tMake version 1 swap [big!] (default for kernels > 2.1.117).\n"
55"\tblock-count\tNumber of block to use (default is entire partition).\n";
37 56
38#define TEST_BUFFER_PAGES 8
39 57
40const char mkswap_usage[] = "mkswap [-c] partition [block-count]\n" 58#ifndef _IO
41"\n" 59/* pre-1.3.45 */
42"\tPrepare a disk partition to be used as a swap partition.\n" 60#define BLKGETSIZE 0x1260
43"\tThe default block count is the size of the entire partition.\n" 61#else
44"\n" 62/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
45"\t-c:\tCheck for read-ability.\n" 63#define BLKGETSIZE _IO(0x12,96)
46"\tblock-count\tUse only this many blocks.\n"; 64#endif
47 65
48static const char * program_name = "mkswap"; 66static char * program_name = "mkswap";
49static const char * device_name = NULL; 67static char * device_name = NULL;
50static int DEV = -1; 68static int DEV = -1;
51static long PAGES = 0; 69static long PAGES = 0;
52static int do_check = 0; 70static int check = 0;
53static int badpages = 0; 71static int badpages = 0;
72static int version = -1;
73
74#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
75
76static int
77linux_version_code(void) {
78 struct utsname my_utsname;
79 int p, q, r;
80
81 if (uname(&my_utsname) == 0) {
82 p = atoi(strtok(my_utsname.release, "."));
83 q = atoi(strtok(NULL, "."));
84 r = atoi(strtok(NULL, "."));
85 return MAKE_VERSION(p,q,r);
86 }
87 return 0;
88}
89
90/*
91 * The definition of the union swap_header uses the constant PAGE_SIZE.
92 * Unfortunately, on some architectures this depends on the hardware model,
93 * and can only be found at run time -- we use getpagesize().
94 */
95
96static int pagesize;
97static int *signature_page;
98
99struct swap_header_v1 {
100 char bootbits[1024]; /* Space for disklabel etc. */
101 unsigned int version;
102 unsigned int last_page;
103 unsigned int nr_badpages;
104 unsigned int padding[125];
105 unsigned int badpages[1];
106} *p;
107
108static void
109init_signature_page() {
110 pagesize = getpagesize();
111
112#ifdef PAGE_SIZE
113 if (pagesize != PAGE_SIZE)
114 fprintf(stderr, "Assuming pages of size %d\n", pagesize);
115#endif
116 signature_page = (int *) malloc(pagesize);
117 memset(signature_page,0,pagesize);
118 p = (struct swap_header_v1 *) signature_page;
119}
54 120
121static void
122write_signature(char *sig) {
123 char *sp = (char *) signature_page;
55 124
56static long bit_test_and_set (unsigned int *addr, unsigned int nr) 125 strncpy(sp+pagesize-10, sig, 10);
126}
127
128#define V0_MAX_PAGES (8 * (pagesize - 10))
129/* Before 2.2.0pre9 */
130#define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
131/* Since 2.2.0pre9:
132 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
133 with variations on
134 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
135 #define SWP_OFFSET(entry) ((entry) >> 8)
136 on the various architectures. Below the result - yuk.
137
138 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
139 i386 2^12 o<<8 e>>8 1<<24 1<<19
140 mips 2^12 o<<15 e>>15 1<<17 1<<19
141 alpha 2^13 o<<40 e>>40 1<<24 1<<18
142 m68k 2^12 o<<12 e>>12 1<<20 1<<19
143 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
144 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
145 ppc 2^12 o<<8 e>>8 1<<24 1<<19
146 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
147 armv 2^12 o<<9 e>>9 1<<23 1<<19
148
149 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
150
151 The bad part is that we need to know this since the kernel will
152 refuse a swap space if it is too large.
153*/
154/* patch from jj - why does this differ from the above? */
155#if defined(__alpha__)
156#define V1_MAX_PAGES ((1 << 24) - 1)
157#elif defined(__mips__)
158#define V1_MAX_PAGES ((1 << 17) - 1)
159#elif defined(__sparc_v9__)
160#define V1_MAX_PAGES ((3 << 29) - 1)
161#elif defined(__sparc__)
162#define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
163#else
164#define V1_MAX_PAGES V1_OLD_MAX_PAGES
165#endif
166/* man page now says:
167The maximum useful size of a swap area now depends on the architecture.
168It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
169128GB on alpha and 3TB on sparc64.
170*/
171
172#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
173
174static void bit_set (unsigned int *addr, unsigned int nr)
57{ 175{
58 unsigned int r, m; 176 unsigned int r, m;
59 177
@@ -61,7 +179,6 @@ static long bit_test_and_set (unsigned int *addr, unsigned int nr)
61 r = *addr; 179 r = *addr;
62 m = 1 << (nr & (8 * sizeof(int) - 1)); 180 m = 1 << (nr & (8 * sizeof(int) - 1));
63 *addr = r | m; 181 *addr = r | m;
64 return (r & m) != 0;
65} 182}
66 183
67static int bit_test_and_clear (unsigned int *addr, unsigned int nr) 184static int bit_test_and_clear (unsigned int *addr, unsigned int nr)
@@ -75,47 +192,59 @@ static int bit_test_and_clear (unsigned int *addr, unsigned int nr)
75 return (r & m) != 0; 192 return (r & m) != 0;
76} 193}
77 194
78/* 195
79 * Volatile to let gcc know that this doesn't return. When trying 196void
80 * to compile this under minix, volatile gives a warning, as 197die(const char *str) {
81 * exit() isn't defined as volatile under minix. 198 fprintf(stderr, "%s: %s\n", program_name, str);
82 */ 199 exit( FALSE);
83volatile void fatal_error(const char * fmt_string)
84{
85 fprintf(stderr,fmt_string,program_name,device_name);
86 exit(FALSE);
87} 200}
88 201
89#define die(str) fatal_error("%s: " str "\n") 202void
203page_ok(int page) {
204 if (version==0)
205 bit_set(signature_page, page);
206}
90 207
91static void check_blocks(int * signature_page) 208void
92{ 209page_bad(int page) {
210 if (version == 0)
211 bit_test_and_clear(signature_page, page);
212 else {
213 if (badpages == MAX_BADPAGES)
214 die("too many bad pages");
215 p->badpages[badpages] = page;
216 }
217 badpages++;
218}
219
220void
221check_blocks(void) {
93 unsigned int current_page; 222 unsigned int current_page;
94 int do_seek = 1; 223 int do_seek = 1;
95 char buffer[PAGE_SIZE]; 224 char *buffer;
96 225
226 buffer = malloc(pagesize);
227 if (!buffer)
228 die("Out of memory");
97 current_page = 0; 229 current_page = 0;
98 while (current_page < PAGES) { 230 while (current_page < PAGES) {
99 if (!do_check) { 231 if (!check) {
100 bit_test_and_set(signature_page,current_page++); 232 page_ok(current_page++);
101 continue; 233 continue;
102 } else {
103 printf("\r%d", current_page);
104 } 234 }
105 if (do_seek && lseek(DEV,current_page*PAGE_SIZE,SEEK_SET) != 235 if (do_seek && lseek(DEV,current_page*pagesize,SEEK_SET) !=
106 current_page*PAGE_SIZE) 236 current_page*pagesize)
107 die("seek failed in check_blocks"); 237 die("seek failed in check_blocks");
108 if ( (do_seek = (PAGE_SIZE != read(DEV, buffer, PAGE_SIZE))) ) { 238 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
109 bit_test_and_clear(signature_page,current_page++); 239 page_bad(current_page++);
110 badpages++;
111 continue; 240 continue;
112 } 241 }
113 bit_test_and_set(signature_page,current_page++); 242 page_ok(current_page++);
114 } 243 }
115 if (do_check) 244 if (badpages == 1)
116 printf("\n"); 245 printf("one bad page\n");
117 if (badpages) 246 else if (badpages > 1)
118 printf("%d bad page%s\n",badpages,(badpages>1)?"s":""); 247 printf("%d bad pages\n", badpages);
119} 248}
120 249
121static long valid_offset (int fd, int offset) 250static long valid_offset (int fd, int offset)
@@ -129,12 +258,13 @@ static long valid_offset (int fd, int offset)
129 return 1; 258 return 1;
130} 259}
131 260
132static int count_blocks (int fd) 261static int
262find_size (int fd)
133{ 263{
134 int high, low; 264 unsigned int high, low;
135 265
136 low = 0; 266 low = 0;
137 for (high = 1; valid_offset (fd, high); high *= 2) 267 for (high = 1; high > 0 && valid_offset (fd, high); high *= 2)
138 low = high; 268 low = high;
139 while (low < high - 1) 269 while (low < high - 1)
140 { 270 {
@@ -145,108 +275,194 @@ static int count_blocks (int fd)
145 else 275 else
146 high = mid; 276 high = mid;
147 } 277 }
148 valid_offset (fd, 0);
149 return (low + 1); 278 return (low + 1);
150} 279}
151 280
152static int get_size(const char *file) 281/* return size in pages, to avoid integer overflow */
282static long
283get_size(const char *file)
153{ 284{
154 int fd; 285 int fd;
155 int size; 286 long size;
156 287
157 fd = open(file, O_RDWR); 288 fd = open(file, O_RDONLY);
158 if (fd < 0) { 289 if (fd < 0) {
159 perror(file); 290 perror(file);
160 exit(1); 291 exit(1);
161 } 292 }
162 if (ioctl(fd, BLKGETSIZE, &size) >= 0) { 293 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
163 close(fd); 294 int sectors_per_page = pagesize/512;
164 return (size * 512); 295 size /= sectors_per_page;
296 } else {
297 size = find_size(fd) / pagesize;
165 } 298 }
166
167 size = count_blocks(fd);
168 close(fd); 299 close(fd);
169 return size; 300 return size;
170} 301}
171 302
172int 303int mkswap_main(int argc, char ** argv)
173mkswap(const char *device_name, int pages, int check) 304{
174 { 305 char * tmp;
175 struct stat statbuf; 306 struct stat statbuf;
307 int sz;
308 int maxpages;
176 int goodpages; 309 int goodpages;
177 int signature_page[PAGE_SIZE/sizeof(int)]; 310 int offset;
311 int force = 0;
178 312
179 PAGES = pages; 313 if (argc && *argv)
180 do_check = check; 314 program_name = *argv;
181 315
182 memset(signature_page,0,PAGE_SIZE); 316 init_signature_page(); /* get pagesize */
183 317
184 if (device_name && !PAGES) { 318 while (argc-- > 1) {
185 PAGES = get_size(device_name) / PAGE_SIZE; 319 argv++;
320 if (argv[0][0] != '-') {
321 if (device_name) {
322 int blocks_per_page = pagesize/1024;
323 PAGES = strtol(argv[0],&tmp,0)/blocks_per_page;
324 if (*tmp)
325 usage( mkswap_usage);
326 } else
327 device_name = argv[0];
328 } else {
329 switch (argv[0][1]) {
330 case 'c':
331 check=1;
332 break;
333 case 'f':
334 force=1;
335 break;
336 case 'v':
337 version=atoi(argv[0]+2);
338 break;
339 default:
340 usage( mkswap_usage);
341 }
342 }
343 }
344 if (!device_name) {
345 fprintf(stderr,
346 "%s: error: Nowhere to set up swap on?\n",
347 program_name);
348 usage( mkswap_usage);
186 } 349 }
187 if (!device_name || PAGES<10) { 350 sz = get_size(device_name);
351 if (!PAGES) {
352 PAGES = sz;
353 } else if (PAGES > sz && !force) {
354 fprintf(stderr,
355 "%s: error: "
356 "size %ld is larger than device size %d\n",
357 program_name,
358 PAGES*(pagesize/1024), sz*(pagesize/1024));
359 exit( FALSE);
360 }
361
362 if (version == -1) {
363 if (PAGES <= V0_MAX_PAGES)
364 version = 0;
365 else if (linux_version_code() < MAKE_VERSION(2,1,117))
366 version = 0;
367 else if (pagesize < 2048)
368 version = 0;
369 else
370 version = 1;
371 }
372 if (version != 0 && version != 1) {
373 fprintf(stderr, "%s: error: unknown version %d\n",
374 program_name, version);
375 usage( mkswap_usage);
376 }
377 if (PAGES < 10) {
188 fprintf(stderr, 378 fprintf(stderr,
189 "%s: error: swap area needs to be at least %ldkB\n", 379 "%s: error: swap area needs to be at least %ldkB\n",
190 program_name, 10 * PAGE_SIZE / 1024); 380 program_name, (long)(10 * pagesize / 1024));
191 /* usage(mkswap_usage); */ 381 usage( mkswap_usage);
192 exit(1); 382 }
383#if 0
384 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
385#else
386 if (!version)
387 maxpages = V0_MAX_PAGES;
388 else if (linux_version_code() >= MAKE_VERSION(2,2,1))
389 maxpages = V1_MAX_PAGES;
390 else {
391 maxpages = V1_OLD_MAX_PAGES;
392 if (maxpages > V1_MAX_PAGES)
393 maxpages = V1_MAX_PAGES;
193 } 394 }
194 if (PAGES > 8 * (PAGE_SIZE - 10)) { 395#endif
195 PAGES = 8 * (PAGE_SIZE - 10); 396 if (PAGES > maxpages) {
397 PAGES = maxpages;
196 fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n", 398 fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n",
197 program_name, PAGES * PAGE_SIZE / 1024); 399 program_name, PAGES * pagesize / 1024);
198 } 400 }
401
199 DEV = open(device_name,O_RDWR); 402 DEV = open(device_name,O_RDWR);
200 if (DEV < 0 || fstat(DEV, &statbuf) < 0) { 403 if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
201 perror(device_name); 404 perror(device_name);
202 exit(1); 405 exit( FALSE);
203 } 406 }
204 if (!S_ISBLK(statbuf.st_mode)) 407 if (!S_ISBLK(statbuf.st_mode))
205 do_check=0; 408 check=0;
206 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) 409 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
207 die("Will not try to make swapdevice on '%s'"); 410 die("Will not try to make swapdevice on '%s'");
208 check_blocks(signature_page); 411
209 if (!bit_test_and_clear(signature_page,0)) 412#ifdef __sparc__
413 if (!force && version == 0) {
414 /* Don't overwrite partition table unless forced */
415 unsigned char *buffer = (unsigned char *)signature_page;
416 unsigned short *q, sum;
417
418 if (read(DEV, buffer, 512) != 512)
419 die("fatal: first page unreadable");
420 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
421 q = (unsigned short *)(buffer + 510);
422 for (sum = 0; q >= (unsigned short *) buffer;)
423 sum ^= *q--;
424 if (!sum) {
425 fprintf(stderr, "\
426%s: Device '%s' contains a valid Sun disklabel.\n\
427This probably means creating v0 swap would destroy your partition table\n\
428No swap created. If you really want to create swap v0 on that device, use\n\
429the -f option to force it.\n",
430 program_name, device_name);
431 exit( FALSE);
432 }
433 }
434 }
435#endif
436
437 if (version == 0 || check)
438 check_blocks();
439 if (version == 0 && !bit_test_and_clear(signature_page,0))
210 die("fatal: first page unreadable"); 440 die("fatal: first page unreadable");
441 if (version == 1) {
442 p->version = version;
443 p->last_page = PAGES-1;
444 p->nr_badpages = badpages;
445 }
446
211 goodpages = PAGES - badpages - 1; 447 goodpages = PAGES - badpages - 1;
212 if (goodpages <= 0) 448 if (goodpages <= 0)
213 die("Unable to set up swap-space: unreadable"); 449 die("Unable to set up swap-space: unreadable");
214 printf("Setting up swapspace, size = %ld bytes\n",goodpages*PAGE_SIZE); 450 printf("Setting up swapspace version %d, size = %ld bytes\n",
215 strncpy((char*)signature_page+PAGE_SIZE-10,"SWAP-SPACE",10); 451 version, (long)(goodpages*pagesize));
216 if (lseek(DEV, 0, SEEK_SET)) 452 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
453
454 offset = ((version == 0) ? 0 : 1024);
455 if (lseek(DEV, offset, SEEK_SET) != offset)
217 die("unable to rewind swap-device"); 456 die("unable to rewind swap-device");
218 if (PAGE_SIZE != write(DEV, signature_page, PAGE_SIZE)) 457 if (write(DEV,(char*)signature_page+offset, pagesize-offset)
458 != pagesize-offset)
219 die("unable to write signature page"); 459 die("unable to write signature page");
220 460
221 close(DEV); 461 /*
222 return (TRUE); 462 * A subsequent swapon() will fail if the signature
223} 463 * is not actually on disk. (This is a kernel bug.)
224 464 */
225int mkswap_main(int argc, char ** argv) 465 if (fsync(DEV))
226{ 466 die("fsync failed");
227 char * tmp; 467 exit ( TRUE);
228 long int pages=0;
229 int check=0;
230
231 if (argc && *argv)
232 program_name = *argv;
233 while (argc > 1) {
234 argv++;
235 argc--;
236 if (argv[0][0] != '-')
237 if (device_name) {
238 pages = strtol(argv[0],&tmp,0)>>(PAGE_SHIFT-10);
239 if (*tmp) {
240 usage (mkswap_usage);
241 }
242 } else
243 device_name = argv[0];
244 else while (*++argv[0])
245 switch (argv[0][0]) {
246 case 'c': check=1; break;
247 default: usage (mkswap_usage);
248 exit( TRUE);
249 }
250 }
251 exit( mkswap(device_name, pages, check));
252} 468}
diff --git a/util-linux/more.c b/util-linux/more.c
index 53437ed58..772d51b18 100644
--- a/util-linux/more.c
+++ b/util-linux/more.c
@@ -30,7 +30,7 @@
30#include <signal.h> 30#include <signal.h>
31 31
32 32
33const char more_usage[] = "[file ...]"; 33static const char more_usage[] = "[file ...]";
34 34
35 35
36#ifdef BB_MORE_TERM 36#ifdef BB_MORE_TERM
diff --git a/util-linux/mount.c b/util-linux/mount.c
index 26d4693d0..a7d5aed2d 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -37,7 +37,7 @@
37#include <ctype.h> 37#include <ctype.h>
38#include <fstab.h> 38#include <fstab.h>
39 39
40const char mount_usage[] = "Usage:\tmount [flags]\n" 40static const char mount_usage[] = "Usage:\tmount [flags]\n"
41 "\tmount [flags] device directory [-o options,more-options]\n" 41 "\tmount [flags] device directory [-o options,more-options]\n"
42 "\n" 42 "\n"
43 "Flags:\n" 43 "Flags:\n"
diff --git a/util-linux/umount.c b/util-linux/umount.c
index 625fcfab9..48efbd349 100644
--- a/util-linux/umount.c
+++ b/util-linux/umount.c
@@ -26,7 +26,7 @@
26#include <fstab.h> 26#include <fstab.h>
27#include <errno.h> 27#include <errno.h>
28 28
29const char umount_usage[] = 29static const char umount_usage[] =
30"Usage: umount filesystem\n" 30"Usage: umount filesystem\n"
31" or: umount directory\n" 31" or: umount directory\n"
32" or: umount -a" 32" or: umount -a"
diff --git a/zcat.c b/zcat.c
index dfc4d21da..d5ea40c5d 100644
--- a/zcat.c
+++ b/zcat.c
@@ -4,7 +4,7 @@
4 4
5#include "internal.h" 5#include "internal.h"
6 6
7const char zcat_usage[] = "zcat\n" 7static const char zcat_usage[] = "zcat\n"
8"\n" 8"\n"
9"\tuncompress gzipped data from stdin to stdout\n"; 9"\tuncompress gzipped data from stdin to stdout\n";
10 10
@@ -59,7 +59,7 @@ static char *license_msg[] = {
59 */ 59 */
60 60
61#ifdef RCSID 61#ifdef RCSID
62static char rcsid[] = "$Id: zcat.c,v 1.2 1999/10/06 20:25:32 andersen Exp $"; 62static char rcsid[] = "$Id: zcat.c,v 1.3 1999/10/19 20:03:34 andersen Exp $";
63#endif 63#endif
64 64
65#include <ctype.h> 65#include <ctype.h>
@@ -80,7 +80,7 @@ static char rcsid[] = "$Id: zcat.c,v 1.2 1999/10/06 20:25:32 andersen Exp $";
80 * The target dependent functions should be defined in tailor.c. 80 * The target dependent functions should be defined in tailor.c.
81 */ 81 */
82 82
83/* $Id: zcat.c,v 1.2 1999/10/06 20:25:32 andersen Exp $ */ 83/* $Id: zcat.c,v 1.3 1999/10/19 20:03:34 andersen Exp $ */
84 84
85#define RECORD_IO 0 85#define RECORD_IO 0
86 86
@@ -436,7 +436,7 @@ extern int unlzw OF((int in, int out));
436# undef LZW 436# undef LZW
437#endif 437#endif
438 438
439/* $Id: zcat.c,v 1.2 1999/10/06 20:25:32 andersen Exp $ */ 439/* $Id: zcat.c,v 1.3 1999/10/19 20:03:34 andersen Exp $ */
440 440
441/* #include "getopt.h" */ 441/* #include "getopt.h" */
442 442
@@ -895,7 +895,7 @@ RETSIGTYPE abort_gzip()
895 */ 895 */
896 896
897#ifdef RCSID 897#ifdef RCSID
898static char rcsid[] = "$Id: zcat.c,v 1.2 1999/10/06 20:25:32 andersen Exp $"; 898static char rcsid[] = "$Id: zcat.c,v 1.3 1999/10/19 20:03:34 andersen Exp $";
899#endif 899#endif
900 900
901/* #include "crypt.h" */ 901/* #include "crypt.h" */
@@ -1021,7 +1021,7 @@ int unzip(in, out)
1021 */ 1021 */
1022 1022
1023#ifdef RCSID 1023#ifdef RCSID
1024static char rcsid[] = "$Id: zcat.c,v 1.2 1999/10/06 20:25:32 andersen Exp $"; 1024static char rcsid[] = "$Id: zcat.c,v 1.3 1999/10/19 20:03:34 andersen Exp $";
1025#endif 1025#endif
1026 1026
1027#include <ctype.h> 1027#include <ctype.h>
@@ -1408,7 +1408,7 @@ ulg crc_32_tab[] = {
1408 */ 1408 */
1409 1409
1410#ifdef RCSID 1410#ifdef RCSID
1411static char rcsid[] = "$Id: zcat.c,v 1.2 1999/10/06 20:25:32 andersen Exp $"; 1411static char rcsid[] = "$Id: zcat.c,v 1.3 1999/10/19 20:03:34 andersen Exp $";
1412#endif 1412#endif
1413 1413
1414#include <sys/types.h> 1414#include <sys/types.h>