Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/util-linux
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- Location:
- branches/stable/mindi-busybox/util-linux
- Files:
-
- 4 deleted
- 25 edited
- 6 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/util-linux/Config.in
r821 r1770 6 6 menu "Linux System Utilities" 7 7 8 config CONFIG_DMESG8 config DMESG 9 9 bool "dmesg" 10 10 default n … … 18 18 wish to enable the 'dmesg' utility. 19 19 20 config CONFIG_FBSET 20 config FEATURE_DMESG_PRETTY 21 bool "pretty dmesg output" 22 default y 23 depends on DMESG 24 help 25 If you wish to scrub the syslog level from the output, say 'Y' here. 26 The syslog level is a string prefixed to every line with the form "<#>". 27 28 With this option you will see: 29 # dmesg 30 Linux version 2.6.17.4 ..... 31 BIOS-provided physical RAM map: 32 BIOS-e820: 0000000000000000 - 000000000009f000 (usable) 33 34 Without this option you will see: 35 # dmesg 36 <5>Linux version 2.6.17.4 ..... 37 <6>BIOS-provided physical RAM map: 38 <6> BIOS-e820: 0000000000000000 - 000000000009f000 (usable) 39 40 config FBSET 21 41 bool "fbset" 22 42 default n … … 27 47 if you wish to enable the 'fbset' utility. 28 48 29 config CONFIG_FEATURE_FBSET_FANCY49 config FEATURE_FBSET_FANCY 30 50 bool "Turn on extra fbset options" 31 51 default n 32 depends on CONFIG_FBSET52 depends on FBSET 33 53 help 34 54 This option enables extended fbset options, allowing one to set the … … 37 57 options. 38 58 39 config CONFIG_FEATURE_FBSET_READMODE59 config FEATURE_FBSET_READMODE 40 60 bool "Turn on fbset readmode support" 41 61 default n 42 depends on CONFIG_FBSET62 depends on FBSET 43 63 help 44 64 This option allows fbset to read the video mode database stored by … … 46 66 device to pre-defined video modes. 47 67 48 config CONFIG_FDFLUSH68 config FDFLUSH 49 69 bool "fdflush" 50 70 default n … … 58 78 leave this disabled. 59 79 60 config CONFIG_FDFORMAT80 config FDFORMAT 61 81 bool "fdformat" 62 82 default n … … 64 84 fdformat is used to low-level format a floppy disk. 65 85 66 config CONFIG_FDISK86 config FDISK 67 87 bool "fdisk" 68 88 default n … … 76 96 bool "support over 4GB disks" 77 97 default y 78 depends on CONFIG_FDISK98 depends on FDISK 79 99 help 80 100 Enable this option to support large disks > 4GB. 81 101 82 config CONFIG_FEATURE_FDISK_WRITABLE102 config FEATURE_FDISK_WRITABLE 83 103 bool "Write support" 84 104 default y 85 depends on CONFIG_FDISK105 depends on FDISK 86 106 help 87 107 Enabling this option allows you to create or change a partition table … … 89 109 disabled, you will only be able to view the partition table. 90 110 91 config CONFIG_FEATURE_AIX_LABEL111 config FEATURE_AIX_LABEL 92 112 bool "Support AIX disklabels" 93 113 default n 94 depends on CONFIG_FDISK && CONFIG_FEATURE_FDISK_WRITABLE114 depends on FDISK && FEATURE_FDISK_WRITABLE 95 115 help 96 116 Enabling this option allows you to create or change AIX disklabels. 97 117 Most people can safely leave this option disabled. 98 118 99 config CONFIG_FEATURE_SGI_LABEL119 config FEATURE_SGI_LABEL 100 120 bool "Support SGI disklabels" 101 121 default n 102 depends on CONFIG_FDISK && CONFIG_FEATURE_FDISK_WRITABLE122 depends on FDISK && FEATURE_FDISK_WRITABLE 103 123 help 104 124 Enabling this option allows you to create or change SGI disklabels. 105 125 Most people can safely leave this option disabled. 106 126 107 config CONFIG_FEATURE_SUN_LABEL127 config FEATURE_SUN_LABEL 108 128 bool "Support SUN disklabels" 109 129 default n 110 depends on CONFIG_FDISK && CONFIG_FEATURE_FDISK_WRITABLE130 depends on FDISK && FEATURE_FDISK_WRITABLE 111 131 help 112 132 Enabling this option allows you to create or change SUN disklabels. 113 133 Most people can safely leave this option disabled. 114 134 115 config CONFIG_FEATURE_OSF_LABEL135 config FEATURE_OSF_LABEL 116 136 bool "Support BSD disklabels" 117 137 default n 118 depends on CONFIG_FDISK && CONFIG_FEATURE_FDISK_WRITABLE138 depends on FDISK && FEATURE_FDISK_WRITABLE 119 139 help 120 140 Enabling this option allows you to create or change BSD disklabels 121 141 and define and edit BSD disk slices. 122 142 123 config CONFIG_FEATURE_FDISK_ADVANCED143 config FEATURE_FDISK_ADVANCED 124 144 bool "Support expert mode" 125 145 default n 126 depends on CONFIG_FDISK && CONFIG_FEATURE_FDISK_WRITABLE146 depends on FDISK && FEATURE_FDISK_WRITABLE 127 147 help 128 148 Enabling this option allows you to do terribly unsafe things like … … 131 151 reason you would be wise to leave this disabled. 132 152 133 config CONFIG_FREERAMDISK153 config FREERAMDISK 134 154 bool "freeramdisk" 135 155 default n … … 142 162 this disabled. 143 163 144 config CONFIG_FSCK_MINIX164 config FSCK_MINIX 145 165 bool "fsck_minix" 146 166 default n … … 153 173 filesystem. 154 174 155 config CONFIG_MKFS_MINIX175 config MKFS_MINIX 156 176 bool "mkfs_minix" 157 177 default n … … 162 182 163 183 comment "Minix filesystem support" 164 depends on CONFIG_FSCK_MINIX || CONFIG_MKFS_MINIX165 166 config CONFIG_FEATURE_MINIX2184 depends on FSCK_MINIX || MKFS_MINIX 185 186 config FEATURE_MINIX2 167 187 bool "Support Minix fs v2 (fsck_minix/mkfs_minix)" 168 188 default y 169 depends on CONFIG_FSCK_MINIX || CONFIG_MKFS_MINIX189 depends on FSCK_MINIX || MKFS_MINIX 170 190 help 171 191 If you wish to be able to create version 2 minix filesystems, enable this. … … 173 193 version 2 filesystem support. 174 194 175 config CONFIG_GETOPT195 config GETOPT 176 196 bool "getopt" 177 197 default n … … 184 204 wisely leave this disabled. 185 205 186 config CONFIG_HEXDUMP206 config HEXDUMP 187 207 bool "hexdump" 188 208 default n … … 191 211 way that is comparable to the output from most hex editors. 192 212 193 config CONFIG_HWCLOCK213 config HWCLOCK 194 214 bool "hwclock" 195 215 default n … … 200 220 correct time when Linux is _not_ running. 201 221 202 config CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS222 config FEATURE_HWCLOCK_LONG_OPTIONS 203 223 bool "Support long options (--hctosys,...)" 204 224 default n 205 depends on CONFIG_HWCLOCK && CONFIG_GETOPT_LONG225 depends on HWCLOCK && GETOPT_LONG 206 226 help 207 227 By default, the hwclock utility only uses short options. If you … … 209 229 then enable this option. 210 230 211 config CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS231 config FEATURE_HWCLOCK_ADJTIME_FHS 212 232 bool "Use FHS /var/lib/hwclock/adjtime" 213 233 default y 214 depends on CONFIG_HWCLOCK234 depends on HWCLOCK 215 235 help 216 236 Starting with FHS 2.3, the adjtime state file is supposed to exist … … 221 241 http://www.pathname.com/fhs/pub/fhs-2.3.html#VARLIBHWCLOCKSTATEDIRECTORYFORHWCLO 222 242 223 config CONFIG_IPCRM243 config IPCRM 224 244 bool "ipcrm" 225 245 default n 226 select CONFIG_FEATURE_SUID246 select FEATURE_SUID 227 247 help 228 248 The ipcrm utility allows the removal of System V interprocess … … 230 250 from the system. 231 251 232 config CONFIG_IPCS252 config IPCS 233 253 bool "ipcs" 234 254 default n 235 select CONFIG_FEATURE_SUID255 select FEATURE_SUID 236 256 help 237 257 The ipcs utility is used to provide information on the currently 238 258 allocated System V interprocess (IPC) objects in the system. 239 259 240 config CONFIG_LOSETUP260 config LOSETUP 241 261 bool "losetup" 242 262 default n … … 246 266 version does not currently support enabling data encryption. 247 267 248 config CONFIG_MDEV268 config MDEV 249 269 bool "mdev" 250 270 default n 251 271 help 252 mdev is a mini-udev implementation : call it with -s to populate253 /dev from /sys, then "echo /sbin/mdev > /proc/sys/kernel/hotplug" to254 have it handle hotplug events afterwards. Device names are taken 255 from sysfs.256 257 config CONFIG_FEATURE_MDEV_CONF272 mdev is a mini-udev implementation for dynamically creating device 273 nodes in the /dev directory. 274 275 For more information, please see docs/mdev.txt 276 277 config FEATURE_MDEV_CONF 258 278 bool "Support /etc/mdev.conf" 259 279 default n 260 depends on CONFIG_MDEV 261 help 262 The mdev config file contains lines that look like: 263 264 hd[a-z][0-9]* 0:3 660 265 266 That's device name (with regex match), uid:gid, and permissions. 267 268 Config file parsing stops on the first matching line. If no config 269 entry is matched, devices are created with default 0:0 660. (Make 270 the last line match .* to override this.) 271 272 config CONFIG_FEATURE_MDEV_EXEC 280 depends on MDEV 281 help 282 Add support for the mdev config file to control ownership and 283 permissions of the device nodes. 284 285 For more information, please see docs/mdev.txt 286 287 config FEATURE_MDEV_EXEC 273 288 bool "Support command execution at device addition/removal" 274 289 default n 275 depends on CONFIG_FEATURE_MDEV_CONF276 help 277 This adds support for an optional field to /etc/mdev.conf , consisting278 of a special character and a command line to run after creating the279 corresponding device(s) and before removing, ala: 280 281 hdc root:cdrom 660 *ln -s $MDEV cdrom 282 283 The $MDEV environment variable is set to the name of the device.284 285 The special characters and their meanings are:286 @ Run after creating the device.287 $ Run before removing the device.288 * Run both after creating and before removing the device. 289 290 Commands are executed via system() so you need /bin/sh, meaning you291 probably want to select a default shell in the Shells menu.292 293 config CONFIG_MKSWAP290 depends on FEATURE_MDEV_CONF 291 help 292 This adds support for an optional field to /etc/mdev.conf for 293 executing commands when devices are created/removed. 294 295 For more information, please see docs/mdev.txt 296 297 config FEATURE_MDEV_LOAD_FIRMWARE 298 bool "Support loading of firmwares" 299 default n 300 depends on MDEV 301 help 302 Some devices need to load firmware before they can be usable. 303 304 These devices will request userspace look up the files in 305 /lib/firmware/ and if it exists, send it to the kernel for 306 loading into the hardware. 307 308 config MKSWAP 294 309 bool "mkswap" 295 310 default n … … 304 319 the swap space using the 'swapon' utility. 305 320 306 config CONFIG_FEATURE_MKSWAP_V0321 config FEATURE_MKSWAP_V0 307 322 bool "version 0 support" 308 323 default n 309 depends on CONFIG_MKSWAP310 # depends on CONFIG_MKSWAP && CONFIG_DEPRECATED324 depends on MKSWAP 325 # depends on MKSWAP && DEPRECATED 311 326 help 312 327 Enable support for the old v0 style. … … 314 329 only option. 315 330 316 config CONFIG_MORE331 config MORE 317 332 bool "more" 318 333 default n … … 324 339 any need to reading text files, you can leave this disabled. 325 340 326 config CONFIG_FEATURE_USE_TERMIOS341 config FEATURE_USE_TERMIOS 327 342 bool "Use termios to manipulate the screen" 328 343 default y 329 depends on CONFIG_MORE344 depends on MORE 330 345 help 331 346 This option allows utilities such as 'more' and 'top' to determine … … 335 350 unable to move the cursor. 336 351 337 config CONFIG_MOUNT352 config MOUNT 338 353 bool "mount" 339 354 default n … … 346 361 the 'mount' utility. 347 362 348 config CONFIG_FEATURE_MOUNT_NFS363 config FEATURE_MOUNT_NFS 349 364 bool "Support mounting NFS file systems" 350 365 default n 351 depends on CONFIG_MOUNT 352 help 353 Enable mounting of NFS file systems. 354 355 config CONFIG_PIVOT_ROOT 366 depends on MOUNT 367 select FEATURE_HAVE_RPC 368 select FEATURE_SYSLOG 369 help 370 Enable mounting of NFS file systems. 371 372 config FEATURE_MOUNT_CIFS 373 bool "Support mounting CIFS/SMB file systems" 374 default n 375 depends on MOUNT 376 help 377 Enable support for samba mounts. 378 379 config FEATURE_MOUNT_FLAGS 380 depends on MOUNT 381 bool "Support lots of -o flags in mount" 382 default y 383 help 384 Without this, mount only supports ro/rw/remount. With this, it 385 supports nosuid, suid, dev, nodev, exec, noexec, sync, async, atime, 386 noatime, diratime, nodiratime, loud, bind, move, shared, slave, 387 private, unbindable, rshared, rslave, rprivate, and runbindable. 388 389 config FEATURE_MOUNT_FSTAB 390 depends on MOUNT 391 bool "Support /etc/fstab and -a" 392 default y 393 help 394 Support mount all and looking for files in /etc/fstab. 395 396 config PIVOT_ROOT 356 397 bool "pivot_root" 357 398 default n … … 365 406 in linux 2.6) use switch_root instead. 366 407 367 config CONFIG_RDATE408 config RDATE 368 409 bool "rdate" 369 410 default n … … 374 415 systems. 375 416 376 config CONFIG_READPROFILE417 config READPROFILE 377 418 bool "readprofile" 378 419 default n … … 380 421 This allows you to parse /proc/profile for basic profiling. 381 422 382 config CONFIG_SETARCH423 config SETARCH 383 424 bool "setarch" 384 425 default n … … 389 430 (like amd64/x86, ppc64/ppc, sparc64/sparc, etc...). 390 431 391 config CONFIG_SWAPONOFF432 config SWAPONOFF 392 433 bool "swaponoff" 393 434 default n … … 400 441 option disabled. 401 442 402 config CONFIG_SWITCH_ROOT443 config SWITCH_ROOT 403 444 bool "switch_root" 404 445 default n … … 419 460 list of active mount points. That's why. 420 461 421 config CONFIG_UMOUNT462 config UMOUNT 422 463 bool "umount" 423 464 default n … … 428 469 also want to enable 'umount'. 429 470 430 config CONFIG_FEATURE_UMOUNT_ALL471 config FEATURE_UMOUNT_ALL 431 472 bool "umount -a option" 432 473 default n 433 depends on CONFIG_UMOUNT474 depends on UMOUNT 434 475 help 435 476 Support -a option to unmount all currently mounted filesystems. 436 477 437 478 comment "Common options for mount/umount" 438 depends on CONFIG_MOUNT || CONFIG_UMOUNT439 440 config CONFIG_FEATURE_MOUNT_LOOP479 depends on MOUNT || UMOUNT 480 481 config FEATURE_MOUNT_LOOP 441 482 bool "Support loopback mounts" 442 483 default n 443 depends on CONFIG_MOUNT || CONFIG_UMOUNT484 depends on MOUNT || UMOUNT 444 485 help 445 486 Enabling this feature allows automatic mounting of files (containing … … 450 491 451 492 You can still use the 'losetup' utility (to manually associate files 452 493 with loop devices) if you need to do something advanced, such as 453 494 specify an offset or cryptographic options to the loopback device. 454 495 (If you don't want umount to free the loop device, use "umount -D".) 455 496 456 config CONFIG_FEATURE_MTAB_SUPPORT497 config FEATURE_MTAB_SUPPORT 457 498 bool "Support for the old /etc/mtab file" 458 499 default n 459 depends on CONFIG_MOUNT || CONFIG_UMOUNT500 depends on MOUNT || UMOUNT 460 501 help 461 502 Historically, Unix systems kept track of the currently mounted -
branches/stable/mindi-busybox/util-linux/dmesg.c
r821 r1770 1 /* vi: set ts=4: 2 * 1 /* vi: set sw=4 ts=4: */ 2 /* 3 * 3 4 * dmesg - display/control kernel ring buffer. 4 5 * 5 * Copyring 2006 Rob Landley <rob@landley.net> 6 * Copyright 2006 Rob Landley <rob@landley.net> 7 * Copyright 2006 Bernhard Fischer <rep.nop@aon.at> 6 8 * 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.9 * Licensed under GPLv2, see file LICENSE in this tarball for details. 8 10 */ 9 11 10 #include "busybox.h"11 #include <unistd.h>12 12 #include <sys/klog.h> 13 #include "libbb.h" 13 14 14 int dmesg_main(int argc, char *argv[]) 15 int dmesg_main(int argc, char **argv); 16 int dmesg_main(int argc, char **argv) 15 17 { 16 18 char *size, *level; 17 int flags = bb_getopt_ulflags(argc,argv, "cs:n:", &size, &level);19 int flags = getopt32(argv, "cs:n:", &size, &level); 18 20 19 21 if (flags & 4) { 20 if (klogctl(8, NULL, bb_xgetlarg(level, 10, 0, 10)))22 if (klogctl(8, NULL, xatoul_range(level, 0, 10))) 21 23 bb_perror_msg_and_die("klogctl"); 22 24 } else { … … 24 26 char *buf; 25 27 26 len = (flags & 2) ? bb_xgetlarg(size, 10, 2, INT_MAX) : 16384;28 len = (flags & 2) ? xatoul_range(size, 2, INT_MAX) : 16384; 27 29 buf = xmalloc(len); 28 30 if (0 > (len = klogctl(3 + (flags & 1), buf, len))) 29 31 bb_perror_msg_and_die("klogctl"); 30 write(1,buf,len); 31 if (len && buf[len-1]!='\n') putchar('\n'); 32 33 // Skip <#> at the start of lines, and make sure we end with a newline. 34 35 if (ENABLE_FEATURE_DMESG_PRETTY) { 36 int last = '\n'; 37 int in; 38 39 for (in = 0; in<len;) { 40 if (last == '\n' && buf[in] == '<') in += 3; 41 else putchar(last = buf[in++]); 42 } 43 if (last != '\n') putchar('\n'); 44 } else { 45 write(1,buf,len); 46 if (len && buf[len-1]!='\n') putchar('\n'); 47 } 48 49 if (ENABLE_FEATURE_CLEAN_UP) free(buf); 32 50 } 33 51 -
branches/stable/mindi-busybox/util-linux/fbset.c
r821 r1770 13 13 */ 14 14 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <unistd.h> 18 #include <fcntl.h> 19 #include <errno.h> 20 #include <ctype.h> 21 #include <string.h> 22 #include <stdint.h> 23 #include <sys/ioctl.h> 24 #include "busybox.h" 15 #include "libbb.h" 25 16 26 17 #define DEFAULTFBDEV FB_0 … … 31 22 OPT_INFO = (1 << 1), 32 23 OPT_READMODE = (1 << 2), 24 OPT_ALL = (1 << 9), 33 25 34 26 CMD_FB = 1, … … 46 38 CMD_CHANGE = 13, 47 39 48 #if def CONFIG_FEATURE_FBSET_FANCY40 #if ENABLE_FEATURE_FBSET_FANCY 49 41 CMD_XRES = 100, 50 42 CMD_YRES = 101, … … 70 62 }; 71 63 72 static unsigned int g_options = 0;64 static unsigned g_options; 73 65 74 66 /* Stuff stolen from the kernel's fb.h */ 67 #define FB_ACTIVATE_ALL 64 75 68 enum { 76 69 FBIOGET_VSCREENINFO = 0x4600, … … 78 71 }; 79 72 struct fb_bitfield { 80 uint32_t offset; /* beginning of bitfield */ 81 uint32_t length; /* length of bitfield */ 82 uint32_t msb_right; /* != 0 : Most significant bit is */ 83 /* right */ 73 uint32_t offset; /* beginning of bitfield */ 74 uint32_t length; /* length of bitfield */ 75 uint32_t msb_right; /* !=0: Most significant bit is right */ 84 76 }; 85 77 struct fb_var_screeninfo { 86 uint32_t xres; /* visible resolution*/78 uint32_t xres; /* visible resolution */ 87 79 uint32_t yres; 88 uint32_t xres_virtual; /* virtual resolution*/80 uint32_t xres_virtual; /* virtual resolution */ 89 81 uint32_t yres_virtual; 90 uint32_t xoffset; 91 uint32_t yoffset; /* resolution*/92 93 uint32_t bits_per_pixel; /* guess what */94 uint32_t grayscale; /* !=0 Graylevels instead of colors */95 96 struct fb_bitfield red; 97 struct fb_bitfield green; 82 uint32_t xoffset; /* offset from virtual to visible */ 83 uint32_t yoffset; /* resolution */ 84 85 uint32_t bits_per_pixel; 86 uint32_t grayscale; /* !=0 Graylevels instead of colors */ 87 88 struct fb_bitfield red; /* bitfield in fb mem if true color, */ 89 struct fb_bitfield green; /* else only length is significant */ 98 90 struct fb_bitfield blue; 99 struct fb_bitfield transp; /* transparency*/100 101 uint32_t nonstd; /* !=0 Non standard pixel format */102 103 uint32_t activate; /* see FB_ACTIVATE_**/104 105 uint32_t height; /* height of picture in mm*/106 uint32_t width; /* width of picture in mm*/91 struct fb_bitfield transp; /* transparency */ 92 93 uint32_t nonstd; /* !=0 Non standard pixel format */ 94 95 uint32_t activate; /* see FB_ACTIVATE_x */ 96 97 uint32_t height; /* height of picture in mm */ 98 uint32_t width; /* width of picture in mm */ 107 99 108 100 uint32_t accel_flags; /* acceleration flags (hints) */ 109 101 110 102 /* Timing: All values in pixclocks, except pixclock (of course) */ 111 uint32_t pixclock; 112 uint32_t left_margin; /* time from sync to picture*/113 uint32_t right_margin; /* time from picture to sync*/114 uint32_t upper_margin; /* time from sync to picture*/103 uint32_t pixclock; /* pixel clock in ps (pico seconds) */ 104 uint32_t left_margin; /* time from sync to picture */ 105 uint32_t right_margin; /* time from picture to sync */ 106 uint32_t upper_margin; /* time from sync to picture */ 115 107 uint32_t lower_margin; 116 uint32_t hsync_len; /* length of horizontal sync*/117 uint32_t vsync_len; /* length of vertical sync*/118 uint32_t sync; /* see FB_SYNC_**/119 uint32_t vmode; /* see FB_VMODE_**/120 uint32_t reserved[6]; 108 uint32_t hsync_len; /* length of horizontal sync */ 109 uint32_t vsync_len; /* length of vertical sync */ 110 uint32_t sync; /* see FB_SYNC_x */ 111 uint32_t vmode; /* see FB_VMODE_x */ 112 uint32_t reserved[6]; /* Reserved for future compatibility */ 121 113 }; 122 114 123 115 124 116 static const struct cmdoptions_t { 125 const char *name;117 const char name[10]; 126 118 const unsigned char param_count; 127 119 const unsigned char code; 128 120 } g_cmdoptions[] = { 129 { 130 "-fb", 1, CMD_FB}, { 131 "-db", 1, CMD_DB}, { 132 "-a", 0, CMD_ALL}, { 133 "-i", 0, CMD_INFO}, { 134 "-g", 5, CMD_GEOMETRY}, { 135 "-t", 7, CMD_TIMING}, { 136 "-accel", 1, CMD_ACCEL}, { 137 "-hsync", 1, CMD_HSYNC}, { 138 "-vsync", 1, CMD_VSYNC}, { 139 "-laced", 1, CMD_LACED}, { 140 "-double", 1, CMD_DOUBLE}, { 141 "-n", 0, CMD_CHANGE}, { 142 #ifdef CONFIG_FEATURE_FBSET_FANCY 143 "-all", 0, CMD_ALL}, { 144 "-xres", 1, CMD_XRES}, { 145 "-yres", 1, CMD_YRES}, { 146 "-vxres", 1, CMD_VXRES}, { 147 "-vyres", 1, CMD_VYRES}, { 148 "-depth", 1, CMD_DEPTH}, { 149 "-match", 0, CMD_MATCH}, { 150 "-geometry", 5, CMD_GEOMETRY}, { 151 "-pixclock", 1, CMD_PIXCLOCK}, { 152 "-left", 1, CMD_LEFT}, { 153 "-right", 1, CMD_RIGHT}, { 154 "-upper", 1, CMD_UPPER}, { 155 "-lower", 1, CMD_LOWER}, { 156 "-hslen", 1, CMD_HSLEN}, { 157 "-vslen", 1, CMD_VSLEN}, { 158 "-timings", 7, CMD_TIMING}, { 159 "-csync", 1, CMD_CSYNC}, { 160 "-gsync", 1, CMD_GSYNC}, { 161 "-extsync", 1, CMD_EXTSYNC}, { 162 "-bcast", 1, CMD_BCAST}, { 163 "-rgba", 1, CMD_RGBA}, { 164 "-step", 1, CMD_STEP}, { 165 "-move", 1, CMD_MOVE}, { 166 #endif 167 0, 0, 0} 168 }; 169 170 #ifdef CONFIG_FEATURE_FBSET_READMODE 121 { "-fb", 1, CMD_FB }, 122 { "-db", 1, CMD_DB }, 123 { "-a", 0, CMD_ALL }, 124 { "-i", 0, CMD_INFO }, 125 { "-g", 5, CMD_GEOMETRY }, 126 { "-t", 7, CMD_TIMING }, 127 { "-accel", 1, CMD_ACCEL }, 128 { "-hsync", 1, CMD_HSYNC }, 129 { "-vsync", 1, CMD_VSYNC }, 130 { "-laced", 1, CMD_LACED }, 131 { "-double", 1, CMD_DOUBLE }, 132 { "-n", 0, CMD_CHANGE }, 133 #if ENABLE_FEATURE_FBSET_FANCY 134 { "-all", 0, CMD_ALL }, 135 { "-xres", 1, CMD_XRES }, 136 { "-yres", 1, CMD_YRES }, 137 { "-vxres", 1, CMD_VXRES }, 138 { "-vyres", 1, CMD_VYRES }, 139 { "-depth", 1, CMD_DEPTH }, 140 { "-match", 0, CMD_MATCH }, 141 { "-geometry", 5, CMD_GEOMETRY }, 142 { "-pixclock", 1, CMD_PIXCLOCK }, 143 { "-left", 1, CMD_LEFT }, 144 { "-right", 1, CMD_RIGHT }, 145 { "-upper", 1, CMD_UPPER }, 146 { "-lower", 1, CMD_LOWER }, 147 { "-hslen", 1, CMD_HSLEN }, 148 { "-vslen", 1, CMD_VSLEN }, 149 { "-timings", 7, CMD_TIMING }, 150 { "-csync", 1, CMD_CSYNC }, 151 { "-gsync", 1, CMD_GSYNC }, 152 { "-extsync", 1, CMD_EXTSYNC }, 153 { "-bcast", 1, CMD_BCAST }, 154 { "-rgba", 1, CMD_RGBA }, 155 { "-step", 1, CMD_STEP }, 156 { "-move", 1, CMD_MOVE }, 157 #endif 158 { "", 0, 0 } 159 }; 160 161 #if ENABLE_FEATURE_FBSET_READMODE 171 162 /* taken from linux/fb.h */ 172 163 enum { … … 179 170 }; 180 171 #endif 172 181 173 static int readmode(struct fb_var_screeninfo *base, const char *fn, 182 174 const char *mode) 183 175 { 184 #if def CONFIG_FEATURE_FBSET_READMODE176 #if ENABLE_FEATURE_FBSET_READMODE 185 177 FILE *f; 186 178 char buf[256]; 187 179 char *p = buf; 188 180 189 f = bb_xfopen(fn, "r");181 f = xfopen(fn, "r"); 190 182 while (!feof(f)) { 191 183 fgets(buf, sizeof(buf), f); 192 if ((p = strstr(buf, "mode ")) || (p = strstr(buf, "mode\t"))) { 193 p += 5; 194 if ((p = strstr(buf, mode))) { 195 p += strlen(mode); 196 if (!isspace(*p) && (*p != 0) && (*p != '"') 197 && (*p != '\r') && (*p != '\n')) 198 continue; /* almost, but not quite */ 199 while (!feof(f)) { 200 fgets(buf, sizeof(buf), f); 201 202 if ((p = strstr(buf, "geometry "))) { 203 p += 9; 204 205 sscanf(p, "%d %d %d %d %d", 206 &(base->xres), &(base->yres), 207 &(base->xres_virtual), &(base->yres_virtual), 208 &(base->bits_per_pixel)); 209 } else if ((p = strstr(buf, "timings "))) { 210 p += 8; 211 212 sscanf(p, "%d %d %d %d %d %d %d", 213 &(base->pixclock), 214 &(base->left_margin), &(base->right_margin), 215 &(base->upper_margin), &(base->lower_margin), 216 &(base->hsync_len), &(base->vsync_len)); 217 } else if ((p = strstr(buf, "laced "))) { 218 p += 6; 219 220 if (strstr(buf, "false")) { 221 base->vmode &= ~FB_VMODE_INTERLACED; 222 } else { 223 base->vmode |= FB_VMODE_INTERLACED; 184 if (!(p = strstr(buf, "mode ")) && !(p = strstr(buf, "mode\t"))) 185 continue; 186 p += 5; 187 if (!(p = strstr(buf, mode))) 188 continue; 189 p += strlen(mode); 190 if (!isspace(*p) && (*p != 0) && (*p != '"') 191 && (*p != '\r') && (*p != '\n')) 192 continue; /* almost, but not quite */ 193 194 while (!feof(f)) { 195 fgets(buf, sizeof(buf), f); 196 if ((p = strstr(buf, "geometry "))) { 197 p += 9; 198 /* FIXME: catastrophic on arches with 64bit ints */ 199 sscanf(p, "%d %d %d %d %d", 200 &(base->xres), &(base->yres), 201 &(base->xres_virtual), &(base->yres_virtual), 202 &(base->bits_per_pixel)); 203 } else if ((p = strstr(buf, "timings "))) { 204 p += 8; 205 sscanf(p, "%d %d %d %d %d %d %d", 206 &(base->pixclock), 207 &(base->left_margin), &(base->right_margin), 208 &(base->upper_margin), &(base->lower_margin), 209 &(base->hsync_len), &(base->vsync_len)); 210 } else if ((p = strstr(buf, "laced "))) { 211 //p += 6; 212 if (strstr(buf, "false")) { 213 base->vmode &= ~FB_VMODE_INTERLACED; 214 } else { 215 base->vmode |= FB_VMODE_INTERLACED; 216 } 217 } else if ((p = strstr(buf, "double "))) { 218 //p += 7; 219 if (strstr(buf, "false")) { 220 base->vmode &= ~FB_VMODE_DOUBLE; 221 } else { 222 base->vmode |= FB_VMODE_DOUBLE; 223 } 224 } else if ((p = strstr(buf, "vsync "))) { 225 //p += 6; 226 if (strstr(buf, "low")) { 227 base->sync &= ~FB_SYNC_VERT_HIGH_ACT; 228 } else { 229 base->sync |= FB_SYNC_VERT_HIGH_ACT; 230 } 231 } else if ((p = strstr(buf, "hsync "))) { 232 //p += 6; 233 if (strstr(buf, "low")) { 234 base->sync &= ~FB_SYNC_HOR_HIGH_ACT; 235 } else { 236 base->sync |= FB_SYNC_HOR_HIGH_ACT; 237 } 238 } else if ((p = strstr(buf, "csync "))) { 239 //p += 6; 240 if (strstr(buf, "low")) { 241 base->sync &= ~FB_SYNC_COMP_HIGH_ACT; 242 } else { 243 base->sync |= FB_SYNC_COMP_HIGH_ACT; 244 } 245 } else if ((p = strstr(buf, "extsync "))) { 246 //p += 8; 247 if (strstr(buf, "false")) { 248 base->sync &= ~FB_SYNC_EXT; 249 } else { 250 base->sync |= FB_SYNC_EXT; 251 } 224 252 } 225 } else if ((p = strstr(buf, "double "))) { 226 p += 7; 227 228 if (strstr(buf, "false")) { 229 base->vmode &= ~FB_VMODE_DOUBLE; 230 } else { 231 base->vmode |= FB_VMODE_DOUBLE; 232 } 233 } else if ((p = strstr(buf, "vsync "))) { 234 p += 6; 235 236 if (strstr(buf, "low")) { 237 base->sync &= ~FB_SYNC_VERT_HIGH_ACT; 238 } else { 239 base->sync |= FB_SYNC_VERT_HIGH_ACT; 240 } 241 } else if ((p = strstr(buf, "hsync "))) { 242 p += 6; 243 244 if (strstr(buf, "low")) { 245 base->sync &= ~FB_SYNC_HOR_HIGH_ACT; 246 } else { 247 base->sync |= FB_SYNC_HOR_HIGH_ACT; 248 } 249 } else if ((p = strstr(buf, "csync "))) { 250 p += 6; 251 252 if (strstr(buf, "low")) { 253 base->sync &= ~FB_SYNC_COMP_HIGH_ACT; 254 } else { 255 base->sync |= FB_SYNC_COMP_HIGH_ACT; 256 } 257 } else if ((p = strstr(buf, "extsync "))) { 258 p += 8; 259 260 if (strstr(buf, "false")) { 261 base->sync &= ~FB_SYNC_EXT; 262 } else { 263 base->sync |= FB_SYNC_EXT; 264 } 265 } 266 267 if (strstr(buf, "endmode")) 268 return 1; 269 } 270 } 253 254 if (strstr(buf, "endmode")) 255 return 1; 271 256 } 272 257 } 273 258 #else 274 bb_error_msg( 259 bb_error_msg("mode reading not compiled in"); 275 260 #endif 276 261 return 0; … … 298 283 if (v->pixclock) { 299 284 drate = 1e12 / v->pixclock; 300 hrate = 301 drate / (v->left_margin + v->xres + v->right_margin + 302 v->hsync_len); 303 vrate = 304 hrate / (v->upper_margin + v->yres + v->lower_margin + 305 v->vsync_len); 285 hrate = drate / (v->left_margin + v->xres + v->right_margin + v->hsync_len); 286 vrate = hrate / (v->upper_margin + v->yres + v->lower_margin + v->vsync_len); 306 287 } 307 288 printf("\nmode \"%ux%u-%u\"\n" 308 #if def CONFIG_FEATURE_FBSET_FANCY289 #if ENABLE_FEATURE_FBSET_FANCY 309 290 "\t# D: %.3f MHz, H: %.3f kHz, V: %.3f Hz\n" 310 291 #endif 311 "\tgeometry %u %u %u %u %u\n\ttimings %u %u %u %u %u %u %u\n\taccel %s\n\trgba %u/%u,%u/%u,%u/%u,%u/%u\nendmode\n\n", 312 v->xres, v->yres, (int) (vrate + 0.5), 313 #ifdef CONFIG_FEATURE_FBSET_FANCY 314 drate / 1e6, hrate / 1e3, vrate, 315 #endif 316 v->xres, v->yres, v->xres_virtual, v->yres_virtual, 317 v->bits_per_pixel, v->pixclock, v->left_margin, 318 v->right_margin, v->upper_margin, v->lower_margin, v->hsync_len, 319 v->vsync_len, (v->accel_flags > 0 ? "true" : "false"), v->red.length, 320 v->red.offset, v->green.length, v->green.offset, v->blue.length, 321 v->blue.offset, v->transp.length, v->transp.offset); 292 "\tgeometry %u %u %u %u %u\n" 293 "\ttimings %u %u %u %u %u %u %u\n" 294 "\taccel %s\n" 295 "\trgba %u/%u,%u/%u,%u/%u,%u/%u\n" 296 "endmode\n\n", 297 v->xres, v->yres, (int) (vrate + 0.5), 298 #if ENABLE_FEATURE_FBSET_FANCY 299 drate / 1e6, hrate / 1e3, vrate, 300 #endif 301 v->xres, v->yres, v->xres_virtual, v->yres_virtual, v->bits_per_pixel, 302 v->pixclock, v->left_margin, v->right_margin, v->upper_margin, v->lower_margin, 303 v->hsync_len, v->vsync_len, 304 (v->accel_flags > 0 ? "true" : "false"), 305 v->red.length, v->red.offset, v->green.length, v->green.offset, 306 v->blue.length, v->blue.offset, v->transp.length, v->transp.offset); 322 307 } 323 308 … … 325 310 int main(int argc, char **argv) 326 311 #else 312 int fbset_main(int argc, char **argv); 327 313 int fbset_main(int argc, char **argv) 328 314 #endif … … 330 316 struct fb_var_screeninfo var, varset; 331 317 int fh, i; 332 c har *fbdev = DEFAULTFBDEV;333 c har *modefile = DEFAULTFBMODE;318 const char *fbdev = DEFAULTFBDEV; 319 const char *modefile = DEFAULTFBMODE; 334 320 char *thisarg, *mode = NULL; 335 321 … … 340 326 argc--; 341 327 for (; argc > 0 && (thisarg = *argv); argc--, argv++) { 342 for (i = 0; g_cmdoptions[i].name; i++) { 343 if (!strcmp(thisarg, g_cmdoptions[i].name)) { 344 if (argc - 1 < g_cmdoptions[i].param_count) 345 bb_show_usage(); 346 switch (g_cmdoptions[i].code) { 347 case CMD_FB: 348 fbdev = argv[1]; 349 break; 350 case CMD_DB: 351 modefile = argv[1]; 352 break; 353 case CMD_GEOMETRY: 354 varset.xres = strtoul(argv[1], 0, 0); 355 varset.yres = strtoul(argv[2], 0, 0); 356 varset.xres_virtual = strtoul(argv[3], 0, 0); 357 varset.yres_virtual = strtoul(argv[4], 0, 0); 358 varset.bits_per_pixel = strtoul(argv[5], 0, 0); 359 break; 360 case CMD_TIMING: 361 varset.pixclock = strtoul(argv[1], 0, 0); 362 varset.left_margin = strtoul(argv[2], 0, 0); 363 varset.right_margin = strtoul(argv[3], 0, 0); 364 varset.upper_margin = strtoul(argv[4], 0, 0); 365 varset.lower_margin = strtoul(argv[5], 0, 0); 366 varset.hsync_len = strtoul(argv[6], 0, 0); 367 varset.vsync_len = strtoul(argv[7], 0, 0); 368 break; 369 case CMD_CHANGE: 370 g_options |= OPT_CHANGE; 371 break; 372 #ifdef CONFIG_FEATURE_FBSET_FANCY 373 case CMD_XRES: 374 varset.xres = strtoul(argv[1], 0, 0); 375 break; 376 case CMD_YRES: 377 varset.yres = strtoul(argv[1], 0, 0); 378 break; 379 case CMD_DEPTH: 380 varset.bits_per_pixel = strtoul(argv[1], 0, 0); 381 break; 382 #endif 383 } 384 argc -= g_cmdoptions[i].param_count; 385 argv += g_cmdoptions[i].param_count; 386 break; 328 for (i = 0; g_cmdoptions[i].name[0]; i++) { 329 if (strcmp(thisarg, g_cmdoptions[i].name)) 330 continue; 331 if (argc-1 < g_cmdoptions[i].param_count) 332 bb_show_usage(); 333 334 switch (g_cmdoptions[i].code) { 335 case CMD_FB: 336 fbdev = argv[1]; 337 break; 338 case CMD_DB: 339 modefile = argv[1]; 340 break; 341 case CMD_GEOMETRY: 342 varset.xres = xatou32(argv[1]); 343 varset.yres = xatou32(argv[2]); 344 varset.xres_virtual = xatou32(argv[3]); 345 varset.yres_virtual = xatou32(argv[4]); 346 varset.bits_per_pixel = xatou32(argv[5]); 347 break; 348 case CMD_TIMING: 349 varset.pixclock = xatou32(argv[1]); 350 varset.left_margin = xatou32(argv[2]); 351 varset.right_margin = xatou32(argv[3]); 352 varset.upper_margin = xatou32(argv[4]); 353 varset.lower_margin = xatou32(argv[5]); 354 varset.hsync_len = xatou32(argv[6]); 355 varset.vsync_len = xatou32(argv[7]); 356 break; 357 case CMD_ALL: 358 g_options |= OPT_ALL; 359 break; 360 case CMD_CHANGE: 361 g_options |= OPT_CHANGE; 362 break; 363 #if ENABLE_FEATURE_FBSET_FANCY 364 case CMD_XRES: 365 varset.xres = xatou32(argv[1]); 366 break; 367 case CMD_YRES: 368 varset.yres = xatou32(argv[1]); 369 break; 370 case CMD_DEPTH: 371 varset.bits_per_pixel = xatou32(argv[1]); 372 break; 373 #endif 387 374 } 375 argc -= g_cmdoptions[i].param_count; 376 argv += g_cmdoptions[i].param_count; 377 break; 388 378 } 389 if (!g_cmdoptions[i].name) { 390 if (argc == 1) { 391 mode = *argv; 392 g_options |= OPT_READMODE; 393 } else { 379 if (!g_cmdoptions[i].name[0]) { 380 if (argc != 1) 394 381 bb_show_usage(); 395 } 382 mode = *argv; 383 g_options |= OPT_READMODE; 396 384 } 397 385 } 398 386 399 fh = bb_xopen(fbdev, O_RDONLY); 400 if (ioctl(fh, FBIOGET_VSCREENINFO, &var)) 401 bb_perror_msg_and_die("fbset(ioctl)"); 387 fh = xopen(fbdev, O_RDONLY); 388 xioctl(fh, FBIOGET_VSCREENINFO, &var); 402 389 if (g_options & OPT_READMODE) { 403 390 if (!readmode(&var, modefile, mode)) { 404 bb_error_msg("Unknown video mode `%s'", mode); 405 return EXIT_FAILURE; 391 bb_error_msg_and_die("unknown video mode '%s'", mode); 406 392 } 407 393 } 408 394 409 395 setmode(&var, &varset); 410 if (g_options & OPT_CHANGE) 411 if (ioctl(fh, FBIOPUT_VSCREENINFO, &var)) 412 bb_perror_msg_and_die("fbset(ioctl)"); 396 if (g_options & OPT_CHANGE) { 397 if (g_options & OPT_ALL) 398 var.activate = FB_ACTIVATE_ALL; 399 xioctl(fh, FBIOPUT_VSCREENINFO, &var); 400 } 413 401 showmode(&var); 414 402 /* Don't close the file, as exiting will take care of that */ -
branches/stable/mindi-busybox/util-linux/fdformat.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* fdformat.c - Low-level formats a floppy disk - Werner Almesberger */ 2 3 … … 9 10 */ 10 11 11 #include <stdio.h> 12 #include <string.h> 13 #include <fcntl.h> 14 #include <errno.h> 15 #include <unistd.h> 16 #include <stdlib.h> 17 #include <sys/stat.h> 18 #include <sys/ioctl.h> 19 #include "busybox.h" 12 #include "libbb.h" 20 13 21 14 … … 53 46 #define FD_FILL_BYTE 0xF6 /* format fill byte. */ 54 47 55 static void print_and_flush(const char * __restrict format, ...) 56 { 57 va_list arg; 58 59 va_start(arg, format); 60 bb_vfprintf(stdout, format, arg); 61 va_end(arg); 62 bb_xfflush_stdout(); 63 } 64 65 static void bb_xioctl(int fd, int request, void *argp, const char *string) 66 { 67 if (ioctl (fd, request, argp) < 0) { 68 bb_perror_msg_and_die(string); 69 } 70 } 71 48 int fdformat_main(int argc,char **argv); 72 49 int fdformat_main(int argc,char **argv) 73 50 { … … 81 58 bb_show_usage(); 82 59 } 83 verify = ! bb_getopt_ulflags(argc,argv, "n");60 verify = !getopt32(argv, "n"); 84 61 argv += optind; 85 62 86 /* R_OK is needed for verifying */ 87 if (stat(*argv,&st) < 0 || access(*argv,W_OK | R_OK ) < 0) { 88 bb_perror_msg_and_die("%s",*argv); 89 } 63 xstat(*argv, &st); 90 64 if (!S_ISBLK(st.st_mode)) { 91 bb_error_msg_and_die("%s: not a block device", *argv);65 bb_error_msg_and_die("%s: not a block device", *argv); 92 66 /* do not test major - perhaps this was an USB floppy */ 93 67 } 94 68 69 /* O_RDWR for formatting and verifying */ 70 fd = xopen(*argv, O_RDWR); 95 71 96 /* O_RDWR for formatting and verifying*/97 fd = bb_xopen(*argv,O_RDWR);72 /* original message was: "Could not determine current format type" */ 73 xioctl(fd, FDGETPRM, ¶m); 98 74 99 bb_xioctl(fd, FDGETPRM, ¶m, "FDGETPRM");/*original message was: "Could not determine current format type" */ 100 101 print_and_flush("%s-sided, %d tracks, %d sec/track. Total capacity %d kB.\n", 75 printf("%s-sided, %d tracks, %d sec/track. Total capacity %d kB\n", 102 76 (param.head == 2) ? "Double" : "Single", 103 77 param.track, param.sect, param.size >> 1); 104 78 105 79 /* FORMAT */ 106 print _and_flush("Formatting ... ", NULL);107 bb_xioctl(fd, FDFMTBEG,NULL,"FDFMTBEG");80 printf("Formatting... "); 81 xioctl(fd, FDFMTBEG, NULL); 108 82 109 83 /* n == track */ 110 for (n = 0; n < param.track; n++) 111 { 112 descr.head = 0; 113 descr.track = n; 114 bb_xioctl(fd, FDFMTTRK,&descr,"FDFMTTRK"); 115 print_and_flush("%3d\b\b\b", n); 116 if (param.head == 2) { 117 descr.head = 1; 118 bb_xioctl(fd, FDFMTTRK,&descr,"FDFMTTRK"); 119 } 84 for (n = 0; n < param.track; n++) { 85 descr.head = 0; 86 descr.track = n; 87 xioctl(fd, FDFMTTRK, &descr); 88 printf("%3d\b\b\b", n); 89 if (param.head == 2) { 90 descr.head = 1; 91 xioctl(fd, FDFMTTRK, &descr); 92 } 120 93 } 121 94 122 bb_xioctl(fd,FDFMTEND,NULL,"FDFMTEND");123 print _and_flush("done\n", NULL);95 xioctl(fd, FDFMTEND, NULL); 96 printf("done\n"); 124 97 125 98 /* VERIFY */ 126 if (verify) {99 if (verify) { 127 100 /* n == cyl_size */ 128 101 n = param.sect*param.head*512; 129 102 130 103 data = xmalloc(n); 131 print _and_flush("Verifying ... ", NULL);104 printf("Verifying... "); 132 105 for (cyl = 0; cyl < param.track; cyl++) { 133 print_and_flush("%3d\b\b\b", cyl); 134 if((read_bytes = safe_read(fd,data,n))!= n ) { 135 if(read_bytes < 0) { 106 printf("%3d\b\b\b", cyl); 107 read_bytes = safe_read(fd, data, n); 108 if (read_bytes != n) { 109 if (read_bytes < 0) { 136 110 bb_perror_msg(bb_msg_read_error); 137 111 } 138 bb_error_msg_and_die("Problem reading cylinder %d, expected %d, read %d", cyl, n, read_bytes); 112 bb_error_msg_and_die("problem reading cylinder %d, " 113 "expected %d, read %d", cyl, n, read_bytes); 114 // FIXME: maybe better seek & continue?? 139 115 } 140 116 /* Check backwards so we don't need a counter */ 141 while (--read_bytes>=0) {142 if (data[read_bytes] != FD_FILL_BYTE) {143 print _and_flush("bad data in cyl %d\nContinuing... ",cyl);117 while (--read_bytes >= 0) { 118 if (data[read_bytes] != FD_FILL_BYTE) { 119 printf("bad data in cyl %d\nContinuing... ",cyl); 144 120 } 145 121 } … … 151 127 if (ENABLE_FEATURE_CLEAN_UP) free(data); 152 128 153 print _and_flush("done\n", NULL);129 printf("done\n"); 154 130 } 155 131 -
branches/stable/mindi-busybox/util-linux/fdisk.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* fdisk.c -- Partition table manipulator for Linux. 2 3 * … … 7 8 */ 8 9 9 /* Current changes have not compatibility with this version */ 10 #define UTIL_LINUX_VERSION "2.12" 11 12 13 #define _(x) x 14 15 #define PROC_PARTITIONS "/proc/partitions" 16 17 #include <features.h> 18 #include <sys/types.h> 19 #include <sys/stat.h> /* stat */ 20 #include <ctype.h> 21 #include <stdlib.h> 22 #include <stdio.h> 23 #include <string.h> 24 #include <errno.h> 25 #include <unistd.h> 26 #include <fcntl.h> 27 #include <setjmp.h> 10 #ifndef _LARGEFILE64_SOURCE 11 /* For lseek64 */ 12 #define _LARGEFILE64_SOURCE 13 #endif 28 14 #include <assert.h> /* assert */ 29 #include <getopt.h> 30 #include <endian.h> 31 #include <sys/ioctl.h> 32 #include <sys/param.h> 33 #include <sys/sysmacros.h> /* major */ 34 35 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */ 36 37 /* Copied from linux/major.h */ 38 #define FLOPPY_MAJOR 2 39 40 #include <sys/utsname.h> 41 42 #include "busybox.h" 43 44 #define DKTYPENAMES 45 46 /* 47 fdisk.h 48 */ 15 #include "libbb.h" 16 17 /* Looks like someone forgot to add this to config system */ 18 #ifndef ENABLE_FEATURE_FDISK_BLKSIZE 19 # define ENABLE_FEATURE_FDISK_BLKSIZE 0 20 # define USE_FEATURE_FDISK_BLKSIZE(a) 21 #endif 49 22 50 23 #define DEFAULT_SECTOR_SIZE 512 51 24 #define MAX_SECTOR_SIZE 2048 52 #define SECTOR_SIZE 512 /* still used in BSDcode */25 #define SECTOR_SIZE 512 /* still used in osf/sgi/sun code */ 53 26 #define MAXIMUM_PARTS 60 54 27 … … 64 37 #define LINUX_RAID 0xfd 65 38 66 #define SUNOS_SWAP 3 67 #define WHOLE_DISK 5 68 69 #define IS_EXTENDED(i) \ 70 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED) 71 72 #define SIZE(a) (sizeof(a)/sizeof((a)[0])) 73 74 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n)) 75 #define scround(x) (((x)+units_per_sector-1)/units_per_sector) 76 77 #ifdef CONFIG_FEATURE_SUN_LABEL 78 #define SCSI_IOCTL_GET_IDLUN 0x5382 79 #endif 80 81 82 /* including <linux/hdreg.h> also fails */ 39 /* Used for sector numbers. Today's disk sizes make it necessary */ 40 typedef unsigned long long ullong; 41 83 42 struct hd_geometry { 84 43 unsigned char heads; … … 88 47 }; 89 48 90 #define HDIO_GETGEO 0x0301 /* get device geometry */ 91 92 93 struct systypes { 94 const char *name; 95 }; 96 97 static uint sector_size = DEFAULT_SECTOR_SIZE; 98 static uint user_set_sector_size; 99 static uint sector_offset = 1; 100 101 /* 102 * Raw disk label. For DOS-type partition tables the MBR, 103 * with descriptions of the primary partitions. 104 */ 105 #if (MAX_SECTOR_SIZE) > (BUFSIZ+1) 106 static char MBRbuffer[MAX_SECTOR_SIZE]; 107 #else 108 # define MBRbuffer bb_common_bufsiz1 109 #endif 110 111 #ifdef CONFIG_FEATURE_OSF_LABEL 49 #define HDIO_GETGEO 0x0301 /* get device geometry */ 50 51 static const char msg_building_new_label[] ALIGN1 = 52 "Building a new %s. Changes will remain in memory only,\n" 53 "until you decide to write them. After that the previous content\n" 54 "won't be recoverable.\n\n"; 55 56 static const char msg_part_already_defined[] ALIGN1 = 57 "Partition %d is already defined, delete it before re-adding\n"; 58 59 60 static unsigned sector_size = DEFAULT_SECTOR_SIZE; 61 static unsigned user_set_sector_size; 62 static unsigned sector_offset = 1; 63 64 #if ENABLE_FEATURE_OSF_LABEL 112 65 static int possibly_osf_label; 113 66 #endif 114 67 115 static u intheads, sectors, cylinders;68 static unsigned heads, sectors, cylinders; 116 69 static void update_units(void); 117 70 118 119 /*120 * return partition name - uses static storage unless buf is supplied121 */122 static const char *123 partname(const char *dev, int pno, int lth)124 {125 static char buffer[80];126 const char *p;127 int w, wp;128 int bufsiz;129 char *bufp;130 131 bufp = buffer;132 bufsiz = sizeof(buffer);133 134 w = strlen(dev);135 p = "";136 137 if (isdigit(dev[w-1]))138 p = "p";139 140 /* devfs kludge - note: fdisk partition names are not supposed141 to equal kernel names, so there is no reason to do this */142 if (strcmp(dev + w - 4, "disc") == 0) {143 w -= 4;144 p = "part";145 }146 147 wp = strlen(p);148 149 if (lth) {150 snprintf(bufp, bufsiz, "%*.*s%s%-2u",151 lth-wp-2, w, dev, p, pno);152 } else {153 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);154 }155 return bufp;156 }157 71 158 72 struct partition { … … 169 83 } ATTRIBUTE_PACKED; 170 84 171 enum failure { 172 ioctl_error, unable_to_open, unable_to_read, unable_to_seek, 173 unable_to_write 174 }; 175 176 enum label_type{ 85 static const char unable_to_open[] ALIGN1 = "cannot open %s"; 86 static const char unable_to_read[] ALIGN1 = "cannot read from %s"; 87 static const char unable_to_seek[] ALIGN1 = "cannot seek on %s"; 88 static const char unable_to_write[] ALIGN1 = "cannot write to %s"; 89 static const char ioctl_error[] ALIGN1 = "BLKGETSIZE ioctl failed on %s"; 90 static void fdisk_fatal(const char *why) ATTRIBUTE_NORETURN; 91 92 enum label_type { 177 93 label_dos, label_sun, label_sgi, label_aix, label_osf 178 94 }; 95 96 #define LABEL_IS_DOS (label_dos == current_label_type) 97 98 #if ENABLE_FEATURE_SUN_LABEL 99 #define LABEL_IS_SUN (label_sun == current_label_type) 100 #define STATIC_SUN static 101 #else 102 #define LABEL_IS_SUN 0 103 #define STATIC_SUN extern 104 #endif 105 106 #if ENABLE_FEATURE_SGI_LABEL 107 #define LABEL_IS_SGI (label_sgi == current_label_type) 108 #define STATIC_SGI static 109 #else 110 #define LABEL_IS_SGI 0 111 #define STATIC_SGI extern 112 #endif 113 114 #if ENABLE_FEATURE_AIX_LABEL 115 #define LABEL_IS_AIX (label_aix == current_label_type) 116 #define STATIC_AIX static 117 #else 118 #define LABEL_IS_AIX 0 119 #define STATIC_AIX extern 120 #endif 121 122 #if ENABLE_FEATURE_OSF_LABEL 123 #define LABEL_IS_OSF (label_osf == current_label_type) 124 #define STATIC_OSF static 125 #else 126 #define LABEL_IS_OSF 0 127 #define STATIC_OSF extern 128 #endif 179 129 180 130 enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun }; … … 185 135 static int fd; /* the disk */ 186 136 static int partitions = 4; /* maximum partition + 1 */ 187 static uint display_in_cyl_units = 1; 188 static uint units_per_sector = 1; 189 #ifdef CONFIG_FEATURE_FDISK_WRITABLE 190 static char *line_ptr; 137 static int display_in_cyl_units = 1; 138 static unsigned units_per_sector = 1; 139 #if ENABLE_FEATURE_FDISK_WRITABLE 191 140 static void change_units(void); 192 141 static void reread_partition_table(int leave); 193 142 static void delete_partition(int i); 194 143 static int get_partition(int warn, int max); 195 static void list_types(const struct systypes*sys);196 static u int read_int(uint low, uint dflt, uint high, uint base,char *mesg);144 static void list_types(const char *const *sys); 145 static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg); 197 146 #endif 198 147 static const char *partition_type(unsigned char type); 199 static void fdisk_fatal(enum failure why) ATTRIBUTE_NORETURN;200 148 static void get_geometry(void); 201 149 static int get_boot(enum action what); … … 204 152 #define SINGULAR 1 205 153 206 #define hex_val(c) ({ \ 207 char _c = (c); \ 208 isdigit(_c) ? _c - '0' : \ 209 tolower(_c) + 10 - 'a'; \ 210 }) 211 212 213 #define LINE_LENGTH 800 214 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \ 215 (n) * sizeof(struct partition))) 216 #define sector(s) ((s) & 0x3f) 217 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2)) 218 219 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \ 220 ((h) + heads * cylinder(s,c))) 221 #define set_hsc(h,s,c,sector) { \ 222 s = sector % sectors + 1; \ 223 sector /= sectors; \ 224 h = sector % heads; \ 225 sector /= heads; \ 226 c = sector & 0xff; \ 227 s |= (sector >> 2) & 0xc0; \ 228 } 229 230 231 static int32_t get_start_sect(const struct partition *p); 232 static int32_t get_nr_sects(const struct partition *p); 154 static unsigned get_start_sect(const struct partition *p); 155 static unsigned get_nr_sects(const struct partition *p); 233 156 234 157 /* … … 240 163 * partition and one link to the next one. 241 164 */ 242 st atic struct pte {165 struct pte { 243 166 struct partition *part_table; /* points into sectorbuffer */ 244 167 struct partition *ext_pointer; /* points into sectorbuffer */ 245 #ifdef CONFIG_FEATURE_FDISK_WRITABLE 168 ullong offset; /* disk sector number */ 169 char *sectorbuffer; /* disk sector contents */ 170 #if ENABLE_FEATURE_FDISK_WRITABLE 246 171 char changed; /* boolean */ 247 172 #endif 248 off_t offset; /* disk sector number */ 249 char *sectorbuffer; /* disk sector contents */ 250 } ptes[MAXIMUM_PARTS]; 251 252 253 #ifdef CONFIG_FEATURE_FDISK_WRITABLE 173 }; 174 175 /* DOS partition types */ 176 177 static const char *const i386_sys_types[] = { 178 "\x00" "Empty", 179 "\x01" "FAT12", 180 "\x04" "FAT16 <32M", 181 "\x05" "Extended", /* DOS 3.3+ extended partition */ 182 "\x06" "FAT16", /* DOS 16-bit >=32M */ 183 "\x07" "HPFS/NTFS", /* OS/2 IFS, eg, HPFS or NTFS or QNX */ 184 "\x0a" "OS/2 Boot Manager",/* OS/2 Boot Manager */ 185 "\x0b" "Win95 FAT32", 186 "\x0c" "Win95 FAT32 (LBA)",/* LBA really is 'Extended Int 13h' */ 187 "\x0e" "Win95 FAT16 (LBA)", 188 "\x0f" "Win95 Ext'd (LBA)", 189 "\x11" "Hidden FAT12", 190 "\x12" "Compaq diagnostics", 191 "\x14" "Hidden FAT16 <32M", 192 "\x16" "Hidden FAT16", 193 "\x17" "Hidden HPFS/NTFS", 194 "\x1b" "Hidden Win95 FAT32", 195 "\x1c" "Hidden W95 FAT32 (LBA)", 196 "\x1e" "Hidden W95 FAT16 (LBA)", 197 "\x3c" "Part.Magic recovery", 198 "\x41" "PPC PReP Boot", 199 "\x42" "SFS", 200 "\x63" "GNU HURD or SysV", /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */ 201 "\x80" "Old Minix", /* Minix 1.4a and earlier */ 202 "\x81" "Minix / old Linux",/* Minix 1.4b and later */ 203 "\x82" "Linux swap", /* also Solaris */ 204 "\x83" "Linux", 205 "\x84" "OS/2 hidden C: drive", 206 "\x85" "Linux extended", 207 "\x86" "NTFS volume set", 208 "\x87" "NTFS volume set", 209 "\x8e" "Linux LVM", 210 "\x9f" "BSD/OS", /* BSDI */ 211 "\xa0" "Thinkpad hibernation", 212 "\xa5" "FreeBSD", /* various BSD flavours */ 213 "\xa6" "OpenBSD", 214 "\xa8" "Darwin UFS", 215 "\xa9" "NetBSD", 216 "\xab" "Darwin boot", 217 "\xb7" "BSDI fs", 218 "\xb8" "BSDI swap", 219 "\xbe" "Solaris boot", 220 "\xeb" "BeOS fs", 221 "\xee" "EFI GPT", /* Intel EFI GUID Partition Table */ 222 "\xef" "EFI (FAT-12/16/32)", /* Intel EFI System Partition */ 223 "\xf0" "Linux/PA-RISC boot", /* Linux/PA-RISC boot loader */ 224 "\xf2" "DOS secondary", /* DOS 3.3+ secondary */ 225 "\xfd" "Linux raid autodetect", /* New (2.2.x) raid partition with 226 autodetect using persistent 227 superblock */ 228 #if 0 /* ENABLE_WEIRD_PARTITION_TYPES */ 229 "\x02" "XENIX root", 230 "\x03" "XENIX usr", 231 "\x08" "AIX", /* AIX boot (AIX -- PS/2 port) or SplitDrive */ 232 "\x09" "AIX bootable", /* AIX data or Coherent */ 233 "\x10" "OPUS", 234 "\x18" "AST SmartSleep", 235 "\x24" "NEC DOS", 236 "\x39" "Plan 9", 237 "\x40" "Venix 80286", 238 "\x4d" "QNX4.x", 239 "\x4e" "QNX4.x 2nd part", 240 "\x4f" "QNX4.x 3rd part", 241 "\x50" "OnTrack DM", 242 "\x51" "OnTrack DM6 Aux1", /* (or Novell) */ 243 "\x52" "CP/M", /* CP/M or Microport SysV/AT */ 244 "\x53" "OnTrack DM6 Aux3", 245 "\x54" "OnTrackDM6", 246 "\x55" "EZ-Drive", 247 "\x56" "Golden Bow", 248 "\x5c" "Priam Edisk", 249 "\x61" "SpeedStor", 250 "\x64" "Novell Netware 286", 251 "\x65" "Novell Netware 386", 252 "\x70" "DiskSecure Multi-Boot", 253 "\x75" "PC/IX", 254 "\x93" "Amoeba", 255 "\x94" "Amoeba BBT", /* (bad block table) */ 256 "\xa7" "NeXTSTEP", 257 "\xbb" "Boot Wizard hidden", 258 "\xc1" "DRDOS/sec (FAT-12)", 259 "\xc4" "DRDOS/sec (FAT-16 < 32M)", 260 "\xc6" "DRDOS/sec (FAT-16)", 261 "\xc7" "Syrinx", 262 "\xda" "Non-FS data", 263 "\xdb" "CP/M / CTOS / ...",/* CP/M or Concurrent CP/M or 264 Concurrent DOS or CTOS */ 265 "\xde" "Dell Utility", /* Dell PowerEdge Server utilities */ 266 "\xdf" "BootIt", /* BootIt EMBRM */ 267 "\xe1" "DOS access", /* DOS access or SpeedStor 12-bit FAT 268 extended partition */ 269 "\xe3" "DOS R/O", /* DOS R/O or SpeedStor */ 270 "\xe4" "SpeedStor", /* SpeedStor 16-bit FAT extended 271 partition < 1024 cyl. */ 272 "\xf1" "SpeedStor", 273 "\xf4" "SpeedStor", /* SpeedStor large partition */ 274 "\xfe" "LANstep", /* SpeedStor >1024 cyl. or LANstep */ 275 "\xff" "BBT", /* Xenix Bad Block Table */ 276 #endif 277 NULL 278 }; 279 280 281 /* Globals */ 282 283 struct globals { 284 char *line_ptr; 285 char line_buffer[80]; 286 char partname_buffer[80]; 287 jmp_buf listingbuf; 288 /* Raw disk label. For DOS-type partition tables the MBR, 289 * with descriptions of the primary partitions. */ 290 char MBRbuffer[MAX_SECTOR_SIZE]; 291 /* Partition tables */ 292 struct pte ptes[MAXIMUM_PARTS]; 293 }; 294 /* bb_common_bufsiz1 is too small for this on 64 bit CPUs */ 295 #define G (*ptr_to_globals) 296 297 #define line_ptr (G.line_ptr) 298 #define listingbuf (G.listingbuf) 299 #define line_buffer (G.line_buffer) 300 #define partname_buffer (G.partname_buffer) 301 #define MBRbuffer (G.MBRbuffer) 302 #define ptes (G.ptes) 303 304 305 /* Code */ 306 307 #define IS_EXTENDED(i) \ 308 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED) 309 310 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n)) 311 312 #define scround(x) (((x)+units_per_sector-1)/units_per_sector) 313 314 #define pt_offset(b, n) \ 315 ((struct partition *)((b) + 0x1be + (n) * sizeof(struct partition))) 316 317 #define sector(s) ((s) & 0x3f) 318 319 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2)) 320 321 #define hsc2sector(h,s,c) \ 322 (sector(s) - 1 + sectors * ((h) + heads * cylinder(s,c))) 323 324 #define set_hsc(h,s,c,sector) \ 325 do { \ 326 s = sector % sectors + 1; \ 327 sector /= sectors; \ 328 h = sector % heads; \ 329 sector /= heads; \ 330 c = sector & 0xff; \ 331 s |= (sector >> 2) & 0xc0; \ 332 } while (0) 333 334 #if ENABLE_FEATURE_FDISK_WRITABLE 335 /* read line; return 0 or first printable char */ 336 static int 337 read_line(const char *prompt) 338 { 339 int sz; 340 341 sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL); 342 if (sz <= 0) 343 exit(0); /* Ctrl-D or Ctrl-C */ 344 345 if (line_buffer[sz-1] == '\n') 346 line_buffer[--sz] = '\0'; 347 348 line_ptr = line_buffer; 349 while (*line_ptr && !isgraph(*line_ptr)) 350 line_ptr++; 351 return *line_ptr; 352 } 353 #endif 354 355 /* 356 * return partition name - uses static storage 357 */ 358 static const char * 359 partname(const char *dev, int pno, int lth) 360 { 361 const char *p; 362 int w, wp; 363 int bufsiz; 364 char *bufp; 365 366 bufp = partname_buffer; 367 bufsiz = sizeof(partname_buffer); 368 369 w = strlen(dev); 370 p = ""; 371 372 if (isdigit(dev[w-1])) 373 p = "p"; 374 375 /* devfs kludge - note: fdisk partition names are not supposed 376 to equal kernel names, so there is no reason to do this */ 377 if (strcmp(dev + w - 4, "disc") == 0) { 378 w -= 4; 379 p = "part"; 380 } 381 382 wp = strlen(p); 383 384 if (lth) { 385 snprintf(bufp, bufsiz, "%*.*s%s%-2u", 386 lth-wp-2, w, dev, p, pno); 387 } else { 388 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno); 389 } 390 return bufp; 391 } 392 393 #if ENABLE_FEATURE_FDISK_WRITABLE 254 394 static void 255 395 set_all_unchanged(void) … … 261 401 } 262 402 263 static void403 static ALWAYS_INLINE void 264 404 set_changed(int i) 265 405 { 266 406 ptes[i].changed = 1; 267 407 } 268 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */ 269 270 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL) 271 static struct partition * 408 #endif /* FEATURE_FDISK_WRITABLE */ 409 410 static ALWAYS_INLINE struct partition * 272 411 get_part_table(int i) 273 412 { 274 413 return ptes[i].part_table; 275 414 } 276 #endif277 415 278 416 static const char * … … 280 418 { /* n==1: use singular */ 281 419 if (n == 1) 282 return display_in_cyl_units ? _("cylinder") : _("sector"); 283 else 284 return display_in_cyl_units ? _("cylinders") : _("sectors"); 420 return display_in_cyl_units ? "cylinder" : "sector"; 421 return display_in_cyl_units ? "cylinders" : "sectors"; 285 422 } 286 423 287 424 static int 288 valid_part_table_flag(const char *mbuffer) { 289 const unsigned char *b = (const unsigned char *)mbuffer; 290 return (b[510] == 0x55 && b[511] == 0xaa); 291 } 292 293 #ifdef CONFIG_FEATURE_FDISK_WRITABLE 294 static char line_buffer[LINE_LENGTH]; 295 296 /* read line; return 0 or first char */ 425 valid_part_table_flag(const char *mbuffer) 426 { 427 return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa); 428 } 429 430 #if ENABLE_FEATURE_FDISK_WRITABLE 431 static ALWAYS_INLINE void 432 write_part_table_flag(char *b) 433 { 434 b[510] = 0x55; 435 b[511] = 0xaa; 436 } 437 438 static char 439 read_nonempty(const char *mesg) 440 { 441 while (!read_line(mesg)) /* repeat */; 442 return *line_ptr; 443 } 444 445 static char 446 read_maybe_empty(const char *mesg) 447 { 448 if (!read_line(mesg)) { 449 line_ptr = line_buffer; 450 line_ptr[0] = '\n'; 451 line_ptr[1] = '\0'; 452 } 453 return line_ptr[0]; 454 } 455 297 456 static int 298 read_line(void) 299 { 300 static int got_eof = 0; 301 302 fflush (stdout); /* requested by niles@scyld.com */ 303 line_ptr = line_buffer; 304 if (!fgets(line_buffer, LINE_LENGTH, stdin)) { 305 if (feof(stdin)) 306 got_eof++; /* user typed ^D ? */ 307 if (got_eof >= 3) { 308 fprintf(stderr, _("\ngot EOF thrice - exiting..\n")); 309 exit(1); 310 } 311 return 0; 312 } 313 while (*line_ptr && !isgraph(*line_ptr)) 314 line_ptr++; 315 return *line_ptr; 316 } 317 318 static char 319 read_char(const char *mesg) 320 { 321 do { 322 fputs(mesg, stdout); 323 } while (!read_line()); 324 return *line_ptr; 325 } 326 327 static char 328 read_chars(const char *mesg) 329 { 330 fputs(mesg, stdout); 331 if (!read_line()) { 332 *line_ptr = '\n'; 333 line_ptr[1] = 0; 334 } 335 return *line_ptr; 336 } 337 338 static int 339 read_hex(const struct systypes *sys) 340 { 341 int hex; 342 457 read_hex(const char *const *sys) 458 { 459 unsigned long v; 343 460 while (1) { 344 read_ char(_("Hex code (type L to list codes): "));345 if (*line_ptr == 'l' || *line_ptr == 'L') 461 read_nonempty("Hex code (type L to list codes): "); 462 if (*line_ptr == 'l' || *line_ptr == 'L') { 346 463 list_types(sys); 347 else if (isxdigit (*line_ptr)) { 348 hex = 0; 349 do 350 hex = hex << 4 | hex_val(*line_ptr++); 351 while (isxdigit(*line_ptr)); 352 return hex; 353 } 354 } 355 } 356 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */ 357 358 #ifdef CONFIG_FEATURE_AIX_LABEL 359 /* 360 * Copyright (C) Andreas Neuper, Sep 1998. 361 * This file may be redistributed under 362 * the terms of the GNU Public License. 363 */ 364 365 typedef struct { 366 unsigned int magic; /* expect AIX_LABEL_MAGIC */ 367 unsigned int fillbytes1[124]; 368 unsigned int physical_volume_id; 369 unsigned int fillbytes2[124]; 370 } aix_partition; 371 372 #define AIX_LABEL_MAGIC 0xc9c2d4c1 373 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9 374 #define AIX_INFO_MAGIC 0x00072959 375 #define AIX_INFO_MAGIC_SWAPPED 0x59290700 376 377 #define aixlabel ((aix_partition *)MBRbuffer) 378 379 380 /* 381 Changes: 382 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br> 383 * Internationalization 384 * 385 * 2003-03-20 Phillip Kesling <pkesling@sgi.com> 386 * Some fixes 387 */ 388 389 static int aix_other_endian; 390 static short aix_volumes = 1; 391 392 /* 393 * only dealing with free blocks here 394 */ 395 396 static void 397 aix_info(void) 398 { 399 puts( 400 _("\n\tThere is a valid AIX label on this disk.\n" 401 "\tUnfortunately Linux cannot handle these\n" 402 "\tdisks at the moment. Nevertheless some\n" 403 "\tadvice:\n" 404 "\t1. fdisk will destroy its contents on write.\n" 405 "\t2. Be sure that this disk is NOT a still vital\n" 406 "\t part of a volume group. (Otherwise you may\n" 407 "\t erase the other disks as well, if unmirrored.)\n" 408 "\t3. Before deleting this physical volume be sure\n" 409 "\t to remove the disk logically from your AIX\n" 410 "\t machine. (Otherwise you become an AIXpert).") 411 ); 412 } 413 414 static int 415 check_aix_label(void) 416 { 417 if (aixlabel->magic != AIX_LABEL_MAGIC && 418 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) { 419 current_label_type = 0; 420 aix_other_endian = 0; 421 return 0; 422 } 423 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED); 424 update_units(); 425 current_label_type = label_aix; 426 partitions = 1016; 427 aix_volumes = 15; 428 aix_info(); 429 /*aix_nolabel();*/ /* %% */ 430 /*aix_label = 1;*/ /* %% */ 431 return 1; 432 } 433 #endif /* AIX_LABEL */ 434 435 #ifdef CONFIG_FEATURE_OSF_LABEL 436 /* 437 * Copyright (c) 1987, 1988 Regents of the University of California. 438 * All rights reserved. 439 * 440 * Redistribution and use in source and binary forms, with or without 441 * modification, are permitted provided that the following conditions 442 * are met: 443 * 1. Redistributions of source code must retain the above copyright 444 * notice, this list of conditions and the following disclaimer. 445 * 2. Redistributions in binary form must reproduce the above copyright 446 * notice, this list of conditions and the following disclaimer in the 447 * documentation and/or other materials provided with the distribution. 448 * 3. All advertising materials mentioning features or use of this software 449 * must display the following acknowledgment: 450 * This product includes software developed by the University of 451 * California, Berkeley and its contributors. 452 * 4. Neither the name of the University nor the names of its contributors 453 * may be used to endorse or promote products derived from this software 454 * without specific prior written permission. 455 * 456 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 457 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 458 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 459 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 460 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 461 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 462 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 463 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 464 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 465 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 466 * SUCH DAMAGE. 467 */ 468 469 470 #ifndef BSD_DISKMAGIC 471 #define BSD_DISKMAGIC ((uint32_t) 0x82564557) 472 #endif 473 474 #ifndef BSD_MAXPARTITIONS 475 #define BSD_MAXPARTITIONS 16 476 #endif 477 478 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec" 479 480 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__m68k__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__) 481 #define BSD_LABELSECTOR 1 482 #define BSD_LABELOFFSET 0 483 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__) 484 #define BSD_LABELSECTOR 0 485 #define BSD_LABELOFFSET 64 486 #elif defined (__s390__) || defined (__s390x__) 487 #define BSD_LABELSECTOR 1 488 #define BSD_LABELOFFSET 0 489 #else 490 #error unknown architecture 491 #endif 492 493 #define BSD_BBSIZE 8192 /* size of boot area, with label */ 494 #define BSD_SBSIZE 8192 /* max size of fs superblock */ 495 496 struct xbsd_disklabel { 497 uint32_t d_magic; /* the magic number */ 498 int16_t d_type; /* drive type */ 499 int16_t d_subtype; /* controller/d_type specific */ 500 char d_typename[16]; /* type name, e.g. "eagle" */ 501 char d_packname[16]; /* pack identifier */ 502 /* disk geometry: */ 503 uint32_t d_secsize; /* # of bytes per sector */ 504 uint32_t d_nsectors; /* # of data sectors per track */ 505 uint32_t d_ntracks; /* # of tracks per cylinder */ 506 uint32_t d_ncylinders; /* # of data cylinders per unit */ 507 uint32_t d_secpercyl; /* # of data sectors per cylinder */ 508 uint32_t d_secperunit; /* # of data sectors per unit */ 509 /* 510 * Spares (bad sector replacements) below 511 * are not counted in d_nsectors or d_secpercyl. 512 * Spare sectors are assumed to be physical sectors 513 * which occupy space at the end of each track and/or cylinder. 514 */ 515 uint16_t d_sparespertrack; /* # of spare sectors per track */ 516 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */ 517 /* 518 * Alternate cylinders include maintenance, replacement, 519 * configuration description areas, etc. 520 */ 521 uint32_t d_acylinders; /* # of alt. cylinders per unit */ 522 523 /* hardware characteristics: */ 524 /* 525 * d_interleave, d_trackskew and d_cylskew describe perturbations 526 * in the media format used to compensate for a slow controller. 527 * Interleave is physical sector interleave, set up by the formatter 528 * or controller when formatting. When interleaving is in use, 529 * logically adjacent sectors are not physically contiguous, 530 * but instead are separated by some number of sectors. 531 * It is specified as the ratio of physical sectors traversed 532 * per logical sector. Thus an interleave of 1:1 implies contiguous 533 * layout, while 2:1 implies that logical sector 0 is separated 534 * by one sector from logical sector 1. 535 * d_trackskew is the offset of sector 0 on track N 536 * relative to sector 0 on track N-1 on the same cylinder. 537 * Finally, d_cylskew is the offset of sector 0 on cylinder N 538 * relative to sector 0 on cylinder N-1. 539 */ 540 uint16_t d_rpm; /* rotational speed */ 541 uint16_t d_interleave; /* hardware sector interleave */ 542 uint16_t d_trackskew; /* sector 0 skew, per track */ 543 uint16_t d_cylskew; /* sector 0 skew, per cylinder */ 544 uint32_t d_headswitch; /* head switch time, usec */ 545 uint32_t d_trkseek; /* track-to-track seek, usec */ 546 uint32_t d_flags; /* generic flags */ 547 #define NDDATA 5 548 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */ 549 #define NSPARE 5 550 uint32_t d_spare[NSPARE]; /* reserved for future use */ 551 uint32_t d_magic2; /* the magic number (again) */ 552 uint16_t d_checksum; /* xor of data incl. partitions */ 553 /* filesystem and partition information: */ 554 uint16_t d_npartitions; /* number of partitions in following */ 555 uint32_t d_bbsize; /* size of boot area at sn0, bytes */ 556 uint32_t d_sbsize; /* max size of fs superblock, bytes */ 557 struct xbsd_partition { /* the partition table */ 558 uint32_t p_size; /* number of sectors in partition */ 559 uint32_t p_offset; /* starting sector */ 560 uint32_t p_fsize; /* filesystem basic fragment size */ 561 uint8_t p_fstype; /* filesystem type, see below */ 562 uint8_t p_frag; /* filesystem fragments per block */ 563 uint16_t p_cpg; /* filesystem cylinders per group */ 564 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */ 565 }; 566 567 /* d_type values: */ 568 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */ 569 #define BSD_DTYPE_MSCP 2 /* MSCP */ 570 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */ 571 #define BSD_DTYPE_SCSI 4 /* SCSI */ 572 #define BSD_DTYPE_ESDI 5 /* ESDI interface */ 573 #define BSD_DTYPE_ST506 6 /* ST506 etc. */ 574 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */ 575 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */ 576 #define BSD_DTYPE_FLOPPY 10 /* floppy */ 577 578 /* d_subtype values: */ 579 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */ 580 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */ 581 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */ 582 583 #ifdef DKTYPENAMES 584 static const char * const xbsd_dktypenames[] = { 585 "unknown", 586 "SMD", 587 "MSCP", 588 "old DEC", 589 "SCSI", 590 "ESDI", 591 "ST506", 592 "HP-IB", 593 "HP-FL", 594 "type 9", 595 "floppy", 596 0 597 }; 598 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1) 599 #endif 600 601 /* 602 * Filesystem type and version. 603 * Used to interpret other filesystem-specific 604 * per-partition information. 605 */ 606 #define BSD_FS_UNUSED 0 /* unused */ 607 #define BSD_FS_SWAP 1 /* swap */ 608 #define BSD_FS_V6 2 /* Sixth Edition */ 609 #define BSD_FS_V7 3 /* Seventh Edition */ 610 #define BSD_FS_SYSV 4 /* System V */ 611 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */ 612 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */ 613 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */ 614 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */ 615 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */ 616 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */ 617 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */ 618 #define BSD_FS_ISOFS BSD_FS_ISO9660 619 #define BSD_FS_BOOT 13 /* partition contains bootstrap */ 620 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */ 621 #define BSD_FS_HFS 15 /* Macintosh HFS */ 622 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */ 623 624 /* this is annoying, but it's also the way it is :-( */ 625 #ifdef __alpha__ 626 #define BSD_FS_EXT2 8 /* ext2 file system */ 627 #else 628 #define BSD_FS_MSDOS 8 /* MS-DOS file system */ 629 #endif 630 631 #ifdef DKTYPENAMES 632 static const struct systypes xbsd_fstypes[] = { 633 { "\x00" "unused" }, /* BSD_FS_UNUSED */ 634 { "\x01" "swap" }, /* BSD_FS_SWAP */ 635 { "\x02" "Version 6" }, /* BSD_FS_V6 */ 636 { "\x03" "Version 7" }, /* BSD_FS_V7 */ 637 { "\x04" "System V" }, /* BSD_FS_SYSV */ 638 { "\x05" "4.1BSD" }, /* BSD_FS_V71K */ 639 { "\x06" "Eighth Edition" }, /* BSD_FS_V8 */ 640 { "\x07" "4.2BSD" }, /* BSD_FS_BSDFFS */ 641 #ifdef __alpha__ 642 { "\x08" "ext2" }, /* BSD_FS_EXT2 */ 643 #else 644 { "\x08" "MS-DOS" }, /* BSD_FS_MSDOS */ 645 #endif 646 { "\x09" "4.4LFS" }, /* BSD_FS_BSDLFS */ 647 { "\x0a" "unknown" }, /* BSD_FS_OTHER */ 648 { "\x0b" "HPFS" }, /* BSD_FS_HPFS */ 649 { "\x0c" "ISO-9660" }, /* BSD_FS_ISO9660 */ 650 { "\x0d" "boot" }, /* BSD_FS_BOOT */ 651 { "\x0e" "ADOS" }, /* BSD_FS_ADOS */ 652 { "\x0f" "HFS" }, /* BSD_FS_HFS */ 653 { "\x10" "AdvFS" }, /* BSD_FS_ADVFS */ 654 { NULL } 655 }; 656 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1) 657 658 #endif 659 660 /* 661 * flags shared by various drives: 662 */ 663 #define BSD_D_REMOVABLE 0x01 /* removable media */ 664 #define BSD_D_ECC 0x02 /* supports ECC */ 665 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */ 666 #define BSD_D_RAMDISK 0x08 /* disk emulator */ 667 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */ 668 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */ 669 670 #endif /* OSF_LABEL */ 671 672 /* 673 * Copyright (C) Andreas Neuper, Sep 1998. 674 * This file may be modified and redistributed under 675 * the terms of the GNU Public License. 676 */ 677 678 struct device_parameter { /* 48 bytes */ 679 unsigned char skew; 680 unsigned char gap1; 681 unsigned char gap2; 682 unsigned char sparecyl; 683 unsigned short pcylcount; 684 unsigned short head_vol0; 685 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */ 686 unsigned char cmd_tag_queue_depth; 687 unsigned char unused0; 688 unsigned short unused1; 689 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */ 690 unsigned short bytes; 691 unsigned short ilfact; 692 unsigned int flags; /* controller flags */ 693 unsigned int datarate; 694 unsigned int retries_on_error; 695 unsigned int ms_per_word; 696 unsigned short xylogics_gap1; 697 unsigned short xylogics_syncdelay; 698 unsigned short xylogics_readdelay; 699 unsigned short xylogics_gap2; 700 unsigned short xylogics_readgate; 701 unsigned short xylogics_writecont; 702 }; 703 704 #define SGI_VOLHDR 0x00 705 /* 1 and 2 were used for drive types no longer supported by SGI */ 706 #define SGI_SWAP 0x03 707 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */ 708 #define SGI_VOLUME 0x06 709 #define SGI_EFS 0x07 710 #define SGI_LVOL 0x08 711 #define SGI_RLVOL 0x09 712 #define SGI_XFS 0x0a 713 #define SGI_XFSLOG 0x0b 714 #define SGI_XLV 0x0c 715 #define SGI_XVM 0x0d 716 #define ENTIRE_DISK SGI_VOLUME 717 /* 718 * controller flags 719 */ 720 #define SECTOR_SLIP 0x01 721 #define SECTOR_FWD 0x02 722 #define TRACK_FWD 0x04 723 #define TRACK_MULTIVOL 0x08 724 #define IGNORE_ERRORS 0x10 725 #define RESEEK 0x20 726 #define ENABLE_CMDTAGQ 0x40 727 728 typedef struct { 729 unsigned int magic; /* expect SGI_LABEL_MAGIC */ 730 unsigned short boot_part; /* active boot partition */ 731 unsigned short swap_part; /* active swap partition */ 732 unsigned char boot_file[16]; /* name of the bootfile */ 733 struct device_parameter devparam; /* 1 * 48 bytes */ 734 struct volume_directory { /* 15 * 16 bytes */ 735 unsigned char vol_file_name[8]; /* a character array */ 736 unsigned int vol_file_start; /* number of logical block */ 737 unsigned int vol_file_size; /* number of bytes */ 738 } directory[15]; 739 struct sgi_partition { /* 16 * 12 bytes */ 740 unsigned int num_sectors; /* number of blocks */ 741 unsigned int start_sector; /* must be cylinder aligned */ 742 unsigned int id; 743 } partitions[16]; 744 unsigned int csum; 745 unsigned int fillbytes; 746 } sgi_partition; 747 748 typedef struct { 749 unsigned int magic; /* looks like a magic number */ 750 unsigned int a2; 751 unsigned int a3; 752 unsigned int a4; 753 unsigned int b1; 754 unsigned short b2; 755 unsigned short b3; 756 unsigned int c[16]; 757 unsigned short d[3]; 758 unsigned char scsi_string[50]; 759 unsigned char serial[137]; 760 unsigned short check1816; 761 unsigned char installer[225]; 762 } sgiinfo; 763 764 #define SGI_LABEL_MAGIC 0x0be5a941 765 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b 766 #define SGI_INFO_MAGIC 0x00072959 767 #define SGI_INFO_MAGIC_SWAPPED 0x59290700 768 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \ 769 : (uint16_t)(x)) 770 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \ 771 : (uint32_t)(x)) 772 773 #define sgilabel ((sgi_partition *)MBRbuffer) 774 #define sgiparam (sgilabel->devparam) 464 continue; 465 } 466 v = bb_strtoul(line_ptr, NULL, 16); 467 if (v > 0xff) 468 /* Bad input also triggers this */ 469 continue; 470 return v; 471 } 472 } 473 #endif /* FEATURE_FDISK_WRITABLE */ 474 475 #include "fdisk_aix.c" 775 476 776 477 typedef struct { … … 794 495 unsigned short nsect; /* Sectors per track */ 795 496 unsigned char spare3[4]; /* Even more magic... */ 796 struct sun_parti tion{497 struct sun_partinfo { 797 498 uint32_t start_cylinder; 798 499 uint32_t num_sectors; … … 801 502 unsigned short csum; /* Label xor'd checksum */ 802 503 } sun_partition; 803 804 805 #define SUN_LABEL_MAGIC 0xDABE806 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA807 504 #define sunlabel ((sun_partition *)MBRbuffer) 808 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \ 809 : (uint16_t)(x)) 810 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \ 811 : (uint32_t)(x)) 812 813 814 #ifdef CONFIG_FEATURE_OSF_LABEL 815 /* 816 Changes: 817 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls 818 819 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better 820 support for OSF/1 disklabels on Alpha. 821 Also fixed unaligned accesses in alpha_bootblock_checksum() 822 */ 823 824 #define FREEBSD_PARTITION 0xa5 825 #define NETBSD_PARTITION 0xa9 826 827 static void xbsd_delete_part(void); 828 static void xbsd_new_part(void); 829 static void xbsd_write_disklabel(void); 830 static int xbsd_create_disklabel(void); 831 static void xbsd_edit_disklabel(void); 832 static void xbsd_write_bootstrap(void); 833 static void xbsd_change_fstype(void); 834 static int xbsd_get_part_index(int max); 835 static int xbsd_check_new_partition(int *i); 836 static void xbsd_list_types(void); 837 static u_short xbsd_dkcksum(struct xbsd_disklabel *lp); 838 static int xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d); 839 static int xbsd_readlabel(struct partition *p, struct xbsd_disklabel *d); 840 static int xbsd_writelabel(struct partition *p, struct xbsd_disklabel *d); 841 842 #if defined (__alpha__) 843 static void alpha_bootblock_checksum(char *boot); 844 #endif 845 846 #if !defined (__alpha__) 847 static int xbsd_translate_fstype(int linux_type); 848 static void xbsd_link_part(void); 849 static struct partition *xbsd_part; 850 static int xbsd_part_index; 851 #endif 852 853 #if defined (__alpha__) 854 /* We access this through a uint64_t * when checksumming */ 855 static char disklabelbuffer[BSD_BBSIZE] ATTRIBUTE_ALIGNED(8); 856 #else 857 static char disklabelbuffer[BSD_BBSIZE]; 858 #endif 859 860 static struct xbsd_disklabel xbsd_dlabel; 861 862 #define bsd_cround(n) \ 863 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n)) 864 865 /* 866 * Test whether the whole disk has BSD disk label magic. 867 * 868 * Note: often reformatting with DOS-type label leaves the BSD magic, 869 * so this does not mean that there is a BSD disk label. 870 */ 871 static int 872 check_osf_label(void) 873 { 874 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0) 875 return 0; 876 return 1; 877 } 878 879 static void xbsd_print_disklabel(int); 880 881 static int 882 btrydev(const char * dev) 883 { 884 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0) 885 return -1; 886 printf(_("\nBSD label for device: %s\n"), dev); 887 xbsd_print_disklabel (0); 888 return 0; 889 } 890 891 static void 892 bmenu(void) 893 { 894 puts (_("Command action")); 895 puts (_("\td\tdelete a BSD partition")); 896 puts (_("\te\tedit drive data")); 897 puts (_("\ti\tinstall bootstrap")); 898 puts (_("\tl\tlist known filesystem types")); 899 puts (_("\tm\tprint this menu")); 900 puts (_("\tn\tadd a new BSD partition")); 901 puts (_("\tp\tprint BSD partition table")); 902 puts (_("\tq\tquit without saving changes")); 903 puts (_("\tr\treturn to main menu")); 904 puts (_("\ts\tshow complete disklabel")); 905 puts (_("\tt\tchange a partition's filesystem id")); 906 puts (_("\tu\tchange units (cylinders/sectors)")); 907 puts (_("\tw\twrite disklabel to disk")); 908 #if !defined (__alpha__) 909 puts (_("\tx\tlink BSD partition to non-BSD partition")); 910 #endif 911 } 912 913 #if !defined (__alpha__) 914 static int 915 hidden(int type) 916 { 917 return type ^ 0x10; 918 } 919 920 static int 921 is_bsd_partition_type(int type) 922 { 923 return (type == FREEBSD_PARTITION || 924 type == hidden(FREEBSD_PARTITION) || 925 type == NETBSD_PARTITION || 926 type == hidden(NETBSD_PARTITION)); 927 } 928 #endif 929 930 static void 931 bselect(void) 932 { 933 #if !defined (__alpha__) 934 int t, ss; 935 struct partition *p; 936 937 for (t = 0; t < 4; t++) { 938 p = get_part_table(t); 939 if (p && is_bsd_partition_type(p->sys_ind)) { 940 xbsd_part = p; 941 xbsd_part_index = t; 942 ss = get_start_sect(xbsd_part); 943 if (ss == 0) { 944 fprintf(stderr, _("Partition %s has invalid starting sector 0.\n"), 945 partname(disk_device, t+1, 0)); 946 return; 947 } 948 printf(_("Reading disklabel of %s at sector %d.\n"), 949 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR); 950 if (xbsd_readlabel(xbsd_part, &xbsd_dlabel) == 0) 951 if (xbsd_create_disklabel() == 0) 952 return; 953 break; 954 } 955 } 956 957 if (t == 4) { 958 printf(_("There is no *BSD partition on %s.\n"), disk_device); 959 return; 960 } 961 962 #elif defined (__alpha__) 963 964 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0) 965 if (xbsd_create_disklabel() == 0) 966 exit (EXIT_SUCCESS); 967 968 #endif 969 970 while (1) { 971 putchar('\n'); 972 switch (tolower(read_char(_("BSD disklabel command (m for help): ")))) { 973 case 'd': 974 xbsd_delete_part(); 975 break; 976 case 'e': 977 xbsd_edit_disklabel(); 978 break; 979 case 'i': 980 xbsd_write_bootstrap(); 981 break; 982 case 'l': 983 xbsd_list_types(); 984 break; 985 case 'n': 986 xbsd_new_part(); 987 break; 988 case 'p': 989 xbsd_print_disklabel(0); 990 break; 991 case 'q': 992 close(fd); 993 exit(EXIT_SUCCESS); 994 case 'r': 995 return; 996 case 's': 997 xbsd_print_disklabel(1); 998 break; 999 case 't': 1000 xbsd_change_fstype(); 1001 break; 1002 case 'u': 1003 change_units(); 1004 break; 1005 case 'w': 1006 xbsd_write_disklabel(); 1007 break; 1008 #if !defined (__alpha__) 1009 case 'x': 1010 xbsd_link_part(); 1011 break; 1012 #endif 1013 default: 1014 bmenu(); 1015 break; 1016 } 1017 } 1018 } 1019 1020 static void 1021 xbsd_delete_part(void) 1022 { 1023 int i; 1024 1025 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions); 1026 xbsd_dlabel.d_partitions[i].p_size = 0; 1027 xbsd_dlabel.d_partitions[i].p_offset = 0; 1028 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED; 1029 if (xbsd_dlabel.d_npartitions == i + 1) 1030 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0) 1031 xbsd_dlabel.d_npartitions--; 1032 } 1033 1034 static void 1035 xbsd_new_part(void) 1036 { 1037 off_t begin, end; 1038 char mesg[256]; 1039 int i; 1040 1041 if (!xbsd_check_new_partition(&i)) 1042 return; 1043 1044 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__) 1045 begin = get_start_sect(xbsd_part); 1046 end = begin + get_nr_sects(xbsd_part) - 1; 1047 #else 1048 begin = 0; 1049 end = xbsd_dlabel.d_secperunit - 1; 1050 #endif 1051 1052 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR)); 1053 begin = read_int(bsd_cround(begin), bsd_cround(begin), bsd_cround(end), 1054 0, mesg); 1055 1056 if (display_in_cyl_units) 1057 begin = (begin - 1) * xbsd_dlabel.d_secpercyl; 1058 1059 snprintf(mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"), 1060 str_units(SINGULAR)); 1061 end = read_int(bsd_cround (begin), bsd_cround (end), bsd_cround (end), 1062 bsd_cround (begin), mesg); 1063 1064 if (display_in_cyl_units) 1065 end = end * xbsd_dlabel.d_secpercyl - 1; 1066 1067 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1; 1068 xbsd_dlabel.d_partitions[i].p_offset = begin; 1069 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED; 1070 } 1071 1072 static void 1073 xbsd_print_disklabel(int show_all) 1074 { 1075 struct xbsd_disklabel *lp = &xbsd_dlabel; 1076 struct xbsd_partition *pp; 1077 int i, j; 1078 1079 if (show_all) { 1080 #if defined (__alpha__) 1081 printf("# %s:\n", disk_device); 1082 #else 1083 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0)); 1084 #endif 1085 if ((unsigned) lp->d_type < BSD_DKMAXTYPES) 1086 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]); 1087 else 1088 printf(_("type: %d\n"), lp->d_type); 1089 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename); 1090 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname); 1091 printf(_("flags:")); 1092 if (lp->d_flags & BSD_D_REMOVABLE) 1093 printf(_(" removable")); 1094 if (lp->d_flags & BSD_D_ECC) 1095 printf(_(" ecc")); 1096 if (lp->d_flags & BSD_D_BADSECT) 1097 printf(_(" badsect")); 1098 printf("\n"); 1099 /* On various machines the fields of *lp are short/int/long */ 1100 /* In order to avoid problems, we cast them all to long. */ 1101 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize); 1102 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors); 1103 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks); 1104 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl); 1105 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders); 1106 printf(_("rpm: %d\n"), lp->d_rpm); 1107 printf(_("interleave: %d\n"), lp->d_interleave); 1108 printf(_("trackskew: %d\n"), lp->d_trackskew); 1109 printf(_("cylinderskew: %d\n"), lp->d_cylskew); 1110 printf(_("headswitch: %ld\t\t# milliseconds\n"), 1111 (long) lp->d_headswitch); 1112 printf(_("track-to-track seek: %ld\t# milliseconds\n"), 1113 (long) lp->d_trkseek); 1114 printf(_("drivedata: ")); 1115 for (i = NDDATA - 1; i >= 0; i--) 1116 if (lp->d_drivedata[i]) 1117 break; 1118 if (i < 0) 1119 i = 0; 1120 for (j = 0; j <= i; j++) 1121 printf("%ld ", (long) lp->d_drivedata[j]); 1122 } 1123 printf(_("\n%d partitions:\n"), lp->d_npartitions); 1124 printf(_("# start end size fstype [fsize bsize cpg]\n")); 1125 pp = lp->d_partitions; 1126 for (i = 0; i < lp->d_npartitions; i++, pp++) { 1127 if (pp->p_size) { 1128 if (display_in_cyl_units && lp->d_secpercyl) { 1129 printf(" %c: %8ld%c %8ld%c %8ld%c ", 1130 'a' + i, 1131 (long) pp->p_offset / lp->d_secpercyl + 1, 1132 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ', 1133 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl, 1134 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ', 1135 (long) pp->p_size / lp->d_secpercyl, 1136 (pp->p_size % lp->d_secpercyl) ? '*' : ' ' 1137 ); 1138 } else { 1139 printf(" %c: %8ld %8ld %8ld ", 1140 'a' + i, 1141 (long) pp->p_offset, 1142 (long) pp->p_offset + pp->p_size - 1, 1143 (long) pp->p_size 1144 ); 1145 } 1146 1147 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES) 1148 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name); 1149 else 1150 printf("%8x", pp->p_fstype); 1151 1152 switch (pp->p_fstype) { 1153 case BSD_FS_UNUSED: 1154 printf(" %5ld %5ld %5.5s ", 1155 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, ""); 1156 break; 1157 case BSD_FS_BSDFFS: 1158 printf(" %5ld %5ld %5d ", 1159 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, pp->p_cpg); 1160 break; 1161 default: 1162 printf("%22.22s", ""); 1163 break; 1164 } 1165 printf("\n"); 1166 } 1167 } 1168 } 1169 1170 static void 1171 xbsd_write_disklabel(void) 1172 { 1173 #if defined (__alpha__) 1174 printf(_("Writing disklabel to %s.\n"), disk_device); 1175 xbsd_writelabel(NULL, &xbsd_dlabel); 1176 #else 1177 printf(_("Writing disklabel to %s.\n"), 1178 partname(disk_device, xbsd_part_index + 1, 0)); 1179 xbsd_writelabel(xbsd_part, &xbsd_dlabel); 1180 #endif 1181 reread_partition_table(0); /* no exit yet */ 1182 } 1183 1184 static int 1185 xbsd_create_disklabel(void) 1186 { 1187 char c; 1188 1189 #if defined (__alpha__) 1190 fprintf(stderr, _("%s contains no disklabel.\n"), disk_device); 1191 #else 1192 fprintf(stderr, _("%s contains no disklabel.\n"), 1193 partname(disk_device, xbsd_part_index + 1, 0)); 1194 #endif 1195 1196 while (1) { 1197 c = read_char(_("Do you want to create a disklabel? (y/n) ")); 1198 if (c == 'y' || c == 'Y') { 1199 if (xbsd_initlabel( 1200 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \ 1201 defined (__s390__) || defined (__s390x__) 1202 NULL, &xbsd_dlabel 1203 #else 1204 xbsd_part, &xbsd_dlabel/* not used, xbsd_part_index*/ 1205 #endif 1206 ) == 1) { 1207 xbsd_print_disklabel (1); 1208 return 1; 1209 } else 1210 return 0; 1211 } else if (c == 'n') 1212 return 0; 1213 } 1214 } 1215 1216 static int 1217 edit_int(int def, char *mesg) 1218 { 1219 do { 1220 fputs(mesg, stdout); 1221 printf(" (%d): ", def); 1222 if (!read_line()) 1223 return def; 1224 } 1225 while (!isdigit(*line_ptr)); /* FIXME: ?!! */ 1226 return atoi(line_ptr); 1227 } 1228 1229 static void 1230 xbsd_edit_disklabel(void) 1231 { 1232 struct xbsd_disklabel *d; 1233 1234 d = &xbsd_dlabel; 1235 1236 #if defined (__alpha__) || defined (__ia64__) 1237 d->d_secsize = (u_long) edit_int((u_long) d->d_secsize ,_("bytes/sector")); 1238 d->d_nsectors = (u_long) edit_int((u_long) d->d_nsectors ,_("sectors/track")); 1239 d->d_ntracks = (u_long) edit_int((u_long) d->d_ntracks ,_("tracks/cylinder")); 1240 d->d_ncylinders = (u_long) edit_int((u_long) d->d_ncylinders ,_("cylinders")); 1241 #endif 1242 1243 /* d->d_secpercyl can be != d->d_nsectors * d->d_ntracks */ 1244 while (1) { 1245 d->d_secpercyl = (u_long) edit_int((u_long) d->d_nsectors * d->d_ntracks, 1246 _("sectors/cylinder")); 1247 if (d->d_secpercyl <= d->d_nsectors * d->d_ntracks) 1248 break; 1249 1250 printf(_("Must be <= sectors/track * tracks/cylinder (default).\n")); 1251 } 1252 d->d_rpm = (u_short) edit_int((u_short) d->d_rpm ,_("rpm")); 1253 d->d_interleave = (u_short) edit_int((u_short) d->d_interleave,_("interleave")); 1254 d->d_trackskew = (u_short) edit_int((u_short) d->d_trackskew ,_("trackskew")); 1255 d->d_cylskew = (u_short) edit_int((u_short) d->d_cylskew ,_("cylinderskew")); 1256 d->d_headswitch = (u_long) edit_int((u_long) d->d_headswitch ,_("headswitch")); 1257 d->d_trkseek = (u_long) edit_int((u_long) d->d_trkseek ,_("track-to-track seek")); 1258 1259 d->d_secperunit = d->d_secpercyl * d->d_ncylinders; 1260 } 1261 1262 static int 1263 xbsd_get_bootstrap (char *path, void *ptr, int size) 1264 { 1265 int fdb; 1266 1267 if ((fdb = open (path, O_RDONLY)) < 0) { 1268 perror(path); 1269 return 0; 1270 } 1271 if (read(fdb, ptr, size) < 0) { 1272 perror(path); 1273 close(fdb); 1274 return 0; 1275 } 1276 printf(" ... %s\n", path); 1277 close(fdb); 1278 return 1; 1279 } 1280 1281 static void 1282 sync_disks(void) 1283 { 1284 printf(_("\nSyncing disks.\n")); 1285 sync(); 1286 sleep(4); /* What? */ 1287 } 1288 1289 static void 1290 xbsd_write_bootstrap(void) 1291 { 1292 char *bootdir = BSD_LINUX_BOOTDIR; 1293 char path[MAXPATHLEN]; 1294 char *dkbasename; 1295 struct xbsd_disklabel dl; 1296 char *d, *p, *e; 1297 int sector; 1298 1299 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI) 1300 dkbasename = "sd"; 1301 else 1302 dkbasename = "wd"; 1303 1304 printf(_("Bootstrap: %sboot -> boot%s (%s): "), 1305 dkbasename, dkbasename, dkbasename); 1306 if (read_line()) { 1307 line_ptr[strlen(line_ptr)-1] = '\0'; 1308 dkbasename = line_ptr; 1309 } 1310 snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename); 1311 if (!xbsd_get_bootstrap(path, disklabelbuffer, (int) xbsd_dlabel.d_secsize)) 1312 return; 1313 1314 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */ 1315 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE]; 1316 memmove(&dl, d, sizeof(struct xbsd_disklabel)); 1317 1318 /* The disklabel will be overwritten by 0's from bootxx anyway */ 1319 memset(d, 0, sizeof(struct xbsd_disklabel)); 1320 1321 snprintf(path, sizeof(path), "%s/boot%s", bootdir, dkbasename); 1322 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize], 1323 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize)) 1324 return; 1325 1326 e = d + sizeof(struct xbsd_disklabel); 1327 for (p = d; p < e; p++) 1328 if (*p) { 1329 fprintf(stderr, _("Bootstrap overlaps with disk label!\n")); 1330 exit(EXIT_FAILURE); 1331 } 1332 1333 memmove(d, &dl, sizeof(struct xbsd_disklabel)); 1334 1335 #if defined (__powerpc__) || defined (__hppa__) 1336 sector = 0; 1337 #elif defined (__alpha__) 1338 sector = 0; 1339 alpha_bootblock_checksum(disklabelbuffer); 1340 #else 1341 sector = get_start_sect(xbsd_part); 1342 #endif 1343 1344 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1) 1345 fdisk_fatal(unable_to_seek); 1346 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE)) 1347 fdisk_fatal(unable_to_write); 1348 1349 #if defined (__alpha__) 1350 printf(_("Bootstrap installed on %s.\n"), disk_device); 1351 #else 1352 printf(_("Bootstrap installed on %s.\n"), 1353 partname (disk_device, xbsd_part_index+1, 0)); 1354 #endif 1355 1356 sync_disks(); 1357 } 1358 1359 static void 1360 xbsd_change_fstype(void) 1361 { 1362 int i; 1363 1364 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions); 1365 xbsd_dlabel.d_partitions[i].p_fstype = read_hex(xbsd_fstypes); 1366 } 1367 1368 static int 1369 xbsd_get_part_index(int max) 1370 { 1371 char prompt[256]; 1372 char l; 1373 1374 snprintf(prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1); 1375 do 1376 l = tolower(read_char(prompt)); 1377 while (l < 'a' || l > 'a' + max - 1); 1378 return l - 'a'; 1379 } 1380 1381 static int 1382 xbsd_check_new_partition(int *i) 1383 { 1384 /* room for more? various BSD flavours have different maxima */ 1385 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) { 1386 int t; 1387 1388 for (t = 0; t < BSD_MAXPARTITIONS; t++) 1389 if (xbsd_dlabel.d_partitions[t].p_size == 0) 1390 break; 1391 1392 if (t == BSD_MAXPARTITIONS) { 1393 fprintf(stderr, _("The maximum number of partitions " 1394 "has been created\n")); 1395 return 0; 1396 } 1397 } 1398 1399 *i = xbsd_get_part_index (BSD_MAXPARTITIONS); 1400 1401 if (*i >= xbsd_dlabel.d_npartitions) 1402 xbsd_dlabel.d_npartitions = (*i) + 1; 1403 1404 if (xbsd_dlabel.d_partitions[*i].p_size != 0) { 1405 fprintf(stderr, _("This partition already exists.\n")); 1406 return 0; 1407 } 1408 1409 return 1; 1410 } 1411 1412 static void 1413 xbsd_list_types(void) 1414 { 1415 list_types(xbsd_fstypes); 1416 } 1417 1418 static u_short 1419 xbsd_dkcksum(struct xbsd_disklabel *lp) 1420 { 1421 u_short *start, *end; 1422 u_short sum = 0; 1423 1424 start = (u_short *) lp; 1425 end = (u_short *) &lp->d_partitions[lp->d_npartitions]; 1426 while (start < end) 1427 sum ^= *start++; 1428 return sum; 1429 } 1430 1431 static int 1432 xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d) 1433 { 1434 struct xbsd_partition *pp; 1435 1436 get_geometry(); 1437 memset(d, 0, sizeof(struct xbsd_disklabel)); 1438 1439 d->d_magic = BSD_DISKMAGIC; 1440 1441 if (strncmp(disk_device, "/dev/sd", 7) == 0) 1442 d->d_type = BSD_DTYPE_SCSI; 1443 else 1444 d->d_type = BSD_DTYPE_ST506; 1445 1446 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */ 1447 d->d_subtype = BSD_DSTYPE_INDOSPART & pindex; 1448 #endif 1449 1450 #if !defined (__alpha__) 1451 d->d_flags = BSD_D_DOSPART; 1452 #else 1453 d->d_flags = 0; 1454 #endif 1455 d->d_secsize = SECTOR_SIZE; /* bytes/sector */ 1456 d->d_nsectors = sectors; /* sectors/track */ 1457 d->d_ntracks = heads; /* tracks/cylinder (heads) */ 1458 d->d_ncylinders = cylinders; 1459 d->d_secpercyl = sectors * heads;/* sectors/cylinder */ 1460 if (d->d_secpercyl == 0) 1461 d->d_secpercyl = 1; /* avoid segfaults */ 1462 d->d_secperunit = d->d_secpercyl * d->d_ncylinders; 1463 1464 d->d_rpm = 3600; 1465 d->d_interleave = 1; 1466 d->d_trackskew = 0; 1467 d->d_cylskew = 0; 1468 d->d_headswitch = 0; 1469 d->d_trkseek = 0; 1470 1471 d->d_magic2 = BSD_DISKMAGIC; 1472 d->d_bbsize = BSD_BBSIZE; 1473 d->d_sbsize = BSD_SBSIZE; 1474 1475 #if !defined (__alpha__) 1476 d->d_npartitions = 4; 1477 pp = &d->d_partitions[2]; /* Partition C should be 1478 the NetBSD partition */ 1479 pp->p_offset = get_start_sect(p); 1480 pp->p_size = get_nr_sects(p); 1481 pp->p_fstype = BSD_FS_UNUSED; 1482 pp = &d->d_partitions[3]; /* Partition D should be 1483 the whole disk */ 1484 pp->p_offset = 0; 1485 pp->p_size = d->d_secperunit; 1486 pp->p_fstype = BSD_FS_UNUSED; 1487 #elif defined (__alpha__) 1488 d->d_npartitions = 3; 1489 pp = &d->d_partitions[2]; /* Partition C should be 1490 the whole disk */ 1491 pp->p_offset = 0; 1492 pp->p_size = d->d_secperunit; 1493 pp->p_fstype = BSD_FS_UNUSED; 1494 #endif 1495 1496 return 1; 1497 } 1498 1499 /* 1500 * Read a xbsd_disklabel from sector 0 or from the starting sector of p. 1501 * If it has the right magic, return 1. 1502 */ 1503 static int 1504 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d) 1505 { 1506 int t, sector; 1507 1508 /* p is used only to get the starting sector */ 1509 #if !defined (__alpha__) 1510 sector = (p ? get_start_sect(p) : 0); 1511 #elif defined (__alpha__) 1512 sector = 0; 1513 #endif 1514 1515 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1) 1516 fdisk_fatal(unable_to_seek); 1517 if (BSD_BBSIZE != read(fd, disklabelbuffer, BSD_BBSIZE)) 1518 fdisk_fatal(unable_to_read); 1519 1520 memmove(d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET], 1521 sizeof(struct xbsd_disklabel)); 1522 1523 if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC) 1524 return 0; 1525 1526 for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) { 1527 d->d_partitions[t].p_size = 0; 1528 d->d_partitions[t].p_offset = 0; 1529 d->d_partitions[t].p_fstype = BSD_FS_UNUSED; 1530 } 1531 1532 if (d->d_npartitions > BSD_MAXPARTITIONS) 1533 fprintf(stderr, _("Warning: too many partitions " 1534 "(%d, maximum is %d).\n"), 1535 d->d_npartitions, BSD_MAXPARTITIONS); 1536 return 1; 1537 } 1538 1539 static int 1540 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d) 1541 { 1542 unsigned int sector; 1543 1544 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__) 1545 sector = get_start_sect(p) + BSD_LABELSECTOR; 1546 #else 1547 sector = BSD_LABELSECTOR; 1548 #endif 1549 1550 d->d_checksum = 0; 1551 d->d_checksum = xbsd_dkcksum (d); 1552 1553 /* This is necessary if we want to write the bootstrap later, 1554 otherwise we'd write the old disklabel with the bootstrap. 1555 */ 1556 memmove(&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET], 1557 d, sizeof(struct xbsd_disklabel)); 1558 1559 #if defined (__alpha__) && BSD_LABELSECTOR == 0 1560 alpha_bootblock_checksum (disklabelbuffer); 1561 if (lseek(fd, 0, SEEK_SET) == -1) 1562 fdisk_fatal(unable_to_seek); 1563 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE)) 1564 fdisk_fatal(unable_to_write); 1565 #else 1566 if (lseek(fd, sector * SECTOR_SIZE + BSD_LABELOFFSET, SEEK_SET) == -1) 1567 fdisk_fatal(unable_to_seek); 1568 if (sizeof(struct xbsd_disklabel) != write(fd, d, sizeof(struct xbsd_disklabel))) 1569 fdisk_fatal(unable_to_write); 1570 #endif 1571 sync_disks(); 1572 return 1; 1573 } 1574 1575 1576 #if !defined (__alpha__) 1577 static int 1578 xbsd_translate_fstype(int linux_type) 1579 { 1580 switch (linux_type) { 1581 case 0x01: /* DOS 12-bit FAT */ 1582 case 0x04: /* DOS 16-bit <32M */ 1583 case 0x06: /* DOS 16-bit >=32M */ 1584 case 0xe1: /* DOS access */ 1585 case 0xe3: /* DOS R/O */ 1586 case 0xf2: /* DOS secondary */ 1587 return BSD_FS_MSDOS; 1588 case 0x07: /* OS/2 HPFS */ 1589 return BSD_FS_HPFS; 1590 default: 1591 return BSD_FS_OTHER; 1592 } 1593 } 1594 1595 static void 1596 xbsd_link_part(void) 1597 { 1598 int k, i; 1599 struct partition *p; 1600 1601 k = get_partition(1, partitions); 1602 1603 if (!xbsd_check_new_partition(&i)) 1604 return; 1605 1606 p = get_part_table(k); 1607 1608 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p); 1609 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p); 1610 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind); 1611 } 1612 #endif 1613 1614 #if defined (__alpha__) 1615 1616 #if !defined(__GLIBC__) 1617 typedef unsigned long long uint64_t; 1618 #endif 1619 1620 static void 1621 alpha_bootblock_checksum(char *boot) 1622 { 1623 uint64_t *dp, sum; 1624 int i; 1625 1626 dp = (uint64_t *)boot; 1627 sum = 0; 1628 for (i = 0; i < 63; i++) 1629 sum += dp[i]; 1630 dp[63] = sum; 1631 } 1632 #endif /* __alpha__ */ 1633 1634 #endif /* OSF_LABEL */ 1635 1636 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL) 1637 static inline unsigned short 1638 __swap16(unsigned short x) 1639 { 1640 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8); 1641 } 1642 1643 static inline uint32_t 1644 __swap32(uint32_t x) 1645 { 1646 return (((x & 0xFF) << 24) | 1647 ((x & 0xFF00) << 8) | 1648 ((x & 0xFF0000) >> 8) | 1649 ((x & 0xFF000000) >> 24)); 1650 } 1651 #endif 1652 1653 #ifdef CONFIG_FEATURE_SGI_LABEL 1654 /* 1655 * 1656 * fdisksgilabel.c 1657 * 1658 * Copyright (C) Andreas Neuper, Sep 1998. 1659 * This file may be modified and redistributed under 1660 * the terms of the GNU Public License. 1661 * 1662 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br> 1663 * Internationalization 1664 */ 1665 1666 1667 static int sgi_other_endian; 1668 static int debug; 1669 static short sgi_volumes = 1; 1670 1671 /* 1672 * only dealing with free blocks here 1673 */ 1674 1675 typedef struct { 1676 unsigned int first; 1677 unsigned int last; 1678 } freeblocks; 1679 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */ 1680 1681 static void 1682 setfreelist(int i, unsigned int f, unsigned int l) 1683 { 1684 freelist[i].first = f; 1685 freelist[i].last = l; 1686 } 1687 1688 static void 1689 add2freelist(unsigned int f, unsigned int l) 1690 { 1691 int i; 1692 for (i = 0; i < 17 ; i++) 1693 if (freelist[i].last == 0) 1694 break; 1695 setfreelist(i, f, l); 1696 } 1697 1698 static void 1699 clearfreelist(void) 1700 { 1701 int i; 1702 1703 for (i = 0; i < 17 ; i++) 1704 setfreelist(i, 0, 0); 1705 } 1706 1707 static unsigned int 1708 isinfreelist(unsigned int b) 1709 { 1710 int i; 1711 1712 for (i = 0; i < 17 ; i++) 1713 if (freelist[i].first <= b && freelist[i].last >= b) 1714 return freelist[i].last; 1715 return 0; 1716 } 1717 /* return last vacant block of this stride (never 0). */ 1718 /* the '>=' is not quite correct, but simplifies the code */ 1719 /* 1720 * end of free blocks section 1721 */ 1722 1723 static const struct systypes sgi_sys_types[] = { 1724 /* SGI_VOLHDR */ { "\x00" "SGI volhdr" }, 1725 /* 0x01 */ { "\x01" "SGI trkrepl" }, 1726 /* 0x02 */ { "\x02" "SGI secrepl" }, 1727 /* SGI_SWAP */ { "\x03" "SGI raw" }, 1728 /* 0x04 */ { "\x04" "SGI bsd" }, 1729 /* 0x05 */ { "\x05" "SGI sysv" }, 1730 /* ENTIRE_DISK */ { "\x06" "SGI volume" }, 1731 /* SGI_EFS */ { "\x07" "SGI efs" }, 1732 /* 0x08 */ { "\x08" "SGI lvol" }, 1733 /* 0x09 */ { "\x09" "SGI rlvol" }, 1734 /* SGI_XFS */ { "\x0a" "SGI xfs" }, 1735 /* SGI_XFSLOG */ { "\x0b" "SGI xfslog" }, 1736 /* SGI_XLV */ { "\x0c" "SGI xlv" }, 1737 /* SGI_XVM */ { "\x0d" "SGI xvm" }, 1738 /* LINUX_SWAP */ { "\x82" "Linux swap" }, 1739 /* LINUX_NATIVE */ { "\x83" "Linux native" }, 1740 /* LINUX_LVM */ { "\x8d" "Linux LVM" }, 1741 /* LINUX_RAID */ { "\xfd" "Linux RAID" }, 1742 { NULL } 1743 }; 1744 1745 1746 static int 1747 sgi_get_nsect(void) 1748 { 1749 return SGI_SSWAP16(sgilabel->devparam.nsect); 1750 } 1751 1752 static int 1753 sgi_get_ntrks(void) 1754 { 1755 return SGI_SSWAP16(sgilabel->devparam.ntrks); 1756 } 1757 1758 static unsigned int 1759 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */) 1760 { 1761 int i = 0; 1762 unsigned int sum = 0; 1763 1764 size /= sizeof(unsigned int); 1765 for (i = 0; i < size; i++) 1766 sum -= SGI_SSWAP32(base[i]); 1767 return sum; 1768 } 1769 1770 static int 1771 check_sgi_label(void) 1772 { 1773 if (sizeof(sgilabel) > 512) { 1774 fprintf(stderr, 1775 _("According to MIPS Computer Systems, Inc the " 1776 "Label must not contain more than 512 bytes\n")); 1777 exit(1); 1778 } 1779 1780 if (sgilabel->magic != SGI_LABEL_MAGIC 1781 && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) { 1782 current_label_type = label_dos; 1783 return 0; 1784 } 1785 1786 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED); 1787 /* 1788 * test for correct checksum 1789 */ 1790 if (two_s_complement_32bit_sum((unsigned int*)sgilabel, 1791 sizeof(*sgilabel))) { 1792 fprintf(stderr, 1793 _("Detected sgi disklabel with wrong checksum.\n")); 1794 } 1795 update_units(); 1796 current_label_type = label_sgi; 1797 partitions = 16; 1798 sgi_volumes = 15; 1799 return 1; 1800 } 1801 1802 static unsigned int 1803 sgi_get_start_sector(int i) 1804 { 1805 return SGI_SSWAP32(sgilabel->partitions[i].start_sector); 1806 } 1807 1808 static unsigned int 1809 sgi_get_num_sectors(int i) 1810 { 1811 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors); 1812 } 1813 1814 static int 1815 sgi_get_sysid(int i) 1816 { 1817 return SGI_SSWAP32(sgilabel->partitions[i].id); 1818 } 1819 1820 static int 1821 sgi_get_bootpartition(void) 1822 { 1823 return SGI_SSWAP16(sgilabel->boot_part); 1824 } 1825 1826 static int 1827 sgi_get_swappartition(void) 1828 { 1829 return SGI_SSWAP16(sgilabel->swap_part); 1830 } 1831 1832 static void 1833 sgi_list_table(int xtra) 1834 { 1835 int i, w, wd; 1836 int kpi = 0; /* kernel partition ID */ 1837 1838 if(xtra) { 1839 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n" 1840 "%d cylinders, %d physical cylinders\n" 1841 "%d extra sects/cyl, interleave %d:1\n" 1842 "%s\n" 1843 "Units = %s of %d * 512 bytes\n\n"), 1844 disk_device, heads, sectors, cylinders, 1845 SGI_SSWAP16(sgiparam.pcylcount), 1846 SGI_SSWAP16(sgiparam.sparecyl), 1847 SGI_SSWAP16(sgiparam.ilfact), 1848 (char *)sgilabel, 1849 str_units(PLURAL), units_per_sector); 1850 } else { 1851 printf( _("\nDisk %s (SGI disk label): " 1852 "%d heads, %d sectors, %d cylinders\n" 1853 "Units = %s of %d * 512 bytes\n\n"), 1854 disk_device, heads, sectors, cylinders, 1855 str_units(PLURAL), units_per_sector ); 1856 } 1857 1858 w = strlen(disk_device); 1859 wd = strlen(_("Device")); 1860 if (w < wd) 1861 w = wd; 1862 1863 printf(_("----- partitions -----\n" 1864 "Pt# %*s Info Start End Sectors Id System\n"), 1865 w + 2, _("Device")); 1866 for (i = 0 ; i < partitions; i++) { 1867 if( sgi_get_num_sectors(i) || debug ) { 1868 uint32_t start = sgi_get_start_sector(i); 1869 uint32_t len = sgi_get_num_sectors(i); 1870 kpi++; /* only count nonempty partitions */ 1871 printf( 1872 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n", 1873 /* fdisk part number */ i+1, 1874 /* device */ partname(disk_device, kpi, w+3), 1875 /* flags */ (sgi_get_swappartition() == i) ? "swap" : 1876 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ", 1877 /* start */ (long) scround(start), 1878 /* end */ (long) scround(start+len)-1, 1879 /* no odd flag on end */(long) len, 1880 /* type id */ sgi_get_sysid(i), 1881 /* type name */ partition_type(sgi_get_sysid(i))); 1882 } 1883 } 1884 printf(_("----- Bootinfo -----\nBootfile: %s\n" 1885 "----- Directory Entries -----\n"), 1886 sgilabel->boot_file); 1887 for (i = 0 ; i < sgi_volumes; i++) { 1888 if (sgilabel->directory[i].vol_file_size) { 1889 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start); 1890 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size); 1891 unsigned char *name = sgilabel->directory[i].vol_file_name; 1892 1893 printf(_("%2d: %-10s sector%5u size%8u\n"), 1894 i, (char*)name, (unsigned int) start, (unsigned int) len); 1895 } 1896 } 1897 } 1898 1899 static void 1900 sgi_set_bootpartition(int i) 1901 { 1902 sgilabel->boot_part = SGI_SSWAP16(((short)i)); 1903 } 1904 1905 static unsigned int 1906 sgi_get_lastblock(void) 1907 { 1908 return heads * sectors * cylinders; 1909 } 1910 1911 static void 1912 sgi_set_swappartition(int i) 1913 { 1914 sgilabel->swap_part = SGI_SSWAP16(((short)i)); 1915 } 1916 1917 static int 1918 sgi_check_bootfile(const char* aFile) 1919 { 1920 if (strlen(aFile) < 3) /* "/a\n" is minimum */ { 1921 printf(_("\nInvalid Bootfile!\n" 1922 "\tThe bootfile must be an absolute non-zero pathname,\n" 1923 "\te.g. \"/unix\" or \"/unix.save\".\n")); 1924 return 0; 1925 } else { 1926 if (strlen(aFile) > 16) { 1927 printf(_("\n\tName of Bootfile too long: " 1928 "16 bytes maximum.\n")); 1929 return 0; 1930 } else { 1931 if (aFile[0] != '/') { 1932 printf(_("\n\tBootfile must have a " 1933 "fully qualified pathname.\n")); 1934 return 0; 1935 } 1936 } 1937 } 1938 if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) { 1939 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t" 1940 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n")); 1941 /* filename is correct and did change */ 1942 return 1; 1943 } 1944 return 0; /* filename did not change */ 1945 } 1946 1947 static const char * 1948 sgi_get_bootfile(void) 1949 { 1950 return (char*)sgilabel->boot_file; 1951 } 1952 1953 static void 1954 sgi_set_bootfile(const char* aFile) 1955 { 1956 int i = 0; 1957 1958 if (sgi_check_bootfile(aFile)) { 1959 while (i < 16) { 1960 if ((aFile[i] != '\n') /* in principle caught again by next line */ 1961 && (strlen(aFile) > i)) 1962 sgilabel->boot_file[i] = aFile[i]; 1963 else 1964 sgilabel->boot_file[i] = 0; 1965 i++; 1966 } 1967 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file); 1968 } 1969 } 1970 1971 static void 1972 create_sgiinfo(void) 1973 { 1974 /* I keep SGI's habit to write the sgilabel to the second block */ 1975 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2); 1976 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo)); 1977 strcpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel"); 1978 } 1979 1980 static sgiinfo *fill_sgiinfo(void); 1981 1982 static void 1983 sgi_write_table(void) 1984 { 1985 sgilabel->csum = 0; 1986 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum( 1987 (unsigned int*)sgilabel, sizeof(*sgilabel))); 1988 assert(two_s_complement_32bit_sum( 1989 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0); 1990 1991 if (lseek(fd, 0, SEEK_SET) < 0) 1992 fdisk_fatal(unable_to_seek); 1993 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE) 1994 fdisk_fatal(unable_to_write); 1995 if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) { 1996 /* 1997 * keep this habit of first writing the "sgilabel". 1998 * I never tested whether it works without (AN 981002). 1999 */ 2000 sgiinfo *info = fill_sgiinfo(); 2001 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start); 2002 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0) 2003 fdisk_fatal(unable_to_seek); 2004 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE) 2005 fdisk_fatal(unable_to_write); 2006 free(info); 2007 } 2008 } 2009 2010 static int 2011 compare_start(int *x, int *y) 2012 { 2013 /* 2014 * sort according to start sectors 2015 * and prefers largest partition: 2016 * entry zero is entire disk entry 2017 */ 2018 unsigned int i = *x; 2019 unsigned int j = *y; 2020 unsigned int a = sgi_get_start_sector(i); 2021 unsigned int b = sgi_get_start_sector(j); 2022 unsigned int c = sgi_get_num_sectors(i); 2023 unsigned int d = sgi_get_num_sectors(j); 2024 2025 if (a == b) 2026 return (d > c) ? 1 : (d == c) ? 0 : -1; 2027 return (a > b) ? 1 : -1; 2028 } 2029 2030 2031 static int 2032 verify_sgi(int verbose) 2033 { 2034 int Index[16]; /* list of valid partitions */ 2035 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */ 2036 int entire = 0, i = 0; 2037 unsigned int start = 0; 2038 long long gap = 0; /* count unused blocks */ 2039 unsigned int lastblock = sgi_get_lastblock(); 2040 2041 clearfreelist(); 2042 for (i = 0; i < 16; i++) { 2043 if (sgi_get_num_sectors(i) != 0) { 2044 Index[sortcount++] = i; 2045 if (sgi_get_sysid(i) == ENTIRE_DISK) { 2046 if (entire++ == 1) { 2047 if (verbose) 2048 printf(_("More than one entire disk entry present.\n")); 2049 } 2050 } 2051 } 2052 } 2053 if (sortcount == 0) { 2054 if (verbose) 2055 printf(_("No partitions defined\n")); 2056 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1; 2057 } 2058 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start); 2059 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) { 2060 if ((Index[0] != 10) && verbose) 2061 printf(_("IRIX likes when Partition 11 covers the entire disk.\n")); 2062 if ((sgi_get_start_sector(Index[0]) != 0) && verbose) 2063 printf(_("The entire disk partition should start " 2064 "at block 0,\n" 2065 "not at diskblock %d.\n"), 2066 sgi_get_start_sector(Index[0])); 2067 if (debug) /* I do not understand how some disks fulfil it */ 2068 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose) 2069 printf(_("The entire disk partition is only %d diskblock large,\n" 2070 "but the disk is %d diskblocks long.\n"), 2071 sgi_get_num_sectors(Index[0]), lastblock); 2072 lastblock = sgi_get_num_sectors(Index[0]); 2073 } else { 2074 if (verbose) 2075 printf(_("One Partition (#11) should cover the entire disk.\n")); 2076 if (debug > 2) 2077 printf("sysid=%d\tpartition=%d\n", 2078 sgi_get_sysid(Index[0]), Index[0]+1); 2079 } 2080 for (i = 1, start = 0; i < sortcount; i++) { 2081 int cylsize = sgi_get_nsect() * sgi_get_ntrks(); 2082 2083 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) { 2084 if (debug) /* I do not understand how some disks fulfil it */ 2085 if (verbose) 2086 printf(_("Partition %d does not start on cylinder boundary.\n"), 2087 Index[i]+1); 2088 } 2089 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) { 2090 if (debug) /* I do not understand how some disks fulfil it */ 2091 if (verbose) 2092 printf(_("Partition %d does not end on cylinder boundary.\n"), 2093 Index[i]+1); 2094 } 2095 /* We cannot handle several "entire disk" entries. */ 2096 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue; 2097 if (start > sgi_get_start_sector(Index[i])) { 2098 if (verbose) 2099 printf(_("The Partition %d and %d overlap by %d sectors.\n"), 2100 Index[i-1]+1, Index[i]+1, 2101 start - sgi_get_start_sector(Index[i])); 2102 if (gap > 0) gap = -gap; 2103 if (gap == 0) gap = -1; 2104 } 2105 if (start < sgi_get_start_sector(Index[i])) { 2106 if (verbose) 2107 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"), 2108 sgi_get_start_sector(Index[i]) - start, 2109 start, sgi_get_start_sector(Index[i])-1); 2110 gap += sgi_get_start_sector(Index[i]) - start; 2111 add2freelist(start, sgi_get_start_sector(Index[i])); 2112 } 2113 start = sgi_get_start_sector(Index[i]) 2114 + sgi_get_num_sectors(Index[i]); 2115 if (debug > 1) { 2116 if (verbose) 2117 printf("%2d:%12d\t%12d\t%12d\n", Index[i], 2118 sgi_get_start_sector(Index[i]), 2119 sgi_get_num_sectors(Index[i]), 2120 sgi_get_sysid(Index[i])); 2121 } 2122 } 2123 if (start < lastblock) { 2124 if (verbose) 2125 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"), 2126 lastblock - start, start, lastblock-1); 2127 gap += lastblock - start; 2128 add2freelist(start, lastblock); 2129 } 2130 /* 2131 * Done with arithmetics 2132 * Go for details now 2133 */ 2134 if (verbose) { 2135 if (!sgi_get_num_sectors(sgi_get_bootpartition())) { 2136 printf(_("\nThe boot partition does not exist.\n")); 2137 } 2138 if (!sgi_get_num_sectors(sgi_get_swappartition())) { 2139 printf(_("\nThe swap partition does not exist.\n")); 2140 } else { 2141 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP) 2142 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP)) 2143 printf(_("\nThe swap partition has no swap type.\n")); 2144 } 2145 if (sgi_check_bootfile("/unix")) 2146 printf(_("\tYou have chosen an unusual boot file name.\n")); 2147 } 2148 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1; 2149 } 2150 2151 static int 2152 sgi_gaps(void) 2153 { 2154 /* 2155 * returned value is: 2156 * = 0 : disk is properly filled to the rim 2157 * < 0 : there is an overlap 2158 * > 0 : there is still some vacant space 2159 */ 2160 return verify_sgi(0); 2161 } 2162 2163 static void 2164 sgi_change_sysid(int i, int sys) 2165 { 2166 if( sgi_get_num_sectors(i) == 0 ) { /* caught already before, ... */ 2167 printf(_("Sorry You may change the Tag of non-empty partitions.\n")); 2168 return; 2169 } 2170 if (((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR)) 2171 && (sgi_get_start_sector(i) < 1) ) { 2172 read_chars( 2173 _("It is highly recommended that the partition at offset 0\n" 2174 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n" 2175 "retrieve from its directory standalone tools like sash and fx.\n" 2176 "Only the \"SGI volume\" entire disk section may violate this.\n" 2177 "Type YES if you are sure about tagging this partition differently.\n")); 2178 if (strcmp(line_ptr, _("YES\n"))) 2179 return; 2180 } 2181 sgilabel->partitions[i].id = SGI_SSWAP32(sys); 2182 } 2183 2184 /* returns partition index of first entry marked as entire disk */ 2185 static int 2186 sgi_entire(void) 2187 { 2188 int i; 2189 2190 for (i = 0; i < 16; i++) 2191 if (sgi_get_sysid(i) == SGI_VOLUME) 2192 return i; 2193 return -1; 2194 } 2195 2196 static void 2197 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) 2198 { 2199 sgilabel->partitions[i].id = SGI_SSWAP32(sys); 2200 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length); 2201 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start); 2202 set_changed(i); 2203 if (sgi_gaps() < 0) /* rebuild freelist */ 2204 printf(_("Do You know, You got a partition overlap on the disk?\n")); 2205 } 2206 2207 static void 2208 sgi_set_entire(void) 2209 { 2210 int n; 2211 2212 for (n = 10; n < partitions; n++) { 2213 if(!sgi_get_num_sectors(n) ) { 2214 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME); 2215 break; 2216 } 2217 } 2218 } 2219 2220 static void 2221 sgi_set_volhdr(void) 2222 { 2223 int n; 2224 2225 for (n = 8; n < partitions; n++) { 2226 if (!sgi_get_num_sectors(n)) { 2227 /* 2228 * 5 cylinders is an arbitrary value I like 2229 * IRIX 5.3 stored files in the volume header 2230 * (like sash, symmon, fx, ide) with ca. 3200 2231 * sectors. 2232 */ 2233 if (heads * sectors * 5 < sgi_get_lastblock()) 2234 sgi_set_partition(n, 0, heads * sectors * 5, SGI_VOLHDR); 2235 break; 2236 } 2237 } 2238 } 2239 2240 static void 2241 sgi_delete_partition(int i) 2242 { 2243 sgi_set_partition(i, 0, 0, 0); 2244 } 2245 2246 static void 2247 sgi_add_partition(int n, int sys) 2248 { 2249 char mesg[256]; 2250 unsigned int first = 0, last = 0; 2251 2252 if (n == 10) { 2253 sys = SGI_VOLUME; 2254 } else if (n == 8) { 2255 sys = 0; 2256 } 2257 if(sgi_get_num_sectors(n)) { 2258 printf(_("Partition %d is already defined. Delete " 2259 "it before re-adding it.\n"), n + 1); 2260 return; 2261 } 2262 if ((sgi_entire() == -1) && (sys != SGI_VOLUME)) { 2263 printf(_("Attempting to generate entire disk entry automatically.\n")); 2264 sgi_set_entire(); 2265 sgi_set_volhdr(); 2266 } 2267 if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) { 2268 printf(_("The entire disk is already covered with partitions.\n")); 2269 return; 2270 } 2271 if (sgi_gaps() < 0) { 2272 printf(_("You got a partition overlap on the disk. Fix it first!\n")); 2273 return; 2274 } 2275 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR)); 2276 while (1) { 2277 if(sys == SGI_VOLUME) { 2278 last = sgi_get_lastblock(); 2279 first = read_int(0, 0, last-1, 0, mesg); 2280 if (first != 0) { 2281 printf(_("It is highly recommended that eleventh partition\n" 2282 "covers the entire disk and is of type `SGI volume'\n")); 2283 } 2284 } else { 2285 first = freelist[0].first; 2286 last = freelist[0].last; 2287 first = read_int(scround(first), scround(first), scround(last)-1, 2288 0, mesg); 2289 } 2290 if (display_in_cyl_units) 2291 first *= units_per_sector; 2292 else 2293 first = first; /* align to cylinder if you know how ... */ 2294 if(!last ) 2295 last = isinfreelist(first); 2296 if(last == 0) { 2297 printf(_("You will get a partition overlap on the disk. " 2298 "Fix it first!\n")); 2299 } else 2300 break; 2301 } 2302 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR)); 2303 last = read_int(scround(first), scround(last)-1, scround(last)-1, 2304 scround(first), mesg)+1; 2305 if (display_in_cyl_units) 2306 last *= units_per_sector; 2307 else 2308 last = last; /* align to cylinder if You know how ... */ 2309 if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) ) 2310 printf(_("It is highly recommended that eleventh partition\n" 2311 "covers the entire disk and is of type `SGI volume'\n")); 2312 sgi_set_partition(n, first, last-first, sys); 2313 } 2314 2315 #ifdef CONFIG_FEATURE_FDISK_ADVANCED 2316 static void 2317 create_sgilabel(void) 2318 { 2319 struct hd_geometry geometry; 2320 struct { 2321 unsigned int start; 2322 unsigned int nsect; 2323 int sysid; 2324 } old[4]; 2325 int i = 0; 2326 long longsectors; /* the number of sectors on the device */ 2327 int res; /* the result from the ioctl */ 2328 int sec_fac; /* the sector factor */ 2329 2330 sec_fac = sector_size / 512; /* determine the sector factor */ 2331 2332 fprintf( stderr, 2333 _("Building a new SGI disklabel. Changes will remain in memory only,\n" 2334 "until you decide to write them. After that, of course, the previous\n" 2335 "content will be unrecoverably lost.\n\n")); 2336 2337 sgi_other_endian = (BB_LITTLE_ENDIAN); 2338 res = ioctl(fd, BLKGETSIZE, &longsectors); 2339 if (!ioctl(fd, HDIO_GETGEO, &geometry)) { 2340 heads = geometry.heads; 2341 sectors = geometry.sectors; 2342 if (res == 0) { 2343 /* the get device size ioctl was successful */ 2344 cylinders = longsectors / (heads * sectors); 2345 cylinders /= sec_fac; 2346 } else { 2347 /* otherwise print error and use truncated version */ 2348 cylinders = geometry.cylinders; 2349 fprintf(stderr, 2350 _("Warning: BLKGETSIZE ioctl failed on %s. " 2351 "Using geometry cylinder value of %d.\n" 2352 "This value may be truncated for devices" 2353 " > 33.8 GB.\n"), disk_device, cylinders); 2354 } 2355 } 2356 for (i = 0; i < 4; i++) { 2357 old[i].sysid = 0; 2358 if (valid_part_table_flag(MBRbuffer)) { 2359 if(get_part_table(i)->sys_ind) { 2360 old[i].sysid = get_part_table(i)->sys_ind; 2361 old[i].start = get_start_sect(get_part_table(i)); 2362 old[i].nsect = get_nr_sects(get_part_table(i)); 2363 printf(_("Trying to keep parameters of partition %d.\n"), i); 2364 if (debug) 2365 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"), 2366 old[i].sysid, old[i].start, old[i].nsect); 2367 } 2368 } 2369 } 2370 2371 memset(MBRbuffer, 0, sizeof(MBRbuffer)); 2372 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC); 2373 sgilabel->boot_part = SGI_SSWAP16(0); 2374 sgilabel->swap_part = SGI_SSWAP16(1); 2375 2376 /* sizeof(sgilabel->boot_file) = 16 > 6 */ 2377 memset(sgilabel->boot_file, 0, 16); 2378 strcpy((char*)sgilabel->boot_file, "/unix"); 2379 2380 sgilabel->devparam.skew = (0); 2381 sgilabel->devparam.gap1 = (0); 2382 sgilabel->devparam.gap2 = (0); 2383 sgilabel->devparam.sparecyl = (0); 2384 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders); 2385 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0); 2386 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads); 2387 /* tracks/cylinder (heads) */ 2388 sgilabel->devparam.cmd_tag_queue_depth = (0); 2389 sgilabel->devparam.unused0 = (0); 2390 sgilabel->devparam.unused1 = SGI_SSWAP16(0); 2391 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors); 2392 /* sectors/track */ 2393 sgilabel->devparam.bytes = SGI_SSWAP16(512); 2394 sgilabel->devparam.ilfact = SGI_SSWAP16(1); 2395 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD| 2396 IGNORE_ERRORS|RESEEK); 2397 sgilabel->devparam.datarate = SGI_SSWAP32(0); 2398 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1); 2399 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0); 2400 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0); 2401 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0); 2402 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0); 2403 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0); 2404 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0); 2405 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0); 2406 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 ); 2407 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 ); 2408 current_label_type = label_sgi; 2409 partitions = 16; 2410 sgi_volumes = 15; 2411 sgi_set_entire(); 2412 sgi_set_volhdr(); 2413 for (i = 0; i < 4; i++) { 2414 if(old[i].sysid) { 2415 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid); 2416 } 2417 } 2418 } 2419 2420 static void 2421 sgi_set_xcyl(void) 2422 { 2423 /* do nothing in the beginning */ 2424 } 2425 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */ 2426 2427 /* _____________________________________________________________ 2428 */ 2429 2430 static sgiinfo * 2431 fill_sgiinfo(void) 2432 { 2433 sgiinfo *info = calloc(1, sizeof(sgiinfo)); 2434 2435 info->magic = SGI_SSWAP32(SGI_INFO_MAGIC); 2436 info->b1 = SGI_SSWAP32(-1); 2437 info->b2 = SGI_SSWAP16(-1); 2438 info->b3 = SGI_SSWAP16(1); 2439 /* You may want to replace this string !!!!!!! */ 2440 strcpy( (char*)info->scsi_string, "IBM OEM 0662S12 3 30" ); 2441 strcpy( (char*)info->serial, "0000" ); 2442 info->check1816 = SGI_SSWAP16(18*256 +16 ); 2443 strcpy( (char*)info->installer, "Sfx version 5.3, Oct 18, 1994" ); 2444 return info; 2445 } 2446 #endif /* SGI_LABEL */ 2447 2448 2449 #ifdef CONFIG_FEATURE_SUN_LABEL 2450 /* 2451 * fdisksunlabel.c 2452 * 2453 * I think this is mostly, or entirely, due to 2454 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996 2455 * 2456 * Merged with fdisk for other architectures, aeb, June 1998. 2457 * 2458 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br> 2459 * Internationalization 2460 */ 2461 2462 2463 static int sun_other_endian; 2464 static int scsi_disk; 2465 static int floppy; 2466 2467 #ifndef IDE0_MAJOR 2468 #define IDE0_MAJOR 3 2469 #endif 2470 #ifndef IDE1_MAJOR 2471 #define IDE1_MAJOR 22 2472 #endif 2473 2474 static void 2475 guess_device_type(void) 2476 { 2477 struct stat bootstat; 2478 2479 if (fstat(fd, &bootstat) < 0) { 2480 scsi_disk = 0; 2481 floppy = 0; 2482 } else if (S_ISBLK(bootstat.st_mode) 2483 && (major(bootstat.st_rdev) == IDE0_MAJOR || 2484 major(bootstat.st_rdev) == IDE1_MAJOR)) { 2485 scsi_disk = 0; 2486 floppy = 0; 2487 } else if (S_ISBLK(bootstat.st_mode) 2488 && major(bootstat.st_rdev) == FLOPPY_MAJOR) { 2489 scsi_disk = 0; 2490 floppy = 1; 2491 } else { 2492 scsi_disk = 1; 2493 floppy = 0; 2494 } 2495 } 2496 2497 static const struct systypes sun_sys_types[] = { 2498 { "\x00" "Empty" }, /* 0 */ 2499 { "\x01" "Boot" }, /* 1 */ 2500 { "\x02" "SunOS root" }, /* 2 */ 2501 { "\x03" "SunOS swap" }, /* SUNOS_SWAP */ 2502 { "\x04" "SunOS usr" }, /* 4 */ 2503 { "\x05" "Whole disk" }, /* WHOLE_DISK */ 2504 { "\x06" "SunOS stand" }, /* 6 */ 2505 { "\x07" "SunOS var" }, /* 7 */ 2506 { "\x08" "SunOS home" }, /* 8 */ 2507 { "\x82" "Linux swap" }, /* LINUX_SWAP */ 2508 { "\x83" "Linux native" }, /* LINUX_NATIVE */ 2509 { "\x8e" "Linux LVM" }, /* 0x8e */ 2510 /* New (2.2.x) raid partition with autodetect using persistent superblock */ 2511 { "\xfd" "Linux raid autodetect" }, /* 0xfd */ 2512 { NULL } 2513 }; 2514 2515 2516 static void 2517 set_sun_partition(int i, uint start, uint stop, int sysid) 2518 { 2519 sunlabel->infos[i].id = sysid; 2520 sunlabel->partitions[i].start_cylinder = 2521 SUN_SSWAP32(start / (heads * sectors)); 2522 sunlabel->partitions[i].num_sectors = 2523 SUN_SSWAP32(stop - start); 2524 set_changed(i); 2525 } 2526 2527 static int 2528 check_sun_label(void) 2529 { 2530 unsigned short *ush; 2531 int csum; 2532 2533 if (sunlabel->magic != SUN_LABEL_MAGIC 2534 && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) { 2535 current_label_type = label_dos; 2536 sun_other_endian = 0; 2537 return 0; 2538 } 2539 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED); 2540 ush = ((unsigned short *) (sunlabel + 1)) - 1; 2541 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--; 2542 if (csum) { 2543 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n" 2544 "Probably you'll have to set all the values,\n" 2545 "e.g. heads, sectors, cylinders and partitions\n" 2546 "or force a fresh label (s command in main menu)\n")); 2547 } else { 2548 heads = SUN_SSWAP16(sunlabel->ntrks); 2549 cylinders = SUN_SSWAP16(sunlabel->ncyl); 2550 sectors = SUN_SSWAP16(sunlabel->nsect); 2551 } 2552 update_units(); 2553 current_label_type = label_sun; 2554 partitions = 8; 2555 return 1; 2556 } 2557 2558 static const struct sun_predefined_drives { 2559 const char *vendor; 2560 const char *model; 2561 unsigned short sparecyl; 2562 unsigned short ncyl; 2563 unsigned short nacyl; 2564 unsigned short pcylcount; 2565 unsigned short ntrks; 2566 unsigned short nsect; 2567 unsigned short rspeed; 2568 } sun_drives[] = { 2569 { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662}, 2570 { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662}, 2571 { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600}, 2572 { "IBM","DPES-31080",0,4901,2,4903,4,108,5400}, 2573 { "IBM","DORS-32160",0,1015,2,1017,67,62,5400}, 2574 { "IBM","DNES-318350",0,11199,2,11474,10,320,7200}, 2575 { "SEAGATE","ST34371",0,3880,2,3882,16,135,7228}, 2576 { "","SUN0104",1,974,2,1019,6,35,3662}, 2577 { "","SUN0207",4,1254,2,1272,9,36,3600}, 2578 { "","SUN0327",3,1545,2,1549,9,46,3600}, 2579 { "","SUN0340",0,1538,2,1544,6,72,4200}, 2580 { "","SUN0424",2,1151,2,2500,9,80,4400}, 2581 { "","SUN0535",0,1866,2,2500,7,80,5400}, 2582 { "","SUN0669",5,1614,2,1632,15,54,3600}, 2583 { "","SUN1.0G",5,1703,2,1931,15,80,3597}, 2584 { "","SUN1.05",0,2036,2,2038,14,72,5400}, 2585 { "","SUN1.3G",6,1965,2,3500,17,80,5400}, 2586 { "","SUN2.1G",0,2733,2,3500,19,80,5400}, 2587 { "IOMEGA","Jaz",0,1019,2,1021,64,32,5394}, 2588 }; 2589 2590 static const struct sun_predefined_drives * 2591 sun_autoconfigure_scsi(void) 2592 { 2593 const struct sun_predefined_drives *p = NULL; 2594 2595 #ifdef SCSI_IOCTL_GET_IDLUN 2596 unsigned int id[2]; 2597 char buffer[2048]; 2598 char buffer2[2048]; 2599 FILE *pfd; 2600 char *vendor; 2601 char *model; 2602 char *q; 2603 int i; 2604 2605 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) { 2606 sprintf(buffer, 2607 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n", 2608 #if 0 2609 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33, 2610 #else 2611 /* This is very wrong (works only if you have one HBA), 2612 but I haven't found a way how to get hostno 2613 from the current kernel */ 2614 0, 2615 #endif 2616 (id[0]>>16) & 0xff, 2617 id[0] & 0xff, 2618 (id[0]>>8) & 0xff 2619 ); 2620 pfd = fopen("/proc/scsi/scsi","r"); 2621 if (pfd) { 2622 while (fgets(buffer2, 2048, pfd)) { 2623 if (!strcmp(buffer, buffer2)) { 2624 if (fgets(buffer2,2048,pfd)) { 2625 q = strstr(buffer2,"Vendor: "); 2626 if (q) { 2627 q += 8; 2628 vendor = q; 2629 q = strstr(q," "); 2630 *q++ = 0; /* truncate vendor name */ 2631 q = strstr(q,"Model: "); 2632 if (q) { 2633 *q = 0; 2634 q += 7; 2635 model = q; 2636 q = strstr(q," Rev: "); 2637 if (q) { 2638 *q = 0; 2639 for (i = 0; i < SIZE(sun_drives); i++) { 2640 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor)) 2641 continue; 2642 if (!strstr(model, sun_drives[i].model)) 2643 continue; 2644 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model); 2645 p = sun_drives + i; 2646 break; 2647 } 2648 } 2649 } 2650 } 2651 } 2652 break; 2653 } 2654 } 2655 fclose(pfd); 2656 } 2657 } 2658 #endif 2659 return p; 2660 } 2661 2662 static void 2663 create_sunlabel(void) 2664 { 2665 struct hd_geometry geometry; 2666 unsigned int ndiv; 2667 int i; 2668 unsigned char c; 2669 const struct sun_predefined_drives *p = NULL; 2670 2671 fprintf(stderr, 2672 _("Building a new sun disklabel. Changes will remain in memory only,\n" 2673 "until you decide to write them. After that, of course, the previous\n" 2674 "content won't be recoverable.\n\n")); 2675 sun_other_endian = BB_LITTLE_ENDIAN; 2676 memset(MBRbuffer, 0, sizeof(MBRbuffer)); 2677 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC); 2678 if (!floppy) { 2679 puts(_("Drive type\n" 2680 " ? auto configure\n" 2681 " 0 custom (with hardware detected defaults)")); 2682 for (i = 0; i < SIZE(sun_drives); i++) { 2683 printf(" %c %s%s%s\n", 2684 i + 'a', sun_drives[i].vendor, 2685 (*sun_drives[i].vendor) ? " " : "", 2686 sun_drives[i].model); 2687 } 2688 while (1) { 2689 c = read_char(_("Select type (? for auto, 0 for custom): ")); 2690 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) { 2691 p = sun_drives + c - 'a'; 2692 break; 2693 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) { 2694 p = sun_drives + c - 'A'; 2695 break; 2696 } else if (c == '0') { 2697 break; 2698 } else if (c == '?' && scsi_disk) { 2699 p = sun_autoconfigure_scsi(); 2700 if (!p) 2701 printf(_("Autoconfigure failed.\n")); 2702 else 2703 break; 2704 } 2705 } 2706 } 2707 if (!p || floppy) { 2708 if (!ioctl(fd, HDIO_GETGEO, &geometry)) { 2709 heads = geometry.heads; 2710 sectors = geometry.sectors; 2711 cylinders = geometry.cylinders; 2712 } else { 2713 heads = 0; 2714 sectors = 0; 2715 cylinders = 0; 2716 } 2717 if (floppy) { 2718 sunlabel->nacyl = 0; 2719 sunlabel->pcylcount = SUN_SSWAP16(cylinders); 2720 sunlabel->rspeed = SUN_SSWAP16(300); 2721 sunlabel->ilfact = SUN_SSWAP16(1); 2722 sunlabel->sparecyl = 0; 2723 } else { 2724 heads = read_int(1,heads,1024,0,_("Heads")); 2725 sectors = read_int(1,sectors,1024,0,_("Sectors/track")); 2726 if (cylinders) 2727 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders")); 2728 else 2729 cylinders = read_int(1,0,65535,0,_("Cylinders")); 2730 sunlabel->nacyl = SUN_SSWAP16(read_int(0,2,65535,0, _("Alternate cylinders"))); 2731 sunlabel->pcylcount = SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535,0, _("Physical cylinders"))); 2732 sunlabel->rspeed = SUN_SSWAP16(read_int(1,5400,100000,0, _("Rotation speed (rpm)"))); 2733 sunlabel->ilfact = SUN_SSWAP16(read_int(1,1,32,0, _("Interleave factor"))); 2734 sunlabel->sparecyl = SUN_SSWAP16(read_int(0,0,sectors,0, _("Extra sectors per cylinder"))); 2735 } 2736 } else { 2737 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl); 2738 sunlabel->ncyl = SUN_SSWAP16(p->ncyl); 2739 sunlabel->nacyl = SUN_SSWAP16(p->nacyl); 2740 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount); 2741 sunlabel->ntrks = SUN_SSWAP16(p->ntrks); 2742 sunlabel->nsect = SUN_SSWAP16(p->nsect); 2743 sunlabel->rspeed = SUN_SSWAP16(p->rspeed); 2744 sunlabel->ilfact = SUN_SSWAP16(1); 2745 cylinders = p->ncyl; 2746 heads = p->ntrks; 2747 sectors = p->nsect; 2748 puts(_("You may change all the disk params from the x menu")); 2749 } 2750 2751 snprintf((char *)(sunlabel->info), sizeof(sunlabel->info), 2752 "%s%s%s cyl %d alt %d hd %d sec %d", 2753 p ? p->vendor : "", (p && *p->vendor) ? " " : "", 2754 p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")), 2755 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors); 2756 2757 sunlabel->ntrks = SUN_SSWAP16(heads); 2758 sunlabel->nsect = SUN_SSWAP16(sectors); 2759 sunlabel->ncyl = SUN_SSWAP16(cylinders); 2760 if (floppy) 2761 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE); 2762 else { 2763 if (cylinders * heads * sectors >= 150 * 2048) { 2764 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */ 2765 } else 2766 ndiv = cylinders * 2 / 3; 2767 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE); 2768 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP); 2769 sunlabel->infos[1].flags |= 0x01; /* Not mountable */ 2770 } 2771 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK); 2772 { 2773 unsigned short *ush = (unsigned short *)sunlabel; 2774 unsigned short csum = 0; 2775 while (ush < (unsigned short *)(&sunlabel->csum)) 2776 csum ^= *ush++; 2777 sunlabel->csum = csum; 2778 } 2779 2780 set_all_unchanged(); 2781 set_changed(0); 2782 get_boot(create_empty_sun); 2783 } 2784 2785 static void 2786 toggle_sunflags(int i, unsigned char mask) 2787 { 2788 if (sunlabel->infos[i].flags & mask) 2789 sunlabel->infos[i].flags &= ~mask; 2790 else 2791 sunlabel->infos[i].flags |= mask; 2792 set_changed(i); 2793 } 2794 2795 static void 2796 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) 2797 { 2798 int i, continuous = 1; 2799 2800 *start = 0; 2801 *stop = cylinders * heads * sectors; 2802 for (i = 0; i < partitions; i++) { 2803 if (sunlabel->partitions[i].num_sectors 2804 && sunlabel->infos[i].id 2805 && sunlabel->infos[i].id != WHOLE_DISK) { 2806 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors; 2807 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors); 2808 if (continuous) { 2809 if (starts[i] == *start) 2810 *start += lens[i]; 2811 else if (starts[i] + lens[i] >= *stop) 2812 *stop = starts[i]; 2813 else 2814 continuous = 0; 2815 /* There will be probably more gaps 2816 than one, so lets check afterwards */ 2817 } 2818 } else { 2819 starts[i] = 0; 2820 lens[i] = 0; 2821 } 2822 } 2823 } 2824 2825 static uint *verify_sun_starts; 2826 2827 static int 2828 verify_sun_cmp(int *a, int *b) 2829 { 2830 if (*a == -1) return 1; 2831 if (*b == -1) return -1; 2832 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1; 2833 return -1; 2834 } 2835 2836 static void 2837 verify_sun(void) 2838 { 2839 uint starts[8], lens[8], start, stop; 2840 int i,j,k,starto,endo; 2841 int array[8]; 2842 2843 verify_sun_starts = starts; 2844 fetch_sun(starts,lens,&start,&stop); 2845 for (k = 0; k < 7; k++) { 2846 for (i = 0; i < 8; i++) { 2847 if (k && (lens[i] % (heads * sectors))) { 2848 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1); 2849 } 2850 if (lens[i]) { 2851 for (j = 0; j < i; j++) 2852 if (lens[j]) { 2853 if (starts[j] == starts[i]+lens[i]) { 2854 starts[j] = starts[i]; lens[j] += lens[i]; 2855 lens[i] = 0; 2856 } else if (starts[i] == starts[j]+lens[j]){ 2857 lens[j] += lens[i]; 2858 lens[i] = 0; 2859 } else if (!k) { 2860 if (starts[i] < starts[j]+lens[j] 2861 && starts[j] < starts[i]+lens[i]) { 2862 starto = starts[i]; 2863 if (starts[j] > starto) 2864 starto = starts[j]; 2865 endo = starts[i]+lens[i]; 2866 if (starts[j]+lens[j] < endo) 2867 endo = starts[j]+lens[j]; 2868 printf(_("Partition %d overlaps with others in " 2869 "sectors %d-%d\n"), i+1, starto, endo); 2870 } 2871 } 2872 } 2873 } 2874 } 2875 } 2876 for (i = 0; i < 8; i++) { 2877 if (lens[i]) 2878 array[i] = i; 2879 else 2880 array[i] = -1; 2881 } 2882 qsort(array,SIZE(array),sizeof(array[0]), 2883 (int (*)(const void *,const void *)) verify_sun_cmp); 2884 if (array[0] == -1) { 2885 printf(_("No partitions defined\n")); 2886 return; 2887 } 2888 stop = cylinders * heads * sectors; 2889 if (starts[array[0]]) 2890 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]); 2891 for (i = 0; i < 7 && array[i+1] != -1; i++) { 2892 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]); 2893 } 2894 start = starts[array[i]] + lens[array[i]]; 2895 if (start < stop) 2896 printf(_("Unused gap - sectors %d-%d\n"),start,stop); 2897 } 2898 2899 static void 2900 add_sun_partition(int n, int sys) 2901 { 2902 uint start, stop, stop2; 2903 uint starts[8], lens[8]; 2904 int whole_disk = 0; 2905 2906 char mesg[256]; 2907 int i, first, last; 2908 2909 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) { 2910 printf(_("Partition %d is already defined. Delete " 2911 "it before re-adding it.\n"), n + 1); 2912 return; 2913 } 2914 2915 fetch_sun(starts,lens,&start,&stop); 2916 if (stop <= start) { 2917 if (n == 2) 2918 whole_disk = 1; 2919 else { 2920 printf(_("Other partitions already cover the whole disk.\nDelete " 2921 "some/shrink them before retry.\n")); 2922 return; 2923 } 2924 } 2925 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR)); 2926 while (1) { 2927 if (whole_disk) 2928 first = read_int(0, 0, 0, 0, mesg); 2929 else 2930 first = read_int(scround(start), scround(stop)+1, 2931 scround(stop), 0, mesg); 2932 if (display_in_cyl_units) 2933 first *= units_per_sector; 2934 else 2935 /* Starting sector has to be properly aligned */ 2936 first = (first + heads * sectors - 1) / (heads * sectors); 2937 if (n == 2 && first != 0) 2938 printf("\ 2939 It is highly recommended that the third partition covers the whole disk\n\ 2940 and is of type `Whole disk'\n"); 2941 /* ewt asks to add: "don't start a partition at cyl 0" 2942 However, edmundo@rano.demon.co.uk writes: 2943 "In addition to having a Sun partition table, to be able to 2944 boot from the disc, the first partition, /dev/sdX1, must 2945 start at cylinder 0. This means that /dev/sdX1 contains 2946 the partition table and the boot block, as these are the 2947 first two sectors of the disc. Therefore you must be 2948 careful what you use /dev/sdX1 for. In particular, you must 2949 not use a partition starting at cylinder 0 for Linux swap, 2950 as that would overwrite the partition table and the boot 2951 block. You may, however, use such a partition for a UFS 2952 or EXT2 file system, as these file systems leave the first 2953 1024 bytes undisturbed. */ 2954 /* On the other hand, one should not use partitions 2955 starting at block 0 in an md, or the label will 2956 be trashed. */ 2957 for (i = 0; i < partitions; i++) 2958 if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first) 2959 break; 2960 if (i < partitions && !whole_disk) { 2961 if (n == 2 && !first) { 2962 whole_disk = 1; 2963 break; 2964 } 2965 printf(_("Sector %d is already allocated\n"), first); 2966 } else 2967 break; 2968 } 2969 stop = cylinders * heads * sectors; 2970 stop2 = stop; 2971 for (i = 0; i < partitions; i++) { 2972 if (starts[i] > first && starts[i] < stop) 2973 stop = starts[i]; 2974 } 2975 snprintf(mesg, sizeof(mesg), 2976 _("Last %s or +size or +sizeM or +sizeK"), 2977 str_units(SINGULAR)); 2978 if (whole_disk) 2979 last = read_int(scround(stop2), scround(stop2), scround(stop2), 2980 0, mesg); 2981 else if (n == 2 && !first) 2982 last = read_int(scround(first), scround(stop2), scround(stop2), 2983 scround(first), mesg); 2984 else 2985 last = read_int(scround(first), scround(stop), scround(stop), 2986 scround(first), mesg); 2987 if (display_in_cyl_units) 2988 last *= units_per_sector; 2989 if (n == 2 && !first) { 2990 if (last >= stop2) { 2991 whole_disk = 1; 2992 last = stop2; 2993 } else if (last > stop) { 2994 printf(_("You haven't covered the whole disk with " 2995 "the 3rd partition, but your value\n" 2996 "%d %s covers some other partition. " 2997 "Your entry has been changed\n" 2998 "to %d %s\n"), 2999 scround(last), str_units(SINGULAR), 3000 scround(stop), str_units(SINGULAR)); 3001 last = stop; 3002 } 3003 } else if (!whole_disk && last > stop) 3004 last = stop; 3005 3006 if (whole_disk) 3007 sys = WHOLE_DISK; 3008 set_sun_partition(n, first, last, sys); 3009 } 3010 3011 static void 3012 sun_delete_partition(int i) 3013 { 3014 unsigned int nsec; 3015 3016 if (i == 2 3017 && sunlabel->infos[i].id == WHOLE_DISK 3018 && !sunlabel->partitions[i].start_cylinder 3019 && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders) 3020 printf(_("If you want to maintain SunOS/Solaris compatibility, " 3021 "consider leaving this\n" 3022 "partition as Whole disk (5), starting at 0, with %u " 3023 "sectors\n"), nsec); 3024 sunlabel->infos[i].id = 0; 3025 sunlabel->partitions[i].num_sectors = 0; 3026 } 3027 3028 static void 3029 sun_change_sysid(int i, int sys) 3030 { 3031 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) { 3032 read_chars( 3033 _("It is highly recommended that the partition at offset 0\n" 3034 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n" 3035 "there may destroy your partition table and bootblock.\n" 3036 "Type YES if you're very sure you would like that partition\n" 3037 "tagged with 82 (Linux swap): ")); 3038 if (strcmp (line_ptr, _("YES\n"))) 3039 return; 3040 } 3041 switch (sys) { 3042 case SUNOS_SWAP: 3043 case LINUX_SWAP: 3044 /* swaps are not mountable by default */ 3045 sunlabel->infos[i].flags |= 0x01; 3046 break; 3047 default: 3048 /* assume other types are mountable; 3049 user can change it anyway */ 3050 sunlabel->infos[i].flags &= ~0x01; 3051 break; 3052 } 3053 sunlabel->infos[i].id = sys; 3054 } 3055 3056 static void 3057 sun_list_table(int xtra) 3058 { 3059 int i, w; 3060 3061 w = strlen(disk_device); 3062 if (xtra) 3063 printf( 3064 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n" 3065 "%d cylinders, %d alternate cylinders, %d physical cylinders\n" 3066 "%d extra sects/cyl, interleave %d:1\n" 3067 "%s\n" 3068 "Units = %s of %d * 512 bytes\n\n"), 3069 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed), 3070 cylinders, SUN_SSWAP16(sunlabel->nacyl), 3071 SUN_SSWAP16(sunlabel->pcylcount), 3072 SUN_SSWAP16(sunlabel->sparecyl), 3073 SUN_SSWAP16(sunlabel->ilfact), 3074 (char *)sunlabel, 3075 str_units(PLURAL), units_per_sector); 3076 else 3077 printf( 3078 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n" 3079 "Units = %s of %d * 512 bytes\n\n"), 3080 disk_device, heads, sectors, cylinders, 3081 str_units(PLURAL), units_per_sector); 3082 3083 printf(_("%*s Flag Start End Blocks Id System\n"), 3084 w + 1, _("Device")); 3085 for (i = 0 ; i < partitions; i++) { 3086 if (sunlabel->partitions[i].num_sectors) { 3087 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors; 3088 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors); 3089 printf("%s %c%c %9ld %9ld %9ld%c %2x %s\n", 3090 partname(disk_device, i+1, w), /* device */ 3091 (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', /* flags */ 3092 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ', 3093 (long) scround(start), /* start */ 3094 (long) scround(start+len), /* end */ 3095 (long) len / 2, len & 1 ? '+' : ' ', /* odd flag on end */ 3096 sunlabel->infos[i].id, /* type id */ 3097 partition_type(sunlabel->infos[i].id)); /* type name */ 3098 } 3099 } 3100 } 3101 3102 #ifdef CONFIG_FEATURE_FDISK_ADVANCED 3103 3104 static void 3105 sun_set_alt_cyl(void) 3106 { 3107 sunlabel->nacyl = 3108 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0, 3109 _("Number of alternate cylinders"))); 3110 } 3111 3112 static void 3113 sun_set_ncyl(int cyl) 3114 { 3115 sunlabel->ncyl = SUN_SSWAP16(cyl); 3116 } 3117 3118 static void 3119 sun_set_xcyl(void) 3120 { 3121 sunlabel->sparecyl = 3122 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0, 3123 _("Extra sectors per cylinder"))); 3124 } 3125 3126 static void 3127 sun_set_ilfact(void) 3128 { 3129 sunlabel->ilfact = 3130 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0, 3131 _("Interleave factor"))); 3132 } 3133 3134 static void 3135 sun_set_rspeed(void) 3136 { 3137 sunlabel->rspeed = 3138 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0, 3139 _("Rotation speed (rpm)"))); 3140 } 3141 3142 static void 3143 sun_set_pcylcount(void) 3144 { 3145 sunlabel->pcylcount = 3146 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0, 3147 _("Number of physical cylinders"))); 3148 } 3149 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */ 3150 3151 static void 3152 sun_write_table(void) 3153 { 3154 unsigned short *ush = (unsigned short *)sunlabel; 3155 unsigned short csum = 0; 3156 3157 while (ush < (unsigned short *)(&sunlabel->csum)) 3158 csum ^= *ush++; 3159 sunlabel->csum = csum; 3160 if (lseek(fd, 0, SEEK_SET) < 0) 3161 fdisk_fatal(unable_to_seek); 3162 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE) 3163 fdisk_fatal(unable_to_write); 3164 } 3165 #endif /* SUN_LABEL */ 3166 3167 /* DOS partition types */ 3168 3169 static const struct systypes i386_sys_types[] = { 3170 { "\x00" "Empty" }, 3171 { "\x01" "FAT12" }, 3172 { "\x04" "FAT16 <32M" }, 3173 { "\x05" "Extended" }, /* DOS 3.3+ extended partition */ 3174 { "\x06" "FAT16" }, /* DOS 16-bit >=32M */ 3175 { "\x07" "HPFS/NTFS" }, /* OS/2 IFS, eg, HPFS or NTFS or QNX */ 3176 { "\x0a" "OS/2 Boot Manager" },/* OS/2 Boot Manager */ 3177 { "\x0b" "Win95 FAT32" }, 3178 { "\x0c" "Win95 FAT32 (LBA)" },/* LBA really is `Extended Int 13h' */ 3179 { "\x0e" "Win95 FAT16 (LBA)" }, 3180 { "\x0f" "Win95 Ext'd (LBA)" }, 3181 { "\x11" "Hidden FAT12" }, 3182 { "\x12" "Compaq diagnostics" }, 3183 { "\x14" "Hidden FAT16 <32M" }, 3184 { "\x16" "Hidden FAT16" }, 3185 { "\x17" "Hidden HPFS/NTFS" }, 3186 { "\x1b" "Hidden Win95 FAT32" }, 3187 { "\x1c" "Hidden Win95 FAT32 (LBA)" }, 3188 { "\x1e" "Hidden Win95 FAT16 (LBA)" }, 3189 { "\x3c" "PartitionMagic recovery" }, 3190 { "\x41" "PPC PReP Boot" }, 3191 { "\x42" "SFS" }, 3192 { "\x63" "GNU HURD or SysV" }, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */ 3193 { "\x80" "Old Minix" }, /* Minix 1.4a and earlier */ 3194 { "\x81" "Minix / old Linux" },/* Minix 1.4b and later */ 3195 { "\x82" "Linux swap" }, /* also Solaris */ 3196 { "\x83" "Linux" }, 3197 { "\x84" "OS/2 hidden C: drive" }, 3198 { "\x85" "Linux extended" }, 3199 { "\x86" "NTFS volume set" }, 3200 { "\x87" "NTFS volume set" }, 3201 { "\x8e" "Linux LVM" }, 3202 { "\x9f" "BSD/OS" }, /* BSDI */ 3203 { "\xa0" "IBM Thinkpad hibernation" }, 3204 { "\xa5" "FreeBSD" }, /* various BSD flavours */ 3205 { "\xa6" "OpenBSD" }, 3206 { "\xa8" "Darwin UFS" }, 3207 { "\xa9" "NetBSD" }, 3208 { "\xab" "Darwin boot" }, 3209 { "\xb7" "BSDI fs" }, 3210 { "\xb8" "BSDI swap" }, 3211 { "\xbe" "Solaris boot" }, 3212 { "\xeb" "BeOS fs" }, 3213 { "\xee" "EFI GPT" }, /* Intel EFI GUID Partition Table */ 3214 { "\xef" "EFI (FAT-12/16/32)" },/* Intel EFI System Partition */ 3215 { "\xf0" "Linux/PA-RISC boot" },/* Linux/PA-RISC boot loader */ 3216 { "\xf2" "DOS secondary" }, /* DOS 3.3+ secondary */ 3217 { "\xfd" "Linux raid autodetect" },/* New (2.2.x) raid partition with 3218 autodetect using persistent 3219 superblock */ 3220 #ifdef CONFIG_WEIRD_PARTITION_TYPES 3221 { "\x02" "XENIX root" }, 3222 { "\x03" "XENIX usr" }, 3223 { "\x08" "AIX" }, /* AIX boot (AIX -- PS/2 port) or SplitDrive */ 3224 { "\x09" "AIX bootable" }, /* AIX data or Coherent */ 3225 { "\x10" "OPUS" }, 3226 { "\x18" "AST SmartSleep" }, 3227 { "\x24" "NEC DOS" }, 3228 { "\x39" "Plan 9" }, 3229 { "\x40" "Venix 80286" }, 3230 { "\x4d" "QNX4.x" }, 3231 { "\x4e" "QNX4.x 2nd part" }, 3232 { "\x4f" "QNX4.x 3rd part" }, 3233 { "\x50" "OnTrack DM" }, 3234 { "\x51" "OnTrack DM6 Aux1" }, /* (or Novell) */ 3235 { "\x52" "CP/M" }, /* CP/M or Microport SysV/AT */ 3236 { "\x53" "OnTrack DM6 Aux3" }, 3237 { "\x54" "OnTrackDM6" }, 3238 { "\x55" "EZ-Drive" }, 3239 { "\x56" "Golden Bow" }, 3240 { "\x5c" "Priam Edisk" }, 3241 { "\x61" "SpeedStor" }, 3242 { "\x64" "Novell Netware 286" }, 3243 { "\x65" "Novell Netware 386" }, 3244 { "\x70" "DiskSecure Multi-Boot" }, 3245 { "\x75" "PC/IX" }, 3246 { "\x93" "Amoeba" }, 3247 { "\x94" "Amoeba BBT" }, /* (bad block table) */ 3248 { "\xa7" "NeXTSTEP" }, 3249 { "\xbb" "Boot Wizard hidden" }, 3250 { "\xc1" "DRDOS/sec (FAT-12)" }, 3251 { "\xc4" "DRDOS/sec (FAT-16 < 32M)" }, 3252 { "\xc6" "DRDOS/sec (FAT-16)" }, 3253 { "\xc7" "Syrinx" }, 3254 { "\xda" "Non-FS data" }, 3255 { "\xdb" "CP/M / CTOS / ..." },/* CP/M or Concurrent CP/M or 3256 Concurrent DOS or CTOS */ 3257 { "\xde" "Dell Utility" }, /* Dell PowerEdge Server utilities */ 3258 { "\xdf" "BootIt" }, /* BootIt EMBRM */ 3259 { "\xe1" "DOS access" }, /* DOS access or SpeedStor 12-bit FAT 3260 extended partition */ 3261 { "\xe3" "DOS R/O" }, /* DOS R/O or SpeedStor */ 3262 { "\xe4" "SpeedStor" }, /* SpeedStor 16-bit FAT extended 3263 partition < 1024 cyl. */ 3264 { "\xf1" "SpeedStor" }, 3265 { "\xf4" "SpeedStor" }, /* SpeedStor large partition */ 3266 { "\xfe" "LANstep" }, /* SpeedStor >1024 cyl. or LANstep */ 3267 { "\xff" "BBT" }, /* Xenix Bad Block Table */ 3268 #endif 3269 { 0 } 3270 }; 3271 3272 3273 3274 /* A valid partition table sector ends in 0x55 0xaa */ 3275 static unsigned int 3276 part_table_flag(const char *b) 3277 { 3278 return ((uint) b[510]) + (((uint) b[511]) << 8); 3279 } 3280 3281 3282 #ifdef CONFIG_FEATURE_FDISK_WRITABLE 3283 static void 3284 write_part_table_flag(char *b) 3285 { 3286 b[510] = 0x55; 3287 b[511] = 0xaa; 3288 } 3289 505 STATIC_OSF void bsd_select(void); 506 STATIC_OSF void xbsd_print_disklabel(int); 507 #include "fdisk_osf.c" 508 509 #if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL 510 static uint16_t 511 fdisk_swap16(uint16_t x) 512 { 513 return (x << 8) | (x >> 8); 514 } 515 516 static uint32_t 517 fdisk_swap32(uint32_t x) 518 { 519 return (x << 24) | 520 ((x & 0xFF00) << 8) | 521 ((x & 0xFF0000) >> 8) | 522 (x >> 24); 523 } 524 #endif 525 526 STATIC_SGI const char *const sgi_sys_types[]; 527 STATIC_SGI unsigned sgi_get_num_sectors(int i); 528 STATIC_SGI int sgi_get_sysid(int i); 529 STATIC_SGI void sgi_delete_partition(int i); 530 STATIC_SGI void sgi_change_sysid(int i, int sys); 531 STATIC_SGI void sgi_list_table(int xtra); 532 #if ENABLE_FEATURE_FDISK_ADVANCED 533 STATIC_SGI void sgi_set_xcyl(void); 534 #endif 535 STATIC_SGI int verify_sgi(int verbose); 536 STATIC_SGI void sgi_add_partition(int n, int sys); 537 STATIC_SGI void sgi_set_swappartition(int i); 538 STATIC_SGI const char *sgi_get_bootfile(void); 539 STATIC_SGI void sgi_set_bootfile(const char* aFile); 540 STATIC_SGI void create_sgiinfo(void); 541 STATIC_SGI void sgi_write_table(void); 542 STATIC_SGI void sgi_set_bootpartition(int i); 543 #include "fdisk_sgi.c" 544 545 STATIC_SUN const char *const sun_sys_types[]; 546 STATIC_SUN void sun_delete_partition(int i); 547 STATIC_SUN void sun_change_sysid(int i, int sys); 548 STATIC_SUN void sun_list_table(int xtra); 549 STATIC_SUN void add_sun_partition(int n, int sys); 550 #if ENABLE_FEATURE_FDISK_ADVANCED 551 STATIC_SUN void sun_set_alt_cyl(void); 552 STATIC_SUN void sun_set_ncyl(int cyl); 553 STATIC_SUN void sun_set_xcyl(void); 554 STATIC_SUN void sun_set_ilfact(void); 555 STATIC_SUN void sun_set_rspeed(void); 556 STATIC_SUN void sun_set_pcylcount(void); 557 #endif 558 STATIC_SUN void toggle_sunflags(int i, unsigned char mask); 559 STATIC_SUN void verify_sun(void); 560 STATIC_SUN void sun_write_table(void); 561 #include "fdisk_sun.c" 562 563 #if ENABLE_FEATURE_FDISK_WRITABLE 3290 564 /* start_sect and nr_sects are stored little endian on all machines */ 3291 565 /* moreover, they are not aligned correctly */ 3292 566 static void 3293 store4_little_endian(unsigned char *cp, unsigned intval)3294 { 3295 cp[0] = (val & 0xff);3296 cp[1] = ((val >> 8) & 0xff);3297 cp[2] = ((val >> 16) & 0xff);3298 cp[3] = ((val >> 24) & 0xff);3299 } 3300 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */3301 3302 static unsigned int567 store4_little_endian(unsigned char *cp, unsigned val) 568 { 569 cp[0] = val; 570 cp[1] = val >> 8; 571 cp[2] = val >> 16; 572 cp[3] = val >> 24; 573 } 574 #endif /* FEATURE_FDISK_WRITABLE */ 575 576 static unsigned 3303 577 read4_little_endian(const unsigned char *cp) 3304 578 { 3305 return (uint)(cp[0]) + ((uint)(cp[1]) << 8) 3306 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24); 3307 } 3308 3309 #ifdef CONFIG_FEATURE_FDISK_WRITABLE 3310 static void 3311 set_start_sect(struct partition *p, unsigned int start_sect) 579 return cp[0] + (cp[1] << 8) + (cp[2] << 16) + (cp[3] << 24); 580 } 581 582 #if ENABLE_FEATURE_FDISK_WRITABLE 583 static void 584 set_start_sect(struct partition *p, unsigned start_sect) 3312 585 { 3313 586 store4_little_endian(p->start4, start_sect); … … 3315 588 #endif 3316 589 3317 static int32_t590 static unsigned 3318 591 get_start_sect(const struct partition *p) 3319 592 { … … 3321 594 } 3322 595 3323 #if def CONFIG_FEATURE_FDISK_WRITABLE3324 static void 3325 set_nr_sects(struct partition *p, int32_tnr_sects)596 #if ENABLE_FEATURE_FDISK_WRITABLE 597 static void 598 set_nr_sects(struct partition *p, unsigned nr_sects) 3326 599 { 3327 600 store4_little_endian(p->size4, nr_sects); … … 3329 602 #endif 3330 603 3331 static int32_t604 static unsigned 3332 605 get_nr_sects(const struct partition *p) 3333 606 { … … 3338 611 static int type_open = O_RDWR; 3339 612 3340 3341 613 static int ext_index; /* the prime extended partition */ 3342 static int listing; 614 static int listing; /* no aborts for fdisk -l */ 3343 615 static int dos_compatible_flag = ~0; 3344 #if def CONFIG_FEATURE_FDISK_WRITABLE616 #if ENABLE_FEATURE_FDISK_WRITABLE 3345 617 static int dos_changed; 3346 618 static int nowarn; /* no warnings for fdisk -l/-s */ 3347 619 #endif 3348 620 3349 3350 3351 static uint user_cylinders, user_heads, user_sectors; 3352 static uint pt_heads, pt_sectors; 3353 static uint kern_heads, kern_sectors; 3354 3355 static off_t extended_offset; /* offset of link pointers */ 3356 3357 static unsigned long long total_number_of_sectors; 3358 3359 3360 static jmp_buf listingbuf; 3361 3362 static void fdisk_fatal(enum failure why) 3363 { 3364 const char *message; 3365 621 static unsigned user_cylinders, user_heads, user_sectors; 622 static unsigned pt_heads, pt_sectors; 623 static unsigned kern_heads, kern_sectors; 624 625 static ullong extended_offset; /* offset of link pointers */ 626 static ullong total_number_of_sectors; 627 628 static void fdisk_fatal(const char *why) 629 { 3366 630 if (listing) { 3367 631 close(fd); 3368 632 longjmp(listingbuf, 1); 3369 633 } 3370 3371 switch (why) { 3372 case unable_to_open: 3373 message = "Unable to open %s\n"; 3374 break; 3375 case unable_to_read: 3376 message = "Unable to read %s\n"; 3377 break; 3378 case unable_to_seek: 3379 message = "Unable to seek on %s\n"; 3380 break; 3381 case unable_to_write: 3382 message = "Unable to write %s\n"; 3383 break; 3384 case ioctl_error: 3385 message = "BLKGETSIZE ioctl failed on %s\n"; 3386 break; 3387 default: 3388 message = "Fatal error\n"; 3389 } 3390 3391 fputc('\n', stderr); 3392 fprintf(stderr, message, disk_device); 3393 exit(1); 3394 } 3395 3396 static void 3397 seek_sector(off_t secno) 3398 { 3399 off_t offset = secno * sector_size; 3400 if (lseek(fd, offset, SEEK_SET) == (off_t) -1) 634 bb_error_msg_and_die(why, disk_device); 635 } 636 637 static void 638 seek_sector(ullong secno) 639 { 640 secno *= sector_size; 641 #if ENABLE_FDISK_SUPPORT_LARGE_DISKS 642 if (lseek64(fd, (off64_t)secno, SEEK_SET) == (off64_t) -1) 3401 643 fdisk_fatal(unable_to_seek); 3402 } 3403 3404 #ifdef CONFIG_FEATURE_FDISK_WRITABLE 3405 static void 3406 write_sector(off_t secno, char *buf) 644 #else 645 if (secno > MAXINT(off_t) 646 || lseek(fd, (off_t)secno, SEEK_SET) == (off_t) -1 647 ) { 648 fdisk_fatal(unable_to_seek); 649 } 650 #endif 651 } 652 653 #if ENABLE_FEATURE_FDISK_WRITABLE 654 static void 655 write_sector(ullong secno, char *buf) 3407 656 { 3408 657 seek_sector(secno); … … 3414 663 /* Allocate a buffer and read a partition table sector */ 3415 664 static void 3416 read_pte(struct pte *pe, off_toffset)665 read_pte(struct pte *pe, ullong offset) 3417 666 { 3418 667 pe->offset = offset; 3419 pe->sectorbuffer = (char *)xmalloc(sector_size);668 pe->sectorbuffer = xmalloc(sector_size); 3420 669 seek_sector(offset); 3421 670 if (read(fd, pe->sectorbuffer, sector_size) != sector_size) 3422 671 fdisk_fatal(unable_to_read); 3423 #if def CONFIG_FEATURE_FDISK_WRITABLE672 #if ENABLE_FEATURE_FDISK_WRITABLE 3424 673 pe->changed = 0; 3425 674 #endif … … 3427 676 } 3428 677 3429 static unsigned int678 static unsigned 3430 679 get_partition_start(const struct pte *pe) 3431 680 { … … 3433 682 } 3434 683 3435 #if def CONFIG_FEATURE_FDISK_WRITABLE684 #if ENABLE_FEATURE_FDISK_WRITABLE 3436 685 /* 3437 686 * Avoid warning about DOS partitions when no DOS partition was changed. … … 3453 702 menu(void) 3454 703 { 3455 #ifdef CONFIG_FEATURE_SUN_LABEL 3456 if (label_sun == current_label_type) { 3457 puts(_("Command action")); 3458 puts(_("\ta\ttoggle a read only flag")); /* sun */ 3459 puts(_("\tb\tedit bsd disklabel")); 3460 puts(_("\tc\ttoggle the mountable flag")); /* sun */ 3461 puts(_("\td\tdelete a partition")); 3462 puts(_("\tl\tlist known partition types")); 3463 puts(_("\tm\tprint this menu")); 3464 puts(_("\tn\tadd a new partition")); 3465 puts(_("\to\tcreate a new empty DOS partition table")); 3466 puts(_("\tp\tprint the partition table")); 3467 puts(_("\tq\tquit without saving changes")); 3468 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */ 3469 puts(_("\tt\tchange a partition's system id")); 3470 puts(_("\tu\tchange display/entry units")); 3471 puts(_("\tv\tverify the partition table")); 3472 puts(_("\tw\twrite table to disk and exit")); 3473 #ifdef CONFIG_FEATURE_FDISK_ADVANCED 3474 puts(_("\tx\textra functionality (experts only)")); 3475 #endif 3476 } else 3477 #endif 3478 #ifdef CONFIG_FEATURE_SGI_LABEL 3479 if (label_sgi == current_label_type) { 3480 puts(_("Command action")); 3481 puts(_("\ta\tselect bootable partition")); /* sgi flavour */ 3482 puts(_("\tb\tedit bootfile entry")); /* sgi */ 3483 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */ 3484 puts(_("\td\tdelete a partition")); 3485 puts(_("\tl\tlist known partition types")); 3486 puts(_("\tm\tprint this menu")); 3487 puts(_("\tn\tadd a new partition")); 3488 puts(_("\to\tcreate a new empty DOS partition table")); 3489 puts(_("\tp\tprint the partition table")); 3490 puts(_("\tq\tquit without saving changes")); 3491 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */ 3492 puts(_("\tt\tchange a partition's system id")); 3493 puts(_("\tu\tchange display/entry units")); 3494 puts(_("\tv\tverify the partition table")); 3495 puts(_("\tw\twrite table to disk and exit")); 3496 } else 3497 #endif 3498 #ifdef CONFIG_FEATURE_AIX_LABEL 3499 if (label_aix == current_label_type) { 3500 puts(_("Command action")); 3501 puts(_("\tm\tprint this menu")); 3502 puts(_("\to\tcreate a new empty DOS partition table")); 3503 puts(_("\tq\tquit without saving changes")); 3504 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */ 3505 } else 3506 #endif 3507 { 3508 puts(_("Command action")); 3509 puts(_("\ta\ttoggle a bootable flag")); 3510 puts(_("\tb\tedit bsd disklabel")); 3511 puts(_("\tc\ttoggle the dos compatibility flag")); 3512 puts(_("\td\tdelete a partition")); 3513 puts(_("\tl\tlist known partition types")); 3514 puts(_("\tm\tprint this menu")); 3515 puts(_("\tn\tadd a new partition")); 3516 puts(_("\to\tcreate a new empty DOS partition table")); 3517 puts(_("\tp\tprint the partition table")); 3518 puts(_("\tq\tquit without saving changes")); 3519 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */ 3520 puts(_("\tt\tchange a partition's system id")); 3521 puts(_("\tu\tchange display/entry units")); 3522 puts(_("\tv\tverify the partition table")); 3523 puts(_("\tw\twrite table to disk and exit")); 3524 #ifdef CONFIG_FEATURE_FDISK_ADVANCED 3525 puts(_("\tx\textra functionality (experts only)")); 3526 #endif 3527 } 3528 } 3529 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */ 3530 3531 3532 #ifdef CONFIG_FEATURE_FDISK_ADVANCED 704 puts("Command Action"); 705 if (LABEL_IS_SUN) { 706 puts("a\ttoggle a read only flag"); /* sun */ 707 puts("b\tedit bsd disklabel"); 708 puts("c\ttoggle the mountable flag"); /* sun */ 709 puts("d\tdelete a partition"); 710 puts("l\tlist known partition types"); 711 puts("n\tadd a new partition"); 712 puts("o\tcreate a new empty DOS partition table"); 713 puts("p\tprint the partition table"); 714 puts("q\tquit without saving changes"); 715 puts("s\tcreate a new empty Sun disklabel"); /* sun */ 716 puts("t\tchange a partition's system id"); 717 puts("u\tchange display/entry units"); 718 puts("v\tverify the partition table"); 719 puts("w\twrite table to disk and exit"); 720 #if ENABLE_FEATURE_FDISK_ADVANCED 721 puts("x\textra functionality (experts only)"); 722 #endif 723 } else if (LABEL_IS_SGI) { 724 puts("a\tselect bootable partition"); /* sgi flavour */ 725 puts("b\tedit bootfile entry"); /* sgi */ 726 puts("c\tselect sgi swap partition"); /* sgi flavour */ 727 puts("d\tdelete a partition"); 728 puts("l\tlist known partition types"); 729 puts("n\tadd a new partition"); 730 puts("o\tcreate a new empty DOS partition table"); 731 puts("p\tprint the partition table"); 732 puts("q\tquit without saving changes"); 733 puts("s\tcreate a new empty Sun disklabel"); /* sun */ 734 puts("t\tchange a partition's system id"); 735 puts("u\tchange display/entry units"); 736 puts("v\tverify the partition table"); 737 puts("w\twrite table to disk and exit"); 738 } else if (LABEL_IS_AIX) { 739 puts("o\tcreate a new empty DOS partition table"); 740 puts("q\tquit without saving changes"); 741 puts("s\tcreate a new empty Sun disklabel"); /* sun */ 742 } else { 743 puts("a\ttoggle a bootable flag"); 744 puts("b\tedit bsd disklabel"); 745 puts("c\ttoggle the dos compatibility flag"); 746 puts("d\tdelete a partition"); 747 puts("l\tlist known partition types"); 748 puts("n\tadd a new partition"); 749 puts("o\tcreate a new empty DOS partition table"); 750 puts("p\tprint the partition table"); 751 puts("q\tquit without saving changes"); 752 puts("s\tcreate a new empty Sun disklabel"); /* sun */ 753 puts("t\tchange a partition's system id"); 754 puts("u\tchange display/entry units"); 755 puts("v\tverify the partition table"); 756 puts("w\twrite table to disk and exit"); 757 #if ENABLE_FEATURE_FDISK_ADVANCED 758 puts("x\textra functionality (experts only)"); 759 #endif 760 } 761 } 762 #endif /* FEATURE_FDISK_WRITABLE */ 763 764 765 #if ENABLE_FEATURE_FDISK_ADVANCED 3533 766 static void 3534 767 xmenu(void) 3535 768 { 3536 #ifdef CONFIG_FEATURE_SUN_LABEL 3537 if (label_sun == current_label_type) { 3538 puts(_("Command action")); 3539 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/ 3540 puts(_("\tc\tchange number of cylinders")); 3541 puts(_("\td\tprint the raw data in the partition table")); 3542 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/ 3543 puts(_("\th\tchange number of heads")); 3544 puts(_("\ti\tchange interleave factor")); /*sun*/ 3545 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/ 3546 puts(_("\tm\tprint this menu")); 3547 puts(_("\tp\tprint the partition table")); 3548 puts(_("\tq\tquit without saving changes")); 3549 puts(_("\tr\treturn to main menu")); 3550 puts(_("\ts\tchange number of sectors/track")); 3551 puts(_("\tv\tverify the partition table")); 3552 puts(_("\tw\twrite table to disk and exit")); 3553 puts(_("\ty\tchange number of physical cylinders")); /*sun*/ 3554 } else 3555 #endif 3556 #ifdef CONFIG_FEATURE_SGI_LABEL 3557 if (label_sgi == current_label_type) { 3558 puts(_("Command action")); 3559 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */ 3560 puts(_("\tc\tchange number of cylinders")); 3561 puts(_("\td\tprint the raw data in the partition table")); 3562 puts(_("\te\tlist extended partitions")); /* !sun */ 3563 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */ 3564 puts(_("\th\tchange number of heads")); 3565 puts(_("\tm\tprint this menu")); 3566 puts(_("\tp\tprint the partition table")); 3567 puts(_("\tq\tquit without saving changes")); 3568 puts(_("\tr\treturn to main menu")); 3569 puts(_("\ts\tchange number of sectors/track")); 3570 puts(_("\tv\tverify the partition table")); 3571 puts(_("\tw\twrite table to disk and exit")); 3572 } else 3573 #endif 3574 #ifdef CONFIG_FEATURE_AIX_LABEL 3575 if (label_aix == current_label_type) { 3576 puts(_("Command action")); 3577 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */ 3578 puts(_("\tc\tchange number of cylinders")); 3579 puts(_("\td\tprint the raw data in the partition table")); 3580 puts(_("\te\tlist extended partitions")); /* !sun */ 3581 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */ 3582 puts(_("\th\tchange number of heads")); 3583 puts(_("\tm\tprint this menu")); 3584 puts(_("\tp\tprint the partition table")); 3585 puts(_("\tq\tquit without saving changes")); 3586 puts(_("\tr\treturn to main menu")); 3587 puts(_("\ts\tchange number of sectors/track")); 3588 puts(_("\tv\tverify the partition table")); 3589 puts(_("\tw\twrite table to disk and exit")); 3590 } else 3591 #endif 3592 { 3593 puts(_("Command action")); 3594 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */ 3595 puts(_("\tc\tchange number of cylinders")); 3596 puts(_("\td\tprint the raw data in the partition table")); 3597 puts(_("\te\tlist extended partitions")); /* !sun */ 3598 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */ 3599 #ifdef CONFIG_FEATURE_SGI_LABEL 3600 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */ 3601 #endif 3602 puts(_("\th\tchange number of heads")); 3603 puts(_("\tm\tprint this menu")); 3604 puts(_("\tp\tprint the partition table")); 3605 puts(_("\tq\tquit without saving changes")); 3606 puts(_("\tr\treturn to main menu")); 3607 puts(_("\ts\tchange number of sectors/track")); 3608 puts(_("\tv\tverify the partition table")); 3609 puts(_("\tw\twrite table to disk and exit")); 769 puts("Command Action"); 770 if (LABEL_IS_SUN) { 771 puts("a\tchange number of alternate cylinders"); /*sun*/ 772 puts("c\tchange number of cylinders"); 773 puts("d\tprint the raw data in the partition table"); 774 puts("e\tchange number of extra sectors per cylinder");/*sun*/ 775 puts("h\tchange number of heads"); 776 puts("i\tchange interleave factor"); /*sun*/ 777 puts("o\tchange rotation speed (rpm)"); /*sun*/ 778 puts("p\tprint the partition table"); 779 puts("q\tquit without saving changes"); 780 puts("r\treturn to main menu"); 781 puts("s\tchange number of sectors/track"); 782 puts("v\tverify the partition table"); 783 puts("w\twrite table to disk and exit"); 784 puts("y\tchange number of physical cylinders"); /*sun*/ 785 } else if (LABEL_IS_SGI) { 786 puts("b\tmove beginning of data in a partition"); /* !sun */ 787 puts("c\tchange number of cylinders"); 788 puts("d\tprint the raw data in the partition table"); 789 puts("e\tlist extended partitions"); /* !sun */ 790 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */ 791 puts("h\tchange number of heads"); 792 puts("p\tprint the partition table"); 793 puts("q\tquit without saving changes"); 794 puts("r\treturn to main menu"); 795 puts("s\tchange number of sectors/track"); 796 puts("v\tverify the partition table"); 797 puts("w\twrite table to disk and exit"); 798 } else if (LABEL_IS_AIX) { 799 puts("b\tmove beginning of data in a partition"); /* !sun */ 800 puts("c\tchange number of cylinders"); 801 puts("d\tprint the raw data in the partition table"); 802 puts("e\tlist extended partitions"); /* !sun */ 803 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */ 804 puts("h\tchange number of heads"); 805 puts("p\tprint the partition table"); 806 puts("q\tquit without saving changes"); 807 puts("r\treturn to main menu"); 808 puts("s\tchange number of sectors/track"); 809 puts("v\tverify the partition table"); 810 puts("w\twrite table to disk and exit"); 811 } else { 812 puts("b\tmove beginning of data in a partition"); /* !sun */ 813 puts("c\tchange number of cylinders"); 814 puts("d\tprint the raw data in the partition table"); 815 puts("e\tlist extended partitions"); /* !sun */ 816 puts("f\tfix partition order"); /* !sun, !aix, !sgi */ 817 #if ENABLE_FEATURE_SGI_LABEL 818 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */ 819 #endif 820 puts("h\tchange number of heads"); 821 puts("p\tprint the partition table"); 822 puts("q\tquit without saving changes"); 823 puts("r\treturn to main menu"); 824 puts("s\tchange number of sectors/track"); 825 puts("v\tverify the partition table"); 826 puts("w\twrite table to disk and exit"); 3610 827 } 3611 828 } 3612 829 #endif /* ADVANCED mode */ 3613 830 3614 #if def CONFIG_FEATURE_FDISK_WRITABLE3615 static const struct systypes*831 #if ENABLE_FEATURE_FDISK_WRITABLE 832 static const char *const * 3616 833 get_sys_types(void) 3617 834 { 3618 835 return ( 3619 #ifdef CONFIG_FEATURE_SUN_LABEL 3620 label_sun == current_label_type ? sun_sys_types : 3621 #endif 3622 #ifdef CONFIG_FEATURE_SGI_LABEL 3623 label_sgi == current_label_type ? sgi_sys_types : 3624 #endif 836 LABEL_IS_SUN ? sun_sys_types : 837 LABEL_IS_SGI ? sgi_sys_types : 3625 838 i386_sys_types); 3626 839 } 3627 840 #else 3628 841 #define get_sys_types() i386_sys_types 3629 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */ 3630 3631 static const char *partition_type(unsigned char type) 842 #endif /* FEATURE_FDISK_WRITABLE */ 843 844 static const char * 845 partition_type(unsigned char type) 3632 846 { 3633 847 int i; 3634 const struct systypes*types = get_sys_types();3635 3636 for (i = 0; types[i] .name; i++)3637 if ((unsigned char )types[i].name[0] == type)3638 return types[i] .name+ 1;3639 3640 return _("Unknown");3641 } 3642 3643 3644 #if def CONFIG_FEATURE_FDISK_WRITABLE848 const char *const *types = get_sys_types(); 849 850 for (i = 0; types[i]; i++) 851 if ((unsigned char)types[i][0] == type) 852 return types[i] + 1; 853 854 return "Unknown"; 855 } 856 857 858 #if ENABLE_FEATURE_FDISK_WRITABLE 3645 859 static int 3646 860 get_sysid(int i) 3647 861 { 3648 return ( 3649 #ifdef CONFIG_FEATURE_SUN_LABEL 3650 label_sun == current_label_type ? sunlabel->infos[i].id : 3651 #endif 3652 #ifdef CONFIG_FEATURE_SGI_LABEL 3653 label_sgi == current_label_type ? sgi_get_sysid(i) : 3654 #endif 3655 ptes[i].part_table->sys_ind); 3656 } 3657 3658 void list_types(const struct systypes *sys) 3659 { 3660 uint last[4], done = 0, next = 0, size; 862 return LABEL_IS_SUN ? sunlabel->infos[i].id : 863 (LABEL_IS_SGI ? sgi_get_sysid(i) : 864 ptes[i].part_table->sys_ind); 865 } 866 867 static void 868 list_types(const char *const *sys) 869 { 870 enum { COLS = 3 }; 871 872 unsigned last[COLS]; 873 unsigned done, next, size; 3661 874 int i; 3662 875 3663 for (i = 0; sys[i].name; i++); 3664 size = i; 3665 3666 for (i = 3; i >= 0; i--) 3667 last[3 - i] = done += (size + i - done) / (i + 1); 3668 i = done = 0; 3669 876 for (size = 0; sys[size]; size++) /* */; 877 878 done = 0; 879 for (i = COLS-1; i >= 0; i--) { 880 done += (size + i - done) / (i + 1); 881 last[COLS-1 - i] = done; 882 } 883 884 i = done = next = 0; 3670 885 do { 3671 printf("%c%2x %-15.15s", i ? ' ' : '\n',3672 (unsigned char)sys[next] .name[0],3673 partition_type((unsigned char)sys[next].name[0]));886 printf("%c%2x %-22.22s", i ? ' ' : '\n', 887 (unsigned char)sys[next][0], 888 sys[next] + 1); 3674 889 next = last[i++] + done; 3675 if (i > 3|| next >= last[i]) {890 if (i >= COLS || next >= last[i]) { 3676 891 i = 0; 3677 892 next = ++done; … … 3680 895 putchar('\n'); 3681 896 } 3682 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */897 #endif /* FEATURE_FDISK_WRITABLE */ 3683 898 3684 899 static int … … 3698 913 } 3699 914 3700 #if def CONFIG_FEATURE_FDISK_WRITABLE3701 static void 3702 set_partition(int i, int doext, off_t start, off_tstop, int sysid)915 #if ENABLE_FEATURE_FDISK_WRITABLE 916 static void 917 set_partition(int i, int doext, ullong start, ullong stop, int sysid) 3703 918 { 3704 919 struct partition *p; 3705 off_toffset;920 ullong offset; 3706 921 3707 922 if (doext) { … … 3727 942 3728 943 static int 3729 test_c(const char **m, const char *mesg)3730 {3731 int val = 0;3732 if (!*m)3733 fprintf(stderr, _("You must set"));3734 else {3735 fprintf(stderr, " %s", *m);3736 val = 1;3737 }3738 *m = mesg;3739 return val;3740 }3741 3742 static int3743 944 warn_geometry(void) 3744 945 { 3745 const char *m = NULL; 3746 int prev = 0; 3747 946 if (heads && sectors && cylinders) 947 return 0; 948 949 printf("Unknown value(s) for:"); 3748 950 if (!heads) 3749 pr ev = test_c(&m, _("heads"));951 printf(" heads"); 3750 952 if (!sectors) 3751 pr ev = test_c(&m, _("sectors"));953 printf(" sectors"); 3752 954 if (!cylinders) 3753 prev = test_c(&m, _("cylinders")); 3754 if (!m) 3755 return 0; 3756 3757 fprintf(stderr, "%s%s.\n" 3758 #ifdef CONFIG_FEATURE_FDISK_WRITABLE 3759 "You can do this from the extra functions menu.\n" 3760 #endif 3761 , prev ? _(" and ") : " ", m); 3762 955 printf(" cylinders"); 956 printf( 957 #if ENABLE_FEATURE_FDISK_WRITABLE 958 " (settable in the extra functions menu)" 959 #endif 960 "\n"); 3763 961 return 1; 3764 962 } 3765 963 3766 static void update_units(void) 964 static void 965 update_units(void) 3767 966 { 3768 967 int cyl_units = heads * sectors; … … 3774 973 } 3775 974 3776 #if def CONFIG_FEATURE_FDISK_WRITABLE975 #if ENABLE_FEATURE_FDISK_WRITABLE 3777 976 static void 3778 977 warn_cylinders(void) 3779 978 { 3780 if ( label_dos == current_label_type&& cylinders > 1024 && !nowarn)3781 fprintf(stderr, _("\n"979 if (LABEL_IS_DOS && cylinders > 1024 && !nowarn) 980 printf("\n" 3782 981 "The number of cylinders for this disk is set to %d.\n" 3783 982 "There is nothing wrong with that, but this is larger than 1024,\n" … … 3785 984 "1) software that runs at boot time (e.g., old versions of LILO)\n" 3786 985 "2) booting and partitioning software from other OSs\n" 3787 " (e.g., DOS FDISK, OS/2 FDISK)\n" ),986 " (e.g., DOS FDISK, OS/2 FDISK)\n", 3788 987 cylinders); 3789 988 } … … 3803 1002 p = pex->part_table; 3804 1003 if (!get_start_sect(p)) { 3805 fprintf(stderr, 3806 _("Bad offset in primary extended partition\n")); 1004 printf("Bad offset in primary extended partition\n"); 3807 1005 return; 3808 1006 } … … 3814 1012 /* This is not a Linux restriction, but 3815 1013 this program uses arrays of size MAXIMUM_PARTS. 3816 Do not try to `improve' this test. */1014 Do not try to 'improve' this test. */ 3817 1015 struct pte *pre = &ptes[partitions-1]; 3818 #ifdef CONFIG_FEATURE_FDISK_WRITABLE 3819 fprintf(stderr, 3820 _("Warning: deleting partitions after %d\n"), 1016 #if ENABLE_FEATURE_FDISK_WRITABLE 1017 printf("Warning: deleting partitions after %d\n", 3821 1018 partitions); 3822 1019 pre->changed = 1; … … 3835 1032 if (IS_EXTENDED(p->sys_ind)) { 3836 1033 if (pe->ext_pointer) 3837 fprintf(stderr, 3838 _("Warning: extra link " 3839 "pointer in partition table" 3840 " %d\n"), partitions + 1); 1034 printf("Warning: extra link " 1035 "pointer in partition table" 1036 " %d\n", partitions + 1); 3841 1037 else 3842 1038 pe->ext_pointer = p; 3843 1039 } else if (p->sys_ind) { 3844 1040 if (pe->part_table) 3845 fprintf(stderr, 3846 _("Warning: ignoring extra " 1041 printf("Warning: ignoring extra " 3847 1042 "data in partition table" 3848 " %d\n" ), partitions + 1);1043 " %d\n", partitions + 1); 3849 1044 else 3850 1045 pe->part_table = p; … … 3870 1065 } 3871 1066 3872 #if def CONFIG_FEATURE_FDISK_WRITABLE1067 #if ENABLE_FEATURE_FDISK_WRITABLE 3873 1068 /* remove empty links */ 3874 1069 remove: … … 3876 1071 struct pte *pe = &ptes[i]; 3877 1072 3878 if (!get_nr_sects(pe->part_table) && 3879 (partitions > 5 || ptes[4].part_table->sys_ind)) { 3880 printf("omitting empty partition (%d)\n", i+1); 1073 if (!get_nr_sects(pe->part_table) 1074 && (partitions > 5 || ptes[4].part_table->sys_ind) 1075 ) { 1076 printf("Omitting empty partition (%d)\n", i+1); 3881 1077 delete_partition(i); 3882 1078 goto remove; /* numbering changed */ … … 3886 1082 } 3887 1083 3888 #if def CONFIG_FEATURE_FDISK_WRITABLE1084 #if ENABLE_FEATURE_FDISK_WRITABLE 3889 1085 static void 3890 1086 create_doslabel(void) … … 3892 1088 int i; 3893 1089 3894 fprintf(stderr, 3895 _("Building a new DOS disklabel. Changes will remain in memory only,\n" 3896 "until you decide to write them. After that, of course, the previous\n" 3897 "content won't be recoverable.\n\n")); 1090 printf(msg_building_new_label, "DOS disklabel"); 3898 1091 3899 1092 current_label_type = label_dos; 3900 1093 3901 #if def CONFIG_FEATURE_OSF_LABEL1094 #if ENABLE_FEATURE_OSF_LABEL 3902 1095 possibly_osf_label = 0; 3903 1096 #endif … … 3912 1105 get_boot(create_empty_dos); 3913 1106 } 3914 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */1107 #endif /* FEATURE_FDISK_WRITABLE */ 3915 1108 3916 1109 static void … … 3922 1115 sector_size = arg; 3923 1116 if (sector_size != DEFAULT_SECTOR_SIZE) 3924 printf( _("Note: sector size is %d (not %d)\n"),1117 printf("Note: sector size is %d (not %d)\n", 3925 1118 sector_size, DEFAULT_SECTOR_SIZE); 3926 1119 } 3927 1120 } 3928 1121 3929 static inlinevoid1122 static void 3930 1123 get_kernel_geometry(void) 3931 1124 { … … 3976 1169 { 3977 1170 int sec_fac; 3978 u nsigned long long bytes; /* really u64 */1171 uint64_t v64; 3979 1172 3980 1173 get_sectorsize(); 3981 1174 sec_fac = sector_size / 512; 3982 #if def CONFIG_FEATURE_SUN_LABEL1175 #if ENABLE_FEATURE_SUN_LABEL 3983 1176 guess_device_type(); 3984 1177 #endif … … 3996 1189 pt_sectors ? pt_sectors : 3997 1190 kern_sectors ? kern_sectors : 63; 3998 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) { 3999 /* got bytes */ 1191 if (ioctl(fd, BLKGETSIZE64, &v64) == 0) { 1192 /* got bytes, convert to 512 byte sectors */ 1193 total_number_of_sectors = (v64 >> 9); 4000 1194 } else { 4001 unsigned long longsectors; 4002 4003 if (ioctl(fd, BLKGETSIZE, &longsectors)) 4004 longsectors = 0; 4005 bytes = ((unsigned long long) longsectors) << 9; 4006 } 4007 4008 total_number_of_sectors = (bytes >> 9); 1195 unsigned long longsectors; /* need temp of type long */ 1196 if (ioctl(fd, BLKGETSIZE, &longsectors)) 1197 longsectors = 0; 1198 total_number_of_sectors = longsectors; 1199 } 4009 1200 4010 1201 sector_offset = 1; … … 4037 1228 pe->offset = 0; 4038 1229 pe->sectorbuffer = MBRbuffer; 4039 #if def CONFIG_FEATURE_FDISK_WRITABLE1230 #if ENABLE_FEATURE_FDISK_WRITABLE 4040 1231 pe->changed = (what == create_empty_dos); 4041 1232 #endif 4042 1233 } 4043 1234 4044 #if def CONFIG_FEATURE_SUN_LABEL1235 #if ENABLE_FEATURE_SUN_LABEL 4045 1236 if (what == create_empty_sun && check_sun_label()) 4046 1237 return 0; … … 4049 1240 memset(MBRbuffer, 0, 512); 4050 1241 4051 #if def CONFIG_FEATURE_FDISK_WRITABLE1242 #if ENABLE_FEATURE_FDISK_WRITABLE 4052 1243 if (what == create_empty_dos) 4053 1244 goto got_dos_table; /* skip reading disk */ 4054 1245 4055 if ((fd = open(disk_device, type_open)) < 0) { 4056 if ((fd = open(disk_device, O_RDONLY)) < 0) { 1246 fd = open(disk_device, type_open); 1247 if (fd < 0) { 1248 fd = open(disk_device, O_RDONLY); 1249 if (fd < 0) { 4057 1250 if (what == try_only) 4058 1251 return 1; 4059 1252 fdisk_fatal(unable_to_open); 4060 1253 } else 4061 printf( _("You will not be able to write "4062 "the partition table .\n"));1254 printf("You will not be able to write " 1255 "the partition table\n"); 4063 1256 } 4064 1257 … … 4069 1262 } 4070 1263 #else 4071 if ((fd = open(disk_device, O_RDONLY)) < 0) 1264 fd = open(disk_device, O_RDONLY); 1265 if (fd < 0) 4072 1266 return 1; 4073 1267 if (512 != read(fd, MBRbuffer, 512)) … … 4079 1273 update_units(); 4080 1274 4081 #if def CONFIG_FEATURE_SUN_LABEL1275 #if ENABLE_FEATURE_SUN_LABEL 4082 1276 if (check_sun_label()) 4083 1277 return 0; 4084 1278 #endif 4085 1279 4086 #if def CONFIG_FEATURE_SGI_LABEL1280 #if ENABLE_FEATURE_SGI_LABEL 4087 1281 if (check_sgi_label()) 4088 1282 return 0; 4089 1283 #endif 4090 1284 4091 #if def CONFIG_FEATURE_AIX_LABEL1285 #if ENABLE_FEATURE_AIX_LABEL 4092 1286 if (check_aix_label()) 4093 1287 return 0; 4094 1288 #endif 4095 1289 4096 #if def CONFIG_FEATURE_OSF_LABEL1290 #if ENABLE_FEATURE_OSF_LABEL 4097 1291 if (check_osf_label()) { 4098 1292 possibly_osf_label = 1; … … 4101 1295 return 0; 4102 1296 } 4103 printf( _("This disk has both DOS and BSD magic.\n"4104 "Give the 'b' command to go to BSD mode.\n") );4105 } 4106 #endif 4107 4108 #if def CONFIG_FEATURE_FDISK_WRITABLE1297 printf("This disk has both DOS and BSD magic.\n" 1298 "Give the 'b' command to go to BSD mode.\n"); 1299 } 1300 #endif 1301 1302 #if ENABLE_FEATURE_FDISK_WRITABLE 4109 1303 got_dos_table: 4110 1304 #endif 4111 1305 4112 1306 if (!valid_part_table_flag(MBRbuffer)) { 4113 #if ndef CONFIG_FEATURE_FDISK_WRITABLE1307 #if !ENABLE_FEATURE_FDISK_WRITABLE 4114 1308 return -1; 4115 1309 #else 4116 1310 switch (what) { 4117 1311 case fdisk: 4118 fprintf(stderr, 4119 _("Device contains neither a valid DOS " 1312 printf("Device contains neither a valid DOS " 4120 1313 "partition table, nor Sun, SGI or OSF " 4121 "disklabel\n") );1314 "disklabel\n"); 4122 1315 #ifdef __sparc__ 4123 #if def CONFIG_FEATURE_SUN_LABEL1316 #if ENABLE_FEATURE_SUN_LABEL 4124 1317 create_sunlabel(); 4125 1318 #endif … … 4131 1324 return -1; 4132 1325 case create_empty_dos: 4133 #if def CONFIG_FEATURE_SUN_LABEL1326 #if ENABLE_FEATURE_SUN_LABEL 4134 1327 case create_empty_sun: 4135 1328 #endif 4136 1329 break; 4137 1330 default: 4138 fprintf(stderr, _("Internal error\n")); 4139 exit(1); 4140 } 4141 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */ 4142 } 4143 4144 #ifdef CONFIG_FEATURE_FDISK_WRITABLE 1331 bb_error_msg_and_die("internal error"); 1332 } 1333 #endif /* FEATURE_FDISK_WRITABLE */ 1334 } 1335 1336 #if ENABLE_FEATURE_FDISK_WRITABLE 4145 1337 warn_cylinders(); 4146 1338 #endif … … 4152 1344 if (IS_EXTENDED(pe->part_table->sys_ind)) { 4153 1345 if (partitions != 4) 4154 fprintf(stderr, _("Ignoring extra extended "4155 "partition %d\n" ), i + 1);1346 printf("Ignoring extra extended " 1347 "partition %d\n", i + 1); 4156 1348 else 4157 1349 read_extended(i); … … 4163 1355 4164 1356 if (!valid_part_table_flag(pe->sectorbuffer)) { 4165 fprintf(stderr, 4166 _("Warning: invalid flag 0x%04x of partition " 4167 "table %d will be corrected by w(rite)\n"), 4168 part_table_flag(pe->sectorbuffer), i + 1); 4169 #ifdef CONFIG_FEATURE_FDISK_WRITABLE 1357 printf("Warning: invalid flag 0x%02x,0x%02x of partition " 1358 "table %d will be corrected by w(rite)\n", 1359 pe->sectorbuffer[510], 1360 pe->sectorbuffer[511], 1361 i + 1); 1362 #if ENABLE_FEATURE_FDISK_WRITABLE 4170 1363 pe->changed = 1; 4171 1364 #endif … … 4176 1369 } 4177 1370 4178 #if def CONFIG_FEATURE_FDISK_WRITABLE1371 #if ENABLE_FEATURE_FDISK_WRITABLE 4179 1372 /* 4180 1373 * Print the message MESG, then read an integer between LOW and HIGH (inclusive). … … 4184 1377 * There is no default if DFLT is not between LOW and HIGH. 4185 1378 */ 4186 static u int4187 read_int(u int low, uint dflt, uint high, uint base,char *mesg)4188 { 4189 u inti;1379 static unsigned 1380 read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg) 1381 { 1382 unsigned i; 4190 1383 int default_ok = 1; 4191 static char *ms = NULL; 4192 static int mslen = 0; 4193 4194 if (!ms || strlen(mesg)+100 > mslen) { 4195 mslen = strlen(mesg)+200; 4196 ms = xrealloc(ms,mslen); 4197 } 4198 4199 if (dflt < low || dflt > high) 1384 const char *fmt = "%s (%u-%u, default %u): "; 1385 1386 if (dflt < low || dflt > high) { 1387 fmt = "%s (%u-%u): "; 4200 1388 default_ok = 0; 4201 4202 if (default_ok) 4203 snprintf(ms, mslen, _("%s (%u-%u, default %u): "), 4204 mesg, low, high, dflt); 4205 else 4206 snprintf(ms, mslen, "%s (%u-%u): ", mesg, low, high); 1389 } 4207 1390 4208 1391 while (1) { … … 4210 1393 4211 1394 /* ask question and read answer */ 4212 while (read_chars(ms) != '\n' && !isdigit(*line_ptr) 4213 && *line_ptr != '-' && *line_ptr != '+') 4214 continue; 1395 do { 1396 printf(fmt, mesg, low, high, dflt); 1397 read_maybe_empty(""); 1398 } while (*line_ptr != '\n' && !isdigit(*line_ptr) 1399 && *line_ptr != '-' && *line_ptr != '+'); 4215 1400 4216 1401 if (*line_ptr == '+' || *line_ptr == '-') { … … 4218 1403 int absolute = 0; 4219 1404 4220 i = atoi(line_ptr +1);1405 i = atoi(line_ptr + 1); 4221 1406 4222 1407 while (isdigit(*++line_ptr)) … … 4247 1432 } 4248 1433 if (absolute) { 4249 u nsigned longlong bytes;1434 ullong bytes; 4250 1435 unsigned long unit; 4251 1436 4252 bytes = (u nsigned longlong) i * absolute;1437 bytes = (ullong) i * absolute; 4253 1438 unit = sector_size * units_per_sector; 4254 1439 bytes += unit/2; /* round */ … … 4266 1451 } 4267 1452 } 4268 if (use_default) 4269 printf(_("Using default value %u\n"), i = dflt); 1453 if (use_default) { 1454 i = dflt; 1455 printf("Using default value %u\n", i); 1456 } 4270 1457 if (i >= low && i <= high) 4271 1458 break; 4272 else 4273 printf(_("Value out of range.\n")); 1459 printf("Value is out of range\n"); 4274 1460 } 4275 1461 return i; … … 4282 1468 int i; 4283 1469 4284 i = read_int(1, 0, max, 0, _("Partition number")) - 1;1470 i = read_int(1, 0, max, 0, "Partition number") - 1; 4285 1471 pe = &ptes[i]; 4286 1472 4287 1473 if (warn) { 4288 if ( 4289 ( 4290 label_sun != current_label_type && 4291 label_sgi != current_label_type && 4292 !pe->part_table->sys_ind 4293 ) 4294 #ifdef CONFIG_FEATURE_SUN_LABEL 4295 || ( 4296 label_sun == current_label_type && 4297 ( 4298 !sunlabel->partitions[i].num_sectors 4299 || !sunlabel->infos[i].id 4300 ) 4301 ) 4302 #endif 4303 #ifdef CONFIG_FEATURE_SGI_LABEL 4304 || ( 4305 label_sgi == current_label_type && 4306 !sgi_get_num_sectors(i) 4307 ) 4308 #endif 4309 ){ 4310 fprintf(stderr, 4311 _("Warning: partition %d has empty type\n"), 4312 i+1 4313 ); 1474 if ((!LABEL_IS_SUN && !LABEL_IS_SGI && !pe->part_table->sys_ind) 1475 || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id)) 1476 || (LABEL_IS_SGI && !sgi_get_num_sectors(i)) 1477 ) { 1478 printf("Warning: partition %d has empty type\n", i+1); 4314 1479 } 4315 1480 } … … 4334 1499 } 4335 1500 if (pno >= 0) { 4336 printf( _("Selected partition %d\n"), pno+1);1501 printf("Selected partition %d\n", pno+1); 4337 1502 return pno; 4338 1503 } 4339 printf( _("No partition is defined yet!\n"));1504 printf("No partition is defined yet!\n"); 4340 1505 return -1; 4341 1506 … … 4361 1526 } 4362 1527 if (pno >= 0) { 4363 printf( _("Selected partition %d\n"), pno+1);1528 printf("Selected partition %d\n", pno+1); 4364 1529 return pno; 4365 1530 } 4366 printf( _("All primary partitions have been defined already!\n"));1531 printf("All primary partitions have been defined already!\n"); 4367 1532 return -1; 4368 1533 … … 4372 1537 4373 1538 4374 void change_units(void) 1539 static void 1540 change_units(void) 4375 1541 { 4376 1542 display_in_cyl_units = !display_in_cyl_units; 4377 1543 update_units(); 4378 printf( _("Changing display/entry units to %s\n"),1544 printf("Changing display/entry units to %s\n", 4379 1545 str_units(PLURAL)); 4380 1546 } … … 4387 1553 4388 1554 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind) 4389 fprintf(stderr, 4390 _("WARNING: Partition %d is an extended partition\n"), 4391 i + 1); 1555 printf("WARNING: Partition %d is an extended partition\n", i + 1); 4392 1556 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG); 4393 1557 pe->changed = 1; … … 4400 1564 if (dos_compatible_flag) { 4401 1565 sector_offset = sectors; 4402 printf(_("DOS Compatibility flag is set\n")); 4403 } 4404 else { 1566 printf("DOS Compatibility flag is set\n"); 1567 } else { 4405 1568 sector_offset = 1; 4406 printf( _("DOS Compatibility flag is not set\n"));1569 printf("DOS Compatibility flag is not set\n"); 4407 1570 } 4408 1571 } … … 4423 1586 pe->changed = 1; 4424 1587 4425 #ifdef CONFIG_FEATURE_SUN_LABEL 4426 if (label_sun == current_label_type) { 1588 if (LABEL_IS_SUN) { 4427 1589 sun_delete_partition(i); 4428 1590 return; 4429 1591 } 4430 #endif 4431 #ifdef CONFIG_FEATURE_SGI_LABEL 4432 if (label_sgi == current_label_type) { 1592 if (LABEL_IS_SGI) { 4433 1593 sgi_delete_partition(i); 4434 1594 return; 4435 1595 } 4436 #endif4437 1596 4438 1597 if (i < 4) { … … 4491 1650 struct partition *p; 4492 1651 4493 #ifdef CONFIG_FEATURE_SGI_LABEL4494 1652 /* If sgi_label then don't use get_existing_partition, 4495 1653 let the user select a partition, since get_existing_partition() 4496 1654 only works for Linux like partition tables. */ 4497 if ( label_sgi != current_label_type) {1655 if (!LABEL_IS_SGI) { 4498 1656 i = get_existing_partition(0, partitions); 4499 1657 } else { 4500 1658 i = get_partition(0, partitions); 4501 1659 } 4502 #else4503 i = get_existing_partition(0, partitions);4504 #endif4505 1660 if (i == -1) 4506 1661 return; … … 4510 1665 /* if changing types T to 0 is allowed, then 4511 1666 the reverse change must be allowed, too */ 4512 if (!sys && label_sgi != current_label_type && 4513 label_sun != current_label_type && !get_nr_sects(p)) 4514 { 4515 printf(_("Partition %d does not exist yet!\n"), i + 1); 4516 }else{ 4517 while (1) { 4518 sys = read_hex (get_sys_types()); 4519 4520 if (!sys && label_sgi != current_label_type && 4521 label_sun != current_label_type) 4522 { 4523 printf(_("Type 0 means free space to many systems\n" 1667 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) { 1668 printf("Partition %d does not exist yet!\n", i + 1); 1669 return; 1670 } 1671 while (1) { 1672 sys = read_hex(get_sys_types()); 1673 1674 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) { 1675 printf("Type 0 means free space to many systems\n" 4524 1676 "(but not to Linux). Having partitions of\n" 4525 "type 0 is probably unwise. You can delete\n" 4526 "a partition using the `d' command.\n")); 1677 "type 0 is probably unwise.\n"); 4527 1678 /* break; */ 4528 1679 } 4529 1680 4530 if ( label_sun != current_label_type && label_sgi != current_label_type) {1681 if (!LABEL_IS_SUN && !LABEL_IS_SGI) { 4531 1682 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) { 4532 printf(_("You cannot change a partition into" 4533 " an extended one or vice versa\n" 4534 "Delete it first.\n")); 1683 printf("You cannot change a partition into" 1684 " an extended one or vice versa\n"); 4535 1685 break; 4536 1686 } … … 4538 1688 4539 1689 if (sys < 256) { 4540 #if def CONFIG_FEATURE_SUN_LABEL4541 if ( label_sun == current_label_type && i == 2 && sys !=WHOLE_DISK)4542 printf( _("Consider leaving partition 3 "1690 #if ENABLE_FEATURE_SUN_LABEL 1691 if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK) 1692 printf("Consider leaving partition 3 " 4543 1693 "as Whole disk (5),\n" 4544 1694 "as SunOS/Solaris expects it and " 4545 "even Linux likes it .\n\n"));4546 #endif 4547 #if def CONFIG_FEATURE_SGI_LABEL4548 if ( label_sgi == current_label_type&&1695 "even Linux likes it\n\n"); 1696 #endif 1697 #if ENABLE_FEATURE_SGI_LABEL 1698 if (LABEL_IS_SGI && 4549 1699 ( 4550 (i == 10 && sys != ENTIRE_DISK) ||1700 (i == 10 && sys != SGI_ENTIRE_DISK) || 4551 1701 (i == 8 && sys != 0) 4552 1702 ) 4553 ) {4554 printf( _("Consider leaving partition 9 "1703 ) { 1704 printf("Consider leaving partition 9 " 4555 1705 "as volume header (0),\nand " 4556 1706 "partition 11 as entire volume (6)" 4557 "as IRIX expects it .\n\n"));1707 "as IRIX expects it\n\n"); 4558 1708 } 4559 1709 #endif 4560 1710 if (sys == origsys) 4561 1711 break; 4562 #ifdef CONFIG_FEATURE_SUN_LABEL 4563 if (label_sun == current_label_type) { 1712 if (LABEL_IS_SUN) { 4564 1713 sun_change_sysid(i, sys); 4565 } else 4566 #endif 4567 #ifdef CONFIG_FEATURE_SGI_LABEL 4568 if (label_sgi == current_label_type) { 1714 } else if (LABEL_IS_SGI) { 4569 1715 sgi_change_sysid(i, sys); 4570 1716 } else 4571 #endif4572 1717 p->sys_ind = sys; 4573 1718 4574 printf( _("Changed system type of partition %d "4575 "to %x (%s)\n" ), i + 1, sys,1719 printf("Changed system type of partition %d " 1720 "to %x (%s)\n", i + 1, sys, 4576 1721 partition_type(sys)); 4577 1722 ptes[i].changed = 1; … … 4581 1726 break; 4582 1727 } 4583 } 4584 } 4585 } 4586 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */ 4587 4588 4589 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993, 1728 } 1729 } 1730 #endif /* FEATURE_FDISK_WRITABLE */ 1731 1732 1733 /* check_consistency() and linear2chs() added Sat Mar 6 12:28:16 1993, 4590 1734 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross, 4591 1735 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S. … … 4593 1737 4594 1738 static void 4595 l ong2chs(ulong ls, uint *c, uint *h, uint*s)1739 linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s) 4596 1740 { 4597 1741 int spc = heads * sectors; … … 4606 1750 check_consistency(const struct partition *p, int partition) 4607 1751 { 4608 u intpbc, pbh, pbs; /* physical beginning c, h, s */4609 u intpec, peh, pes; /* physical ending c, h, s */4610 u intlbc, lbh, lbs; /* logical beginning c, h, s */4611 u intlec, leh, les; /* logical ending c, h, s */1752 unsigned pbc, pbh, pbs; /* physical beginning c, h, s */ 1753 unsigned pec, peh, pes; /* physical ending c, h, s */ 1754 unsigned lbc, lbh, lbs; /* logical beginning c, h, s */ 1755 unsigned lec, leh, les; /* logical ending c, h, s */ 4612 1756 4613 1757 if (!heads || !sectors || (partition >= 4)) … … 4625 1769 4626 1770 /* compute logical beginning (c, h, s) */ 4627 l ong2chs(get_start_sect(p), &lbc, &lbh, &lbs);1771 linear2chs(get_start_sect(p), &lbc, &lbh, &lbs); 4628 1772 4629 1773 /* compute logical ending (c, h, s) */ 4630 l ong2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);1774 linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les); 4631 1775 4632 1776 /* Same physical / logical beginning? */ 4633 1777 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) { 4634 printf( _("Partition %d has different physical/logical "4635 "beginnings (non-Linux?):\n" ), partition + 1);4636 printf( _(" phys=(%d, %d, %d) "), pbc, pbh, pbs);4637 printf( _("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);1778 printf("Partition %d has different physical/logical " 1779 "beginnings (non-Linux?):\n", partition + 1); 1780 printf(" phys=(%d, %d, %d) ", pbc, pbh, pbs); 1781 printf("logical=(%d, %d, %d)\n",lbc, lbh, lbs); 4638 1782 } 4639 1783 4640 1784 /* Same physical / logical ending? */ 4641 1785 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) { 4642 printf(_("Partition %d has different physical/logical " 4643 "endings:\n"), partition + 1); 4644 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes); 4645 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les); 4646 } 4647 4648 #if 0 4649 /* Beginning on cylinder boundary? */ 4650 if (pbh != !pbc || pbs != 1) { 4651 printf(_("Partition %i does not start on cylinder " 4652 "boundary:\n"), partition + 1); 4653 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs); 4654 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc); 4655 } 4656 #endif 1786 printf("Partition %d has different physical/logical " 1787 "endings:\n", partition + 1); 1788 printf(" phys=(%d, %d, %d) ", pec, peh, pes); 1789 printf("logical=(%d, %d, %d)\n", lec, leh, les); 1790 } 4657 1791 4658 1792 /* Ending on cylinder boundary? */ 4659 1793 if (peh != (heads - 1) || pes != sectors) { 4660 printf( _("Partition %i does not end on cylinder boundary.\n"),1794 printf("Partition %i does not end on cylinder boundary\n", 4661 1795 partition + 1); 4662 #if 04663 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);4664 printf(_("should be (%d, %d, %d)\n"),4665 pec, heads - 1, sectors);4666 #endif4667 1796 } 4668 1797 } … … 4675 1804 4676 1805 if (megabytes < 10000) 4677 printf( _("\nDisk %s: %ld MB, %lld bytes\n"),1806 printf("\nDisk %s: %ld MB, %lld bytes\n", 4678 1807 disk_device, megabytes, bytes); 4679 1808 else 4680 printf( _("\nDisk %s: %ld.%ld GB, %lld bytes\n"),1809 printf("\nDisk %s: %ld.%ld GB, %lld bytes\n", 4681 1810 disk_device, megabytes/1000, (megabytes/100)%10, bytes); 4682 printf( _("%d heads, %d sectors/track, %d cylinders"),1811 printf("%d heads, %d sectors/track, %d cylinders", 4683 1812 heads, sectors, cylinders); 4684 1813 if (units_per_sector == 1) 4685 printf( _(", total %llu sectors"),1814 printf(", total %llu sectors", 4686 1815 total_number_of_sectors / (sector_size/512)); 4687 printf( _("\nUnits = %s of %d * %d = %d bytes\n\n"),1816 printf("\nUnits = %s of %d * %d = %d bytes\n\n", 4688 1817 str_units(PLURAL), 4689 1818 units_per_sector, sector_size, units_per_sector * sector_size); … … 4700 1829 const struct pte *pe; 4701 1830 const struct partition *p; 4702 off_tlast_p_start_pos = 0, p_start_pos;1831 ullong last_p_start_pos = 0, p_start_pos; 4703 1832 int i, last_i = 0; 4704 1833 4705 for (i = 0 1834 for (i = 0; i < partitions; i++) { 4706 1835 if (i == 4) { 4707 1836 last_i = 4; … … 4725 1854 } 4726 1855 4727 #if def CONFIG_FEATURE_FDISK_ADVANCED1856 #if ENABLE_FEATURE_FDISK_ADVANCED 4728 1857 /* 4729 1858 * Fix the chain of logicals. … … 4798 1927 4799 1928 if (!wrong_p_order(NULL)) { 4800 printf( _("Nothing to do. Ordering is correct already.\n\n"));1929 printf("Ordering is already correct\n\n"); 4801 1930 return; 4802 1931 } … … 4837 1966 int i, w; 4838 1967 4839 #ifdef CONFIG_FEATURE_SUN_LABEL 4840 if (label_sun == current_label_type) { 1968 if (LABEL_IS_SUN) { 4841 1969 sun_list_table(xtra); 4842 1970 return; 4843 1971 } 4844 #endif 4845 4846 #ifdef CONFIG_FEATURE_SGI_LABEL 4847 if (label_sgi == current_label_type) { 1972 if (LABEL_IS_SUN) { 4848 1973 sgi_list_table(xtra); 4849 1974 return; 4850 1975 } 4851 #endif4852 1976 4853 1977 list_disk_geometry(); 4854 1978 4855 #ifdef CONFIG_FEATURE_OSF_LABEL 4856 if (label_osf == current_label_type) { 1979 if (LABEL_IS_OSF) { 4857 1980 xbsd_print_disklabel(xtra); 4858 1981 return; 4859 1982 } 4860 #endif4861 1983 4862 1984 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3, … … 4869 1991 w = 5; 4870 1992 4871 printf(_("%*s Boot Start End Blocks Id System\n"), 4872 w+1, _("Device")); 1993 // 1 12345678901 12345678901 12345678901 12 1994 printf("%*s Boot Start End Blocks Id System\n", 1995 w+1, "Device"); 4873 1996 4874 1997 for (i = 0; i < partitions; i++) { 4875 1998 const struct pte *pe = &ptes[i]; 1999 ullong psects; 2000 ullong pblocks; 2001 unsigned podd; 4876 2002 4877 2003 p = pe->part_table; 4878 if (p && !is_cleared_partition(p)) { 4879 off_t psects = get_nr_sects(p); 4880 off_t pblocks = psects; 4881 unsigned int podd = 0; 4882 4883 if (sector_size < 1024) { 4884 pblocks /= (1024 / sector_size); 4885 podd = psects % (1024 / sector_size); 4886 } 4887 if (sector_size > 1024) 4888 pblocks *= (sector_size / 1024); 4889 printf( 4890 "%s %c %11llu %11llu %11llu%c %2x %s\n", 2004 if (!p || is_cleared_partition(p)) 2005 continue; 2006 2007 psects = get_nr_sects(p); 2008 pblocks = psects; 2009 podd = 0; 2010 2011 if (sector_size < 1024) { 2012 pblocks /= (1024 / sector_size); 2013 podd = psects % (1024 / sector_size); 2014 } 2015 if (sector_size > 1024) 2016 pblocks *= (sector_size / 1024); 2017 2018 printf("%s %c %11llu %11llu %11llu%c %2x %s\n", 4891 2019 partname(disk_device, i+1, w+2), 4892 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG 4893 ? '*' : '?',4894 /* start */ (unsigned long long) cround(get_partition_start(pe)), 4895 /* end */ (unsigned long long) cround(get_partition_start(pe) + psects 2020 !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */ 2021 ? '*' : '?', 2022 (ullong) cround(get_partition_start(pe)), /* start */ 2023 (ullong) cround(get_partition_start(pe) + psects /* end */ 4896 2024 - (psects ? 1 : 0)), 4897 /* odd flag on end */ (unsigned long long) pblocks, podd ? '+' : ' ', 4898 /* type id */ p->sys_ind, 4899 /* type name */ partition_type(p->sys_ind)); 4900 check_consistency(p, i); 4901 }2025 (ullong) pblocks, podd ? '+' : ' ', /* odd flag on end */ 2026 p->sys_ind, /* type id */ 2027 partition_type(p->sys_ind)); /* type name */ 2028 2029 check_consistency(p, i); 4902 2030 } 4903 2031 … … 4905 2033 /* partition table entries are not checked for correct order if this 4906 2034 is a sgi, sun or aix labeled disk... */ 4907 if ( label_dos == current_label_type&& wrong_p_order(NULL)) {2035 if (LABEL_IS_DOS && wrong_p_order(NULL)) { 4908 2036 /* FIXME */ 4909 printf( _("\nPartition table entries are not in disk order\n"));4910 } 4911 } 4912 4913 #if def CONFIG_FEATURE_FDISK_ADVANCED2037 printf("\nPartition table entries are not in disk order\n"); 2038 } 2039 } 2040 2041 #if ENABLE_FEATURE_FDISK_ADVANCED 4914 2042 static void 4915 2043 x_list_table(int extend) … … 4919 2047 int i; 4920 2048 4921 printf( _("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),2049 printf("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n", 4922 2050 disk_device, heads, sectors, cylinders); 4923 printf( _("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));4924 for (i = 0 2051 printf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"); 2052 for (i = 0; i < partitions; i++) { 4925 2053 pe = &ptes[i]; 4926 2054 p = (extend ? pe->ext_pointer : pe->part_table); … … 4940 2068 #endif 4941 2069 4942 #if def CONFIG_FEATURE_FDISK_WRITABLE4943 static void 4944 fill_bounds( off_t *first, off_t*last)2070 #if ENABLE_FEATURE_FDISK_WRITABLE 2071 static void 2072 fill_bounds(ullong *first, ullong *last) 4945 2073 { 4946 2074 int i; … … 4961 2089 4962 2090 static void 4963 check(int n, u int h, uint s, uint c, off_tstart)4964 { 4965 off_ttotal, real_s, real_c;2091 check(int n, unsigned h, unsigned s, unsigned c, ullong start) 2092 { 2093 ullong total, real_s, real_c; 4966 2094 4967 2095 real_s = sector(s) - 1; … … 4969 2097 total = (real_c * sectors + real_s) * heads + h; 4970 2098 if (!total) 4971 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);2099 printf("Partition %d contains sector 0\n", n); 4972 2100 if (h >= heads) 4973 fprintf(stderr, 4974 _("Partition %d: head %d greater than maximum %d\n"), 2101 printf("Partition %d: head %d greater than maximum %d\n", 4975 2102 n, h + 1, heads); 4976 2103 if (real_s >= sectors) 4977 fprintf(stderr, _("Partition %d: sector %d greater than "4978 "maximum %d\n" ), n, s, sectors);2104 printf("Partition %d: sector %d greater than " 2105 "maximum %d\n", n, s, sectors); 4979 2106 if (real_c >= cylinders) 4980 fprintf(stderr, _("Partitions%d: cylinder %llu greater than "4981 "maximum %d\n" ), n, (unsigned long long)real_c + 1, cylinders);2107 printf("Partition %d: cylinder %llu greater than " 2108 "maximum %d\n", n, real_c + 1, cylinders); 4982 2109 if (cylinders <= 1024 && start != total) 4983 fprintf(stderr, 4984 _("Partition %d: previous sectors %llu disagrees with " 4985 "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total); 2110 printf("Partition %d: previous sectors %llu disagrees with " 2111 "total %llu\n", n, start, total); 4986 2112 } 4987 2113 … … 4990 2116 { 4991 2117 int i, j; 4992 u inttotal = 1;4993 off_tfirst[partitions], last[partitions];2118 unsigned total = 1; 2119 ullong first[partitions], last[partitions]; 4994 2120 struct partition *p; 4995 2121 … … 4997 2123 return; 4998 2124 4999 #ifdef CONFIG_FEATURE_SUN_LABEL 5000 if (label_sun == current_label_type) { 2125 if (LABEL_IS_SUN) { 5001 2126 verify_sun(); 5002 2127 return; 5003 2128 } 5004 #endif 5005 #ifdef CONFIG_FEATURE_SGI_LABEL 5006 if (label_sgi == current_label_type) { 2129 if (LABEL_IS_SGI) { 5007 2130 verify_sgi(1); 5008 2131 return; 5009 2132 } 5010 #endif5011 2133 5012 2134 fill_bounds(first, last); … … 5018 2140 check_consistency(p, i); 5019 2141 if (get_partition_start(pe) < first[i]) 5020 printf( _("Warning: bad start-of-data in "5021 "partition %d\n" ), i + 1);2142 printf("Warning: bad start-of-data in " 2143 "partition %d\n", i + 1); 5022 2144 check(i + 1, p->end_head, p->end_sector, p->end_cyl, 5023 2145 last[i]); 5024 2146 total += last[i] + 1 - first[i]; 5025 for (j = 0; j < i; j++) 5026 if ((first[i] >= first[j] && first[i] <= last[j]) 5027 || ((last[i] <= last[j] && last[i] >= first[j]))) { 5028 printf(_("Warning: partition %d overlaps " 5029 "partition %d.\n"), j + 1, i + 1); 5030 total += first[i] >= first[j] ? 5031 first[i] : first[j]; 5032 total -= last[i] <= last[j] ? 5033 last[i] : last[j]; 2147 for (j = 0; j < i; j++) { 2148 if ((first[i] >= first[j] && first[i] <= last[j]) 2149 || ((last[i] <= last[j] && last[i] >= first[j]))) { 2150 printf("Warning: partition %d overlaps " 2151 "partition %d\n", j + 1, i + 1); 2152 total += first[i] >= first[j] ? 2153 first[i] : first[j]; 2154 total -= last[i] <= last[j] ? 2155 last[i] : last[j]; 2156 } 5034 2157 } 5035 2158 } … … 5038 2161 if (extended_offset) { 5039 2162 struct pte *pex = &ptes[ext_index]; 5040 off_te_last = get_start_sect(pex->part_table) +2163 ullong e_last = get_start_sect(pex->part_table) + 5041 2164 get_nr_sects(pex->part_table) - 1; 5042 2165 … … 5046 2169 if (!p->sys_ind) { 5047 2170 if (i != 4 || i + 1 < partitions) 5048 printf(_("Warning: partition %d " 5049 "is empty\n"), i + 1); 2171 printf("Warning: partition %d " 2172 "is empty\n", i + 1); 2173 } else if (first[i] < extended_offset || last[i] > e_last) { 2174 printf("Logical partition %d not entirely in " 2175 "partition %d\n", i + 1, ext_index + 1); 5050 2176 } 5051 else if (first[i] < extended_offset ||5052 last[i] > e_last)5053 printf(_("Logical partition %d not entirely in "5054 "partition %d\n"), i + 1, ext_index + 1);5055 2177 } 5056 2178 } 5057 2179 5058 2180 if (total > heads * sectors * cylinders) 5059 printf(_("Total allocated sectors %d greater than the maximum " 5060 "%d\n"), total, heads * sectors * cylinders); 5061 else if ((total = heads * sectors * cylinders - total) != 0) 5062 printf(_("%d unallocated sectors\n"), total); 2181 printf("Total allocated sectors %d greater than the maximum " 2182 "%d\n", total, heads * sectors * cylinders); 2183 else { 2184 total = heads * sectors * cylinders - total; 2185 if (total != 0) 2186 printf("%d unallocated sectors\n", total); 2187 } 5063 2188 } 5064 2189 … … 5070 2195 struct partition *p = ptes[n].part_table; 5071 2196 struct partition *q = ptes[ext_index].part_table; 5072 long long llimit;5073 off_t start, stop = 0, limit, temp,5074 2197 ullong limit, temp; 2198 ullong start, stop = 0; 2199 ullong first[partitions], last[partitions]; 5075 2200 5076 2201 if (p && p->sys_ind) { 5077 printf(_("Partition %d is already defined. Delete " 5078 "it before re-adding it.\n"), n + 1); 2202 printf(msg_part_already_defined, n + 1); 5079 2203 return; 5080 2204 } … … 5083 2207 start = sector_offset; 5084 2208 if (display_in_cyl_units || !total_number_of_sectors) 5085 l limit =heads * sectors * cylinders - 1;2209 limit = (ullong) heads * sectors * cylinders - 1; 5086 2210 else 5087 llimit = total_number_of_sectors - 1; 5088 limit = llimit; 5089 if (limit != llimit) 5090 limit = 0x7fffffff; 2211 limit = total_number_of_sectors - 1; 5091 2212 if (extended_offset) { 5092 2213 first[ext_index] = extended_offset; … … 5102 2223 first[i] = (cround(first[i]) - 1) * units_per_sector; 5103 2224 5104 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));2225 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR)); 5105 2226 do { 5106 2227 temp = start; … … 5117 2238 break; 5118 2239 if (start >= temp+units_per_sector && num_read) { 5119 printf( _("Sector %llu is already allocated\n"), (unsigned long long)temp);2240 printf("Sector %lld is already allocated\n", temp); 5120 2241 temp = start; 5121 2242 num_read = 0; 5122 2243 } 5123 2244 if (!num_read && start == temp) { 5124 off_tsaved_start;2245 ullong saved_start; 5125 2246 5126 2247 saved_start = start; … … 5154 2275 } 5155 2276 if (start > limit) { 5156 printf( _("No free sectors available\n"));2277 printf("No free sectors available\n"); 5157 2278 if (n > 4) 5158 2279 partitions--; … … 5163 2284 } else { 5164 2285 snprintf(mesg, sizeof(mesg), 5165 _("Last %s or +size or +sizeM or +sizeK"),2286 "Last %s or +size or +sizeM or +sizeK", 5166 2287 str_units(SINGULAR)); 5167 2288 stop = read_int(cround(start), cround(limit), cround(limit), … … 5185 2306 pen->ext_pointer = p; 5186 2307 pe4->offset = extended_offset = start; 5187 pe4->sectorbuffer = x calloc(1,sector_size);2308 pe4->sectorbuffer = xzalloc(sector_size); 5188 2309 pe4->part_table = pt_offset(pe4->sectorbuffer, 0); 5189 2310 pe4->ext_pointer = pe4->part_table + 1; … … 5199 2320 struct pte *pe = &ptes[partitions]; 5200 2321 5201 pe->sectorbuffer = x calloc(1,sector_size);2322 pe->sectorbuffer = xzalloc(sector_size); 5202 2323 pe->part_table = pt_offset(pe->sectorbuffer, 0); 5203 2324 pe->ext_pointer = pe->part_table + 1; … … 5217 2338 return; 5218 2339 5219 #ifdef CONFIG_FEATURE_SUN_LABEL 5220 if (label_sun == current_label_type) { 2340 if (LABEL_IS_SUN) { 5221 2341 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE); 5222 2342 return; 5223 2343 } 5224 #endif 5225 #ifdef CONFIG_FEATURE_SGI_LABEL 5226 if (label_sgi == current_label_type) { 2344 if (LABEL_IS_SGI) { 5227 2345 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE); 5228 2346 return; 5229 2347 } 5230 #endif 5231 #ifdef CONFIG_FEATURE_AIX_LABEL 5232 if (label_aix == current_label_type) { 5233 printf(_("\tSorry - this fdisk cannot handle AIX disk labels." 5234 "\n\tIf you want to add DOS-type partitions, create" 5235 "\n\ta new empty DOS partition table first. (Use o.)" 5236 "\n\tWARNING: " 5237 "This will destroy the present disk contents.\n")); 2348 if (LABEL_IS_AIX) { 2349 printf("Sorry - this fdisk cannot handle AIX disk labels.\n" 2350 "If you want to add DOS-type partitions, create a new empty DOS partition\n" 2351 "table first (use 'o'). This will destroy the present disk contents.\n"); 5238 2352 return; 5239 2353 } 5240 #endif5241 2354 5242 2355 for (i = 0; i < 4; i++) … … 5244 2357 5245 2358 if (!free_primary && partitions >= MAXIMUM_PARTS) { 5246 printf( _("The maximum number of partitions has been created\n"));2359 printf("The maximum number of partitions has been created\n"); 5247 2360 return; 5248 2361 } … … 5252 2365 add_logical(); 5253 2366 else 5254 printf( _("You must delete some partition and add "5255 "an extended partition first\n") );2367 printf("You must delete some partition and add " 2368 "an extended partition first\n"); 5256 2369 } else { 5257 char c, line[LINE_LENGTH]; 5258 snprintf(line, sizeof(line), "%s\n %s\n p primary " 5259 "partition (1-4)\n", 5260 "Command action", (extended_offset ? 5261 "l logical (5 or over)" : "e extended")); 2370 char c, line[80]; 2371 snprintf(line, sizeof(line), 2372 "Command action\n" 2373 " %s\n" 2374 " p primary partition (1-4)\n", 2375 (extended_offset ? 2376 "l logical (5 or over)" : "e extended")); 5262 2377 while (1) { 5263 if ((c = read_char(line)) == 'p' || c == 'P') { 2378 c = read_nonempty(line); 2379 if (c == 'p' || c == 'P') { 5264 2380 i = get_nonexisting_partition(0, 4); 5265 2381 if (i >= 0) … … 5267 2383 return; 5268 2384 } 5269 elseif (c == 'l' && extended_offset) {2385 if (c == 'l' && extended_offset) { 5270 2386 add_logical(); 5271 2387 return; 5272 2388 } 5273 elseif (c == 'e' && !extended_offset) {2389 if (c == 'e' && !extended_offset) { 5274 2390 i = get_nonexisting_partition(0, 4); 5275 2391 if (i >= 0) … … 5277 2393 return; 5278 2394 } 5279 else 5280 printf(_("Invalid partition number " 5281 "for type `%c'\n"), c); 2395 printf("Invalid partition number " 2396 "for type '%c'\n", c); 5282 2397 } 5283 2398 } … … 5289 2404 int i; 5290 2405 5291 if ( label_dos == current_label_type) {2406 if (LABEL_IS_DOS) { 5292 2407 for (i = 0; i < 3; i++) 5293 2408 if (ptes[i].changed) … … 5302 2417 } 5303 2418 } 5304 #ifdef CONFIG_FEATURE_SGI_LABEL 5305 else if (label_sgi == current_label_type) { 2419 else if (LABEL_IS_SGI) { 5306 2420 /* no test on change? the printf below might be mistaken */ 5307 2421 sgi_write_table(); 5308 2422 } 5309 #endif 5310 #ifdef CONFIG_FEATURE_SUN_LABEL 5311 else if (label_sun == current_label_type) { 2423 else if (LABEL_IS_SUN) { 5312 2424 int needw = 0; 5313 2425 … … 5318 2430 sun_write_table(); 5319 2431 } 5320 #endif 5321 5322 printf(_("The partition table has been altered!\n\n")); 2432 2433 printf("The partition table has been altered!\n\n"); 5323 2434 reread_partition_table(1); 5324 2435 } … … 5327 2438 reread_partition_table(int leave) 5328 2439 { 5329 int error = 0;5330 2440 int i; 5331 2441 5332 printf( _("Calling ioctl() to re-read partition table.\n"));2442 printf("Calling ioctl() to re-read partition table\n"); 5333 2443 sync(); 5334 sleep(2); 5335 if ((i = ioctl(fd, BLKRRPART)) != 0) { 5336 error = errno; 5337 } else { 5338 /* some kernel versions (1.2.x) seem to have trouble 5339 rereading the partition table, but if asked to do it 5340 twice, the second time works. - biro@yggdrasil.com */ 5341 sync(); 5342 sleep(2); 5343 if ((i = ioctl(fd, BLKRRPART)) != 0) 5344 error = errno; 5345 } 5346 5347 if (i) { 5348 printf(_("\nWARNING: Re-reading the partition table " 5349 "failed with error %d: %s.\n" 5350 "The kernel still uses the old table.\n" 5351 "The new table will be used " 5352 "at the next reboot.\n"), 5353 error, strerror(error)); 5354 } 5355 2444 /* sleep(2); Huh? */ 2445 i = ioctl_or_perror(fd, BLKRRPART, NULL, 2446 "WARNING: rereading partition table " 2447 "failed, kernel still uses old table"); 2448 #if 0 5356 2449 if (dos_changed) 5357 2450 printf( 5358 _("\nWARNING: If you have created or modified any DOS 6.x\n"2451 "\nWARNING: If you have created or modified any DOS 6.x\n" 5359 2452 "partitions, please see the fdisk manual page for additional\n" 5360 "information.\n")); 2453 "information\n"); 2454 #endif 5361 2455 5362 2456 if (leave) { 5363 close(fd); 5364 5365 printf(_("Syncing disks.\n")); 5366 sync(); 5367 sleep(4); /* for sync() */ 5368 exit(!!i); 5369 } 5370 } 5371 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */ 5372 5373 #ifdef CONFIG_FEATURE_FDISK_ADVANCED 2457 if (ENABLE_FEATURE_CLEAN_UP) 2458 close(fd); 2459 exit(i != 0); 2460 } 2461 } 2462 #endif /* FEATURE_FDISK_WRITABLE */ 2463 2464 #if ENABLE_FEATURE_FDISK_ADVANCED 5374 2465 #define MAX_PER_LINE 16 5375 2466 static void … … 5383 2474 printf(" %02X", (unsigned char) pbuffer[i]); 5384 2475 if (l == MAX_PER_LINE - 1) { 5385 p rintf("\n");2476 puts(""); 5386 2477 l = -1; 5387 2478 } 5388 2479 } 5389 2480 if (l > 0) 5390 printf("\n"); 5391 printf("\n"); 5392 } 5393 2481 puts(""); 2482 puts(""); 2483 } 5394 2484 5395 2485 static void … … 5398 2488 int i; 5399 2489 5400 printf(_("Device: %s\n"), disk_device); 5401 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL) 5402 if (label_sun == current_label_type || label_sgi == current_label_type) 2490 printf("Device: %s\n", disk_device); 2491 if (LABEL_IS_SGI || LABEL_IS_SUN) 5403 2492 print_buffer(MBRbuffer); 5404 else 5405 #endif 2493 else { 5406 2494 for (i = 3; i < partitions; i++) 5407 2495 print_buffer(ptes[i].sectorbuffer); 2496 } 5408 2497 } 5409 2498 … … 5413 2502 struct pte *pe = &ptes[i]; 5414 2503 struct partition *p = pe->part_table; 5415 off_tnew, first;2504 ullong new, first; 5416 2505 5417 2506 if (warn_geometry()) 5418 2507 return; 5419 2508 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) { 5420 printf( _("Partition %d has no data area\n"), i + 1);2509 printf("Partition %d has no data area\n", i + 1); 5421 2510 return; 5422 2511 } 5423 2512 first = get_partition_start(pe); 5424 2513 new = read_int(first, first, first + get_nr_sects(p) - 1, first, 5425 _("New beginning of data")) - pe->offset;2514 "New beginning of data") - pe->offset; 5426 2515 5427 2516 if (new != get_nr_sects(p)) { … … 5440 2529 while (1) { 5441 2530 putchar('\n'); 5442 c = tolower(read_ char(_("Expert command (m for help): ")));2531 c = tolower(read_nonempty("Expert command (m for help): ")); 5443 2532 switch (c) { 5444 2533 case 'a': 5445 #ifdef CONFIG_FEATURE_SUN_LABEL 5446 if (label_sun == current_label_type) 2534 if (LABEL_IS_SUN) 5447 2535 sun_set_alt_cyl(); 5448 #endif5449 2536 break; 5450 2537 case 'b': 5451 if ( label_dos == current_label_type)2538 if (LABEL_IS_DOS) 5452 2539 move_begin(get_partition(0, partitions)); 5453 2540 break; … … 5455 2542 user_cylinders = cylinders = 5456 2543 read_int(1, cylinders, 1048576, 0, 5457 _("Number of cylinders")); 5458 #ifdef CONFIG_FEATURE_SUN_LABEL 5459 if (label_sun == current_label_type) 2544 "Number of cylinders"); 2545 if (LABEL_IS_SUN) 5460 2546 sun_set_ncyl(cylinders); 5461 #endif 5462 if (label_dos == current_label_type) 2547 if (LABEL_IS_DOS) 5463 2548 warn_cylinders(); 5464 2549 break; … … 5467 2552 break; 5468 2553 case 'e': 5469 #ifdef CONFIG_FEATURE_SGI_LABEL 5470 if (label_sgi == current_label_type) 2554 if (LABEL_IS_SGI) 5471 2555 sgi_set_xcyl(); 5472 else 5473 #endif 5474 #ifdef CONFIG_FEATURE_SUN_LABEL 5475 if (label_sun == current_label_type) 2556 else if (LABEL_IS_SUN) 5476 2557 sun_set_xcyl(); 5477 else 5478 #endif 5479 if (label_dos == current_label_type) 2558 else if (LABEL_IS_DOS) 5480 2559 x_list_table(1); 5481 2560 break; 5482 2561 case 'f': 5483 if ( label_dos == current_label_type)2562 if (LABEL_IS_DOS) 5484 2563 fix_partition_table_order(); 5485 2564 break; 5486 2565 case 'g': 5487 #if def CONFIG_FEATURE_SGI_LABEL2566 #if ENABLE_FEATURE_SGI_LABEL 5488 2567 create_sgilabel(); 5489 2568 #endif … … 5491 2570 case 'h': 5492 2571 user_heads = heads = read_int(1, heads, 256, 0, 5493 _("Number of heads"));2572 "Number of heads"); 5494 2573 update_units(); 5495 2574 break; 5496 2575 case 'i': 5497 #ifdef CONFIG_FEATURE_SUN_LABEL 5498 if (label_sun == current_label_type) 2576 if (LABEL_IS_SUN) 5499 2577 sun_set_ilfact(); 5500 #endif5501 2578 break; 5502 2579 case 'o': 5503 #ifdef CONFIG_FEATURE_SUN_LABEL 5504 if (label_sun == current_label_type) 2580 if (LABEL_IS_SUN) 5505 2581 sun_set_rspeed(); 5506 #endif5507 2582 break; 5508 2583 case 'p': 5509 #ifdef CONFIG_FEATURE_SUN_LABEL 5510 if (label_sun == current_label_type) 2584 if (LABEL_IS_SUN) 5511 2585 list_table(1); 5512 2586 else 5513 #endif5514 2587 x_list_table(0); 5515 2588 break; 5516 2589 case 'q': 5517 2590 close(fd); 5518 p rintf("\n");2591 puts(""); 5519 2592 exit(0); 5520 2593 case 'r': … … 5522 2595 case 's': 5523 2596 user_sectors = sectors = read_int(1, sectors, 63, 0, 5524 _("Number of sectors"));2597 "Number of sectors"); 5525 2598 if (dos_compatible_flag) { 5526 2599 sector_offset = sectors; 5527 fprintf(stderr, _("Warning: setting " 5528 "sector offset for DOS " 5529 "compatiblity\n")); 2600 printf("Warning: setting sector offset for DOS " 2601 "compatiblity\n"); 5530 2602 } 5531 2603 update_units(); … … 5538 2610 break; 5539 2611 case 'y': 5540 #ifdef CONFIG_FEATURE_SUN_LABEL 5541 if (label_sun == current_label_type) 2612 if (LABEL_IS_SUN) 5542 2613 sun_set_pcylcount(); 5543 #endif5544 2614 break; 5545 2615 default: … … 5586 2656 5587 2657 static void 5588 try (const char *device, int user_specified)2658 trydev(const char *device, int user_specified) 5589 2659 { 5590 2660 int gb; … … 5596 2666 if (is_ide_cdrom_or_tape(device)) 5597 2667 return; 5598 if ((fd = open(disk_device, type_open)) >= 0) { 2668 fd = open(disk_device, type_open); 2669 if (fd >= 0) { 5599 2670 gb = get_boot(try_only); 5600 2671 if (gb > 0) { /* I/O error */ … … 5602 2673 } else if (gb < 0) { /* no DOS signature */ 5603 2674 list_disk_geometry(); 5604 if ( label_aix == current_label_type){2675 if (LABEL_IS_AIX) { 5605 2676 return; 5606 2677 } 5607 #ifdef CONFIG_FEATURE_OSF_LABEL 5608 if (btrydev(device) < 0) 5609 #endif 5610 fprintf(stderr, 5611 _("Disk %s doesn't contain a valid " 5612 "partition table\n"), device); 2678 #if ENABLE_FEATURE_OSF_LABEL 2679 if (bsd_trydev(device) < 0) 2680 #endif 2681 printf("Disk %s doesn't contain a valid " 2682 "partition table\n", device); 5613 2683 close(fd); 5614 2684 } else { 5615 2685 close(fd); 5616 2686 list_table(0); 5617 #if def CONFIG_FEATURE_FDISK_WRITABLE5618 if ( label_sun != current_label_type&& partitions > 4){2687 #if ENABLE_FEATURE_FDISK_WRITABLE 2688 if (!LABEL_IS_SUN && partitions > 4){ 5619 2689 delete_partition(ext_index); 5620 2690 } … … 5626 2696 installed on the system. */ 5627 2697 if (errno == EACCES) { 5628 fprintf(stderr, _("Cannot open %s\n"), device);2698 printf("Cannot open %s\n", device); 5629 2699 return; 5630 2700 } … … 5641 2711 int ma, mi, sz; 5642 2712 5643 procpt = bb_wfopen(PROC_PARTITIONS, "r");2713 procpt = fopen_or_warn("/proc/partitions", "r"); 5644 2714 5645 2715 while (fgets(line, sizeof(line), procpt)) { … … 5651 2721 continue; 5652 2722 sprintf(devname, "/dev/%s", ptname); 5653 try (devname, 0);5654 } 5655 #if def CONFIG_FEATURE_CLEAN_UP2723 trydev(devname, 0); 2724 } 2725 #if ENABLE_FEATURE_CLEAN_UP 5656 2726 fclose(procpt); 5657 2727 #endif 5658 2728 } 5659 2729 5660 #if def CONFIG_FEATURE_FDISK_WRITABLE2730 #if ENABLE_FEATURE_FDISK_WRITABLE 5661 2731 static void 5662 2732 unknown_command(int c) 5663 2733 { 5664 printf(_("%c: unknown command\n"), c); 5665 } 5666 #endif 5667 2734 printf("%c: unknown command\n", c); 2735 } 2736 #endif 2737 2738 int fdisk_main(int argc, char **argv); 5668 2739 int fdisk_main(int argc, char **argv) 5669 2740 { 5670 int c; 5671 #ifdef CONFIG_FEATURE_FDISK_WRITABLE 5672 int optl = 0; 5673 #endif 5674 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE 5675 int opts = 0; 5676 #endif 2741 char *str_b, *str_C, *str_H, *str_S; 2742 unsigned opt; 5677 2743 /* 5678 * Calls:5679 2744 * fdisk -v 5680 2745 * fdisk -l [-b sectorsize] [-u] device ... … … 5683 2748 * 5684 2749 * Options -C, -H, -S set the geometry. 5685 *5686 2750 */ 5687 while ((c = getopt(argc, argv, "b:C:H:lS:uvV" 5688 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE 5689 "s" 5690 #endif 5691 )) != -1) { 5692 switch (c) { 5693 case 'b': 5694 /* Ugly: this sector size is really per device, 5695 so cannot be combined with multiple disks, 5696 and te same goes for the C/H/S options. 5697 */ 5698 sector_size = atoi(optarg); 5699 if (sector_size != 512 && sector_size != 1024 && 5700 sector_size != 2048) 5701 bb_show_usage(); 5702 sector_offset = 2; 5703 user_set_sector_size = 1; 5704 break; 5705 case 'C': 5706 user_cylinders = atoi(optarg); 5707 break; 5708 case 'H': 5709 user_heads = atoi(optarg); 5710 if (user_heads <= 0 || user_heads >= 256) 5711 user_heads = 0; 5712 break; 5713 case 'S': 5714 user_sectors = atoi(optarg); 5715 if (user_sectors <= 0 || user_sectors >= 64) 5716 user_sectors = 0; 5717 break; 5718 case 'l': 5719 #ifdef CONFIG_FEATURE_FDISK_WRITABLE 5720 optl = 1; 5721 #endif 5722 break; 5723 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE 5724 case 's': 5725 opts = 1; 5726 break; 5727 #endif 5728 case 'u': 5729 display_in_cyl_units = 0; 5730 break; 5731 case 'V': 5732 case 'v': 5733 printf("fdisk v" UTIL_LINUX_VERSION "\n"); 5734 return 0; 5735 default: 2751 enum { 2752 OPT_b = 1 << 0, 2753 OPT_C = 1 << 1, 2754 OPT_H = 1 << 2, 2755 OPT_l = 1 << 3, 2756 OPT_S = 1 << 4, 2757 OPT_u = 1 << 5, 2758 OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE, 2759 }; 2760 2761 PTR_TO_GLOBALS = xzalloc(sizeof(G)); 2762 2763 opt = getopt32(argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"), 2764 &str_b, &str_C, &str_H, &str_S); 2765 argc -= optind; 2766 argv += optind; 2767 if (opt & OPT_b) { // -b 2768 /* Ugly: this sector size is really per device, 2769 so cannot be combined with multiple disks, 2770 and the same goes for the C/H/S options. 2771 */ 2772 sector_size = xatoi_u(str_b); 2773 if (sector_size != 512 && sector_size != 1024 && 2774 sector_size != 2048) 5736 2775 bb_show_usage(); 5737 } 5738 } 5739 5740 #if 0 5741 printf(_("This kernel finds the sector size itself - " 5742 "-b option ignored\n")); 5743 #else 5744 if (user_set_sector_size && argc-optind != 1) 5745 printf(_("Warning: the -b (set sector size) option should" 5746 " be used with one specified device\n")); 5747 #endif 5748 5749 #ifdef CONFIG_FEATURE_FDISK_WRITABLE 5750 if (optl) { 2776 sector_offset = 2; 2777 user_set_sector_size = 1; 2778 } 2779 if (opt & OPT_C) user_cylinders = xatoi_u(str_C); // -C 2780 if (opt & OPT_H) { // -H 2781 user_heads = xatoi_u(str_H); 2782 if (user_heads <= 0 || user_heads >= 256) 2783 user_heads = 0; 2784 } 2785 //if (opt & OPT_l) // -l 2786 if (opt & OPT_S) { // -S 2787 user_sectors = xatoi_u(str_S); 2788 if (user_sectors <= 0 || user_sectors >= 64) 2789 user_sectors = 0; 2790 } 2791 if (opt & OPT_u) display_in_cyl_units = 0; // -u 2792 //if (opt & OPT_s) // -s 2793 2794 if (user_set_sector_size && argc != 1) 2795 printf("Warning: the -b (set sector size) option should" 2796 " be used with one specified device\n"); 2797 2798 #if ENABLE_FEATURE_FDISK_WRITABLE 2799 if (opt & OPT_l) { 5751 2800 nowarn = 1; 5752 2801 #endif 5753 2802 type_open = O_RDONLY; 5754 if (argc > optind) {2803 if (argc > 0) { 5755 2804 int k; 5756 #if __GNUC__2805 #if defined(__GNUC__) 5757 2806 /* avoid gcc warning: 5758 2807 variable `k' might be clobbered by `longjmp' */ … … 5760 2809 #endif 5761 2810 listing = 1; 5762 for (k = optind; k < argc; k++)5763 try (argv[k], 1);2811 for (k = 0; k < argc; k++) 2812 trydev(argv[k], 1); 5764 2813 } else { 5765 2814 /* we no longer have default device names */ … … 5768 2817 } 5769 2818 return 0; 5770 #if def CONFIG_FEATURE_FDISK_WRITABLE5771 } 5772 #endif 5773 5774 #if def CONFIG_FEATURE_FDISK_BLKSIZE5775 if (opt s) {2819 #if ENABLE_FEATURE_FDISK_WRITABLE 2820 } 2821 #endif 2822 2823 #if ENABLE_FEATURE_FDISK_BLKSIZE 2824 if (opt & OPT_s) { 5776 2825 long size; 5777 2826 int j; … … 5780 2829 type_open = O_RDONLY; 5781 2830 5782 opts = argc - optind; 5783 if (opts <= 0) 2831 if (argc <= 0) 5784 2832 bb_show_usage(); 5785 2833 5786 for (j = optind; j < argc; j++) {2834 for (j = 0; j < argc; j++) { 5787 2835 disk_device = argv[j]; 5788 if ((fd = open(disk_device, type_open)) < 0) 2836 fd = open(disk_device, type_open); 2837 if (fd < 0) 5789 2838 fdisk_fatal(unable_to_open); 5790 2839 if (ioctl(fd, BLKGETSIZE, &size)) 5791 2840 fdisk_fatal(ioctl_error); 5792 2841 close(fd); 5793 if ( opts== 1)2842 if (argc == 1) 5794 2843 printf("%ld\n", size/2); 5795 2844 else … … 5800 2849 #endif 5801 2850 5802 #ifdef CONFIG_FEATURE_FDISK_WRITABLE 5803 if (argc-optind == 1) 5804 disk_device = argv[optind]; 5805 else 2851 #if ENABLE_FEATURE_FDISK_WRITABLE 2852 if (argc != 1) 5806 2853 bb_show_usage(); 5807 2854 2855 disk_device = argv[0]; 5808 2856 get_boot(fdisk); 5809 2857 5810 #ifdef CONFIG_FEATURE_OSF_LABEL 5811 if (label_osf == current_label_type) { 2858 if (LABEL_IS_OSF) { 5812 2859 /* OSF label, and no DOS label */ 5813 printf(_("Detected an OSF/1 disklabel on %s, entering " 5814 "disklabel mode.\n"), 5815 disk_device); 5816 bselect(); 2860 printf("Detected an OSF/1 disklabel on %s, entering " 2861 "disklabel mode\n", disk_device); 2862 bsd_select(); 5817 2863 /*Why do we do this? It seems to be counter-intuitive*/ 5818 2864 current_label_type = label_dos; 5819 2865 /* If we return we may want to make an empty DOS label? */ 5820 2866 } 5821 #endif5822 2867 5823 2868 while (1) { 2869 int c; 5824 2870 putchar('\n'); 5825 c = tolower(read_ char(_("Command (m for help): ")));2871 c = tolower(read_nonempty("Command (m for help): ")); 5826 2872 switch (c) { 5827 2873 case 'a': 5828 if ( label_dos == current_label_type)2874 if (LABEL_IS_DOS) 5829 2875 toggle_active(get_partition(1, partitions)); 5830 #ifdef CONFIG_FEATURE_SUN_LABEL 5831 else if (label_sun == current_label_type) 2876 else if (LABEL_IS_SUN) 5832 2877 toggle_sunflags(get_partition(1, partitions), 5833 2878 0x01); 5834 #endif 5835 #ifdef CONFIG_FEATURE_SGI_LABEL 5836 else if (label_sgi == current_label_type) 2879 else if (LABEL_IS_SGI) 5837 2880 sgi_set_bootpartition( 5838 2881 get_partition(1, partitions)); 5839 #endif5840 2882 else 5841 2883 unknown_command(c); 5842 2884 break; 5843 2885 case 'b': 5844 #ifdef CONFIG_FEATURE_SGI_LABEL 5845 if (label_sgi == current_label_type) { 5846 printf(_("\nThe current boot file is: %s\n"), 2886 if (LABEL_IS_SGI) { 2887 printf("\nThe current boot file is: %s\n", 5847 2888 sgi_get_bootfile()); 5848 if (read_ chars(_("Please enter the name of the "5849 "new boot file: ") )== '\n')5850 printf( _("Boot file unchanged\n"));2889 if (read_maybe_empty("Please enter the name of the " 2890 "new boot file: ") == '\n') 2891 printf("Boot file unchanged\n"); 5851 2892 else 5852 2893 sgi_set_bootfile(line_ptr); 5853 } else5854 # endif5855 #ifdef CONFIG_FEATURE_OSF_LABEL 5856 bs elect();2894 } 2895 #if ENABLE_FEATURE_OSF_LABEL 2896 else 2897 bsd_select(); 5857 2898 #endif 5858 2899 break; 5859 2900 case 'c': 5860 if ( label_dos == current_label_type)2901 if (LABEL_IS_DOS) 5861 2902 toggle_dos_compatibility_flag(); 5862 #ifdef CONFIG_FEATURE_SUN_LABEL 5863 else if (label_sun == current_label_type) 2903 else if (LABEL_IS_SUN) 5864 2904 toggle_sunflags(get_partition(1, partitions), 5865 2905 0x10); 5866 #endif 5867 #ifdef CONFIG_FEATURE_SGI_LABEL 5868 else if (label_sgi == current_label_type) 2906 else if (LABEL_IS_SGI) 5869 2907 sgi_set_swappartition( 5870 2908 get_partition(1, partitions)); 5871 #endif5872 2909 else 5873 2910 unknown_command(c); … … 5876 2913 { 5877 2914 int j; 5878 #ifdef CONFIG_FEATURE_SGI_LABEL5879 2915 /* If sgi_label then don't use get_existing_partition, 5880 2916 let the user select a partition, since 5881 2917 get_existing_partition() only works for Linux-like 5882 2918 partition tables */ 5883 if ( label_sgi != current_label_type) {2919 if (!LABEL_IS_SGI) { 5884 2920 j = get_existing_partition(1, partitions); 5885 2921 } else { 5886 2922 j = get_partition(1, partitions); 5887 2923 } 5888 #else5889 j = get_existing_partition(1, partitions);5890 #endif5891 2924 if (j >= 0) 5892 2925 delete_partition(j); … … 5894 2927 break; 5895 2928 case 'i': 5896 #ifdef CONFIG_FEATURE_SGI_LABEL 5897 if (label_sgi == current_label_type) 2929 if (LABEL_IS_SGI) 5898 2930 create_sgiinfo(); 5899 2931 else 5900 #endif5901 2932 unknown_command(c); 5902 2933 case 'l': … … 5917 2948 case 'q': 5918 2949 close(fd); 5919 p rintf("\n");2950 puts(""); 5920 2951 return 0; 5921 2952 case 's': 5922 #if def CONFIG_FEATURE_SUN_LABEL2953 #if ENABLE_FEATURE_SUN_LABEL 5923 2954 create_sunlabel(); 5924 2955 #endif … … 5936 2967 write_table(); /* does not return */ 5937 2968 break; 5938 #if def CONFIG_FEATURE_FDISK_ADVANCED2969 #if ENABLE_FEATURE_FDISK_ADVANCED 5939 2970 case 'x': 5940 #ifdef CONFIG_FEATURE_SGI_LABEL 5941 if (label_sgi == current_label_type) { 5942 fprintf(stderr, 5943 _("\n\tSorry, no experts menu for SGI " 5944 "partition tables available.\n\n")); 2971 if (LABEL_IS_SGI) { 2972 printf("\n\tSorry, no experts menu for SGI " 2973 "partition tables available\n\n"); 5945 2974 } else 5946 #endif5947 5948 2975 xselect(); 5949 2976 break; … … 5955 2982 } 5956 2983 return 0; 5957 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */5958 } 2984 #endif /* FEATURE_FDISK_WRITABLE */ 2985 } -
branches/stable/mindi-busybox/util-linux/freeramdisk.c
r821 r1770 7 7 * Unified with fdflush by Tito Ragusa <farmatito@tiscali.it> 8 8 * 9 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.9 * Licensed under GPLv2, see file LICENSE in this tarball for details. 10 10 */ 11 11 12 #include <stdio.h> 13 #include <string.h> 14 #include <sys/types.h> 15 #include <fcntl.h> 16 #include <sys/ioctl.h> 17 #include <stdlib.h> 18 #include <unistd.h> 19 #include "busybox.h" 12 #include "libbb.h" 20 13 21 14 /* From <linux/fd.h> */ 22 15 #define FDFLUSH _IO(2,0x4b) 23 16 17 int freeramdisk_main(int argc, char **argv); 24 18 int freeramdisk_main(int argc, char **argv) 25 19 { 26 int result;27 20 int fd; 28 21 29 22 if (argc != 2) bb_show_usage(); 30 23 31 fd = bb_xopen(argv[1], O_RDWR);24 fd = xopen(argv[1], O_RDWR); 32 25 33 26 // Act like freeramdisk, fdflush, or both depending on configuration. 34 result = ioctl(fd, (ENABLE_FREERAMDISK && bb_applet_name[1]=='r')35 || !ENABLE_FDFLUSH ? BLKFLSBUF : FDFLUSH );27 ioctl_or_perror_and_die(fd, (ENABLE_FREERAMDISK && applet_name[1]=='r') 28 || !ENABLE_FDFLUSH ? BLKFLSBUF : FDFLUSH, NULL, "%s", argv[1]); 36 29 37 30 if (ENABLE_FEATURE_CLEAN_UP) close(fd); 38 31 39 if (result) bb_perror_msg_and_die("%s", argv[1]);40 32 return EXIT_SUCCESS; 41 33 } -
branches/stable/mindi-busybox/util-linux/fsck_minix.c
r821 r1770 3 3 * fsck.c - a file system consistency checker for Linux. 4 4 * 5 * (C) 1991, 1992 Linus Torvalds. This file may be redistributed 6 * as per the GNU copyleft. 5 * (C) 1991, 1992 Linus Torvalds. 6 * 7 * Licensed under GPLv2, see file LICENSE in this tarball for details. 7 8 */ 8 9 … … 87 88 */ 88 89 89 #include <stdio.h>90 #include <errno.h>91 #include <unistd.h>92 #include <string.h>93 #include <fcntl.h>94 #include <ctype.h>95 #include <stdlib.h>96 #include <termios.h>97 90 #include <mntent.h> 98 #include <sys/param.h> 99 #include "busybox.h" 100 101 /* 102 * This is the original minix inode layout on disk. 103 * Note the 8-bit gid and atime and ctime. 104 */ 105 struct minix_inode { 106 uint16_t i_mode; 107 uint16_t i_uid; 108 uint32_t i_size; 109 uint32_t i_time; 110 uint8_t i_gid; 111 uint8_t i_nlinks; 112 uint16_t i_zone[9]; 113 }; 114 115 /* 116 * The new minix inode has all the time entries, as well as 117 * long block numbers and a third indirect block (7+1+1+1 118 * instead of 7+1+1). Also, some previously 8-bit values are 119 * now 16-bit. The inode is now 64 bytes instead of 32. 120 */ 121 struct minix2_inode { 122 uint16_t i_mode; 123 uint16_t i_nlinks; 124 uint16_t i_uid; 125 uint16_t i_gid; 126 uint32_t i_size; 127 uint32_t i_atime; 128 uint32_t i_mtime; 129 uint32_t i_ctime; 130 uint32_t i_zone[10]; 131 }; 91 #include "libbb.h" 92 #include "minix.h" 93 94 #ifndef BLKGETSIZE 95 #define BLKGETSIZE _IO(0x12,96) /* return device size */ 96 #endif 132 97 133 98 enum { 134 MINIX_ROOT_INO = 1, 135 MINIX _LINK_MAX = 250,99 #ifdef UNUSED 100 MINIX1_LINK_MAX = 250, 136 101 MINIX2_LINK_MAX = 65530, 137 138 102 MINIX_I_MAP_SLOTS = 8, 139 103 MINIX_Z_MAP_SLOTS = 64, 140 MINIX_SUPER_MAGIC = 0x137F, /* original minix fs */ 141 MINIX_SUPER_MAGIC2 = 0x138F, /* minix fs, 30 char names */ 142 MINIX2_SUPER_MAGIC = 0x2468, /* minix V2 fs */ 143 MINIX2_SUPER_MAGIC2 = 0x2478, /* minix V2 fs, 30 char names */ 144 MINIX_VALID_FS = 0x0001, /* Clean fs. */ 145 MINIX_ERROR_FS = 0x0002, /* fs has errors. */ 146 147 MINIX_INODES_PER_BLOCK = ((BLOCK_SIZE)/(sizeof (struct minix_inode))), 148 MINIX2_INODES_PER_BLOCK = ((BLOCK_SIZE)/(sizeof (struct minix2_inode))), 149 150 MINIX_V1 = 0x0001, /* original minix fs */ 151 MINIX_V2 = 0x0002 /* minix V2 fs */ 104 MINIX_V1 = 0x0001, /* original minix fs */ 105 MINIX_V2 = 0x0002, /* minix V2 fs */ 106 #endif 107 MINIX_NAME_MAX = 255, /* # chars in a file name */ 152 108 }; 153 109 154 #define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version 155 156 /* 157 * minix super-block data on disk 158 */ 159 struct minix_super_block { 160 uint16_t s_ninodes; 161 uint16_t s_nzones; 162 uint16_t s_imap_blocks; 163 uint16_t s_zmap_blocks; 164 uint16_t s_firstdatazone; 165 uint16_t s_log_zone_size; 166 uint32_t s_max_size; 167 uint16_t s_magic; 168 uint16_t s_state; 169 uint32_t s_zones; 110 #if !ENABLE_FEATURE_MINIX2 111 enum { version2 = 0 }; 112 #endif 113 114 enum { MAX_DEPTH = 32 }; 115 116 struct globals { 117 int dev_fd; 118 #if ENABLE_FEATURE_MINIX2 119 smallint version2; 120 #endif 121 smallint repair, automatic, verbose, list, show, warn_mode, force; 122 smallint changed; /* is filesystem modified? */ 123 smallint errors_uncorrected; /* flag if some error was not corrected */ 124 smallint termios_set; 125 smallint dirsize; 126 smallint namelen; 127 char *device_name; 128 int directory, regular, blockdev, chardev, links, symlinks, total; 129 char *inode_buffer; 130 131 char *inode_map; 132 char *zone_map; 133 134 unsigned char *inode_count; 135 unsigned char *zone_count; 136 137 /* File-name data */ 138 int name_depth; 139 char *name_component[MAX_DEPTH+1]; 140 141 /* Bigger stuff */ 142 struct termios sv_termios; 143 char super_block_buffer[BLOCK_SIZE]; 144 char add_zone_ind_blk[BLOCK_SIZE]; 145 char add_zone_dind_blk[BLOCK_SIZE]; 146 USE_FEATURE_MINIX2(char add_zone_tind_blk[BLOCK_SIZE];) 147 char check_file_blk[BLOCK_SIZE]; 148 149 /* File-name data */ 150 char current_name[MAX_DEPTH * MINIX_NAME_MAX]; 170 151 }; 171 152 172 struct minix_dir_entry { 173 uint16_t inode; 174 char name[0]; 175 }; 176 177 178 #define NAME_MAX 255 /* # chars in a file name */ 179 180 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode))) 181 182 #ifndef BLKGETSIZE 183 #define BLKGETSIZE _IO(0x12,96) /* return device size */ 184 #endif 185 186 #ifndef __linux__ 187 #define volatile 188 #endif 189 190 enum { ROOT_INO = 1 }; 191 192 #define UPPER(size,n) ((size+((n)-1))/(n)) 193 #define INODE_SIZE (sizeof(struct minix_inode)) 194 #ifdef CONFIG_FEATURE_MINIX2 195 #define INODE_SIZE2 (sizeof(struct minix2_inode)) 196 #define INODE_BLOCKS UPPER(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \ 197 : MINIX_INODES_PER_BLOCK)) 153 #define G (*ptr_to_globals) 154 #define dev_fd (G.dev_fd ) 155 #if ENABLE_FEATURE_MINIX2 156 #define version2 (G.version2 ) 157 #endif 158 #define repair (G.repair ) 159 #define automatic (G.automatic ) 160 #define verbose (G.verbose ) 161 #define list (G.list ) 162 #define show (G.show ) 163 #define warn_mode (G.warn_mode ) 164 #define force (G.force ) 165 #define changed (G.changed ) 166 #define errors_uncorrected (G.errors_uncorrected ) 167 #define termios_set (G.termios_set ) 168 #define dirsize (G.dirsize ) 169 #define namelen (G.namelen ) 170 #define device_name (G.device_name ) 171 #define directory (G.directory ) 172 #define regular (G.regular ) 173 #define blockdev (G.blockdev ) 174 #define chardev (G.chardev ) 175 #define links (G.links ) 176 #define symlinks (G.symlinks ) 177 #define total (G.total ) 178 #define inode_buffer (G.inode_buffer ) 179 #define inode_map (G.inode_map ) 180 #define zone_map (G.zone_map ) 181 #define inode_count (G.inode_count ) 182 #define zone_count (G.zone_count ) 183 #define name_depth (G.name_depth ) 184 #define name_component (G.name_component ) 185 #define sv_termios (G.sv_termios ) 186 #define super_block_buffer (G.super_block_buffer ) 187 #define add_zone_ind_blk (G.add_zone_ind_blk ) 188 #define add_zone_dind_blk (G.add_zone_dind_blk ) 189 #define add_zone_tind_blk (G.add_zone_tind_blk ) 190 #define check_file_blk (G.check_file_blk ) 191 #define current_name (G.current_name ) 192 #define INIT_G() do { \ 193 PTR_TO_GLOBALS = xzalloc(sizeof(G)); \ 194 dirsize = 16; \ 195 namelen = 14; \ 196 current_name[0] = '/'; \ 197 /*current_name[1] = '\0';*/ \ 198 name_component[0] = ¤t_name[0]; \ 199 } while (0) 200 201 #define Inode1 (((struct minix1_inode *) inode_buffer)-1) 202 #define Inode2 (((struct minix2_inode *) inode_buffer)-1) 203 204 #define Super (*(struct minix_super_block *)(super_block_buffer)) 205 206 #if ENABLE_FEATURE_MINIX2 207 # define ZONES ((unsigned)(version2 ? Super.s_zones : Super.s_nzones)) 198 208 #else 199 #define INODE_BLOCKS UPPER(INODES, (MINIX_INODES_PER_BLOCK)) 200 #endif 209 # define ZONES ((unsigned)(Super.s_nzones)) 210 #endif 211 #define INODES ((unsigned)Super.s_ninodes) 212 #define IMAPS ((unsigned)Super.s_imap_blocks) 213 #define ZMAPS ((unsigned)Super.s_zmap_blocks) 214 #define FIRSTZONE ((unsigned)Super.s_firstdatazone) 215 #define ZONESIZE ((unsigned)Super.s_log_zone_size) 216 #define MAXSIZE ((unsigned)Super.s_max_size) 217 #define MAGIC (Super.s_magic) 218 219 /* gcc likes this more (code is smaller) than macro variant */ 220 static ALWAYS_INLINE unsigned div_roundup(unsigned size, unsigned n) 221 { 222 return (size + n-1) / n; 223 } 224 225 #if ENABLE_FEATURE_MINIX2 226 #define INODE_BLOCKS div_roundup(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \ 227 : MINIX1_INODES_PER_BLOCK)) 228 #else 229 #define INODE_BLOCKS div_roundup(INODES, MINIX1_INODES_PER_BLOCK) 230 #endif 231 201 232 #define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE) 202 203 #define BITS_PER_BLOCK (BLOCK_SIZE<<3) 204 205 static char *program_version = "1.2 - 11/11/96"; 206 static char *device_name; 207 static int IN; 208 static int repair, automatic, verbose, list, show, warn_mode, force; 209 static int directory, regular, blockdev, chardev, links, symlinks, total; 210 211 static int changed; /* flags if the filesystem has been changed */ 212 static int errors_uncorrected; /* flag if some error was not corrected */ 213 static int dirsize = 16; 214 static int namelen = 14; 215 static struct termios termios; 216 static int termios_set; 217 218 static char *inode_buffer; 219 #define Inode (((struct minix_inode *) inode_buffer)-1) 220 #define Inode2 (((struct minix2_inode *) inode_buffer)-1) 221 static char super_block_buffer[BLOCK_SIZE]; 222 223 #define Super (*(struct minix_super_block *)super_block_buffer) 224 #define INODES ((unsigned long)Super.s_ninodes) 225 #ifdef CONFIG_FEATURE_MINIX2 226 static int version2; 227 #define ZONES ((unsigned long)(version2 ? Super.s_zones : Super.s_nzones)) 228 #else 229 #define ZONES ((unsigned long)(Super.s_nzones)) 230 #endif 231 #define IMAPS ((unsigned long)Super.s_imap_blocks) 232 #define ZMAPS ((unsigned long)Super.s_zmap_blocks) 233 #define FIRSTZONE ((unsigned long)Super.s_firstdatazone) 234 #define ZONESIZE ((unsigned long)Super.s_log_zone_size) 235 #define MAXSIZE ((unsigned long)Super.s_max_size) 236 #define MAGIC (Super.s_magic) 237 #define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS) 238 239 static char *inode_map; 240 static char *zone_map; 241 242 static unsigned char *inode_count; 243 static unsigned char *zone_count; 244 245 static void recursive_check(unsigned int ino); 246 #ifdef CONFIG_FEATURE_MINIX2 247 static void recursive_check2(unsigned int ino); 248 #endif 249 250 static inline int bit(char *a, unsigned int i) 251 { 252 return (a[i >> 3] & (1<<(i & 7))) != 0; 253 } 254 #define inode_in_use(x) (bit(inode_map,(x))) 255 #define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1)) 256 257 #define mark_inode(x) (setbit(inode_map,(x)),changed=1) 258 #define unmark_inode(x) (clrbit(inode_map,(x)),changed=1) 259 260 #define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1),changed=1) 261 #define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1),changed=1) 262 263 static void leave(int) ATTRIBUTE_NORETURN; 264 static void leave(int status) 233 #define NORM_FIRSTZONE (2 + IMAPS + ZMAPS + INODE_BLOCKS) 234 235 /* Before you ask "where they come from?": */ 236 /* setbit/clrbit are supplied by sys/param.h */ 237 238 static int minix_bit(const char *a, unsigned i) 239 { 240 return (a[i >> 3] & (1<<(i & 7))); 241 } 242 243 static void minix_setbit(char *a, unsigned i) 244 { 245 setbit(a, i); 246 changed = 1; 247 } 248 static void minix_clrbit(char *a, unsigned i) 249 { 250 clrbit(a, i); 251 changed = 1; 252 } 253 254 /* Note: do not assume 0/1, it is 0/nonzero */ 255 #define zone_in_use(x) (minix_bit(zone_map,(x)-FIRSTZONE+1)) 256 #define inode_in_use(x) (minix_bit(inode_map,(x))) 257 258 #define mark_inode(x) (minix_setbit(inode_map,(x))) 259 #define unmark_inode(x) (minix_clrbit(inode_map,(x))) 260 261 #define mark_zone(x) (minix_setbit(zone_map,(x)-FIRSTZONE+1)) 262 #define unmark_zone(x) (minix_clrbit(zone_map,(x)-FIRSTZONE+1)) 263 264 265 static void recursive_check(unsigned ino); 266 #if ENABLE_FEATURE_MINIX2 267 static void recursive_check2(unsigned ino); 268 #endif 269 270 static void die(const char *str) ATTRIBUTE_NORETURN; 271 static void die(const char *str) 265 272 { 266 273 if (termios_set) 267 tcsetattr(0, TCSANOW, &termios); 268 exit(status); 269 } 270 271 static void die(const char *str) 272 { 273 bb_error_msg("%s", str); 274 leave(8); 275 } 276 277 /* File-name data */ 278 enum { MAX_DEPTH = 32 }; 279 static int name_depth; 280 static char *current_name; 281 static char *name_component[MAX_DEPTH+1]; 282 283 /* Wed Feb 9 15:17:06 MST 2000 */ 284 /* dynamically allocate name_list (instead of making it static) */ 285 static inline void alloc_current_name(void) 286 { 287 current_name = xmalloc(MAX_DEPTH * (BUFSIZ + 1)); 288 current_name[0] = '/'; 289 current_name[1] = '\0'; 290 name_component[0] = ¤t_name[0]; 291 } 292 293 #ifdef CONFIG_FEATURE_CLEAN_UP 294 /* execute this atexit() to deallocate name_list[] */ 295 /* piptigger was here */ 296 static inline void free_current_name(void) 297 { 298 free(current_name); 299 } 300 #endif 274 tcsetattr(0, TCSANOW, &sv_termios); 275 bb_error_msg_and_die("%s", str); 276 } 301 277 302 278 static void push_filename(const char *name) … … 315 291 } 316 292 317 static void pop_filename(void) { 293 static void pop_filename(void) 294 { 318 295 name_depth--; 319 296 if (name_depth < MAX_DEPTH) { … … 331 308 332 309 if (!repair) { 333 p rintf("\n");310 puts(""); 334 311 errors_uncorrected = 1; 335 312 return 0; 336 313 } 337 314 if (automatic) { 338 p rintf("\n");315 puts(""); 339 316 if (!def) 340 317 errors_uncorrected = 1; … … 344 321 for (;;) { 345 322 fflush(stdout); 346 if ((c = getchar()) == EOF) { 323 c = getchar(); 324 if (c == EOF) { 347 325 if (!def) 348 326 errors_uncorrected = 1; … … 380 358 int fd; 381 359 382 if ((f = setmntent(MOUNTED, "r")) == NULL) 360 f = setmntent(MOUNTED, "r"); 361 if (f == NULL) 383 362 return; 384 363 while ((mnt = getmntent(f)) != NULL) … … 397 376 if (fd < 0 && errno == EROFS) 398 377 return; 399 else 400 close(fd); 378 close(fd); 401 379 402 380 printf("%s is mounted. ", device_name); … … 408 386 exit(0); 409 387 } 410 return;411 388 } 412 389 … … 417 394 * or a bad zone-number). 418 395 */ 419 static int check_zone_nr2(uint32_t *nr, int *corrected)396 static int check_zone_nr2(uint32_t *nr, smallint *corrected) 420 397 { 421 398 const char *msg; … … 436 413 } 437 414 438 static int check_zone_nr(uint16_t *nr, int *corrected)415 static int check_zone_nr(uint16_t *nr, smallint *corrected) 439 416 { 440 417 uint32_t nr32 = *nr; … … 447 424 * read-block reads block nr into the buffer at addr. 448 425 */ 449 static void read_block(unsigned intnr, char *addr)426 static void read_block(unsigned nr, char *addr) 450 427 { 451 428 if (!nr) { … … 453 430 return; 454 431 } 455 if (BLOCK_SIZE * nr != lseek( IN, BLOCK_SIZE * nr, SEEK_SET)) {456 printf("%s: unable toseek to block in file '%s'\n",432 if (BLOCK_SIZE * nr != lseek(dev_fd, BLOCK_SIZE * nr, SEEK_SET)) { 433 printf("%s: cannot seek to block in file '%s'\n", 457 434 bb_msg_read_error, current_name); 458 435 errors_uncorrected = 1; 459 436 memset(addr, 0, BLOCK_SIZE); 460 } else if (BLOCK_SIZE != read( IN, addr, BLOCK_SIZE)) {437 } else if (BLOCK_SIZE != read(dev_fd, addr, BLOCK_SIZE)) { 461 438 printf("%s: bad block in file '%s'\n", 462 439 bb_msg_read_error, current_name); … … 469 446 * write_block writes block nr to disk. 470 447 */ 471 static void write_block(unsigned intnr, char *addr)448 static void write_block(unsigned nr, char *addr) 472 449 { 473 450 if (!nr) … … 479 456 return; 480 457 } 481 if (BLOCK_SIZE * nr != lseek( IN, BLOCK_SIZE * nr, SEEK_SET))482 die(" Seek failed in write_block");483 if (BLOCK_SIZE != write( IN, addr, BLOCK_SIZE)) {458 if (BLOCK_SIZE * nr != lseek(dev_fd, BLOCK_SIZE * nr, SEEK_SET)) 459 die("seek failed in write_block"); 460 if (BLOCK_SIZE != write(dev_fd, addr, BLOCK_SIZE)) { 484 461 printf("%s: bad block in file '%s'\n", 485 462 bb_msg_write_error, current_name); … … 493 470 * any indirect blocks with errors. 494 471 */ 495 static int map_block(struct minix _inode *inode, unsigned intblknr)472 static int map_block(struct minix1_inode *inode, unsigned blknr) 496 473 { 497 474 uint16_t ind[BLOCK_SIZE >> 1]; 498 475 uint16_t dind[BLOCK_SIZE >> 1]; 499 int blk_chg, block, result; 476 int block, result; 477 smallint blk_chg; 500 478 501 479 if (blknr < 7) … … 527 505 } 528 506 529 #if def CONFIG_FEATURE_MINIX2530 static int map_block2(struct minix2_inode *inode, unsigned intblknr)507 #if ENABLE_FEATURE_MINIX2 508 static int map_block2(struct minix2_inode *inode, unsigned blknr) 531 509 { 532 510 uint32_t ind[BLOCK_SIZE >> 2]; 533 511 uint32_t dind[BLOCK_SIZE >> 2]; 534 512 uint32_t tind[BLOCK_SIZE >> 2]; 535 int blk_chg, block, result; 513 int block, result; 514 smallint blk_chg; 536 515 537 516 if (blknr < 7) … … 593 572 * unconditionally set if we get this far. 594 573 */ 595 Super.s_state |= MINIX_VALID_FS; 596 if (errors_uncorrected) 597 Super.s_state |= MINIX_ERROR_FS; 598 else 574 Super.s_state |= MINIX_VALID_FS | MINIX_ERROR_FS; 575 if (!errors_uncorrected) 599 576 Super.s_state &= ~MINIX_ERROR_FS; 600 577 601 if (BLOCK_SIZE != lseek( IN, BLOCK_SIZE, SEEK_SET))602 die(" Seek failed in write_super_block");603 if (BLOCK_SIZE != write( IN, super_block_buffer, BLOCK_SIZE))604 die(" Unable towrite super-block");578 if (BLOCK_SIZE != lseek(dev_fd, BLOCK_SIZE, SEEK_SET)) 579 die("seek failed in write_super_block"); 580 if (BLOCK_SIZE != write(dev_fd, super_block_buffer, BLOCK_SIZE)) 581 die("cannot write super-block"); 605 582 } 606 583 … … 609 586 write_super_block(); 610 587 611 if (IMAPS * BLOCK_SIZE != write( IN, inode_map, IMAPS * BLOCK_SIZE))612 die(" Unable towrite inode map");613 if (ZMAPS * BLOCK_SIZE != write( IN, zone_map, ZMAPS * BLOCK_SIZE))614 die(" Unable towrite zone map");615 if (INODE_BUFFER_SIZE != write( IN, inode_buffer, INODE_BUFFER_SIZE))616 die(" Unable towrite inodes");588 if (IMAPS * BLOCK_SIZE != write(dev_fd, inode_map, IMAPS * BLOCK_SIZE)) 589 die("cannot write inode map"); 590 if (ZMAPS * BLOCK_SIZE != write(dev_fd, zone_map, ZMAPS * BLOCK_SIZE)) 591 die("cannot write zone map"); 592 if (INODE_BUFFER_SIZE != write(dev_fd, inode_buffer, INODE_BUFFER_SIZE)) 593 die("cannot write inodes"); 617 594 } 618 595 … … 623 600 int size; 624 601 625 #if def CONFIG_FEATURE_MINIX2602 #if ENABLE_FEATURE_MINIX2 626 603 if (version2) 627 block = Inode2[ ROOT_INO].i_zone[0];604 block = Inode2[MINIX_ROOT_INO].i_zone[0]; 628 605 else 629 606 #endif 630 block = Inode [ROOT_INO].i_zone[0];607 block = Inode1[MINIX_ROOT_INO].i_zone[0]; 631 608 read_block(block, blk); 632 609 for (size = 16; size < BLOCK_SIZE; size <<= 1) { … … 642 619 static void read_superblock(void) 643 620 { 644 if (BLOCK_SIZE != lseek( IN, BLOCK_SIZE, SEEK_SET))645 die(" Seek failed");646 if (BLOCK_SIZE != read( IN, super_block_buffer, BLOCK_SIZE))647 die(" Unable toread super block");621 if (BLOCK_SIZE != lseek(dev_fd, BLOCK_SIZE, SEEK_SET)) 622 die("seek failed"); 623 if (BLOCK_SIZE != read(dev_fd, super_block_buffer, BLOCK_SIZE)) 624 die("cannot read super block"); 648 625 /* already initialized to: 649 626 namelen = 14; … … 651 628 version2 = 0; 652 629 */ 653 if (MAGIC == MINIX _SUPER_MAGIC) {654 } else if (MAGIC == MINIX _SUPER_MAGIC2) {630 if (MAGIC == MINIX1_SUPER_MAGIC) { 631 } else if (MAGIC == MINIX1_SUPER_MAGIC2) { 655 632 namelen = 30; 656 633 dirsize = 32; 657 #if def CONFIG_FEATURE_MINIX2634 #if ENABLE_FEATURE_MINIX2 658 635 } else if (MAGIC == MINIX2_SUPER_MAGIC) { 659 636 version2 = 1; … … 664 641 #endif 665 642 } else 666 die(" Bad magic number in super-block");643 die("bad magic number in super-block"); 667 644 if (ZONESIZE != 0 || BLOCK_SIZE != 1024) 668 die(" Only 1k blocks/zones supported");645 die("only 1k blocks/zones supported"); 669 646 if (IMAPS * BLOCK_SIZE * 8 < INODES + 1) 670 die(" Bad s_imap_blocks field in super-block");647 die("bad s_imap_blocks field in super-block"); 671 648 if (ZMAPS * BLOCK_SIZE * 8 < ZONES - FIRSTZONE + 1) 672 die(" Bad s_zmap_blocks field in super-block");649 die("bad s_zmap_blocks field in super-block"); 673 650 } 674 651 … … 680 657 inode_count = xmalloc(INODES + 1); 681 658 zone_count = xmalloc(ZONES); 682 if (IMAPS * BLOCK_SIZE != read( IN, inode_map, IMAPS * BLOCK_SIZE))683 die(" Unable toread inode map");684 if (ZMAPS * BLOCK_SIZE != read( IN, zone_map, ZMAPS * BLOCK_SIZE))685 die(" Unable toread zone map");686 if (INODE_BUFFER_SIZE != read( IN, inode_buffer, INODE_BUFFER_SIZE))687 die(" Unable toread inodes");659 if (IMAPS * BLOCK_SIZE != read(dev_fd, inode_map, IMAPS * BLOCK_SIZE)) 660 die("cannot read inode map"); 661 if (ZMAPS * BLOCK_SIZE != read(dev_fd, zone_map, ZMAPS * BLOCK_SIZE)) 662 die("cannot read zone map"); 663 if (INODE_BUFFER_SIZE != read(dev_fd, inode_buffer, INODE_BUFFER_SIZE)) 664 die("cannot read inodes"); 688 665 if (NORM_FIRSTZONE != FIRSTZONE) { 689 printf(" Warning: Firstzone!=Norm_firstzone\n");666 printf("warning: firstzone!=norm_firstzone\n"); 690 667 errors_uncorrected = 1; 691 668 } 692 669 get_dirsize(); 693 670 if (show) { 694 printf("% ldinodes\n"695 "% ldblocks\n"696 "Firstdatazone=% ld (%ld)\n"697 "Zonesize=% d\n"698 "Maxsize=% ld\n"699 "Filesystem state=% d\n"700 "namelen=% d\n\n",671 printf("%u inodes\n" 672 "%u blocks\n" 673 "Firstdatazone=%u (%u)\n" 674 "Zonesize=%u\n" 675 "Maxsize=%u\n" 676 "Filesystem state=%u\n" 677 "namelen=%u\n\n", 701 678 INODES, 702 679 ZONES, … … 709 686 } 710 687 711 static struct minix _inode *get_inode(unsigned intnr)712 { 713 struct minix _inode *inode;688 static struct minix1_inode *get_inode(unsigned nr) 689 { 690 struct minix1_inode *inode; 714 691 715 692 if (!nr || nr > INODES) 716 693 return NULL; 717 694 total++; 718 inode = Inode + nr;695 inode = Inode1 + nr; 719 696 if (!inode_count[nr]) { 720 697 if (!inode_in_use(nr)) { … … 724 701 if (ask("Mark as 'in use'", 1)) 725 702 mark_inode(nr); 726 } else {727 errors_uncorrected = 1;703 else 704 errors_uncorrected = 1; 728 705 } 729 706 } … … 754 731 } 755 732 756 #if def CONFIG_FEATURE_MINIX2757 static struct minix2_inode *get_inode2(unsigned intnr)733 #if ENABLE_FEATURE_MINIX2 734 static struct minix2_inode *get_inode2(unsigned nr) 758 735 { 759 736 struct minix2_inode *inode; … … 802 779 static void check_root(void) 803 780 { 804 struct minix _inode *inode = Inode +ROOT_INO;781 struct minix1_inode *inode = Inode1 + MINIX_ROOT_INO; 805 782 806 783 if (!inode || !S_ISDIR(inode->i_mode)) 807 die(" Root inode isn't a directory");808 } 809 810 #if def CONFIG_FEATURE_MINIX2784 die("root inode isn't a directory"); 785 } 786 787 #if ENABLE_FEATURE_MINIX2 811 788 static void check_root2(void) 812 789 { 813 struct minix2_inode *inode = Inode2 + ROOT_INO;790 struct minix2_inode *inode = Inode2 + MINIX_ROOT_INO; 814 791 815 792 if (!inode || !S_ISDIR(inode->i_mode)) 816 die("Root inode isn't a directory"); 817 } 818 #endif 819 820 static int add_zone(uint16_t *znr, int *corrected) 793 die("root inode isn't a directory"); 794 } 795 #else 796 void check_root2(void); 797 #endif 798 799 static int add_zone(uint16_t *znr, smallint *corrected) 821 800 { 822 801 int result; … … 848 827 } 849 828 850 #if def CONFIG_FEATURE_MINIX2851 static int add_zone2(uint32_t *znr, int *corrected)829 #if ENABLE_FEATURE_MINIX2 830 static int add_zone2(uint32_t *znr, smallint *corrected) 852 831 { 853 832 int result; … … 880 859 #endif 881 860 882 static void add_zone_ind(uint16_t *znr, int *corrected) 883 { 884 static char blk[BLOCK_SIZE]; 885 int i, chg_blk = 0; 861 static void add_zone_ind(uint16_t *znr, smallint *corrected) 862 { 863 int i; 886 864 int block; 865 smallint chg_blk = 0; 887 866 888 867 block = add_zone(znr, corrected); 889 868 if (!block) 890 869 return; 891 read_block(block, blk);870 read_block(block, add_zone_ind_blk); 892 871 for (i = 0; i < (BLOCK_SIZE >> 1); i++) 893 add_zone(i + (uint16_t *) blk, &chg_blk);872 add_zone(i + (uint16_t *) add_zone_ind_blk, &chg_blk); 894 873 if (chg_blk) 895 write_block(block, blk); 896 } 897 898 #ifdef CONFIG_FEATURE_MINIX2 899 static void add_zone_ind2(uint32_t *znr, int *corrected) 900 { 901 static char blk[BLOCK_SIZE]; 902 int i, chg_blk = 0; 874 write_block(block, add_zone_ind_blk); 875 } 876 877 #if ENABLE_FEATURE_MINIX2 878 static void add_zone_ind2(uint32_t *znr, smallint *corrected) 879 { 880 int i; 903 881 int block; 882 smallint chg_blk = 0; 904 883 905 884 block = add_zone2(znr, corrected); 906 885 if (!block) 907 886 return; 908 read_block(block, blk);887 read_block(block, add_zone_ind_blk); 909 888 for (i = 0; i < BLOCK_SIZE >> 2; i++) 910 add_zone2(i + (uint32_t *) blk, &chg_blk);889 add_zone2(i + (uint32_t *) add_zone_ind_blk, &chg_blk); 911 890 if (chg_blk) 912 write_block(block, blk); 913 } 914 #endif 915 916 static void add_zone_dind(uint16_t *znr, int *corrected) 917 { 918 static char blk[BLOCK_SIZE]; 919 int i, blk_chg = 0; 891 write_block(block, add_zone_ind_blk); 892 } 893 #endif 894 895 static void add_zone_dind(uint16_t *znr, smallint *corrected) 896 { 897 int i; 920 898 int block; 899 smallint chg_blk = 0; 921 900 922 901 block = add_zone(znr, corrected); 923 902 if (!block) 924 903 return; 925 read_block(block, blk);904 read_block(block, add_zone_dind_blk); 926 905 for (i = 0; i < (BLOCK_SIZE >> 1); i++) 927 add_zone_ind(i + (uint16_t *) blk, &blk_chg); 928 if (blk_chg) 929 write_block(block, blk); 930 } 931 932 #ifdef CONFIG_FEATURE_MINIX2 933 static void add_zone_dind2(uint32_t *znr, int *corrected) 934 { 935 static char blk[BLOCK_SIZE]; 936 int i, blk_chg = 0; 906 add_zone_ind(i + (uint16_t *) add_zone_dind_blk, &chg_blk); 907 if (chg_blk) 908 write_block(block, add_zone_dind_blk); 909 } 910 911 #if ENABLE_FEATURE_MINIX2 912 static void add_zone_dind2(uint32_t *znr, smallint *corrected) 913 { 914 int i; 937 915 int block; 916 smallint chg_blk = 0; 938 917 939 918 block = add_zone2(znr, corrected); 940 919 if (!block) 941 920 return; 942 read_block(block, blk);921 read_block(block, add_zone_dind_blk); 943 922 for (i = 0; i < BLOCK_SIZE >> 2; i++) 944 add_zone_ind2(i + (uint32_t *) blk, &blk_chg); 945 if (blk_chg) 946 write_block(block, blk); 947 } 948 949 static void add_zone_tind2(uint32_t *znr, int *corrected) 950 { 951 static char blk[BLOCK_SIZE]; 952 int i, blk_chg = 0; 923 add_zone_ind2(i + (uint32_t *) add_zone_dind_blk, &chg_blk); 924 if (chg_blk) 925 write_block(block, add_zone_dind_blk); 926 } 927 928 static void add_zone_tind2(uint32_t *znr, smallint *corrected) 929 { 930 int i; 953 931 int block; 932 smallint chg_blk = 0; 954 933 955 934 block = add_zone2(znr, corrected); 956 935 if (!block) 957 936 return; 958 read_block(block, blk);937 read_block(block, add_zone_tind_blk); 959 938 for (i = 0; i < BLOCK_SIZE >> 2; i++) 960 add_zone_dind2(i + (uint32_t *) blk, &blk_chg);961 if ( blk_chg)962 write_block(block, blk);963 } 964 #endif 965 966 static void check_zones(unsigned i nt i)967 { 968 struct minix _inode *inode;939 add_zone_dind2(i + (uint32_t *) add_zone_tind_blk, &chg_blk); 940 if (chg_blk) 941 write_block(block, add_zone_tind_blk); 942 } 943 #endif 944 945 static void check_zones(unsigned i) 946 { 947 struct minix1_inode *inode; 969 948 970 949 if (!i || i > INODES) … … 972 951 if (inode_count[i] > 1) /* have we counted this file already? */ 973 952 return; 974 inode = Inode + i;953 inode = Inode1 + i; 975 954 if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) && 976 955 !S_ISLNK(inode->i_mode)) return; … … 981 960 } 982 961 983 #if def CONFIG_FEATURE_MINIX2984 static void check_zones2(unsigned i nt i)962 #if ENABLE_FEATURE_MINIX2 963 static void check_zones2(unsigned i) 985 964 { 986 965 struct minix2_inode *inode; … … 1002 981 #endif 1003 982 1004 static void check_file(struct minix_inode *dir, unsigned int offset) 1005 { 1006 static char blk[BLOCK_SIZE]; 1007 struct minix_inode *inode; 983 static void check_file(struct minix1_inode *dir, unsigned offset) 984 { 985 struct minix1_inode *inode; 1008 986 int ino; 1009 987 char *name; … … 1011 989 1012 990 block = map_block(dir, offset / BLOCK_SIZE); 1013 read_block(block, blk);1014 name = blk + (offset % BLOCK_SIZE) + 2;991 read_block(block, check_file_blk); 992 name = check_file_blk + (offset % BLOCK_SIZE) + 2; 1015 993 ino = *(uint16_t *) (name - 2); 1016 994 if (ino > INODES) { … … 1019 997 if (ask("Remove", 1)) { 1020 998 *(uint16_t *) (name - 2) = 0; 1021 write_block(block, blk);999 write_block(block, check_file_blk); 1022 1000 } 1023 1001 ino = 0; … … 1027 1005 pop_filename(); 1028 1006 if (!offset) { 1029 if (!inode || strcmp(".", name)) { 1030 printf("%s: bad directory: '.' isn't first\n", current_name); 1031 errors_uncorrected = 1; 1032 } else 1007 if (inode && LONE_CHAR(name, '.')) 1033 1008 return; 1009 printf("%s: bad directory: '.' isn't first\n", current_name); 1010 errors_uncorrected = 1; 1034 1011 } 1035 1012 if (offset == dirsize) { 1036 if (!inode || strcmp("..", name)) { 1037 printf("%s: bad directory: '..' isn't second\n", current_name); 1038 errors_uncorrected = 1; 1039 } else 1013 if (inode && strcmp("..", name) == 0) 1040 1014 return; 1015 printf("%s: bad directory: '..' isn't second\n", current_name); 1016 errors_uncorrected = 1; 1041 1017 } 1042 1018 if (!inode) … … 1052 1028 recursive_check(ino); 1053 1029 pop_filename(); 1054 return; 1055 } 1056 1057 #ifdef CONFIG_FEATURE_MINIX2 1058 static void check_file2(struct minix2_inode *dir, unsigned int offset) 1059 { 1060 static char blk[BLOCK_SIZE]; 1030 } 1031 1032 #if ENABLE_FEATURE_MINIX2 1033 static void check_file2(struct minix2_inode *dir, unsigned offset) 1034 { 1061 1035 struct minix2_inode *inode; 1062 1036 int ino; … … 1065 1039 1066 1040 block = map_block2(dir, offset / BLOCK_SIZE); 1067 read_block(block, blk);1068 name = blk + (offset % BLOCK_SIZE) + 2;1041 read_block(block, check_file_blk); 1042 name = check_file_blk + (offset % BLOCK_SIZE) + 2; 1069 1043 ino = *(uint16_t *) (name - 2); 1070 1044 if (ino > INODES) { … … 1073 1047 if (ask("Remove", 1)) { 1074 1048 *(uint16_t *) (name - 2) = 0; 1075 write_block(block, blk);1049 write_block(block, check_file_blk); 1076 1050 } 1077 1051 ino = 0; … … 1081 1055 pop_filename(); 1082 1056 if (!offset) { 1083 if (!inode || strcmp(".", name)) { 1084 printf("%s: bad directory: '.' isn't first\n", current_name); 1085 errors_uncorrected = 1; 1086 } else 1057 if (inode && LONE_CHAR(name, '.')) 1087 1058 return; 1059 printf("%s: bad directory: '.' isn't first\n", current_name); 1060 errors_uncorrected = 1; 1088 1061 } 1089 1062 if (offset == dirsize) { 1090 if (!inode || strcmp("..", name)) { 1091 printf("%s: bad directory: '..' isn't second\n", current_name); 1092 errors_uncorrected = 1; 1093 } else 1063 if (inode && strcmp("..", name) == 0) 1094 1064 return; 1065 printf("%s: bad directory: '..' isn't second\n", current_name); 1066 errors_uncorrected = 1; 1095 1067 } 1096 1068 if (!inode) … … 1106 1078 recursive_check2(ino); 1107 1079 pop_filename(); 1108 return; 1109 } 1110 #endif 1111 1112 static void recursive_check(unsigned int ino) 1113 { 1114 struct minix_inode *dir; 1115 unsigned int offset; 1116 1117 dir = Inode + ino; 1080 } 1081 #endif 1082 1083 static void recursive_check(unsigned ino) 1084 { 1085 struct minix1_inode *dir; 1086 unsigned offset; 1087 1088 dir = Inode1 + ino; 1118 1089 if (!S_ISDIR(dir->i_mode)) 1119 die(" Internal error");1090 die("internal error"); 1120 1091 if (dir->i_size < 2 * dirsize) { 1121 1092 printf("%s: bad directory: size<32", current_name); … … 1126 1097 } 1127 1098 1128 #if def CONFIG_FEATURE_MINIX21129 static void recursive_check2(unsigned in t ino)1099 #if ENABLE_FEATURE_MINIX2 1100 static void recursive_check2(unsigned ino) 1130 1101 { 1131 1102 struct minix2_inode *dir; 1132 unsigned intoffset;1103 unsigned offset; 1133 1104 1134 1105 dir = Inode2 + ino; 1135 1106 if (!S_ISDIR(dir->i_mode)) 1136 die(" Internal error");1107 die("internal error"); 1137 1108 if (dir->i_size < 2 * dirsize) { 1138 1109 printf("%s: bad directory: size<32", current_name); … … 1146 1117 static int bad_zone(int i) 1147 1118 { 1148 char buffer[ 1024];1149 1150 if (BLOCK_SIZE * i != lseek( IN, BLOCK_SIZE * i, SEEK_SET))1151 die(" Seek failed in bad_zone");1152 return (BLOCK_SIZE != read( IN, buffer, BLOCK_SIZE));1119 char buffer[BLOCK_SIZE]; 1120 1121 if (BLOCK_SIZE * i != lseek(dev_fd, BLOCK_SIZE * i, SEEK_SET)) 1122 die("seek failed in bad_zone"); 1123 return (BLOCK_SIZE != read(dev_fd, buffer, BLOCK_SIZE)); 1153 1124 } 1154 1125 … … 1158 1129 1159 1130 for (i = 1; i <= INODES; i++) { 1160 if (warn_mode && Inode [i].i_mode && !inode_in_use(i)) {1131 if (warn_mode && Inode1[i].i_mode && !inode_in_use(i)) { 1161 1132 printf("Inode %d has non-zero mode. ", i); 1162 1133 if (ask("Clear", 1)) { 1163 Inode [i].i_mode = 0;1134 Inode1[i].i_mode = 0; 1164 1135 changed = 1; 1165 1136 } … … 1178 1149 mark_inode(i); 1179 1150 } 1180 if (Inode [i].i_nlinks != inode_count[i]) {1151 if (Inode1[i].i_nlinks != inode_count[i]) { 1181 1152 printf("Inode %d (mode=%07o), i_nlinks=%d, counted=%d. ", 1182 i, Inode[i].i_mode, Inode[i].i_nlinks, inode_count[i]); 1153 i, Inode1[i].i_mode, Inode1[i].i_nlinks, 1154 inode_count[i]); 1183 1155 if (ask("Set i_nlinks to count", 1)) { 1184 Inode [i].i_nlinks = inode_count[i];1156 Inode1[i].i_nlinks = inode_count[i]; 1185 1157 changed = 1; 1186 1158 } … … 1188 1160 } 1189 1161 for (i = FIRSTZONE; i < ZONES; i++) { 1190 if ( zone_in_use(i) == zone_count[i])1162 if ((zone_in_use(i) != 0) == zone_count[i]) 1191 1163 continue; 1192 1164 if (!zone_count[i]) { … … 1203 1175 } 1204 1176 1205 #if def CONFIG_FEATURE_MINIX21177 #if ENABLE_FEATURE_MINIX2 1206 1178 static void check_counts2(void) 1207 1179 { … … 1231 1203 if (Inode2[i].i_nlinks != inode_count[i]) { 1232 1204 printf("Inode %d (mode=%07o), i_nlinks=%d, counted=%d. ", 1233 1234 1205 i, Inode2[i].i_mode, Inode2[i].i_nlinks, 1206 inode_count[i]); 1235 1207 if (ask("Set i_nlinks to count", 1)) { 1236 1208 Inode2[i].i_nlinks = inode_count[i]; … … 1240 1212 } 1241 1213 for (i = FIRSTZONE; i < ZONES; i++) { 1242 if ( zone_in_use(i) == zone_count[i])1214 if ((zone_in_use(i) != 0) == zone_count[i]) 1243 1215 continue; 1244 1216 if (!zone_count[i]) { … … 1260 1232 memset(inode_count, 0, (INODES + 1) * sizeof(*inode_count)); 1261 1233 memset(zone_count, 0, ZONES * sizeof(*zone_count)); 1262 check_zones( ROOT_INO);1263 recursive_check( ROOT_INO);1234 check_zones(MINIX_ROOT_INO); 1235 recursive_check(MINIX_ROOT_INO); 1264 1236 check_counts(); 1265 1237 } 1266 1238 1267 #if def CONFIG_FEATURE_MINIX21239 #if ENABLE_FEATURE_MINIX2 1268 1240 static void check2(void) 1269 1241 { 1270 1242 memset(inode_count, 0, (INODES + 1) * sizeof(*inode_count)); 1271 1243 memset(zone_count, 0, ZONES * sizeof(*zone_count)); 1272 check_zones2( ROOT_INO);1273 recursive_check2( ROOT_INO);1244 check_zones2(MINIX_ROOT_INO); 1245 recursive_check2(MINIX_ROOT_INO); 1274 1246 check_counts2(); 1275 1247 } 1276 #endif 1277 1248 #else 1249 void check2(void); 1250 #endif 1251 1252 int fsck_minix_main(int argc, char **argv); 1278 1253 int fsck_minix_main(int argc, char **argv) 1279 1254 { … … 1281 1256 int retcode = 0; 1282 1257 1283 alloc_current_name(); 1284 #ifdef CONFIG_FEATURE_CLEAN_UP 1285 /* Don't bother to free memory. Exit does 1286 * that automagically, so we can save a few bytes */ 1287 atexit(free_current_name); 1288 #endif 1289 1290 if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) 1291 die("Bad inode size"); 1292 #ifdef CONFIG_FEATURE_MINIX2 1258 xfunc_error_retval = 8; 1259 1260 INIT_G(); 1261 1262 if (INODE_SIZE1 * MINIX1_INODES_PER_BLOCK != BLOCK_SIZE) 1263 die("bad inode size"); 1264 #if ENABLE_FEATURE_MINIX2 1293 1265 if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE) 1294 die(" Bad v2 inode size");1295 #endif 1296 while ( argc-- > 1) {1266 die("bad v2 inode size"); 1267 #endif 1268 while (--argc != 0) { 1297 1269 argv++; 1298 1270 if (argv[0][0] != '-') { 1299 1271 if (device_name) 1300 1272 bb_show_usage(); 1301 else 1302 device_name = argv[0]; 1303 } else 1304 while (*++argv[0]) 1273 device_name = argv[0]; 1274 } else { 1275 while (*++argv[0]) { 1305 1276 switch (argv[0][0]) { 1306 1277 case 'l': … … 1330 1301 bb_show_usage(); 1331 1302 } 1303 } 1304 } 1332 1305 } 1333 1306 if (!device_name) 1334 1307 bb_show_usage(); 1308 1335 1309 check_mount(); /* trying to check a mounted filesystem? */ 1336 1310 if (repair && !automatic) { 1337 1311 if (!isatty(0) || !isatty(1)) 1338 die("Need terminal for interactive repairs"); 1339 } 1340 IN = open(device_name, repair ? O_RDWR : O_RDONLY); 1341 if (IN < 0){ 1342 printf("Unable to open device '%s'\n", device_name); 1343 leave(8); 1344 } 1345 sync(); /* paranoia? */ 1312 die("need terminal for interactive repairs"); 1313 } 1314 dev_fd = xopen(device_name, repair ? O_RDWR : O_RDONLY); 1315 1316 /*sync(); paranoia? */ 1346 1317 read_superblock(); 1347 1318 … … 1352 1323 * command line. 1353 1324 */ 1354 printf("%s, %s\n", bb_applet_name, program_version); 1355 if (!(Super.s_state & MINIX_ERROR_FS) && 1356 (Super.s_state & MINIX_VALID_FS) && !force) { 1325 printf("%s: %s\n", applet_name, bb_banner); 1326 1327 if (!(Super.s_state & MINIX_ERROR_FS) 1328 && (Super.s_state & MINIX_VALID_FS) && !force 1329 ) { 1357 1330 if (repair) 1358 1331 printf("%s is clean, check is skipped\n", device_name); 1359 return retcode;1332 return 0; 1360 1333 } else if (force) 1361 1334 printf("Forcing filesystem check on %s\n", device_name); … … 1367 1340 1368 1341 if (repair && !automatic) { 1369 tcgetattr(0, & termios);1370 tmp = termios;1342 tcgetattr(0, &sv_termios); 1343 tmp = sv_termios; 1371 1344 tmp.c_lflag &= ~(ICANON | ECHO); 1372 1345 tcsetattr(0, TCSANOW, &tmp); 1373 1346 termios_set = 1; 1374 1347 } 1375 #ifdef CONFIG_FEATURE_MINIX2 1348 1376 1349 if (version2) { 1377 1350 check_root2(); 1378 1351 check2(); 1379 } else 1380 #endif 1381 { 1352 } else { 1382 1353 check_root(); 1383 1354 check(); 1384 1355 } 1356 1385 1357 if (verbose) { 1386 1358 int i, free_cnt; … … 1389 1361 if (!inode_in_use(i)) 1390 1362 free_cnt++; 1391 printf("\n%6 ld inodes used (%ld%%)\n", (INODES - free_cnt),1363 printf("\n%6u inodes used (%u%%)\n", (INODES - free_cnt), 1392 1364 100 * (INODES - free_cnt) / INODES); 1393 1365 for (i = FIRSTZONE, free_cnt = 0; i < ZONES; i++) 1394 1366 if (!zone_in_use(i)) 1395 1367 free_cnt++; 1396 printf("%6 ld zones used (%ld%%)\n\n"1397 "%6 dregular files\n"1398 "%6 ddirectories\n"1399 "%6 dcharacter device files\n"1400 "%6 dblock device files\n"1401 "%6 dlinks\n"1402 "%6 dsymbolic links\n"1368 printf("%6u zones used (%u%%)\n\n" 1369 "%6u regular files\n" 1370 "%6u directories\n" 1371 "%6u character device files\n" 1372 "%6u block device files\n" 1373 "%6u links\n" 1374 "%6u symbolic links\n" 1403 1375 "------\n" 1404 "%6 dfiles\n",1376 "%6u files\n", 1405 1377 (ZONES - free_cnt), 100 * (ZONES - free_cnt) / ZONES, 1406 1378 regular, directory, chardev, blockdev, … … 1416 1388 1417 1389 if (repair && !automatic) 1418 tcsetattr(0, TCSANOW, & termios);1390 tcsetattr(0, TCSANOW, &sv_termios); 1419 1391 1420 1392 if (changed) -
branches/stable/mindi-busybox/util-linux/getopt.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 3 * getopt.c - Enhanced implementation of BSD getopt(1) … … 31 32 */ 32 33 33 #include <stdio.h>34 #include <stdlib.h>35 #include <string.h>36 #include <unistd.h>37 #include <ctype.h>38 34 #include <getopt.h> 39 40 #include "busybox.h" 35 #include "libbb.h" 41 36 42 37 /* NON_OPT is the code that is returned when a non-option is found in '+' … … 44 39 enum { 45 40 NON_OPT = 1, 41 #if ENABLE_GETOPT_LONG 46 42 /* LONG_OPT is the code that is returned when a long option is found. */ 47 43 LONG_OPT = 2 44 #endif 48 45 }; 49 46 50 /* The shells recognized. */ 51 typedef enum {BASH,TCSH} shell_t; 52 53 54 /* Some global variables that tells us how to parse. */ 55 static shell_t shell=BASH; /* The shell we generate output for. */ 56 static int quiet_errors; /* 0 is not quiet. */ 57 static int quiet_output; /* 0 is not quiet. */ 58 static int quote=1; /* 1 is do quote. */ 59 static int alternative; /* 0 is getopt_long, 1 is getopt_long_only */ 60 61 /* Function prototypes */ 62 static const char *normalize(const char *arg); 63 static int generate_output(char * argv[],int argc,const char *optstr, 64 const struct option *longopts); 65 static void add_long_options(char *options); 66 static void add_longopt(const char *name,int has_arg); 67 static void set_shell(const char *new_shell); 68 47 /* For finding activated option flags. Must match getopt32 call! */ 48 enum { 49 OPT_o = 0x1, // -o 50 OPT_n = 0x2, // -n 51 OPT_q = 0x4, // -q 52 OPT_Q = 0x8, // -Q 53 OPT_s = 0x10, // -s 54 OPT_T = 0x20, // -T 55 OPT_u = 0x40, // -u 56 #if ENABLE_GETOPT_LONG 57 OPT_a = 0x80, // -a 58 OPT_l = 0x100, // -l 59 #endif 60 SHELL_IS_TCSH = 0x8000, /* hijack this bit for other purposes */ 61 }; 62 63 /* 0 is getopt_long, 1 is getopt_long_only */ 64 #define alternative (option_mask32 & OPT_a) 65 66 #define quiet_errors (option_mask32 & OPT_q) 67 #define quiet_output (option_mask32 & OPT_Q) 68 #define quote (!(option_mask32 & OPT_u)) 69 #define shell_TCSH (option_mask32 & SHELL_IS_TCSH) 69 70 70 71 /* … … 77 78 * each call. 78 79 */ 79 const char *normalize(const char *arg) 80 { 81 static char *BUFFER=NULL; 82 const char *argptr=arg; 80 static const char *normalize(const char *arg) 81 { 83 82 char *bufptr; 84 83 #if ENABLE_FEATURE_CLEAN_UP 84 static char *BUFFER = NULL; 85 85 free(BUFFER); 86 #else 87 char *BUFFER; 88 #endif 86 89 87 90 if (!quote) { /* Just copy arg */ 88 BUFFER=bb_xstrdup(arg);91 BUFFER = xstrdup(arg); 89 92 return BUFFER; 90 93 } … … 94 97 opening quote! We need also the global opening and closing quote, 95 98 and one extra character for '\0'. */ 96 BUFFER =xmalloc(strlen(arg)*4+3);97 98 bufptr =BUFFER;99 *bufptr ++='\'';100 101 while (*arg ptr) {102 if (*arg ptr== '\'') {99 BUFFER = xmalloc(strlen(arg)*4 + 3); 100 101 bufptr = BUFFER; 102 *bufptr ++= '\''; 103 104 while (*arg) { 105 if (*arg == '\'') { 103 106 /* Quote: replace it with: '\'' */ 104 *bufptr ++='\'';105 *bufptr ++='\\';106 *bufptr ++='\'';107 *bufptr ++='\'';108 } else if (shell ==TCSH && *argptr=='!') {107 *bufptr ++= '\''; 108 *bufptr ++= '\\'; 109 *bufptr ++= '\''; 110 *bufptr ++= '\''; 111 } else if (shell_TCSH && *arg == '!') { 109 112 /* Exclamation mark: replace it with: \! */ 110 *bufptr ++='\'';111 *bufptr ++='\\';112 *bufptr ++='!';113 *bufptr ++='\'';114 } else if (shell ==TCSH && *argptr=='\n') {113 *bufptr ++= '\''; 114 *bufptr ++= '\\'; 115 *bufptr ++= '!'; 116 *bufptr ++= '\''; 117 } else if (shell_TCSH && *arg == '\n') { 115 118 /* Newline: replace it with: \n */ 116 *bufptr ++='\\';117 *bufptr ++='n';118 } else if (shell ==TCSH && isspace(*argptr)) {119 *bufptr ++= '\\'; 120 *bufptr ++= 'n'; 121 } else if (shell_TCSH && isspace(*arg)) { 119 122 /* Non-newline whitespace: replace it with \<ws> */ 120 *bufptr ++='\'';121 *bufptr ++='\\';122 *bufptr ++=*argptr;123 *bufptr ++='\'';123 *bufptr ++= '\''; 124 *bufptr ++= '\\'; 125 *bufptr ++= *arg; 126 *bufptr ++= '\''; 124 127 } else 125 128 /* Just copy */ 126 *bufptr ++=*argptr;127 arg ptr++;128 } 129 *bufptr ++='\'';130 *bufptr ++='\0';129 *bufptr ++= *arg; 130 arg++; 131 } 132 *bufptr ++= '\''; 133 *bufptr ++= '\0'; 131 134 return BUFFER; 132 135 } … … 139 142 * Other settings are found in global variables. 140 143 */ 141 int generate_output(char * argv[],int argc,const char *optstr, 142 const struct option *longopts) 144 #if !ENABLE_GETOPT_LONG 145 #define generate_output(argv,argc,optstr,longopts) generate_output(argv,argc,optstr) 146 #endif 147 static int generate_output(char **argv, int argc, const char *optstr, const struct option *longopts) 143 148 { 144 149 int exit_code = 0; /* We assume everything will be OK */ 145 int opt; 150 unsigned opt; 151 #if ENABLE_GETOPT_LONG 146 152 int longindex; 153 #endif 147 154 const char *charptr; 148 155 149 156 if (quiet_errors) /* No error reporting from getopt(3) */ 150 opterr=0; 151 optind=0; /* Reset getopt(3) */ 152 153 while ((opt = (alternative? 154 getopt_long_only(argc,argv,optstr,longopts,&longindex): 155 getopt_long(argc,argv,optstr,longopts,&longindex))) 156 != EOF) 157 opterr = 0; 158 optind = 0; /* Reset getopt(3) */ 159 160 while (1) { 161 opt = 162 #if ENABLE_GETOPT_LONG 163 alternative ? 164 getopt_long_only(argc, argv, optstr, longopts, &longindex) : 165 getopt_long(argc, argv, optstr, longopts, &longindex); 166 #else 167 getopt(argc, argv, optstr); 168 #endif 169 if (opt == EOF) 170 break; 157 171 if (opt == '?' || opt == ':' ) 158 172 exit_code = 1; 159 173 else if (!quiet_output) { 174 #if ENABLE_GETOPT_LONG 160 175 if (opt == LONG_OPT) { 161 printf(" --%s", longopts[longindex].name);176 printf(" --%s", longopts[longindex].name); 162 177 if (longopts[longindex].has_arg) 163 178 printf(" %s", 164 normalize(optarg?optarg:"")); 165 } else if (opt == NON_OPT) 166 printf(" %s",normalize(optarg)); 179 normalize(optarg ? optarg : "")); 180 } else 181 #endif 182 if (opt == NON_OPT) 183 printf(" %s", normalize(optarg)); 167 184 else { 168 printf(" -%c", opt);185 printf(" -%c", opt); 169 186 charptr = strchr(optstr,opt); 170 187 if (charptr != NULL && *++charptr == ':') 171 188 printf(" %s", 172 normalize(optarg?optarg:""));189 normalize(optarg ? optarg : "")); 173 190 } 174 191 } 175 176 if (! quiet_output) { 192 } 193 194 if (!quiet_output) { 177 195 printf(" --"); 178 196 while (optind < argc) 179 printf(" %s", normalize(argv[optind++]));180 p rintf("\n");197 printf(" %s", normalize(argv[optind++])); 198 puts(""); 181 199 } 182 200 return exit_code; 183 201 } 184 202 185 static struct option *long_options; 186 static int long_options_length; /* Length of array */ 187 static int long_options_nr; /* Nr of used elements in array */ 188 enum { LONG_OPTIONS_INCR = 10 }; 189 #define init_longopt() add_longopt(NULL,0) 190 191 /* Register a long option. The contents of name is copied. */ 192 void add_longopt(const char *name,int has_arg) 193 { 194 if (!name) { /* init */ 195 free(long_options); 196 long_options=NULL; 197 long_options_length=0; 198 long_options_nr=0; 199 } 200 201 if (long_options_nr == long_options_length) { 202 long_options_length += LONG_OPTIONS_INCR; 203 long_options=xrealloc(long_options, 204 sizeof(struct option) * 205 long_options_length); 206 } 207 208 long_options[long_options_nr].name=NULL; 209 long_options[long_options_nr].has_arg=0; 210 long_options[long_options_nr].flag=NULL; 211 long_options[long_options_nr].val=0; 212 213 if (long_options_nr) { /* Not for init! */ 214 long_options[long_options_nr-1].has_arg=has_arg; 215 long_options[long_options_nr-1].flag=NULL; 216 long_options[long_options_nr-1].val=LONG_OPT; 217 long_options[long_options_nr-1].name=bb_xstrdup(name); 218 } 219 long_options_nr++; 220 } 221 222 203 #if ENABLE_GETOPT_LONG 223 204 /* 224 205 * Register several long options. options is a string of long options, … … 226 207 * This nukes options! 227 208 */ 228 void add_long_options(char *options) 229 { 209 static struct option *add_long_options(struct option *long_options, char *options) 210 { 211 int long_nr = 0; 230 212 int arg_opt, tlen; 231 char *tokptr=strtok(options,", \t\n"); 213 char *tokptr = strtok(options, ", \t\n"); 214 215 if (long_options) 216 while (long_options[long_nr].name) 217 long_nr++; 218 232 219 while (tokptr) { 233 arg_opt=no_argument; 234 tlen=strlen(tokptr); 235 if (tlen > 0) { 236 if (tokptr[tlen-1] == ':') { 237 if (tlen > 1 && tokptr[tlen-2] == ':') { 238 tokptr[tlen-2]='\0'; 239 tlen -= 2; 240 arg_opt=optional_argument; 241 } else { 242 tokptr[tlen-1]='\0'; 243 tlen -= 1; 244 arg_opt=required_argument; 220 arg_opt = no_argument; 221 tlen = strlen(tokptr); 222 if (tlen) { 223 tlen--; 224 if (tokptr[tlen] == ':') { 225 arg_opt = required_argument; 226 if (tlen && tokptr[tlen-1] == ':') { 227 tlen--; 228 arg_opt = optional_argument; 245 229 } 230 tokptr[tlen] = '\0'; 246 231 if (tlen == 0) 247 bb_error_msg ("empty long option after -l or --long argument");232 bb_error_msg_and_die("empty long option specified"); 248 233 } 249 add_longopt(tokptr,arg_opt); 234 long_options = xrealloc(long_options, 235 sizeof(long_options[0]) * (long_nr+2)); 236 long_options[long_nr].has_arg = arg_opt; 237 long_options[long_nr].flag = NULL; 238 long_options[long_nr].val = LONG_OPT; 239 long_options[long_nr].name = xstrdup(tokptr); 240 long_nr++; 241 memset(&long_options[long_nr], 0, sizeof(long_options[0])); 250 242 } 251 tokptr=strtok(NULL,", \t\n"); 252 } 253 } 254 255 void set_shell(const char *new_shell) 256 { 257 if (!strcmp(new_shell,"bash")) 258 shell=BASH; 259 else if (!strcmp(new_shell,"tcsh")) 260 shell=TCSH; 261 else if (!strcmp(new_shell,"sh")) 262 shell=BASH; 263 else if (!strcmp(new_shell,"csh")) 264 shell=TCSH; 243 tokptr = strtok(NULL, ", \t\n"); 244 } 245 return long_options; 246 } 247 #endif 248 249 static void set_shell(const char *new_shell) 250 { 251 if (!strcmp(new_shell,"bash") || !strcmp(new_shell,"sh")) 252 return; 253 if (!strcmp(new_shell,"tcsh") || !strcmp(new_shell,"csh")) 254 option_mask32 |= SHELL_IS_TCSH; 265 255 else 266 bb_error_msg("unknown shell after -s or --shell argument");256 bb_error_msg("unknown shell '%s', assuming bash", new_shell); 267 257 } 268 258 … … 276 266 */ 277 267 278 static const struct option longopts[]= 279 { 280 {"options",required_argument,NULL,'o'}, 281 {"longoptions",required_argument,NULL,'l'}, 282 {"quiet",no_argument,NULL,'q'}, 283 {"quiet-output",no_argument,NULL,'Q'}, 284 {"shell",required_argument,NULL,'s'}, 285 {"test",no_argument,NULL,'T'}, 286 {"unquoted",no_argument,NULL,'u'}, 287 {"alternative",no_argument,NULL,'a'}, 288 {"name",required_argument,NULL,'n'}, 289 {NULL,0,NULL,0} 290 }; 291 292 /* Stop scanning as soon as a non-option argument is found! */ 293 static const char shortopts[]="+ao:l:n:qQs:Tu"; 294 295 268 #if ENABLE_GETOPT_LONG 269 static const char getopt_longopts[] ALIGN1 = 270 "options\0" Required_argument "o" 271 "longoptions\0" Required_argument "l" 272 "quiet\0" No_argument "q" 273 "quiet-output\0" No_argument "Q" 274 "shell\0" Required_argument "s" 275 "test\0" No_argument "T" 276 "unquoted\0" No_argument "u" 277 "alternative\0" No_argument "a" 278 "name\0" Required_argument "n" 279 ; 280 #endif 281 282 int getopt_main(int argc, char *argv[]); 296 283 int getopt_main(int argc, char *argv[]) 297 284 { 298 c onst char *optstr = NULL;285 char *optstr = NULL; 299 286 char *name = NULL; 300 int opt; 301 int compatible=0; 302 303 init_longopt(); 304 305 if (getenv("GETOPT_COMPATIBLE")) 306 compatible=1; 287 unsigned opt; 288 const char *compatible; 289 char *s_arg; 290 #if ENABLE_GETOPT_LONG 291 struct option *long_options = NULL; 292 llist_t *l_arg = NULL; 293 #endif 294 295 compatible = getenv("GETOPT_COMPATIBLE"); /* used as yes/no flag */ 307 296 308 297 if (argc == 1) { … … 311 300 when there were no arguments. */ 312 301 printf(" --\n"); 313 314 } else315 302 return 0; 303 } 304 bb_error_msg_and_die("missing optstring argument"); 316 305 } 317 306 … … 319 308 char *s; 320 309 321 quote=0; 322 s=xmalloc(strlen(argv[1])+1); 323 strcpy(s,argv[1]+strspn(argv[1],"-+")); 324 argv[1]=argv[0]; 325 return (generate_output(argv+1,argc-1,s,long_options)); 326 } 327 328 while ((opt=getopt_long(argc,argv,shortopts,longopts,NULL)) != EOF) 329 switch (opt) { 330 case 'a': 331 alternative=1; 332 break; 333 case 'o': 334 optstr = optarg; 335 break; 336 case 'l': 337 add_long_options(optarg); 338 break; 339 case 'n': 340 name = optarg; 341 break; 342 case 'q': 343 quiet_errors=1; 344 break; 345 case 'Q': 346 quiet_output=1; 347 break; 348 case 's': 349 set_shell(optarg); 350 break; 351 case 'T': 352 return 4; 353 case 'u': 354 quote=0; 355 break; 356 default: 357 bb_show_usage(); 358 } 359 310 option_mask32 |= OPT_u; /* quoting off */ 311 s = xstrdup(argv[1] + strspn(argv[1], "-+")); 312 argv[1] = argv[0]; 313 return generate_output(argv+1, argc-1, s, long_options); 314 } 315 316 #if !ENABLE_GETOPT_LONG 317 opt = getopt32(argv, "+o:n:qQs:Tu", &optstr, &name, &s_arg); 318 #else 319 applet_long_options = getopt_longopts; 320 opt_complementary = "l::"; 321 opt = getopt32(argv, "+o:n:qQs:Tual:", 322 &optstr, &name, &s_arg, &l_arg); 323 /* Effectuate the read options for the applet itself */ 324 while (l_arg) { 325 long_options = add_long_options(long_options, l_arg->data); 326 l_arg = l_arg->link; 327 } 328 #endif 329 330 if (opt & OPT_s) { 331 set_shell(s_arg); 332 } 333 334 if (opt & OPT_T) { 335 return 4; 336 } 337 338 /* All options controlling the applet have now been parsed */ 360 339 if (!optstr) { 361 340 if (optind >= argc) 362 341 bb_error_msg_and_die("missing optstring argument"); 363 else optstr=argv[optind++]; 364 } 365 if (name) 366 argv[optind-1]=name; 367 else 368 argv[optind-1]=argv[0]; 369 return (generate_output(argv+optind-1,argc-optind+1,optstr,long_options)); 370 } 342 optstr = argv[optind++]; 343 } 344 345 argv[optind-1] = name ? name : argv[0]; 346 return generate_output(argv+optind-1, argc-optind+1, optstr, long_options); 347 } -
branches/stable/mindi-busybox/util-linux/hexdump.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 3 * hexdump implementation for busybox … … 9 10 */ 10 11 11 #include "busybox.h"12 12 #include <getopt.h> 13 #include <string.h>13 #include "libbb.h" 14 14 #include "dump.h" 15 16 /* This is a NOEXEC applet. Be very careful! */ 17 15 18 16 19 static void bb_dump_addfile(char *name) 17 20 { 18 registerchar *p;21 char *p; 19 22 FILE *fp; 20 23 char *buf; 21 24 22 fp = bb_xfopen(name, "r");25 fp = xfopen(name, "r"); 23 26 24 while ((buf = bb_get_chomped_line_from_file(fp)) != NULL) {27 while ((buf = xmalloc_getline(fp)) != NULL) { 25 28 p = skip_whitespace(buf); 26 29 … … 33 36 } 34 37 35 static const char * 36 37 38 39 40 38 static const char *const add_strings[] = { 39 "\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"", /* b */ 40 "\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"", /* c */ 41 "\"%07.7_ax \" 8/2 \" %05u \" \"\\n\"", /* d */ 42 "\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"", /* o */ 43 "\"%07.7_ax \" 8/2 \" %04x \" \"\\n\"", /* x */ 41 44 }; 42 45 43 static const char add_first[] = "\"%07.7_Ax\n\"";46 static const char add_first[] ALIGN1 = "\"%07.7_Ax\n\""; 44 47 45 static const char hexdump_opts[] = "bcdoxCe:f:n:s:v";48 static const char hexdump_opts[] ALIGN1 = "bcdoxCe:f:n:s:v"; 46 49 47 50 static const struct suffix_mult suffixes[] = { 48 { "b",512 },49 { "k",1024 },50 { "m",1024*1024 },51 { NULL, 0}51 { "b", 512 }, 52 { "k", 1024 }, 53 { "m", 1024*1024 }, 54 { } 52 55 }; 53 56 57 int hexdump_main(int argc, char **argv); 54 58 int hexdump_main(int argc, char **argv) 55 59 { 56 // register FS *tfs;57 60 const char *p; 58 61 int ch; … … 62 65 63 66 while ((ch = getopt(argc, argv, hexdump_opts)) > 0) { 64 if ((p = strchr(hexdump_opts, ch)) != NULL) { 65 if ((p - hexdump_opts) < 5) { 66 bb_dump_add(add_first); 67 bb_dump_add(add_strings[(int)(p - hexdump_opts)]); 68 } else if (ch == 'C') { 69 bb_dump_add("\"%08.8_Ax\n\""); 70 bb_dump_add("\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" "); 71 bb_dump_add("\" |\" 16/1 \"%_p\" \"|\\n\""); 72 } else { 73 /* Sae a little bit of space below by omitting the 'else's. */ 74 if (ch == 'e') { 75 bb_dump_add(optarg); 76 } /* else */ 77 if (ch == 'f') { 78 bb_dump_addfile(optarg); 79 } /* else */ 80 if (ch == 'n') { 81 bb_dump_length = bb_xgetularg10_bnd(optarg, 0, INT_MAX); 82 } /* else */ 83 if (ch == 's') { 84 bb_dump_skip = bb_xgetularg_bnd_sfx(optarg, 10, 0, LONG_MAX, suffixes); 85 } /* else */ 86 if (ch == 'v') { 87 bb_dump_vflag = ALL; 88 } 67 p = strchr(hexdump_opts, ch); 68 if (!p) 69 bb_show_usage(); 70 if ((p - hexdump_opts) < 5) { 71 bb_dump_add(add_first); 72 bb_dump_add(add_strings[(int)(p - hexdump_opts)]); 73 } else if (ch == 'C') { 74 bb_dump_add("\"%08.8_Ax\n\""); 75 bb_dump_add("\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" "); 76 bb_dump_add("\" |\" 16/1 \"%_p\" \"|\\n\""); 77 } else { 78 /* Save a little bit of space below by omitting the 'else's. */ 79 if (ch == 'e') { 80 bb_dump_add(optarg); 81 } /* else */ 82 if (ch == 'f') { 83 bb_dump_addfile(optarg); 84 } /* else */ 85 if (ch == 'n') { 86 bb_dump_length = xatoi_u(optarg); 87 } /* else */ 88 if (ch == 's') { 89 bb_dump_skip = xatoul_range_sfx(optarg, 0, LONG_MAX, suffixes); 90 } /* else */ 91 if (ch == 'v') { 92 bb_dump_vflag = ALL; 89 93 } 90 } else {91 bb_show_usage();92 94 } 93 95 } … … 100 102 argv += optind; 101 103 102 return (bb_dump_dump(argv));104 return bb_dump_dump(argv); 103 105 } -
branches/stable/mindi-busybox/util-linux/hwclock.c
r821 r1770 8 8 */ 9 9 10 11 #include <sys/ioctl.h>12 10 #include <sys/utsname.h> 13 #include <ctype.h>14 #include <fcntl.h>15 11 #include <getopt.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include <syslog.h> 19 #include <time.h> 20 #include <unistd.h> 21 #include "busybox.h" 12 #include "libbb.h" 22 13 23 14 /* Copied from linux/rtc.h to eliminate the kernel dependency */ … … 43 34 #endif 44 35 36 static const char *rtcname; 37 38 static int xopen_rtc(int flags) 39 { 40 int rtc; 41 42 if (!rtcname) { 43 rtc = open("/dev/rtc", flags); 44 if (rtc >= 0) 45 return rtc; 46 rtc = open("/dev/rtc0", flags); 47 if (rtc >= 0) 48 return rtc; 49 rtcname = "/dev/misc/rtc"; 50 } 51 return xopen(rtcname, flags); 52 } 53 45 54 static time_t read_rtc(int utc) 46 55 { 47 int rtc;48 56 struct tm tm; 49 57 char *oldtz = 0; 50 58 time_t t = 0; 51 52 if (( rtc = open ( "/dev/rtc", O_RDONLY )) < 0 ) { 53 if (( rtc = open ( "/dev/misc/rtc", O_RDONLY )) < 0 ) 54 bb_perror_msg_and_die ( "Could not access RTC" ); 55 } 56 memset ( &tm, 0, sizeof( struct tm )); 57 if ( ioctl ( rtc, RTC_RD_TIME, &tm ) < 0 ) 58 bb_perror_msg_and_die ( "Could not read time from RTC" ); 59 int rtc = xopen_rtc(O_RDONLY); 60 61 memset(&tm, 0, sizeof(struct tm)); 62 xioctl(rtc, RTC_RD_TIME, &tm); 59 63 tm.tm_isdst = -1; /* not known */ 60 64 61 close ( rtc ); 62 63 if ( utc ) { 64 oldtz = getenv ( "TZ" ); 65 setenv ( "TZ", "UTC 0", 1 ); 66 tzset ( ); 67 } 68 69 t = mktime ( &tm ); 70 71 if ( utc ) { 72 if ( oldtz ) 73 setenv ( "TZ", oldtz, 1 ); 74 else 75 unsetenv ( "TZ" ); 76 tzset ( ); 65 close(rtc); 66 67 if (utc) { 68 oldtz = getenv("TZ"); 69 putenv((char*)"TZ=UTC0"); 70 tzset(); 71 } 72 73 t = mktime(&tm); 74 75 if (utc) { 76 unsetenv("TZ"); 77 if (oldtz) 78 putenv(oldtz - 3); 79 tzset(); 77 80 } 78 81 return t; … … 81 84 static void write_rtc(time_t t, int utc) 82 85 { 83 int rtc;84 86 struct tm tm; 85 86 if (( rtc = open ( "/dev/rtc", O_WRONLY )) < 0 ) { 87 if (( rtc = open ( "/dev/misc/rtc", O_WRONLY )) < 0 ) 88 bb_perror_msg_and_die ( "Could not access RTC" ); 89 } 90 91 tm = *( utc ? gmtime ( &t ) : localtime ( &t )); 87 int rtc = xopen_rtc(O_WRONLY); 88 89 tm = *(utc ? gmtime(&t) : localtime(&t)); 92 90 tm.tm_isdst = 0; 93 91 94 if ( ioctl ( rtc, RTC_SET_TIME, &tm ) < 0 ) 95 bb_perror_msg_and_die ( "Could not set the RTC time" ); 96 97 close ( rtc ); 98 } 99 100 static int show_clock(int utc) 101 { 102 struct tm *ptm; 92 xioctl(rtc, RTC_SET_TIME, &tm); 93 94 close(rtc); 95 } 96 97 static void show_clock(int utc) 98 { 99 //struct tm *ptm; 103 100 time_t t; 104 RESERVE_CONFIG_BUFFER(buffer, 64); 105 106 t = read_rtc ( utc ); 107 ptm = localtime ( &t ); /* Sets 'tzname[]' */ 108 109 safe_strncpy ( buffer, ctime ( &t ), 64); 110 if ( buffer [0] ) 111 buffer [strlen ( buffer ) - 1] = 0; 112 113 //printf ( "%s %.6f seconds %s\n", buffer, 0.0, utc ? "" : ( ptm-> tm_isdst ? tzname [1] : tzname [0] )); 114 printf ( "%s %.6f seconds\n", buffer, 0.0 ); 115 RELEASE_CONFIG_BUFFER(buffer); 116 117 return 0; 118 } 119 120 static int to_sys_clock(int utc) 121 { 122 struct timeval tv = { 0, 0 }; 101 char *cp; 102 103 t = read_rtc(utc); 104 //ptm = localtime(&t); /* Sets 'tzname[]' */ 105 106 cp = ctime(&t); 107 if (cp[0]) 108 cp[strlen(cp) - 1] = '\0'; 109 110 //printf("%s %.6f seconds %s\n", cp, 0.0, utc ? "" : (ptm->tm_isdst ? tzname[1] : tzname[0])); 111 printf("%s 0.000000 seconds\n", cp); 112 } 113 114 static void to_sys_clock(int utc) 115 { 116 struct timeval tv; 123 117 const struct timezone tz = { timezone/60 - 60*daylight, 0 }; 124 118 125 tv.tv_sec = read_rtc ( utc ); 126 127 if ( settimeofday ( &tv, &tz )) 128 bb_perror_msg_and_die ( "settimeofday() failed" ); 129 130 return 0; 131 } 132 133 static int from_sys_clock(int utc) 134 { 135 struct timeval tv = { 0, 0 }; 136 struct timezone tz = { 0, 0 }; 137 138 if ( gettimeofday ( &tv, &tz )) 139 bb_perror_msg_and_die ( "gettimeofday() failed" ); 140 141 write_rtc ( tv.tv_sec, utc ); 142 return 0; 143 } 144 145 #ifdef CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS 119 tv.tv_sec = read_rtc(utc); 120 tv.tv_usec = 0; 121 if (settimeofday(&tv, &tz)) 122 bb_perror_msg_and_die("settimeofday() failed"); 123 } 124 125 static void from_sys_clock(int utc) 126 { 127 struct timeval tv; 128 129 gettimeofday(&tv, NULL); 130 //if (gettimeofday(&tv, NULL)) 131 // bb_perror_msg_and_die("gettimeofday() failed"); 132 write_rtc(tv.tv_sec, utc); 133 } 134 135 #if ENABLE_FEATURE_HWCLOCK_ADJTIME_FHS 146 136 # define ADJTIME_PATH "/var/lib/hwclock/adjtime" 147 137 #else … … 151 141 { 152 142 int utc = 0; 153 FILE *f = fopen ( ADJTIME_PATH, "r");154 155 if ( f) {143 FILE *f = fopen(ADJTIME_PATH, "r"); 144 145 if (f) { 156 146 RESERVE_CONFIG_BUFFER(buffer, 128); 157 147 158 while ( fgets ( buffer, sizeof( buffer ), f)) {159 int len = strlen ( buffer);160 161 while ( len && isspace ( buffer [len - 1]))148 while (fgets(buffer, sizeof(buffer), f)) { 149 int len = strlen(buffer); 150 151 while (len && isspace(buffer[len - 1])) 162 152 len--; 163 153 164 buffer 165 166 if ( strncmp ( buffer, "UTC", 3 ) == 0) {154 buffer[len] = 0; 155 156 if (strncmp(buffer, "UTC", 3) == 0) { 167 157 utc = 1; 168 158 break; 169 159 } 170 160 } 171 fclose ( f);161 fclose(f); 172 162 RELEASE_CONFIG_BUFFER(buffer); 173 163 } … … 175 165 } 176 166 177 #define HWCLOCK_OPT_LOCALTIME 0x01 178 #define HWCLOCK_OPT_UTC 0x02 179 #define HWCLOCK_OPT_SHOW 0x04 180 #define HWCLOCK_OPT_HCTOSYS 0x08 181 #define HWCLOCK_OPT_SYSTOHC 0x10 182 183 int hwclock_main ( int argc, char **argv ) 184 { 185 unsigned long opt; 167 #define HWCLOCK_OPT_LOCALTIME 0x01 168 #define HWCLOCK_OPT_UTC 0x02 169 #define HWCLOCK_OPT_SHOW 0x04 170 #define HWCLOCK_OPT_HCTOSYS 0x08 171 #define HWCLOCK_OPT_SYSTOHC 0x10 172 #define HWCLOCK_OPT_RTCFILE 0x20 173 174 int hwclock_main(int argc, char **argv); 175 int hwclock_main(int argc, char **argv) 176 { 177 unsigned opt; 186 178 int utc; 187 179 188 180 #if ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS 189 static const struct option hwclock_long_options[] = { 190 { "localtime", 0, 0, 'l' },191 { "utc", 0, 0, 'u' },192 { "show", 0, 0, 'r' },193 { "hctosys", 0, 0, 's' },194 { "systohc", 0, 0, 'w' },195 { 0, 0, 0, 0 }196 };197 bb_applet_long_options = hwclock_long_options;181 static const char hwclock_longopts[] ALIGN1 = 182 "localtime\0" No_argument "l" 183 "utc\0" No_argument "u" 184 "show\0" No_argument "r" 185 "hctosys\0" No_argument "s" 186 "systohc\0" No_argument "w" 187 "file\0" Required_argument "f" 188 ; 189 applet_long_options = hwclock_longopts; 198 190 #endif 199 200 bb_opt_complementally = "?:r--ws:w--rs:s--wr:l--u:u--l"; 201 opt = bb_getopt_ulflags(argc, argv, "lursw"); 191 opt_complementary = "r--ws:w--rs:s--wr:l--u:u--l"; 192 opt = getopt32(argv, "lurswf:", &rtcname); 202 193 203 194 /* If -u or -l wasn't given check if we are using utc */ … … 208 199 209 200 if (opt & HWCLOCK_OPT_HCTOSYS) { 210 return to_sys_clock ( utc ); 211 } 212 else if (opt & HWCLOCK_OPT_SYSTOHC) { 213 return from_sys_clock ( utc ); 214 } else { 215 /* default HWCLOCK_OPT_SHOW */ 216 return show_clock ( utc ); 217 } 218 } 201 to_sys_clock(utc); 202 return 0; 203 } 204 if (opt & HWCLOCK_OPT_SYSTOHC) { 205 from_sys_clock(utc); 206 return 0; 207 } 208 /* default HWCLOCK_OPT_SHOW */ 209 show_clock(utc); 210 return 0; 211 } -
branches/stable/mindi-busybox/util-linux/ipcrm.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 * ipcrm.c - -utility to allow removal of IPC objects and data structures.3 * ipcrm.c - utility to allow removal of IPC objects and data structures. 3 4 * 4 5 * 01 Sept 2004 - Rodney Radford <rradford@mindspring.com> 5 6 * Adapted for busybox from util-linux-2.12a. 6 7 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * 21 * --- Pre-busybox history from util-linux-2.12a ------------------------ 22 * 23 * 1999-04-02 frank zago 24 * - can now remove several id's in the same call 25 * 26 * 1999-02-22 Arkadiusz Miÿkiewicz <misiek@pld.ORG.PL> 27 * - added Native Language Support 28 * 29 * Original author - krishna balasubramanian 1993 8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 30 9 */ 31 10 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <errno.h> 36 37 #include <sys/types.h> 11 #include "libbb.h" 12 13 /* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */ 14 /* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */ 38 15 #include <sys/ipc.h> 39 16 #include <sys/shm.h> … … 41 18 #include <sys/sem.h> 42 19 43 /* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */ 44 /* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */ 45 /* for getopt */ 46 #include <unistd.h> 47 48 /* for tolower and isupper */ 49 #include <ctype.h> 50 51 #include "busybox.h" 52 53 #if defined (__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) 20 #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) 54 21 /* union semun is defined by including <sys/sem.h> */ 55 22 #else … … 63 30 #endif 64 31 32 #define IPCRM_LEGACY 1 33 34 35 #if IPCRM_LEGACY 36 65 37 typedef enum type_id { 66 38 SHM, … … 69 41 } type_id; 70 42 71 static int 72 remove_ids(type_id type, int argc, char **argv) { 73 int id; 74 int ret = 0; /* for gcc */ 75 char *end; 43 static int remove_ids(type_id type, int argc, char **argv) 44 { 45 unsigned long id; 46 int ret = 0; /* silence gcc */ 76 47 int nb_errors = 0; 77 48 union semun arg; … … 79 50 arg.val = 0; 80 51 81 while(argc) { 82 83 id = strtoul(argv[0], &end, 10); 84 85 if (*end != 0) { 86 bb_printf ("invalid id: %s\n", argv[0]); 87 nb_errors ++; 52 while (argc) { 53 id = bb_strtoul(argv[0], NULL, 10); 54 if (errno || id > INT_MAX) { 55 bb_error_msg("invalid id: %s", argv[0]); 56 nb_errors++; 88 57 } else { 89 switch(type) { 90 case SEM: 91 ret = semctl (id, 0, IPC_RMID, arg); 92 break; 93 94 case MSG: 95 ret = msgctl (id, IPC_RMID, NULL); 96 break; 97 98 case SHM: 99 ret = shmctl (id, IPC_RMID, NULL); 100 break; 101 } 58 if (type == SEM) 59 ret = semctl(id, 0, IPC_RMID, arg); 60 else if (type == MSG) 61 ret = msgctl(id, IPC_RMID, NULL); 62 else if (type == SHM) 63 ret = shmctl(id, IPC_RMID, NULL); 102 64 103 65 if (ret) { 104 bb_printf ("cannot remove id %s (%s)\n", 105 argv[0], strerror(errno)); 106 nb_errors ++; 66 bb_perror_msg("cannot remove id %s", argv[0]); 67 nb_errors++; 107 68 } 108 69 } … … 111 72 } 112 73 113 return (nb_errors);74 return nb_errors; 114 75 } 115 116 static int deprecated_main(int argc, char **argv) 117 { 118 if (argc < 3) { 119 bb_show_usage(); 120 bb_fflush_stdout_and_exit(1); 121 } 122 123 if (!strcmp(argv[1], "shm")) { 124 if (remove_ids(SHM, argc-2, &argv[2])) 125 bb_fflush_stdout_and_exit(1); 126 } 127 else if (!strcmp(argv[1], "msg")) { 128 if (remove_ids(MSG, argc-2, &argv[2])) 129 bb_fflush_stdout_and_exit(1); 130 } 131 else if (!strcmp(argv[1], "sem")) { 132 if (remove_ids(SEM, argc-2, &argv[2])) 133 bb_fflush_stdout_and_exit(1); 134 } 135 else { 136 bb_printf ("unknown resource type: %s\n", argv[1]); 137 bb_show_usage(); 138 bb_fflush_stdout_and_exit(1); 139 } 140 141 bb_printf ("resource(s) deleted\n"); 142 return 0; 143 } 144 145 76 #endif /* IPCRM_LEGACY */ 77 78 79 int ipcrm_main(int argc, char **argv); 146 80 int ipcrm_main(int argc, char **argv) 147 81 { 148 int c; 149 int error = 0; 150 char *prog = argv[0]; 82 int c; 83 int error = 0; 151 84 152 85 /* if the command is executed without parameters, do nothing */ 153 86 if (argc == 1) 154 87 return 0; 155 88 #if IPCRM_LEGACY 156 89 /* check to see if the command is being invoked in the old way if so 157 then run the old code */ 158 if (strcmp(argv[1], "shm") == 0 || 159 strcmp(argv[1], "msg") == 0 || 160 strcmp(argv[1], "sem") == 0) 161 return deprecated_main(argc, argv); 90 then run the old code. Valid commands are msg, shm, sem. */ 91 { 92 type_id what = 0; /* silence gcc */ 93 char w; 94 95 w=argv[1][0]; 96 if ( ((w == 'm' && argv[1][1] == 's' && argv[1][2] == 'g') 97 || (argv[1][0] == 's' 98 && ((w=argv[1][1]) == 'h' || w == 'e') 99 && argv[1][2] == 'm') 100 ) && argv[1][3] == '\0' 101 ) { 102 103 if (argc < 3) 104 bb_show_usage(); 105 106 if (w == 'h') 107 what = SHM; 108 else if (w == 'm') 109 what = MSG; 110 else if (w == 'e') 111 what = SEM; 112 113 if (remove_ids(what, argc-2, &argv[2])) 114 fflush_stdout_and_exit(1); 115 printf("resource(s) deleted\n"); 116 return 0; 117 } 118 } 119 #endif /* IPCRM_LEGACY */ 162 120 163 121 /* process new syntax to conform with SYSV ipcrm */ … … 165 123 int result; 166 124 int id = 0; 167 int iskey = isupper(c);125 int iskey = (isupper)(c); 168 126 169 127 /* needed to delete semaphores */ 170 128 union semun arg; 129 171 130 arg.val = 0; 172 131 173 if ((c == '?') || (c == 'h')) 174 { 132 if ((c == '?') || (c == 'h')) { 175 133 bb_show_usage(); 176 return 0;177 134 } 178 135 … … 180 137 c = tolower(c); 181 138 182 /* make sure the option is in range */139 /* make sure the option is in range: allowed are q, m, s */ 183 140 if (c != 'q' && c != 'm' && c != 's') { 184 141 bb_show_usage(); 185 error++;186 return error;187 142 } 188 143 189 144 if (iskey) { 190 145 /* keys are in hex or decimal */ 191 key_t key = strtoul(optarg, NULL, 0); 146 key_t key = xstrtoul(optarg, 0); 147 192 148 if (key == IPC_PRIVATE) { 193 149 error++; 194 bb_fprintf(stderr, "%s: illegal key (%s)\n", 195 prog, optarg); 150 bb_error_msg("illegal key (%s)", optarg); 196 151 continue; 197 152 } … … 199 154 /* convert key to id */ 200 155 id = ((c == 'q') ? msgget(key, 0) : 201 (c == 'm') ? shmget(key, 0, 0) : 202 semget(key, 0, 0)); 156 (c == 'm') ? shmget(key, 0, 0) : semget(key, 0, 0)); 203 157 204 158 if (id < 0) { 205 char *errmsg; 159 const char *errmsg; 160 206 161 error++; 207 switch (errno) {162 switch (errno) { 208 163 case EACCES: 209 errmsg = "permission denied for key";164 errmsg = "permission denied for"; 210 165 break; 211 166 case EIDRM: 212 errmsg = "already removed key";167 errmsg = "already removed"; 213 168 break; 214 169 case ENOENT: 215 errmsg = "invalid key";170 errmsg = "invalid"; 216 171 break; 217 172 default: 218 errmsg = "unknown error in key";173 errmsg = "unknown error in"; 219 174 break; 220 175 } 221 bb_fprintf(stderr, "%s: %s (%s)\n", 222 prog, errmsg, optarg); 176 bb_error_msg("%s %s (%s)", errmsg, "key", optarg); 223 177 continue; 224 178 } 225 179 } else { 226 180 /* ids are in decimal */ 227 id = strtoul(optarg, NULL, 10);181 id = xatoul(optarg); 228 182 } 229 183 230 184 result = ((c == 'q') ? msgctl(id, IPC_RMID, NULL) : 231 (c == 'm') ? shmctl(id, IPC_RMID, NULL) : 232 semctl(id, 0, IPC_RMID, arg)); 233 234 if (result < 0) { 235 char *errmsg; 185 (c == 'm') ? shmctl(id, IPC_RMID, NULL) : 186 semctl(id, 0, IPC_RMID, arg)); 187 188 if (result) { 189 const char *errmsg; 190 const char *const what = iskey ? "key" : "id"; 191 236 192 error++; 237 switch (errno) {193 switch (errno) { 238 194 case EACCES: 239 195 case EPERM: 240 errmsg = iskey 241 ? "permission denied for key" 242 : "permission denied for id"; 196 errmsg = "permission denied for"; 243 197 break; 244 198 case EINVAL: 245 errmsg = iskey 246 ? "invalid key" 247 : "invalid id"; 199 errmsg = "invalid"; 248 200 break; 249 201 case EIDRM: 250 errmsg = iskey 251 ? "already removed key" 252 : "already removed id"; 202 errmsg = "already removed"; 253 203 break; 254 204 default: 255 errmsg = iskey 256 ? "unknown error in key" 257 : "unknown error in id"; 258 break; 259 } 260 bb_fprintf(stderr, "%s: %s (%s)\n", 261 prog, errmsg, optarg); 205 errmsg = "unknown error in"; 206 break; 207 } 208 bb_error_msg("%s %s (%s)", errmsg, what, optarg); 262 209 continue; 263 210 } -
branches/stable/mindi-busybox/util-linux/ipcs.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 3 * ipcs.c -- provides information on allocated ipc resources. … … 8 9 */ 9 10 10 #include <stdio.h>11 #include <stdlib.h>12 #include <getopt.h>13 #include <errno.h>14 #include <time.h>15 #include <pwd.h>16 #include <grp.h>17 18 11 /* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */ 19 12 /* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */ … … 25 18 #include <sys/shm.h> 26 19 27 #include " busybox.h"20 #include "libbb.h" 28 21 29 22 /*-------------------------------------------------------------------*/ … … 32 25 #ifndef SHM_DEST 33 26 /* shm_mode upper byte flags */ 34 #define SHM_DEST 01000 35 #define SHM_LOCKED 02000 27 #define SHM_DEST 01000 /* segment will be destroyed on last detach */ 28 #define SHM_LOCKED 02000 /* segment will not be swapped */ 36 29 #endif 37 30 … … 46 39 #define SHM_INFO 14 47 40 struct shm_info { 48 intused_ids;49 ulong shm_tot;/* total allocated shm */50 ulong shm_rss;/* total resident shm */51 ulong shm_swp;/* total swapped shm */52 53 41 int used_ids; 42 ulong shm_tot; /* total allocated shm */ 43 ulong shm_rss; /* total resident shm */ 44 ulong shm_swp; /* total swapped shm */ 45 ulong swap_attempts; 46 ulong swap_successes; 54 47 }; 55 48 #endif … … 69 62 X/OPEN tells us to define it ourselves, but until recently 70 63 Linux include files would also define it. */ 71 #if defined 64 #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) 72 65 /* union semun is defined by including <sys/sem.h> */ 73 66 #else … … 86 79 glibc-1.09 has no support for sysv ipc. 87 80 glibc 2 uses __key, __seq */ 88 #if defined 81 #if defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1 89 82 #define KEY __key 90 83 #else … … 98 91 #define PID 5 99 92 100 101 static void print_perms (int id, struct ipc_perm *ipcp) { 93 static char format; 94 95 static void print_perms(int id, struct ipc_perm *ipcp) 96 { 102 97 struct passwd *pw; 103 98 struct group *gr; 104 99 105 bb_printf("%-10d %-10o", id, ipcp->mode & 0777);100 printf("%-10d %-10o", id, ipcp->mode & 0777); 106 101 107 102 if ((pw = getpwuid(ipcp->cuid))) 108 bb_printf(" %-10s", pw->pw_name);103 printf(" %-10s", pw->pw_name); 109 104 else 110 bb_printf(" %-10d", ipcp->cuid);105 printf(" %-10d", ipcp->cuid); 111 106 if ((gr = getgrgid(ipcp->cgid))) 112 bb_printf(" %-10s", gr->gr_name);107 printf(" %-10s", gr->gr_name); 113 108 else 114 bb_printf(" %-10d", ipcp->cgid);109 printf(" %-10d", ipcp->cgid); 115 110 116 111 if ((pw = getpwuid(ipcp->uid))) 117 bb_printf(" %-10s", pw->pw_name);112 printf(" %-10s", pw->pw_name); 118 113 else 119 bb_printf(" %-10d", ipcp->uid);114 printf(" %-10d", ipcp->uid); 120 115 if ((gr = getgrgid(ipcp->gid))) 121 bb_printf(" %-10s\n", gr->gr_name);116 printf(" %-10s\n", gr->gr_name); 122 117 else 123 bb_printf(" %-10d\n", ipcp->gid);124 } 125 126 127 static void do_shm (char format)118 printf(" %-10d\n", ipcp->gid); 119 } 120 121 122 static void do_shm(void) 128 123 { 129 124 int maxid, shmid, id; … … 134 129 struct passwd *pw; 135 130 136 maxid = shmctl 131 maxid = shmctl(0, SHM_INFO, (struct shmid_ds *) (void *) &shm_info); 137 132 if (maxid < 0) { 138 bb_printf ("kernel not configured for shared memory\n");133 printf("kernel not configured for %s\n", "shared memory"); 139 134 return; 140 135 } … … 142 137 switch (format) { 143 138 case LIMITS: 144 bb_printf ("------ Shared Memory Limits --------\n");145 if ((shmctl (0, IPC_INFO, (struct shmid_ds *) (void *) &shminfo)) < 0)139 printf("------ Shared Memory %s --------\n", "Limits"); 140 if ((shmctl(0, IPC_INFO, (struct shmid_ds *) (void *) &shminfo)) < 0) 146 141 return; 147 142 /* glibc 2.1.3 and all earlier libc's have ints as fields 148 143 of struct shminfo; glibc 2.1.91 has unsigned long; ach */ 149 bb_printf("max number of segments = %lu\n"150 "max seg size (kbytes) = %lu\n"151 "max total shared memory (pages) = %lu\n"152 "min seg size (bytes) = %lu\n",153 (unsigned long) shminfo.shmmni,154 (unsigned long) (shminfo.shmmax >> 10),155 (unsigned long) shminfo.shmall,156 (unsigned long) shminfo.shmmin);144 printf("max number of segments = %lu\n" 145 "max seg size (kbytes) = %lu\n" 146 "max total shared memory (pages) = %lu\n" 147 "min seg size (bytes) = %lu\n", 148 (unsigned long) shminfo.shmmni, 149 (unsigned long) (shminfo.shmmax >> 10), 150 (unsigned long) shminfo.shmall, 151 (unsigned long) shminfo.shmmin); 157 152 return; 158 153 159 154 case STATUS: 160 bb_printf ("------ Shared Memory Status --------\n"161 162 "pages allocated %ld\n"163 "pages resident %ld\n"164 "pages swapped %ld\n"165 "Swap performance: %ld attempts\t%ld successes\n",166 shm_info.used_ids,167 shm_info.shm_tot,168 shm_info.shm_rss,169 shm_info.shm_swp,170 shm_info.swap_attempts, shm_info.swap_successes);155 printf("------ Shared Memory %s --------\n", "Status"); 156 printf( "segments allocated %d\n" 157 "pages allocated %ld\n" 158 "pages resident %ld\n" 159 "pages swapped %ld\n" 160 "Swap performance: %ld attempts\t%ld successes\n", 161 shm_info.used_ids, 162 shm_info.shm_tot, 163 shm_info.shm_rss, 164 shm_info.shm_swp, 165 shm_info.swap_attempts, shm_info.swap_successes); 171 166 return; 172 167 173 168 case CREATOR: 174 bb_printf ("------ Shared Memory Segment Creators/Owners --------\n"175 176 "shmid","perms","cuid","cgid","uid","gid");169 printf("------ Shared Memory %s --------\n", "Segment Creators/Owners"); 170 printf( "%-10s %-10s %-10s %-10s %-10s %-10s\n", 171 "shmid", "perms", "cuid", "cgid", "uid", "gid"); 177 172 break; 178 173 179 174 case TIME: 180 bb_printf ("------ Shared Memory Attach/Detach/Change Times --------\n"181 182 "shmid","owner","attached","detached","changed");175 printf("------ Shared Memory %s --------\n", "Attach/Detach/Change Times"); 176 printf( "%-10s %-10s %-20s %-20s %-20s\n", 177 "shmid", "owner", "attached", "detached", "changed"); 183 178 break; 184 179 185 180 case PID: 186 bb_printf ("------ Shared Memory Creator/Last-op --------\n"187 188 "shmid","owner","cpid","lpid");181 printf("------ Shared Memory %s --------\n", "Creator/Last-op"); 182 printf( "%-10s %-10s %-10s %-10s\n", 183 "shmid", "owner", "cpid", "lpid"); 189 184 break; 190 185 191 186 default: 192 bb_printf ("------ Shared Memory Segments --------\n" 193 "%-10s %-10s %-10s %-10s %-10s %-10s %-12s\n", 194 "key","shmid","owner","perms","bytes","nattch","status"); 187 printf("------ Shared Memory %s --------\n", "Segments"); 188 printf( "%-10s %-10s %-10s %-10s %-10s %-10s %-12s\n", 189 "key", "shmid", "owner", "perms", "bytes", "nattch", 190 "status"); 195 191 break; 196 192 } 197 193 198 194 for (id = 0; id <= maxid; id++) { 199 shmid = shmctl 195 shmid = shmctl(id, SHM_STAT, &shmseg); 200 196 if (shmid < 0) 201 197 continue; 202 if (format == CREATOR) 203 print_perms 198 if (format == CREATOR) { 199 print_perms(shmid, ipcp); 204 200 continue; 205 201 } … … 208 204 case TIME: 209 205 if (pw) 210 bb_printf("%-10d %-10.10s", shmid, pw->pw_name);211 else 212 bb_printf("%-10d %-10d", shmid, ipcp->uid);206 printf("%-10d %-10.10s", shmid, pw->pw_name); 207 else 208 printf("%-10d %-10d", shmid, ipcp->uid); 213 209 /* ctime uses static buffer: use separate calls */ 214 bb_printf("%-20.16s", shmseg.shm_atime215 216 bb_printf(" %-20.16s", shmseg.shm_dtime217 218 bb_printf(" %-20.16s\n", shmseg.shm_ctime219 210 printf(" %-20.16s", shmseg.shm_atime 211 ? ctime(&shmseg.shm_atime) + 4 : "Not set"); 212 printf(" %-20.16s", shmseg.shm_dtime 213 ? ctime(&shmseg.shm_dtime) + 4 : "Not set"); 214 printf(" %-20.16s\n", shmseg.shm_ctime 215 ? ctime(&shmseg.shm_ctime) + 4 : "Not set"); 220 216 break; 221 217 case PID: 222 218 if (pw) 223 bb_printf ("%-10d %-10.10s", shmid, pw->pw_name); 224 else 225 bb_printf ("%-10d %-10d", shmid, ipcp->uid); 226 bb_printf (" %-10d %-10d\n", 227 shmseg.shm_cpid, shmseg.shm_lpid); 219 printf("%-10d %-10.10s", shmid, pw->pw_name); 220 else 221 printf("%-10d %-10d", shmid, ipcp->uid); 222 printf(" %-10d %-10d\n", shmseg.shm_cpid, shmseg.shm_lpid); 228 223 break; 229 224 230 225 default: 231 bb_printf("0x%08x ",ipcp->KEY ); 232 if (pw) 233 bb_printf ("%-10d %-10.10s", shmid, pw->pw_name); 234 else 235 bb_printf ("%-10d %-10d", shmid, ipcp->uid); 236 bb_printf ("%-10o %-10lu %-10ld %-6s %-6s\n", 237 ipcp->mode & 0777, 238 /* 239 * earlier: int, Austin has size_t 240 */ 241 (unsigned long) shmseg.shm_segsz, 242 /* 243 * glibc-2.1.3 and earlier has unsigned short; 244 * Austin has shmatt_t 245 */ 246 (long) shmseg.shm_nattch, 247 ipcp->mode & SHM_DEST ? "dest" : " ", 248 ipcp->mode & SHM_LOCKED ? "locked" : " "); 249 break; 250 } 251 } 252 return; 253 } 254 255 256 static void do_sem (char format) 226 printf("0x%08x ", ipcp->KEY); 227 if (pw) 228 printf("%-10d %-10.10s", shmid, pw->pw_name); 229 else 230 printf("%-10d %-10d", shmid, ipcp->uid); 231 printf(" %-10o %-10lu %-10ld %-6s %-6s\n", ipcp->mode & 0777, 232 /* 233 * earlier: int, Austin has size_t 234 */ 235 (unsigned long) shmseg.shm_segsz, 236 /* 237 * glibc-2.1.3 and earlier has unsigned short; 238 * Austin has shmatt_t 239 */ 240 (long) shmseg.shm_nattch, 241 ipcp->mode & SHM_DEST ? "dest" : " ", 242 ipcp->mode & SHM_LOCKED ? "locked" : " "); 243 break; 244 } 245 } 246 } 247 248 249 static void do_sem(void) 257 250 { 258 251 int maxid, semid, id; … … 263 256 union semun arg; 264 257 265 arg.array = (ushort *) 266 maxid = semctl 258 arg.array = (ushort *) (void *) &seminfo; 259 maxid = semctl(0, 0, SEM_INFO, arg); 267 260 if (maxid < 0) { 268 bb_printf ("kernel not configured for semaphores\n");261 printf("kernel not configured for %s\n", "semaphores"); 269 262 return; 270 263 } … … 272 265 switch (format) { 273 266 case LIMITS: 274 bb_printf ("------ Semaphore Limits --------\n");275 arg.array = (ushort *) (void *) &seminfo; 276 if ((semctl (0, 0, IPC_INFO, arg)) < 0)267 printf("------ Semaphore %s --------\n", "Limits"); 268 arg.array = (ushort *) (void *) &seminfo; /* damn union */ 269 if ((semctl(0, 0, IPC_INFO, arg)) < 0) 277 270 return; 278 bb_printf ("max number of arrays = %d\n" 279 "max semaphores per array = %d\n" 280 "max semaphores system wide = %d\n" 281 "max ops per semop call = %d\n" 282 "semaphore max value = %d\n", 283 seminfo.semmni, 284 seminfo.semmsl, 285 seminfo.semmns, 286 seminfo.semopm, 287 seminfo.semvmx); 271 printf("max number of arrays = %d\n" 272 "max semaphores per array = %d\n" 273 "max semaphores system wide = %d\n" 274 "max ops per semop call = %d\n" 275 "semaphore max value = %d\n", 276 seminfo.semmni, 277 seminfo.semmsl, 278 seminfo.semmns, seminfo.semopm, seminfo.semvmx); 288 279 return; 289 280 290 281 case STATUS: 291 bb_printf ("------ Semaphore Status --------\n" 292 "used arrays = %d\n" 293 "allocated semaphores = %d\n", 294 seminfo.semusz, 295 seminfo.semaem); 282 printf("------ Semaphore %s --------\n", "Status"); 283 printf( "used arrays = %d\n" 284 "allocated semaphores = %d\n", 285 seminfo.semusz, seminfo.semaem); 296 286 return; 297 287 298 288 case CREATOR: 299 bb_printf ("------ Semaphore Arrays Creators/Owners --------\n"300 301 "semid","perms","cuid","cgid","uid","gid");289 printf("------ Semaphore %s --------\n", "Arrays Creators/Owners"); 290 printf( "%-10s %-10s %-10s %-10s %-10s %-10s\n", 291 "semid", "perms", "cuid", "cgid", "uid", "gid"); 302 292 break; 303 293 304 294 case TIME: 305 bb_printf ("------ Shared Memory Operation/Change Times --------\n"306 307 "shmid","owner","last-op","last-changed");295 printf("------ Shared Memory %s --------\n", "Operation/Change Times"); 296 printf( "%-8s %-10s %-26.24s %-26.24s\n", 297 "shmid", "owner", "last-op", "last-changed"); 308 298 break; 309 299 … … 312 302 313 303 default: 314 bb_printf ("------ Semaphore Arrays --------\n"315 316 "key","semid","owner","perms","nsems");304 printf("------ Semaphore %s --------\n", "Arrays"); 305 printf( "%-10s %-10s %-10s %-10s %-10s\n", 306 "key", "semid", "owner", "perms", "nsems"); 317 307 break; 318 308 } … … 320 310 for (id = 0; id <= maxid; id++) { 321 311 arg.buf = (struct semid_ds *) &semary; 322 semid = semctl 312 semid = semctl(id, 0, SEM_STAT, arg); 323 313 if (semid < 0) 324 314 continue; 325 if (format == CREATOR) 326 print_perms 315 if (format == CREATOR) { 316 print_perms(semid, ipcp); 327 317 continue; 328 318 } … … 331 321 case TIME: 332 322 if (pw) 333 bb_printf ("%-8d %-10.10s", semid, pw->pw_name); 334 else 335 bb_printf ("%-8d %-10d", semid, ipcp->uid); 336 bb_printf (" %-26.24s", semary.sem_otime 337 ? ctime(&semary.sem_otime) : "Not set"); 338 bb_printf (" %-26.24s\n", semary.sem_ctime 339 ? ctime(&semary.sem_ctime) : "Not set"); 323 printf("%-8d %-10.10s", semid, pw->pw_name); 324 else 325 printf("%-8d %-10d", semid, ipcp->uid); 326 /* ctime uses static buffer: use separate calls */ 327 printf(" %-26.24s", semary.sem_otime 328 ? ctime(&semary.sem_otime) : "Not set"); 329 printf(" %-26.24s\n", semary.sem_ctime 330 ? ctime(&semary.sem_ctime) : "Not set"); 340 331 break; 341 332 case PID: … … 343 334 344 335 default: 345 bb_printf("0x%08x ", ipcp->KEY); 346 if (pw) 347 bb_printf ("%-10d %-10.9s", semid, pw->pw_name); 348 else 349 bb_printf ("%-10d %-9d", semid, ipcp->uid); 350 bb_printf ("%-10o %-10ld\n", 351 ipcp->mode & 0777, 352 /* 353 * glibc-2.1.3 and earlier has unsigned short; 354 * glibc-2.1.91 has variation between 355 * unsigned short and unsigned long 356 * Austin prescribes unsigned short. 357 */ 358 (long) semary.sem_nsems); 359 break; 360 } 361 } 362 } 363 364 365 static void do_msg (char format) 336 printf("0x%08x ", ipcp->KEY); 337 if (pw) 338 printf("%-10d %-10.9s", semid, pw->pw_name); 339 else 340 printf("%-10d %-9d", semid, ipcp->uid); 341 printf(" %-10o %-10ld\n", ipcp->mode & 0777, 342 /* 343 * glibc-2.1.3 and earlier has unsigned short; 344 * glibc-2.1.91 has variation between 345 * unsigned short and unsigned long 346 * Austin prescribes unsigned short. 347 */ 348 (long) semary.sem_nsems); 349 break; 350 } 351 } 352 } 353 354 355 static void do_msg(void) 366 356 { 367 357 int maxid, msqid, id; … … 371 361 struct passwd *pw; 372 362 373 maxid = msgctl 363 maxid = msgctl(0, MSG_INFO, (struct msqid_ds *) (void *) &msginfo); 374 364 if (maxid < 0) { 375 bb_printf ("kernel not configured for message queues\n");365 printf("kernel not configured for %s\n", "message queues"); 376 366 return; 377 367 } … … 379 369 switch (format) { 380 370 case LIMITS: 381 if ((msgctl (0, IPC_INFO, (struct msqid_ds *) (void *) &msginfo)) < 0)371 if ((msgctl(0, IPC_INFO, (struct msqid_ds *) (void *) &msginfo)) < 0) 382 372 return; 383 bb_printf ("------ Messages: Limits --------\n" 384 "max queues system wide = %d\n" 385 "max size of message (bytes) = %d\n" 386 "default max size of queue (bytes) = %d\n", 387 msginfo.msgmni, 388 msginfo.msgmax, 389 msginfo.msgmnb); 373 printf("------ Message%s --------\n", "s: Limits"); 374 printf( "max queues system wide = %d\n" 375 "max size of message (bytes) = %d\n" 376 "default max size of queue (bytes) = %d\n", 377 msginfo.msgmni, msginfo.msgmax, msginfo.msgmnb); 390 378 return; 391 379 392 380 case STATUS: 393 bb_printf ("------ Messages: Status --------\n" 394 "allocated queues = %d\n" 395 "used headers = %d\n" 396 "used space = %d bytes\n", 397 msginfo.msgpool, 398 msginfo.msgmap, 399 msginfo.msgtql); 381 printf("------ Message%s --------\n", "s: Status"); 382 printf( "allocated queues = %d\n" 383 "used headers = %d\n" 384 "used space = %d bytes\n", 385 msginfo.msgpool, msginfo.msgmap, msginfo.msgtql); 400 386 return; 401 387 402 388 case CREATOR: 403 bb_printf ("------ Message Queues: Creators/Owners --------\n"404 405 "msqid","perms","cuid","cgid","uid","gid");389 printf("------ Message%s --------\n", " Queues: Creators/Owners"); 390 printf( "%-10s %-10s %-10s %-10s %-10s %-10s\n", 391 "msqid", "perms", "cuid", "cgid", "uid", "gid"); 406 392 break; 407 393 408 394 case TIME: 409 bb_printf ("------ Message Queues Send/Recv/Change Times --------\n"410 411 "msqid","owner","send","recv","change");395 printf("------ Message%s --------\n", " Queues Send/Recv/Change Times"); 396 printf( "%-8s %-10s %-20s %-20s %-20s\n", 397 "msqid", "owner", "send", "recv", "change"); 412 398 break; 413 399 414 400 case PID: 415 bb_printf ("------ Message Queues PIDs --------\n"416 417 "msqid","owner","lspid","lrpid");401 printf("------ Message%s --------\n", " Queues PIDs"); 402 printf( "%-10s %-10s %-10s %-10s\n", 403 "msqid", "owner", "lspid", "lrpid"); 418 404 break; 419 405 420 406 default: 421 bb_printf ("------ Message Queues --------\n"422 423 "key","msqid","owner","perms","used-bytes","messages");407 printf("------ Message%s --------\n", " Queues"); 408 printf( "%-10s %-10s %-10s %-10s %-12s %-12s\n", 409 "key", "msqid", "owner", "perms", "used-bytes", "messages"); 424 410 break; 425 411 } 426 412 427 413 for (id = 0; id <= maxid; id++) { 428 msqid = msgctl 414 msqid = msgctl(id, MSG_STAT, &msgque); 429 415 if (msqid < 0) 430 416 continue; 431 if (format == CREATOR) 432 print_perms 417 if (format == CREATOR) { 418 print_perms(msqid, ipcp); 433 419 continue; 434 420 } … … 437 423 case TIME: 438 424 if (pw) 439 bb_printf("%-8d %-10.10s", msqid, pw->pw_name);440 else 441 bb_printf("%-8d %-10d", msqid, ipcp->uid);442 bb_printf(" %-20.16s", msgque.msg_stime443 ? ctime(&msgque.msg_stime) + 4 : "Not set");444 bb_printf(" %-20.16s", msgque.msg_rtime445 ? ctime(&msgque.msg_rtime) + 4 : "Not set");446 bb_printf(" %-20.16s\n", msgque.msg_ctime447 ? ctime(&msgque.msg_ctime) + 4 : "Not set");425 printf("%-8d %-10.10s", msqid, pw->pw_name); 426 else 427 printf("%-8d %-10d", msqid, ipcp->uid); 428 printf(" %-20.16s", msgque.msg_stime 429 ? ctime(&msgque.msg_stime) + 4 : "Not set"); 430 printf(" %-20.16s", msgque.msg_rtime 431 ? ctime(&msgque.msg_rtime) + 4 : "Not set"); 432 printf(" %-20.16s\n", msgque.msg_ctime 433 ? ctime(&msgque.msg_ctime) + 4 : "Not set"); 448 434 break; 449 435 case PID: 450 436 if (pw) 451 bb_printf ("%-8d %-10.10s", msqid, pw->pw_name); 452 else 453 bb_printf ("%-8d %-10d", msqid, ipcp->uid); 454 bb_printf (" %5d %5d\n", 455 msgque.msg_lspid, msgque.msg_lrpid); 437 printf("%-8d %-10.10s", msqid, pw->pw_name); 438 else 439 printf("%-8d %-10d", msqid, ipcp->uid); 440 printf(" %5d %5d\n", msgque.msg_lspid, msgque.msg_lrpid); 456 441 break; 457 442 458 443 default: 459 bb_printf( "0x%08x ",ipcp->KEY ); 460 if (pw) 461 bb_printf ("%-10d %-10.10s", msqid, pw->pw_name); 462 else 463 bb_printf ("%-10d %-10d", msqid, ipcp->uid); 464 bb_printf (" %-10o %-12ld %-12ld\n", 465 ipcp->mode & 0777, 466 /* 467 * glibc-2.1.3 and earlier has unsigned short; 468 * glibc-2.1.91 has variation between 469 * unsigned short, unsigned long 470 * Austin has msgqnum_t 471 */ 472 (long) msgque.msg_cbytes, 473 (long) msgque.msg_qnum); 474 break; 475 } 476 } 477 return; 478 } 479 480 481 static void print_shm (int shmid) 444 printf("0x%08x ", ipcp->KEY); 445 if (pw) 446 printf("%-10d %-10.10s", msqid, pw->pw_name); 447 else 448 printf("%-10d %-10d", msqid, ipcp->uid); 449 printf(" %-10o %-12ld %-12ld\n", ipcp->mode & 0777, 450 /* 451 * glibc-2.1.3 and earlier has unsigned short; 452 * glibc-2.1.91 has variation between 453 * unsigned short, unsigned long 454 * Austin has msgqnum_t 455 */ 456 (long) msgque.msg_cbytes, (long) msgque.msg_qnum); 457 break; 458 } 459 } 460 } 461 462 463 static void print_shm(int shmid) 482 464 { 483 465 struct shmid_ds shmds; 484 466 struct ipc_perm *ipcp = &shmds.shm_perm; 485 467 486 if (shmctl (shmid, IPC_STAT, &shmds) == -1) { 487 perror ("shmctl "); 488 return; 489 } 490 491 bb_printf ("\nShared memory Segment shmid=%d\n" 492 "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\n" 493 "mode=%#o\taccess_perms=%#o\n" 494 "bytes=%ld\tlpid=%d\tcpid=%d\tnattch=%ld\n" 495 "att_time=%-26.24s\n" 496 "det_time=%-26.24s\n" 497 "change_time=%-26.24s\n" 498 "\n", 499 shmid, 500 ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, 501 ipcp->mode, ipcp->mode & 0777, 502 (long) shmds.shm_segsz, shmds.shm_lpid, shmds.shm_cpid, 503 (long) shmds.shm_nattch, 504 shmds.shm_atime ? ctime (&shmds.shm_atime) : "Not set", 505 shmds.shm_dtime ? ctime (&shmds.shm_dtime) : "Not set", 506 ctime (&shmds.shm_ctime)); 507 return; 508 } 509 510 511 static void print_msg (int msqid) 468 if (shmctl(shmid, IPC_STAT, &shmds) == -1) { 469 bb_perror_msg("shmctl"); 470 return; 471 } 472 473 printf("\nShared memory Segment shmid=%d\n" 474 "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\n" 475 "mode=%#o\taccess_perms=%#o\n" 476 "bytes=%ld\tlpid=%d\tcpid=%d\tnattch=%ld\n", 477 shmid, 478 ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, 479 ipcp->mode, ipcp->mode & 0777, 480 (long) shmds.shm_segsz, shmds.shm_lpid, shmds.shm_cpid, 481 (long) shmds.shm_nattch); 482 printf("att_time=%-26.24s\n", 483 shmds.shm_atime ? ctime(&shmds.shm_atime) : "Not set"); 484 printf("det_time=%-26.24s\n", 485 shmds.shm_dtime ? ctime(&shmds.shm_dtime) : "Not set"); 486 printf("change_time=%-26.24s\n\n", ctime(&shmds.shm_ctime)); 487 } 488 489 490 static void print_msg(int msqid) 512 491 { 513 492 struct msqid_ds buf; 514 493 struct ipc_perm *ipcp = &buf.msg_perm; 515 494 516 if (msgctl (msqid, IPC_STAT, &buf) == -1) { 517 perror ("msgctl "); 518 return; 519 } 520 521 bb_printf ("\nMessage Queue msqid=%d\n" 522 "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\tmode=%#o\n" 523 "cbytes=%ld\tqbytes=%ld\tqnum=%ld\tlspid=%d\tlrpid=%d\n" 524 "send_time=%-26.24s\n" 525 "rcv_time=%-26.24s\n" 526 "change_time=%-26.24s\n" 527 "\n", 528 msqid, 529 ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, ipcp->mode, 530 /* 531 * glibc-2.1.3 and earlier has unsigned short; 532 * glibc-2.1.91 has variation between 533 * unsigned short, unsigned long 534 * Austin has msgqnum_t (for msg_qbytes) 535 */ 536 (long) buf.msg_cbytes, (long) buf.msg_qbytes, 537 (long) buf.msg_qnum, buf.msg_lspid, buf.msg_lrpid, 538 buf.msg_stime ? ctime (&buf.msg_stime) : "Not set", 539 buf.msg_rtime ? ctime (&buf.msg_rtime) : "Not set", 540 buf.msg_ctime ? ctime (&buf.msg_ctime) : "Not set"); 541 return; 542 } 543 544 static void print_sem (int semid) 495 if (msgctl(msqid, IPC_STAT, &buf) == -1) { 496 bb_perror_msg("msgctl"); 497 return; 498 } 499 500 printf("\nMessage Queue msqid=%d\n" 501 "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\tmode=%#o\n" 502 "cbytes=%ld\tqbytes=%ld\tqnum=%ld\tlspid=%d\tlrpid=%d\n", 503 msqid, ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, ipcp->mode, 504 /* 505 * glibc-2.1.3 and earlier has unsigned short; 506 * glibc-2.1.91 has variation between 507 * unsigned short, unsigned long 508 * Austin has msgqnum_t (for msg_qbytes) 509 */ 510 (long) buf.msg_cbytes, (long) buf.msg_qbytes, 511 (long) buf.msg_qnum, buf.msg_lspid, buf.msg_lrpid); 512 513 printf("send_time=%-26.24s\n", 514 buf.msg_stime ? ctime(&buf.msg_stime) : "Not set"); 515 printf("rcv_time=%-26.24s\n", 516 buf.msg_rtime ? ctime(&buf.msg_rtime) : "Not set"); 517 printf("change_time=%-26.24s\n\n", 518 buf.msg_ctime ? ctime(&buf.msg_ctime) : "Not set"); 519 } 520 521 static void print_sem(int semid) 545 522 { 546 523 struct semid_ds semds; … … 550 527 551 528 arg.buf = &semds; 552 if (semctl (semid, 0, IPC_STAT, arg) < 0) {553 perror ("semctl");554 return; 555 } 556 557 bb_printf("\nSemaphore Array semid=%d\n"558 "uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n"559 "mode=%#o, access_perms=%#o\n"560 "nsems = %ld\n"561 "otime = %-26.24s\n"562 "ctime = %-26.24s\n"563 "%-10s %-10s %-10s %-10s %-10s\n",564 semid,565 ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,566 ipcp->mode, ipcp->mode & 0777,567 (long) semds.sem_nsems,568 semds.sem_otime ? ctime (&semds.sem_otime) : "Not set",569 ctime(&semds.sem_ctime),570 "semnum","value","ncount","zcount","pid");529 if (semctl(semid, 0, IPC_STAT, arg)) { 530 bb_perror_msg("semctl"); 531 return; 532 } 533 534 printf("\nSemaphore Array semid=%d\n" 535 "uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n" 536 "mode=%#o, access_perms=%#o\n" 537 "nsems = %ld\n" 538 "otime = %-26.24s\n", 539 semid, 540 ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, 541 ipcp->mode, ipcp->mode & 0777, 542 (long) semds.sem_nsems, 543 semds.sem_otime ? ctime(&semds.sem_otime) : "Not set"); 544 printf("ctime = %-26.24s\n" 545 "%-10s %-10s %-10s %-10s %-10s\n", 546 ctime(&semds.sem_ctime), 547 "semnum", "value", "ncount", "zcount", "pid"); 571 548 572 549 arg.val = 0; 573 for (i =0; i < semds.sem_nsems; i++) {550 for (i = 0; i < semds.sem_nsems; i++) { 574 551 int val, ncnt, zcnt, pid; 575 val = semctl (semid, i, GETVAL, arg); 576 ncnt = semctl (semid, i, GETNCNT, arg); 577 zcnt = semctl (semid, i, GETZCNT, arg); 578 pid = semctl (semid, i, GETPID, arg); 552 553 val = semctl(semid, i, GETVAL, arg); 554 ncnt = semctl(semid, i, GETNCNT, arg); 555 zcnt = semctl(semid, i, GETZCNT, arg); 556 pid = semctl(semid, i, GETPID, arg); 579 557 if (val < 0 || ncnt < 0 || zcnt < 0 || pid < 0) { 580 perror ("semctl "); 581 bb_fflush_stdout_and_exit (1); 582 } 583 bb_printf ("%-10d %-10d %-10d %-10d %-10d\n", 584 i, val, ncnt, zcnt, pid); 585 } 586 bb_printf ("\n"); 587 return; 588 } 589 590 int ipcs_main (int argc, char **argv) { 591 int opt, msg = 0, sem = 0, shm = 0, id=0, print=0; 592 char format = 0; 593 char options[] = "atclupsmqi:ih?"; 594 595 while ((opt = getopt (argc, argv, options)) != -1) { 596 switch (opt) { 597 case 'i': 598 id = atoi (optarg); 599 print = 1; 600 break; 601 case 'a': 602 msg = shm = sem = 1; 603 break; 604 case 'q': 605 msg = 1; 606 break; 607 case 's': 608 sem = 1; 609 break; 610 case 'm': 611 shm = 1; 612 break; 613 case 't': 614 format = TIME; 615 break; 616 case 'c': 617 format = CREATOR; 618 break; 619 case 'p': 620 format = PID; 621 break; 622 case 'l': 623 format = LIMITS; 624 break; 625 case 'u': 626 format = STATUS; 627 break; 628 case 'h': 629 case '?': 630 bb_show_usage(); 631 bb_fflush_stdout_and_exit (0); 632 } 633 } 634 635 if (print) { 636 if (shm) { 637 print_shm (id); 638 bb_fflush_stdout_and_exit (0); 639 } 640 if (sem) { 641 print_sem (id); 642 bb_fflush_stdout_and_exit (0); 643 } 644 if (msg) { 645 print_msg (id); 646 bb_fflush_stdout_and_exit (0); 558 bb_perror_msg_and_die("semctl"); 559 } 560 printf("%-10d %-10d %-10d %-10d %-10d\n", i, val, ncnt, zcnt, pid); 561 } 562 puts(""); 563 } 564 565 int ipcs_main(int argc, char **argv); 566 int ipcs_main(int argc, char **argv) 567 { 568 int id = 0; 569 unsigned flags = 0; 570 unsigned opt; 571 char *opt_i; 572 #define flag_print (1<<0) 573 #define flag_msg (1<<1) 574 #define flag_sem (1<<2) 575 #define flag_shm (1<<3) 576 577 opt = getopt32(argv, "i:aqsmtcplu", &opt_i); 578 if (opt & 0x1) { // -i 579 id = xatoi(opt_i); 580 flags |= flag_print; 581 } 582 if (opt & 0x2) flags |= flag_msg | flag_sem | flag_shm; // -a 583 if (opt & 0x4) flags |= flag_msg; // -q 584 if (opt & 0x8) flags |= flag_sem; // -s 585 if (opt & 0x10) flags |= flag_shm; // -m 586 if (opt & 0x20) format = TIME; // -t 587 if (opt & 0x40) format = CREATOR; // -c 588 if (opt & 0x80) format = PID; // -p 589 if (opt & 0x100) format = LIMITS; // -l 590 if (opt & 0x200) format = STATUS; // -u 591 592 if (flags & flag_print) { 593 if (flags & flag_shm) { 594 print_shm(id); 595 fflush_stdout_and_exit(0); 596 } 597 if (flags & flag_sem) { 598 print_sem(id); 599 fflush_stdout_and_exit(0); 600 } 601 if (flags & flag_msg) { 602 print_msg(id); 603 fflush_stdout_and_exit(0); 647 604 } 648 605 bb_show_usage(); 649 bb_fflush_stdout_and_exit (0); 650 } 651 652 if ( !shm && !msg && !sem) 653 msg = sem = shm = 1; 654 bb_printf ("\n"); 655 656 if (shm) { 657 do_shm (format); 658 bb_printf ("\n"); 659 } 660 if (sem) { 661 do_sem (format); 662 bb_printf ("\n"); 663 } 664 if (msg) { 665 do_msg (format); 666 bb_printf ("\n"); 667 } 668 return 0; 669 } 670 606 } 607 608 if (!(flags & (flag_shm | flag_msg | flag_sem))) 609 flags |= flag_msg | flag_shm | flag_sem; 610 puts(""); 611 612 if (flags & flag_shm) { 613 do_shm(); 614 puts(""); 615 } 616 if (flags & flag_sem) { 617 do_sem(); 618 puts(""); 619 } 620 if (flags & flag_msg) { 621 do_msg(); 622 puts(""); 623 } 624 fflush_stdout_and_exit(0); 625 } -
branches/stable/mindi-busybox/util-linux/losetup.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 3 * Mini losetup implementation for busybox … … 8 9 9 10 #include <getopt.h> 10 #include <stdlib.h>11 11 12 #include " busybox.h"12 #include "libbb.h" 13 13 14 int losetup_main (int argc, char **argv) 14 int losetup_main(int argc, char **argv); 15 int losetup_main(int argc, char **argv) 15 16 { 16 int offset = 0; 17 unsigned opt; 18 char *opt_o; 19 unsigned long long offset = 0; 17 20 18 /* This will need a "while(getopt()!=-1)" loop when we can have more than 19 one option, but for now we can't. */ 20 switch(getopt(argc,argv, "do:")) { 21 case 'd': 22 /* detach takes exactly one argument */ 23 if(optind+1!=argc) bb_show_usage(); 24 if(!del_loop(argv[optind])) return EXIT_SUCCESS; 25 die_failed: 26 bb_perror_msg_and_die("%s",argv[optind]); 21 opt = getopt32(argv, "do:", &opt_o); 22 argc -= optind; 23 argv += optind; 27 24 28 case 'o': 29 offset = bb_xparse_number (optarg, NULL); 30 /* Fall through to do the losetup */ 31 case -1: 32 /* losetup takes two argument:, loop_device and file */ 33 if(optind+2==argc) { 34 if(set_loop(&argv[optind], argv[optind + 1], offset)>=0) 35 return EXIT_SUCCESS; 36 else goto die_failed; 37 } 38 if(optind+1==argc) { 39 char *s=query_loop(argv[optind]); 40 if (!s) goto die_failed; 41 printf("%s: %s\n",argv[optind],s); 42 if(ENABLE_FEATURE_CLEAN_UP) free(s); 25 if (opt == 0x3) // -d + -o (illegal) 26 bb_show_usage(); 27 28 if (opt == 0x1) { // -d 29 /* detach takes exactly one argument */ 30 if (argc != 1) 31 bb_show_usage(); 32 if (!del_loop(argv[0])) 33 return EXIT_SUCCESS; 34 bb_perror_nomsg_and_die(); 35 } 36 37 if (opt == 0x2) // -o 38 offset = xatoull(opt_o); 39 40 /* -o or no option */ 41 42 if (argc == 2) { 43 if (set_loop(&argv[0], argv[1], offset) < 0) 44 bb_perror_nomsg_and_die(); 45 } else if (argc == 1) { 46 char *s = query_loop(argv[0]); 47 if (!s) 48 bb_perror_nomsg_and_die(); 49 printf("%s: %s\n", argv[0], s); 50 if (ENABLE_FEATURE_CLEAN_UP) 51 free(s); 52 } else { 53 char dev[sizeof(LOOP_NAME"0")] = LOOP_NAME"0"; 54 char c; 55 for (c = '0'; c <= '9'; ++c) { 56 char *s; 57 dev[sizeof(LOOP_NAME"0")-2] = c; 58 s = query_loop(dev); 59 if (s) { 60 printf("%s: %s\n", dev, s); 61 if (ENABLE_FEATURE_CLEAN_UP) 62 free(s); 63 } 64 } 65 } 43 66 return EXIT_SUCCESS; 44 }45 break;46 }47 bb_show_usage();48 return EXIT_FAILURE;49 67 } -
branches/stable/mindi-busybox/util-linux/mdev.c
r902 r1770 1 /* vi:set ts=4: 1 /* vi: set sw=4 ts=4: */ 2 /* 2 3 * 3 4 * mdev - Mini udev for busybox … … 6 7 * Copyright 2005 Frank Sorenson <frank@tuxrocks.com> 7 8 * 8 * Licensed under GPL v2 or later, see file LICENSE in this tarball for details.9 * Licensed under GPL version 2, see file LICENSE in this tarball for details. 9 10 */ 10 11 11 #include "busybox.h" 12 #include <ctype.h> 13 #include <errno.h> 14 #include <sys/mman.h> 15 #include <sys/sysmacros.h> 12 #include "libbb.h" 16 13 #include "xregex.h" 17 14 18 #define DEV_PATH "/dev" 19 20 struct mdev_globals 21 { 15 struct globals { 22 16 int root_major, root_minor; 23 } mdev_globals; 24 25 #define bbg mdev_globals 17 }; 18 #define G (*(struct globals*)&bb_common_bufsiz1) 19 #define root_major (G.root_major) 20 #define root_minor (G.root_minor) 21 22 #define MAX_SYSFS_DEPTH 3 /* prevent infinite loops in /sys symlinks */ 26 23 27 24 /* mknod in /dev based on a path like "/sys/block/hda/hda1" */ 28 25 static void make_device(char *path, int delete) 29 26 { 30 c har *device_name;31 int major, minor, type, len , fd;27 const char *device_name; 28 int major, minor, type, len; 32 29 int mode = 0660; 33 30 uid_t uid = 0; … … 43 40 if (!delete) { 44 41 strcat(path, "/dev"); 45 fd = open(path, O_RDONLY); 46 len = read(fd, temp + 1, 64); 42 len = open_read_close(path, temp + 1, 64); 47 43 *temp++ = 0; 48 close(fd);49 44 if (len < 1) return; 50 45 } … … 52 47 /* Determine device name, type, major and minor */ 53 48 54 device_name = strrchr(path, '/') + 1;49 device_name = bb_basename(path); 55 50 type = path[5]=='c' ? S_IFCHR : S_IFBLK; 56 51 … … 59 54 if (ENABLE_FEATURE_MDEV_CONF) { 60 55 char *conf, *pos, *end; 56 int line, fd; 61 57 62 58 /* mmap the config file */ 63 if (-1 != (fd=open("/etc/mdev.conf",O_RDONLY))) { 64 len = lseek(fd, 0, SEEK_END); 65 conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); 66 if (conf) { 67 int line = 0; 68 69 /* Loop through lines in mmaped file*/ 70 for (pos=conf; pos-conf<len;) { 71 int field; 72 char *end2; 73 74 line++; 75 /* find end of this line */ 76 for(end=pos; end-conf<len && *end!='\n'; end++) 59 fd = open("/etc/mdev.conf", O_RDONLY); 60 if (fd < 0) 61 goto end_parse; 62 len = xlseek(fd, 0, SEEK_END); 63 conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); 64 close(fd); 65 if (!conf) 66 goto end_parse; 67 68 line = 0; 69 /* Loop through lines in mmaped file*/ 70 for (pos=conf; pos-conf<len;) { 71 int field; 72 char *end2; 73 74 line++; 75 /* find end of this line */ 76 for (end=pos; end-conf<len && *end!='\n'; end++) 77 ; 78 79 /* Three fields: regex, uid:gid, mode */ 80 for (field=0; field < (3 + ENABLE_FEATURE_MDEV_EXEC); 81 field++) 82 { 83 /* Skip whitespace */ 84 while (pos<end && isspace(*pos)) pos++; 85 if (pos==end || *pos=='#') break; 86 for (end2=pos; 87 end2<end && !isspace(*end2) && *end2!='#'; end2++) 88 ; 89 90 if (field == 0) { 91 /* Regex to match this device */ 92 93 char *regex = xstrndup(pos, end2-pos); 94 regex_t match; 95 regmatch_t off; 96 int result; 97 98 /* Is this it? */ 99 xregcomp(&match,regex, REG_EXTENDED); 100 result = regexec(&match, device_name, 1, &off, 0); 101 regfree(&match); 102 free(regex); 103 104 /* If not this device, skip rest of line */ 105 if (result || off.rm_so 106 || off.rm_eo != strlen(device_name)) 107 break; 108 } 109 if (field == 1) { 110 /* uid:gid */ 111 112 char *s, *s2; 113 114 /* Find : */ 115 for (s=pos; s<end2 && *s!=':'; s++) 77 116 ; 78 79 /* Three fields: regex, uid:gid, mode */ 80 for (field=0; field < (3 + ENABLE_FEATURE_MDEV_EXEC); 81 field++) 82 { 83 /* Skip whitespace */ 84 while (pos<end && isspace(*pos)) pos++; 85 if (pos==end || *pos=='#') break; 86 for (end2=pos; 87 end2<end && !isspace(*end2) && *end2!='#'; end2++) 88 ; 89 90 if (!field) { 91 /* Regex to match this device */ 92 93 char *regex = strndupa(pos, end2-pos); 94 regex_t match; 95 regmatch_t off; 96 int result; 97 98 /* Is this it? */ 99 xregcomp(&match,regex, REG_EXTENDED); 100 result = regexec(&match, device_name, 1, &off, 0); 101 regfree(&match); 102 103 /* If not this device, skip rest of line */ 104 if (result || off.rm_so 105 || off.rm_eo != strlen(device_name)) 106 break; 107 108 } else if (field == 1) { 109 /* uid:gid */ 110 111 char *s, *s2; 112 113 /* Find : */ 114 for(s=pos; s<end2 && *s!=':'; s++) 115 ; 116 if (s == end2) break; 117 118 /* Parse UID */ 119 uid = strtoul(pos,&s2,10); 120 if (s != s2) { 121 struct passwd *pass; 122 pass = getpwnam(strndupa(pos, s-pos)); 123 if (!pass) break; 124 uid = pass->pw_uid; 125 } 126 s++; 127 /* parse GID */ 128 gid = strtoul(s, &s2, 10); 129 if (end2 != s2) { 130 struct group *grp; 131 grp = getgrnam(strndupa(s, end2-s)); 132 if (!grp) break; 133 gid = grp->gr_gid; 134 } 135 } else if (field == 2) { 136 /* mode */ 137 138 mode = strtoul(pos, &pos, 8); 139 if (pos != end2) break; 140 } else if (ENABLE_FEATURE_MDEV_EXEC && field == 3) { 141 // Command to run 142 char *s = "@$*", *s2; 143 if (!(s2 = strchr(s, *pos++))) { 144 // Force error 145 field = 1; 146 break; 147 } 148 if ((s2-s+1) & (1<<delete)) 149 command = bb_xstrndup(pos, end-pos); 150 } 151 152 pos = end2; 117 if (s == end2) break; 118 119 /* Parse UID */ 120 uid = strtoul(pos, &s2, 10); 121 if (s != s2) { 122 struct passwd *pass; 123 char *_unam = xstrndup(pos, s-pos); 124 pass = getpwnam(_unam); 125 free(_unam); 126 if (!pass) break; 127 uid = pass->pw_uid; 153 128 } 154 155 /* Did everything parse happily? */ 156 157 if (field > 2) break; 158 if (field) bb_error_msg_and_die("Bad line %d",line); 159 160 /* Next line */ 161 pos = ++end; 129 s++; 130 /* parse GID */ 131 gid = strtoul(s, &s2, 10); 132 if (end2 != s2) { 133 struct group *grp; 134 char *_grnam = xstrndup(s, end2-s); 135 grp = getgrnam(_grnam); 136 free(_grnam); 137 if (!grp) break; 138 gid = grp->gr_gid; 139 } 162 140 } 163 munmap(conf, len); 141 if (field == 2) { 142 /* mode */ 143 144 mode = strtoul(pos, &pos, 8); 145 if (pos != end2) break; 146 } 147 if (ENABLE_FEATURE_MDEV_EXEC && field == 3) { 148 // Command to run 149 const char *s = "@$*"; 150 const char *s2; 151 s2 = strchr(s, *pos++); 152 if (!s2) { 153 // Force error 154 field = 1; 155 break; 156 } 157 if ((s2-s+1) & (1<<delete)) 158 command = xstrndup(pos, end-pos); 159 } 160 161 pos = end2; 164 162 } 165 close(fd); 163 164 /* Did everything parse happily? */ 165 166 if (field > 2) break; 167 if (field) bb_error_msg_and_die("bad line %d",line); 168 169 /* Next line */ 170 pos = ++end; 166 171 } 172 munmap(conf, len); 173 end_parse: /* nothing */ ; 167 174 } 168 175 … … 171 178 if (sscanf(temp, "%d:%d", &major, &minor) != 2) return; 172 179 if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST) 173 bb_perror_msg_and_die("mknod %s failed", device_name);174 175 if (major == bbg.root_major && minor == bbg.root_minor)180 bb_perror_msg_and_die("mknod %s", device_name); 181 182 if (major == root_major && minor == root_minor) 176 183 symlink(device_name, "root"); 177 184 178 185 if (ENABLE_FEATURE_MDEV_CONF) chown(device_name, uid, gid); 179 186 } 180 187 if (command) { 181 int rc; 182 char *s; 183 184 s=bb_xasprintf("MDEV=%s",device_name); 188 /* setenv will leak memory, so use putenv */ 189 char *s = xasprintf("MDEV=%s", device_name); 185 190 putenv(s); 186 rc = system(command); 187 s[4]=0; 188 putenv(s); 191 if (system(command) == -1) 192 bb_perror_msg_and_die("cannot run %s", command); 193 s[4] = '\0'; 194 unsetenv(s); 189 195 free(s); 190 196 free(command); 191 if (rc == -1) bb_perror_msg_and_die("Couldn't run %s", command);192 197 } 193 198 if (delete) unlink(device_name); 194 199 } 195 200 196 /* Recursive search of /sys/block or /sys/class. path must be a writeable 197 * buffer of size PATH_MAX containing the directory string to start at. */ 198 199 static void find_dev(char *path) 200 { 201 DIR *dir; 202 size_t len = strlen(path); 203 struct dirent *entry; 204 205 if ((dir = opendir(path)) == NULL) 206 return; 207 208 while ((entry = readdir(dir)) != NULL) { 209 struct stat st; 210 211 /* Skip "." and ".." (also skips hidden files, which is ok) */ 212 213 if (entry->d_name[0] == '.') 214 continue; 215 216 // uClibc doesn't fill out entry->d_type reliably. so we use lstat(). 217 218 snprintf(path+len, PATH_MAX-len, "/%s", entry->d_name); 219 if (!lstat(path, &st) && S_ISDIR(st.st_mode)) find_dev(path); 220 path[len] = 0; 221 222 /* If there's a dev entry, mknod it */ 223 224 if (!strcmp(entry->d_name, "dev")) make_device(path, 0); 225 } 226 227 closedir(dir); 228 } 229 230 int mdev_main(int argc, char *argv[]) 201 /* File callback for /sys/ traversal */ 202 static int fileAction(const char *fileName, struct stat *statbuf, 203 void *userData, int depth) 204 { 205 size_t len = strlen(fileName) - 4; 206 char *scratch = userData; 207 208 if (strcmp(fileName + len, "/dev")) 209 return FALSE; 210 211 strcpy(scratch, fileName); 212 scratch[len] = 0; 213 make_device(scratch, 0); 214 215 return TRUE; 216 } 217 218 /* Directory callback for /sys/ traversal */ 219 static int dirAction(const char *fileName, struct stat *statbuf, 220 void *userData, int depth) 221 { 222 return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE); 223 } 224 225 /* For the full gory details, see linux/Documentation/firmware_class/README 226 * 227 * Firmware loading works like this: 228 * - kernel sets FIRMWARE env var 229 * - userspace checks /lib/firmware/$FIRMWARE 230 * - userspace waits for /sys/$DEVPATH/loading to appear 231 * - userspace writes "1" to /sys/$DEVPATH/loading 232 * - userspace copies /lib/firmware/$FIRMWARE into /sys/$DEVPATH/data 233 * - userspace writes "0" (worked) or "-1" (failed) to /sys/$DEVPATH/loading 234 * - kernel loads firmware into device 235 */ 236 static void load_firmware(const char *const firmware, const char *const sysfs_path) 237 { 238 int cnt; 239 int firmware_fd, loading_fd, data_fd; 240 241 /* check for $FIRMWARE from kernel */ 242 /* XXX: dont bother: open(NULL) works same as open("no-such-file") 243 * if (!firmware) 244 * return; 245 */ 246 247 /* check for /lib/firmware/$FIRMWARE */ 248 xchdir("/lib/firmware"); 249 firmware_fd = xopen(firmware, O_RDONLY); 250 251 /* in case we goto out ... */ 252 data_fd = -1; 253 254 /* check for /sys/$DEVPATH/loading ... give 30 seconds to appear */ 255 xchdir(sysfs_path); 256 for (cnt = 0; cnt < 30; ++cnt) { 257 loading_fd = open("loading", O_WRONLY); 258 if (loading_fd == -1) 259 sleep(1); 260 else 261 break; 262 } 263 if (loading_fd == -1) 264 goto out; 265 266 /* tell kernel we're loading by `echo 1 > /sys/$DEVPATH/loading` */ 267 if (write(loading_fd, "1", 1) != 1) 268 goto out; 269 270 /* load firmware by `cat /lib/firmware/$FIRMWARE > /sys/$DEVPATH/data */ 271 data_fd = open("data", O_WRONLY); 272 if (data_fd == -1) 273 goto out; 274 cnt = bb_copyfd_eof(firmware_fd, data_fd); 275 276 /* tell kernel result by `echo [0|-1] > /sys/$DEVPATH/loading` */ 277 if (cnt > 0) 278 write(loading_fd, "0", 1); 279 else 280 write(loading_fd, "-1", 2); 281 282 out: 283 if (ENABLE_FEATURE_CLEAN_UP) { 284 close(firmware_fd); 285 close(loading_fd); 286 close(data_fd); 287 } 288 } 289 290 int mdev_main(int argc, char **argv); 291 int mdev_main(int argc, char **argv) 231 292 { 232 293 char *action; … … 234 295 RESERVE_CONFIG_BUFFER(temp,PATH_MAX); 235 296 236 bb_xchdir(DEV_PATH);297 xchdir("/dev"); 237 298 238 299 /* Scan */ … … 241 302 struct stat st; 242 303 243 stat("/", &st); // If this fails, we have bigger problems. 244 bbg.root_major=major(st.st_dev); 245 bbg.root_minor=minor(st.st_dev); 246 strcpy(temp,"/sys/block"); 247 find_dev(temp); 248 strcpy(temp,"/sys/class"); 249 find_dev(temp); 304 xstat("/", &st); 305 root_major = major(st.st_dev); 306 root_minor = minor(st.st_dev); 307 308 recursive_action("/sys/block", 309 ACTION_RECURSE | ACTION_FOLLOWLINKS, 310 fileAction, dirAction, temp, 0); 311 312 recursive_action("/sys/class", 313 ACTION_RECURSE | ACTION_FOLLOWLINKS, 314 fileAction, dirAction, temp, 0); 250 315 251 316 /* Hotplug */ … … 254 319 action = getenv("ACTION"); 255 320 env_path = getenv("DEVPATH"); 256 321 if (!action || !env_path) 257 322 bb_show_usage(); 258 323 259 324 sprintf(temp, "/sys%s", env_path); 260 if (!strcmp(action, "add")) make_device(temp,0); 261 else if (!strcmp(action, "remove")) make_device(temp,1); 325 if (!strcmp(action, "remove")) 326 make_device(temp, 1); 327 else if (!strcmp(action, "add")) { 328 make_device(temp, 0); 329 330 if (ENABLE_FEATURE_MDEV_LOAD_FIRMWARE) 331 load_firmware(getenv("FIRMWARE"), temp); 332 } 262 333 } 263 334 -
branches/stable/mindi-busybox/util-linux/mkfs_minix.c
r821 r1770 34 34 * (Dr. Wettstein, greg%wind.uucp@plains.nodak.edu) 35 35 * 36 * 30.10.94 -added support for v2 filesystem37 * (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de)36 * 30.10.94 - added support for v2 filesystem 37 * (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de) 38 38 * 39 39 * 09.11.94 - Added test to prevent overwrite of mounted fs adapted … … 63 63 */ 64 64 65 #include <stdio.h> 66 #include <time.h> 67 #include <unistd.h> 68 #include <string.h> 69 #include <signal.h> 70 #include <fcntl.h> 71 #include <ctype.h> 72 #include <stdlib.h> 73 #include <stdint.h> 74 #include <termios.h> 75 #include <sys/ioctl.h> 76 #include <sys/param.h> 65 #include "libbb.h" 77 66 #include <mntent.h> 78 #include "busybox.h" 79 80 #define MINIX_ROOT_INO 1 81 #define MINIX_LINK_MAX 250 82 #define MINIX2_LINK_MAX 65530 83 84 #define MINIX_I_MAP_SLOTS 8 85 #define MINIX_Z_MAP_SLOTS 64 86 #define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ 87 #define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ 88 #define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */ 89 #define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */ 90 #define MINIX_VALID_FS 0x0001 /* Clean fs. */ 91 #define MINIX_ERROR_FS 0x0002 /* fs has errors. */ 92 93 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode))) 94 #define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode))) 95 96 #define MINIX_V1 0x0001 /* original minix fs */ 97 #define MINIX_V2 0x0002 /* minix V2 fs */ 98 99 #define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version 100 101 /* 102 * This is the original minix inode layout on disk. 103 * Note the 8-bit gid and atime and ctime. 104 */ 105 struct minix_inode { 106 uint16_t i_mode; 107 uint16_t i_uid; 108 uint32_t i_size; 109 uint32_t i_time; 110 uint8_t i_gid; 111 uint8_t i_nlinks; 112 uint16_t i_zone[9]; 67 68 #include "minix.h" 69 70 #define DEBUG 0 71 72 /* If debugging, store the very same times/uids/gids for image consistency */ 73 #if DEBUG 74 # define CUR_TIME 0 75 # define GETUID 0 76 # define GETGID 0 77 #else 78 # define CUR_TIME time(NULL) 79 # define GETUID getuid() 80 # define GETGID getgid() 81 #endif 82 83 enum { 84 MAX_GOOD_BLOCKS = 512, 85 TEST_BUFFER_BLOCKS = 16, 113 86 }; 114 87 115 /* 116 * The new minix inode has all the time entries, as well as 117 * long block numbers and a third indirect block (7+1+1+1 118 * instead of 7+1+1). Also, some previously 8-bit values are 119 * now 16-bit. The inode is now 64 bytes instead of 32. 120 */ 121 struct minix2_inode { 122 uint16_t i_mode; 123 uint16_t i_nlinks; 124 uint16_t i_uid; 125 uint16_t i_gid; 126 uint32_t i_size; 127 uint32_t i_atime; 128 uint32_t i_mtime; 129 uint32_t i_ctime; 130 uint32_t i_zone[10]; 88 #if !ENABLE_FEATURE_MINIX2 89 enum { version2 = 0 }; 90 #endif 91 92 struct globals { 93 int dev_fd; 94 95 #if ENABLE_FEATURE_MINIX2 96 smallint version2; 97 #define version2 G.version2 98 #endif 99 char *device_name; 100 uint32_t total_blocks; 101 int badblocks; 102 int namelen; 103 int dirsize; 104 int magic; 105 char *inode_buffer; 106 char *inode_map; 107 char *zone_map; 108 int used_good_blocks; 109 unsigned long req_nr_inodes; 110 unsigned currently_testing; 111 112 113 char root_block[BLOCK_SIZE]; 114 char super_block_buffer[BLOCK_SIZE]; 115 char boot_block_buffer[512]; 116 unsigned short good_blocks_table[MAX_GOOD_BLOCKS]; 117 /* check_blocks(): buffer[] was the biggest static in entire bbox */ 118 char check_blocks_buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS]; 131 119 }; 132 120 133 /* 134 * minix super-block data on disk 135 */ 136 struct minix_super_block { 137 uint16_t s_ninodes; 138 uint16_t s_nzones; 139 uint16_t s_imap_blocks; 140 uint16_t s_zmap_blocks; 141 uint16_t s_firstdatazone; 142 uint16_t s_log_zone_size; 143 uint32_t s_max_size; 144 uint16_t s_magic; 145 uint16_t s_state; 146 uint32_t s_zones; 147 }; 148 149 struct minix_dir_entry { 150 uint16_t inode; 151 char name[0]; 152 }; 153 154 #define NAME_MAX 255 /* # chars in a file name */ 155 156 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode))) 157 158 #define MINIX_VALID_FS 0x0001 /* Clean fs. */ 159 #define MINIX_ERROR_FS 0x0002 /* fs has errors. */ 160 161 #define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ 162 #define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ 121 #define G (*ptr_to_globals) 122 123 static ALWAYS_INLINE unsigned div_roundup(unsigned size, unsigned n) 124 { 125 return (size + n-1) / n; 126 } 127 128 #define INODE_BUF1 (((struct minix1_inode*)G.inode_buffer) - 1) 129 #define INODE_BUF2 (((struct minix2_inode*)G.inode_buffer) - 1) 130 131 #define SB (*(struct minix_super_block*)G.super_block_buffer) 132 133 #define SB_INODES (SB.s_ninodes) 134 #define SB_IMAPS (SB.s_imap_blocks) 135 #define SB_ZMAPS (SB.s_zmap_blocks) 136 #define SB_FIRSTZONE (SB.s_firstdatazone) 137 #define SB_ZONE_SIZE (SB.s_log_zone_size) 138 #define SB_MAXSIZE (SB.s_max_size) 139 #define SB_MAGIC (SB.s_magic) 140 141 #if !ENABLE_FEATURE_MINIX2 142 # define SB_ZONES (SB.s_nzones) 143 # define INODE_BLOCKS div_roundup(SB_INODES, MINIX1_INODES_PER_BLOCK) 144 #else 145 # define SB_ZONES (version2 ? SB.s_zones : SB.s_nzones) 146 # define INODE_BLOCKS div_roundup(SB_INODES, \ 147 version2 ? MINIX2_INODES_PER_BLOCK : MINIX1_INODES_PER_BLOCK) 148 #endif 149 150 #define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE) 151 #define NORM_FIRSTZONE (2 + SB_IMAPS + SB_ZMAPS + INODE_BLOCKS) 152 153 /* Before you ask "where they come from?": */ 154 /* setbit/clrbit are supplied by sys/param.h */ 155 156 static int minix_bit(const char* a, unsigned i) 157 { 158 return a[i >> 3] & (1<<(i & 7)); 159 } 160 161 static void minix_setbit(char *a, unsigned i) 162 { 163 setbit(a, i); 164 } 165 static void minix_clrbit(char *a, unsigned i) 166 { 167 clrbit(a, i); 168 } 169 170 /* Note: do not assume 0/1, it is 0/nonzero */ 171 #define zone_in_use(x) minix_bit(G.zone_map,(x)-SB_FIRSTZONE+1) 172 /*#define inode_in_use(x) minix_bit(G.inode_map,(x))*/ 173 174 #define mark_inode(x) minix_setbit(G.inode_map,(x)) 175 #define unmark_inode(x) minix_clrbit(G.inode_map,(x)) 176 #define mark_zone(x) minix_setbit(G.zone_map,(x)-SB_FIRSTZONE+1) 177 #define unmark_zone(x) minix_clrbit(G.zone_map,(x)-SB_FIRSTZONE+1) 163 178 164 179 #ifndef BLKGETSIZE 165 #define BLKGETSIZE _IO(0x12,96) /* return device size */ 166 #endif 167 168 169 #ifndef __linux__ 170 #define volatile 171 #endif 172 173 #define MINIX_ROOT_INO 1 174 #define MINIX_BAD_INO 2 175 176 #define TEST_BUFFER_BLOCKS 16 177 #define MAX_GOOD_BLOCKS 512 178 179 #define UPPER(size,n) (((size)+((n)-1))/(n)) 180 #define INODE_SIZE (sizeof(struct minix_inode)) 181 #ifdef CONFIG_FEATURE_MINIX2 182 #define INODE_SIZE2 (sizeof(struct minix2_inode)) 183 #define INODE_BLOCKS UPPER(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \ 184 : MINIX_INODES_PER_BLOCK)) 185 #else 186 #define INODE_BLOCKS UPPER(INODES, (MINIX_INODES_PER_BLOCK)) 187 #endif 188 #define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE) 189 190 #define BITS_PER_BLOCK (BLOCK_SIZE<<3) 191 192 static char *device_name; 193 static int DEV = -1; 194 static uint32_t BLOCKS; 195 static int check; 196 static int badblocks; 197 static int namelen = 30; /* default (changed to 30, per Linus's 198 199 suggestion, Sun Nov 21 08:05:07 1993) */ 200 static int dirsize = 32; 201 static int magic = MINIX_SUPER_MAGIC2; 202 static int version2; 203 204 static char root_block[BLOCK_SIZE]; 205 206 static char *inode_buffer; 207 208 #define Inode (((struct minix_inode *) inode_buffer)-1) 209 #ifdef CONFIG_FEATURE_MINIX2 210 #define Inode2 (((struct minix2_inode *) inode_buffer)-1) 211 #endif 212 static char super_block_buffer[BLOCK_SIZE]; 213 static char boot_block_buffer[512]; 214 215 #define Super (*(struct minix_super_block *)super_block_buffer) 216 #define INODES (Super.s_ninodes) 217 #ifdef CONFIG_FEATURE_MINIX2 218 #define ZONES (version2 ? Super.s_zones : Super.s_nzones) 219 #else 220 #define ZONES (Super.s_nzones) 221 #endif 222 #define IMAPS (Super.s_imap_blocks) 223 #define ZMAPS (Super.s_zmap_blocks) 224 #define FIRSTZONE (Super.s_firstdatazone) 225 #define ZONESIZE (Super.s_log_zone_size) 226 #define MAXSIZE (Super.s_max_size) 227 #define MAGIC (Super.s_magic) 228 #define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS) 229 230 static char *inode_map; 231 static char *zone_map; 232 233 static unsigned short good_blocks_table[MAX_GOOD_BLOCKS]; 234 static int used_good_blocks; 235 static unsigned long req_nr_inodes; 236 237 static inline int bit(char * a,unsigned int i) 238 { 239 return (a[i >> 3] & (1<<(i & 7))) != 0; 240 } 241 #define inode_in_use(x) (bit(inode_map,(x))) 242 #define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1)) 243 244 #define mark_inode(x) (setbit(inode_map,(x))) 245 #define unmark_inode(x) (clrbit(inode_map,(x))) 246 247 #define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1)) 248 #define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1)) 249 250 /* 251 * Check to make certain that our new filesystem won't be created on 252 * an already mounted partition. Code adapted from mke2fs, Copyright 253 * (C) 1994 Theodore Ts'o. Also licensed under GPL. 254 */ 255 static inline void check_mount(void) 256 { 257 FILE *f; 258 struct mntent *mnt; 259 260 if ((f = setmntent(MOUNTED, "r")) == NULL) 261 return; 262 while ((mnt = getmntent(f)) != NULL) 263 if (strcmp(device_name, mnt->mnt_fsname) == 0) 264 break; 265 endmntent(f); 266 if (!mnt) 267 return; 268 269 bb_error_msg_and_die("%s is mounted; will not make a filesystem here!", device_name); 270 } 180 # define BLKGETSIZE _IO(0x12,96) /* return device size */ 181 #endif 182 271 183 272 184 static long valid_offset(int fd, int offset) … … 274 186 char ch; 275 187 276 if (lseek(fd, offset, 0) < 0)188 if (lseek(fd, offset, SEEK_SET) < 0) 277 189 return 0; 278 190 if (read(fd, &ch, 1) < 1) … … 281 193 } 282 194 283 static in line int count_blocks(int fd)195 static int count_blocks(int fd) 284 196 { 285 197 int high, low; … … 288 200 for (high = 1; valid_offset(fd, high); high *= 2) 289 201 low = high; 202 290 203 while (low < high - 1) { 291 204 const int mid = (low + high) / 2; … … 300 213 } 301 214 302 static in line int get_size(const char *file)215 static int get_size(const char *file) 303 216 { 304 217 int fd; 305 218 long size; 306 219 307 fd = bb_xopen3(file, O_RDWR, 0);220 fd = xopen(file, O_RDWR); 308 221 if (ioctl(fd, BLKGETSIZE, &size) >= 0) { 309 222 close(fd); … … 316 229 } 317 230 318 static inlinevoid write_tables(void)231 static void write_tables(void) 319 232 { 320 233 /* Mark the super block valid. */ 321 Super.s_state |= MINIX_VALID_FS; 322 Super.s_state &= ~MINIX_ERROR_FS; 323 324 if (lseek(DEV, 0, SEEK_SET)) 325 bb_error_msg_and_die("seek to boot block failed in write_tables"); 326 if (512 != write(DEV, boot_block_buffer, 512)) 327 bb_error_msg_and_die("unable to clear boot sector"); 328 if (BLOCK_SIZE != lseek(DEV, BLOCK_SIZE, SEEK_SET)) 329 bb_error_msg_and_die("seek failed in write_tables"); 330 if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE)) 331 bb_error_msg_and_die("unable to write super-block"); 332 if (IMAPS * BLOCK_SIZE != write(DEV, inode_map, IMAPS * BLOCK_SIZE)) 333 bb_error_msg_and_die("unable to write inode map"); 334 if (ZMAPS * BLOCK_SIZE != write(DEV, zone_map, ZMAPS * BLOCK_SIZE)) 335 bb_error_msg_and_die("unable to write zone map"); 336 if (INODE_BUFFER_SIZE != write(DEV, inode_buffer, INODE_BUFFER_SIZE)) 337 bb_error_msg_and_die("unable to write inodes"); 338 234 SB.s_state |= MINIX_VALID_FS; 235 SB.s_state &= ~MINIX_ERROR_FS; 236 237 msg_eol = "seek to 0 failed"; 238 xlseek(G.dev_fd, 0, SEEK_SET); 239 240 msg_eol = "cannot clear boot sector"; 241 xwrite(G.dev_fd, G.boot_block_buffer, 512); 242 243 msg_eol = "seek to BLOCK_SIZE failed"; 244 xlseek(G.dev_fd, BLOCK_SIZE, SEEK_SET); 245 246 msg_eol = "cannot write superblock"; 247 xwrite(G.dev_fd, G.super_block_buffer, BLOCK_SIZE); 248 249 msg_eol = "cannot write inode map"; 250 xwrite(G.dev_fd, G.inode_map, SB_IMAPS * BLOCK_SIZE); 251 252 msg_eol = "cannot write zone map"; 253 xwrite(G.dev_fd, G.zone_map, SB_ZMAPS * BLOCK_SIZE); 254 255 msg_eol = "cannot write inodes"; 256 xwrite(G.dev_fd, G.inode_buffer, INODE_BUFFER_SIZE); 257 258 msg_eol = "\n"; 339 259 } 340 260 341 261 static void write_block(int blk, char *buffer) 342 262 { 343 if (blk * BLOCK_SIZE != lseek(DEV, blk * BLOCK_SIZE, SEEK_SET)) 344 bb_error_msg_and_die("seek failed in write_block"); 345 if (BLOCK_SIZE != write(DEV, buffer, BLOCK_SIZE)) 346 bb_error_msg_and_die("write failed in write_block"); 263 xlseek(G.dev_fd, blk * BLOCK_SIZE, SEEK_SET); 264 xwrite(G.dev_fd, buffer, BLOCK_SIZE); 347 265 } 348 266 … … 351 269 int blk; 352 270 353 if ( used_good_blocks + 1 >= MAX_GOOD_BLOCKS)271 if (G.used_good_blocks + 1 >= MAX_GOOD_BLOCKS) 354 272 bb_error_msg_and_die("too many bad blocks"); 355 if ( used_good_blocks)356 blk = good_blocks_table[used_good_blocks - 1] + 1;273 if (G.used_good_blocks) 274 blk = G.good_blocks_table[G.used_good_blocks - 1] + 1; 357 275 else 358 blk = FIRSTZONE;359 while (blk < ZONES && zone_in_use(blk))276 blk = SB_FIRSTZONE; 277 while (blk < SB_ZONES && zone_in_use(blk)) 360 278 blk++; 361 if (blk >= ZONES)279 if (blk >= SB_ZONES) 362 280 bb_error_msg_and_die("not enough good blocks"); 363 good_blocks_table[used_good_blocks] = blk;364 used_good_blocks++;281 G.good_blocks_table[G.used_good_blocks] = blk; 282 G.used_good_blocks++; 365 283 return blk; 366 284 } 367 285 368 static inlinevoid mark_good_blocks(void)286 static void mark_good_blocks(void) 369 287 { 370 288 int blk; 371 289 372 for (blk = 0; blk < used_good_blocks; blk++)373 mark_zone( good_blocks_table[blk]);290 for (blk = 0; blk < G.used_good_blocks; blk++) 291 mark_zone(G.good_blocks_table[blk]); 374 292 } 375 293 … … 377 295 { 378 296 if (!zone) 379 zone = FIRSTZONE - 1;380 while (++zone < ZONES)297 zone = SB_FIRSTZONE - 1; 298 while (++zone < SB_ZONES) 381 299 if (zone_in_use(zone)) 382 300 return zone; … … 384 302 } 385 303 386 static inlinevoid make_bad_inode(void)387 { 388 struct minix _inode *inode = &Inode[MINIX_BAD_INO];304 static void make_bad_inode(void) 305 { 306 struct minix1_inode *inode = &INODE_BUF1[MINIX_BAD_INO]; 389 307 int i, j, zone; 390 308 int ind = 0, dind = 0; … … 394 312 #define NEXT_BAD (zone = next(zone)) 395 313 396 if (! badblocks)314 if (!G.badblocks) 397 315 return; 398 316 mark_inode(MINIX_BAD_INO); 399 317 inode->i_nlinks = 1; 400 inode->i_time = time(NULL); 318 /* BTW, setting this makes all images different */ 319 /* it's harder to check for bugs then - diff isn't helpful :(... */ 320 inode->i_time = CUR_TIME; 401 321 inode->i_mode = S_IFREG + 0000; 402 inode->i_size = badblocks * BLOCK_SIZE;322 inode->i_size = G.badblocks * BLOCK_SIZE; 403 323 zone = next(0); 404 324 for (i = 0; i < 7; i++) { … … 427 347 } 428 348 bb_error_msg_and_die("too many bad blocks"); 429 349 end_bad: 430 350 if (ind) 431 351 write_block(ind, (char *) ind_block); … … 434 354 } 435 355 436 #if def CONFIG_FEATURE_MINIX2437 static inlinevoid make_bad_inode2(void)438 { 439 struct minix2_inode *inode = &I node2[MINIX_BAD_INO];356 #if ENABLE_FEATURE_MINIX2 357 static void make_bad_inode2(void) 358 { 359 struct minix2_inode *inode = &INODE_BUF2[MINIX_BAD_INO]; 440 360 int i, j, zone; 441 361 int ind = 0, dind = 0; … … 443 363 unsigned long dind_block[BLOCK_SIZE >> 2]; 444 364 445 if (! badblocks)365 if (!G.badblocks) 446 366 return; 447 367 mark_inode(MINIX_BAD_INO); 448 368 inode->i_nlinks = 1; 449 inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL);369 inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME; 450 370 inode->i_mode = S_IFREG + 0000; 451 inode->i_size = badblocks * BLOCK_SIZE;371 inode->i_size = G.badblocks * BLOCK_SIZE; 452 372 zone = next(0); 453 373 for (i = 0; i < 7; i++) { … … 477 397 /* Could make triple indirect block here */ 478 398 bb_error_msg_and_die("too many bad blocks"); 479 399 end_bad: 480 400 if (ind) 481 401 write_block(ind, (char *) ind_block); … … 483 403 write_block(dind, (char *) dind_block); 484 404 } 485 #endif 486 487 static inline void make_root_inode(void) 488 { 489 struct minix_inode *inode = &Inode[MINIX_ROOT_INO]; 405 #else 406 void make_bad_inode2(void); 407 #endif 408 409 static void make_root_inode(void) 410 { 411 struct minix1_inode *inode = &INODE_BUF1[MINIX_ROOT_INO]; 490 412 491 413 mark_inode(MINIX_ROOT_INO); 492 414 inode->i_zone[0] = get_free_block(); 493 415 inode->i_nlinks = 2; 494 inode->i_time = time(NULL);495 if ( badblocks)496 inode->i_size = 3 * dirsize;416 inode->i_time = CUR_TIME; 417 if (G.badblocks) 418 inode->i_size = 3 * G.dirsize; 497 419 else { 498 root_block[2 *dirsize] = '\0';499 root_block[2 *dirsize + 1] = '\0';500 inode->i_size = 2 * dirsize;420 G.root_block[2 * G.dirsize] = '\0'; 421 G.root_block[2 * G.dirsize + 1] = '\0'; 422 inode->i_size = 2 * G.dirsize; 501 423 } 502 424 inode->i_mode = S_IFDIR + 0755; 503 inode->i_uid = getuid();425 inode->i_uid = GETUID; 504 426 if (inode->i_uid) 505 inode->i_gid = getgid();506 write_block(inode->i_zone[0], root_block);507 } 508 509 #if def CONFIG_FEATURE_MINIX2510 static inlinevoid make_root_inode2(void)511 { 512 struct minix2_inode *inode = &I node2[MINIX_ROOT_INO];427 inode->i_gid = GETGID; 428 write_block(inode->i_zone[0], G.root_block); 429 } 430 431 #if ENABLE_FEATURE_MINIX2 432 static void make_root_inode2(void) 433 { 434 struct minix2_inode *inode = &INODE_BUF2[MINIX_ROOT_INO]; 513 435 514 436 mark_inode(MINIX_ROOT_INO); 515 437 inode->i_zone[0] = get_free_block(); 516 438 inode->i_nlinks = 2; 517 inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL);518 if ( badblocks)519 inode->i_size = 3 * dirsize;439 inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME; 440 if (G.badblocks) 441 inode->i_size = 3 * G.dirsize; 520 442 else { 521 root_block[2 *dirsize] = '\0';522 root_block[2 *dirsize + 1] = '\0';523 inode->i_size = 2 * dirsize;443 G.root_block[2 * G.dirsize] = '\0'; 444 G.root_block[2 * G.dirsize + 1] = '\0'; 445 inode->i_size = 2 * G.dirsize; 524 446 } 525 447 inode->i_mode = S_IFDIR + 0755; 526 inode->i_uid = getuid();448 inode->i_uid = GETUID; 527 449 if (inode->i_uid) 528 inode->i_gid = getgid(); 529 write_block(inode->i_zone[0], root_block); 530 } 531 #endif 532 533 static inline void setup_tables(void) 534 { 535 int i; 450 inode->i_gid = GETGID; 451 write_block(inode->i_zone[0], G.root_block); 452 } 453 #else 454 void make_root_inode2(void); 455 #endif 456 457 /* 458 * Perform a test of a block; return the number of 459 * blocks readable. 460 */ 461 static size_t do_check(char *buffer, size_t try, unsigned current_block) 462 { 463 ssize_t got; 464 465 /* Seek to the correct loc. */ 466 msg_eol = "seek failed during testing of blocks"; 467 xlseek(G.dev_fd, current_block * BLOCK_SIZE, SEEK_SET); 468 msg_eol = "\n"; 469 470 /* Try the read */ 471 got = read(G.dev_fd, buffer, try * BLOCK_SIZE); 472 if (got < 0) 473 got = 0; 474 try = ((size_t)got) / BLOCK_SIZE; 475 476 if (got & (BLOCK_SIZE - 1)) 477 fprintf(stderr, "Short read at block %u\n", (unsigned)(current_block + try)); 478 return try; 479 } 480 481 static void alarm_intr(int alnum) 482 { 483 if (G.currently_testing >= SB_ZONES) 484 return; 485 signal(SIGALRM, alarm_intr); 486 alarm(5); 487 if (!G.currently_testing) 488 return; 489 printf("%d ...", G.currently_testing); 490 fflush(stdout); 491 } 492 493 static void check_blocks(void) 494 { 495 size_t try, got; 496 497 G.currently_testing = 0; 498 signal(SIGALRM, alarm_intr); 499 alarm(5); 500 while (G.currently_testing < SB_ZONES) { 501 msg_eol = "seek failed in check_blocks"; 502 xlseek(G.dev_fd, G.currently_testing * BLOCK_SIZE, SEEK_SET); 503 msg_eol = "\n"; 504 try = TEST_BUFFER_BLOCKS; 505 if (G.currently_testing + try > SB_ZONES) 506 try = SB_ZONES - G.currently_testing; 507 got = do_check(G.check_blocks_buffer, try, G.currently_testing); 508 G.currently_testing += got; 509 if (got == try) 510 continue; 511 if (G.currently_testing < SB_FIRSTZONE) 512 bb_error_msg_and_die("bad blocks before data-area: cannot make fs"); 513 mark_zone(G.currently_testing); 514 G.badblocks++; 515 G.currently_testing++; 516 } 517 alarm(0); 518 printf("%d bad block(s)\n", G.badblocks); 519 } 520 521 static void get_list_blocks(char *filename) 522 { 523 FILE *listfile; 524 unsigned long blockno; 525 526 listfile = xfopen(filename, "r"); 527 while (!feof(listfile)) { 528 fscanf(listfile, "%ld\n", &blockno); 529 mark_zone(blockno); 530 G.badblocks++; 531 } 532 printf("%d bad block(s)\n", G.badblocks); 533 } 534 535 static void setup_tables(void) 536 { 536 537 unsigned long inodes; 537 538 memset(super_block_buffer, 0, BLOCK_SIZE); 539 memset(boot_block_buffer, 0, 512); 540 MAGIC = magic; 541 ZONESIZE = 0; 542 MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024; 543 #ifdef CONFIG_FEATURE_MINIX2 544 if (version2) { 545 Super.s_zones = BLOCKS; 546 } else 547 #endif 548 Super.s_nzones = BLOCKS; 549 550 /* some magic nrs: 1 inode / 3 blocks */ 551 if (req_nr_inodes == 0) 552 inodes = BLOCKS / 3; 538 unsigned norm_firstzone; 539 unsigned sb_zmaps; 540 unsigned i; 541 542 /* memset(G.super_block_buffer, 0, BLOCK_SIZE); */ 543 /* memset(G.boot_block_buffer, 0, 512); */ 544 SB_MAGIC = G.magic; 545 SB_ZONE_SIZE = 0; 546 SB_MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024; 547 if (version2) 548 SB.s_zones = G.total_blocks; 553 549 else 554 inodes = req_nr_inodes; 550 SB.s_nzones = G.total_blocks; 551 552 /* some magic nrs: 1 inode / 3 blocks */ 553 if (G.req_nr_inodes == 0) 554 inodes = G.total_blocks / 3; 555 else 556 inodes = G.req_nr_inodes; 555 557 /* Round up inode count to fill block size */ 556 #ifdef CONFIG_FEATURE_MINIX2557 558 if (version2) 558 inodes = ( (inodes + MINIX2_INODES_PER_BLOCK - 1) &559 ~(MINIX2_INODES_PER_BLOCK - 1));559 inodes = (inodes + MINIX2_INODES_PER_BLOCK - 1) & 560 ~(MINIX2_INODES_PER_BLOCK - 1); 560 561 else 561 #endif 562 inodes = ((inodes + MINIX_INODES_PER_BLOCK - 1) & 563 ~(MINIX_INODES_PER_BLOCK - 1)); 562 inodes = (inodes + MINIX1_INODES_PER_BLOCK - 1) & 563 ~(MINIX1_INODES_PER_BLOCK - 1); 564 564 if (inodes > 65535) 565 565 inodes = 65535; 566 INODES = inodes; 567 IMAPS = UPPER(INODES + 1, BITS_PER_BLOCK); 568 ZMAPS = 0; 569 i = 0; 570 while (ZMAPS != 571 UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1, 572 BITS_PER_BLOCK) && i < 1000) { 573 ZMAPS = 574 UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1, 575 BITS_PER_BLOCK); 576 i++; 577 } 566 SB_INODES = inodes; 567 SB_IMAPS = div_roundup(SB_INODES + 1, BITS_PER_BLOCK); 568 578 569 /* Real bad hack but overwise mkfs.minix can be thrown 579 570 * in infinite loop... 580 571 * try: 581 572 * dd if=/dev/zero of=test.fs count=10 bs=1024 582 * /sbin/mkfs.minix -i 200 test.fs 583 * */ 584 if (i >= 999) { 585 bb_error_msg_and_die("unable to allocate buffers for maps"); 586 } 587 FIRSTZONE = NORM_FIRSTZONE; 588 inode_map = xmalloc(IMAPS * BLOCK_SIZE); 589 zone_map = xmalloc(ZMAPS * BLOCK_SIZE); 590 memset(inode_map, 0xff, IMAPS * BLOCK_SIZE); 591 memset(zone_map, 0xff, ZMAPS * BLOCK_SIZE); 592 for (i = FIRSTZONE; i < ZONES; i++) 573 * mkfs.minix -i 200 test.fs 574 */ 575 /* This code is not insane: NORM_FIRSTZONE is not a constant, 576 * it is calculated from SB_INODES, SB_IMAPS and SB_ZMAPS */ 577 i = 999; 578 SB_ZMAPS = 0; 579 do { 580 norm_firstzone = NORM_FIRSTZONE; 581 sb_zmaps = div_roundup(G.total_blocks - norm_firstzone + 1, BITS_PER_BLOCK); 582 if (SB_ZMAPS == sb_zmaps) goto got_it; 583 SB_ZMAPS = sb_zmaps; 584 /* new SB_ZMAPS, need to recalc NORM_FIRSTZONE */ 585 } while (--i); 586 bb_error_msg_and_die("incompatible size/inode count, try different -i N"); 587 got_it: 588 589 SB_FIRSTZONE = norm_firstzone; 590 G.inode_map = xmalloc(SB_IMAPS * BLOCK_SIZE); 591 G.zone_map = xmalloc(SB_ZMAPS * BLOCK_SIZE); 592 memset(G.inode_map, 0xff, SB_IMAPS * BLOCK_SIZE); 593 memset(G.zone_map, 0xff, SB_ZMAPS * BLOCK_SIZE); 594 for (i = SB_FIRSTZONE; i < SB_ZONES; i++) 593 595 unmark_zone(i); 594 for (i = MINIX_ROOT_INO; i <= INODES; i++)596 for (i = MINIX_ROOT_INO; i <= SB_INODES; i++) 595 597 unmark_inode(i); 596 inode_buffer = xmalloc(INODE_BUFFER_SIZE); 597 memset(inode_buffer, 0, INODE_BUFFER_SIZE); 598 printf("%ld inodes\n", (long)INODES); 599 printf("%ld blocks\n", (long)ZONES); 600 printf("Firstdatazone=%ld (%ld)\n", (long)FIRSTZONE, (long)NORM_FIRSTZONE); 601 printf("Zonesize=%d\n", BLOCK_SIZE << ZONESIZE); 602 printf("Maxsize=%ld\n\n", (long)MAXSIZE); 603 } 604 605 /* 606 * Perform a test of a block; return the number of 607 * blocks readable/writable. 608 */ 609 static inline long do_check(char *buffer, int try, unsigned int current_block) 610 { 611 long got; 612 613 /* Seek to the correct loc. */ 614 if (lseek(DEV, current_block * BLOCK_SIZE, SEEK_SET) != 615 current_block * BLOCK_SIZE) { 616 bb_error_msg_and_die("seek failed during testing of blocks"); 617 } 618 619 620 /* Try the read */ 621 got = read(DEV, buffer, try * BLOCK_SIZE); 622 if (got < 0) 623 got = 0; 624 if (got & (BLOCK_SIZE - 1)) { 625 printf("Weird values in do_check: probably bugs\n"); 626 } 627 got /= BLOCK_SIZE; 628 return got; 629 } 630 631 static unsigned int currently_testing; 632 633 static void alarm_intr(int alnum) 634 { 635 if (currently_testing >= ZONES) 636 return; 637 signal(SIGALRM, alarm_intr); 638 alarm(5); 639 if (!currently_testing) 640 return; 641 printf("%d ...", currently_testing); 642 fflush(stdout); 643 } 644 645 static void check_blocks(void) 646 { 647 int try, got; 648 static char buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS]; 649 650 currently_testing = 0; 651 signal(SIGALRM, alarm_intr); 652 alarm(5); 653 while (currently_testing < ZONES) { 654 if (lseek(DEV, currently_testing * BLOCK_SIZE, SEEK_SET) != 655 currently_testing * BLOCK_SIZE) 656 bb_error_msg_and_die("seek failed in check_blocks"); 657 try = TEST_BUFFER_BLOCKS; 658 if (currently_testing + try > ZONES) 659 try = ZONES - currently_testing; 660 got = do_check(buffer, try, currently_testing); 661 currently_testing += got; 662 if (got == try) 663 continue; 664 if (currently_testing < FIRSTZONE) 665 bb_error_msg_and_die("bad blocks before data-area: cannot make fs"); 666 mark_zone(currently_testing); 667 badblocks++; 668 currently_testing++; 669 } 670 if (badblocks > 1) 671 printf("%d bad blocks\n", badblocks); 672 else if (badblocks == 1) 673 printf("one bad block\n"); 674 } 675 676 static void get_list_blocks(char *filename) 677 { 678 FILE *listfile; 679 unsigned long blockno; 680 681 listfile = bb_xfopen(filename, "r"); 682 while (!feof(listfile)) { 683 fscanf(listfile, "%ld\n", &blockno); 684 mark_zone(blockno); 685 badblocks++; 686 } 687 if (badblocks > 1) 688 printf("%d bad blocks\n", badblocks); 689 else if (badblocks == 1) 690 printf("one bad block\n"); 691 } 692 598 G.inode_buffer = xzalloc(INODE_BUFFER_SIZE); 599 printf("%ld inodes\n", (long)SB_INODES); 600 printf("%ld blocks\n", (long)SB_ZONES); 601 printf("Firstdatazone=%ld (%ld)\n", (long)SB_FIRSTZONE, (long)norm_firstzone); 602 printf("Zonesize=%d\n", BLOCK_SIZE << SB_ZONE_SIZE); 603 printf("Maxsize=%ld\n", (long)SB_MAXSIZE); 604 } 605 606 int mkfs_minix_main(int argc, char **argv); 693 607 int mkfs_minix_main(int argc, char **argv) 694 608 { 695 int i=1; 609 struct mntent *mp; 610 unsigned opt; 696 611 char *tmp; 697 612 struct stat statbuf; 613 char *str_i, *str_n; 698 614 char *listfile = NULL; 699 int stopIt=FALSE; 700 701 if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) 615 616 PTR_TO_GLOBALS = xzalloc(sizeof(G)); 617 /* default (changed to 30, per Linus's suggestion, Sun Nov 21 08:05:07 1993) */ 618 G.namelen = 30; 619 G.dirsize = 32; 620 G.magic = MINIX1_SUPER_MAGIC2; 621 622 if (INODE_SIZE1 * MINIX1_INODES_PER_BLOCK != BLOCK_SIZE) 702 623 bb_error_msg_and_die("bad inode size"); 703 #if def CONFIG_FEATURE_MINIX2624 #if ENABLE_FEATURE_MINIX2 704 625 if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE) 705 626 bb_error_msg_and_die("bad inode size"); 706 627 #endif 707 628 708 /* Parse options */ 709 argv++; 710 while (--argc >= 0 && *argv && **argv) { 711 if (**argv == '-') { 712 stopIt=FALSE; 713 while (i > 0 && *++(*argv) && stopIt==FALSE) { 714 switch (**argv) { 715 case 'c': 716 check = 1; 717 break; 718 case 'i': 719 { 720 char *cp=NULL; 721 if (*(*argv+1) != 0) { 722 cp = ++(*argv); 723 } else { 724 if (--argc == 0) { 725 goto goodbye; 726 } 727 cp = *(++argv); 728 } 729 req_nr_inodes = strtoul(cp, &tmp, 0); 730 if (*tmp) 731 bb_show_usage(); 732 stopIt=TRUE; 733 break; 734 } 735 case 'l': 736 if (--argc == 0) { 737 goto goodbye; 738 } 739 listfile = *(++argv); 740 break; 741 case 'n': 742 { 743 char *cp=NULL; 744 745 if (*(*argv+1) != 0) { 746 cp = ++(*argv); 747 } else { 748 if (--argc == 0) { 749 goto goodbye; 750 } 751 cp = *(++argv); 752 } 753 i = strtoul(cp, &tmp, 0); 754 if (*tmp) 755 bb_show_usage(); 756 if (i == 14) 757 magic = MINIX_SUPER_MAGIC; 758 else if (i == 30) 759 magic = MINIX_SUPER_MAGIC2; 760 else 761 bb_show_usage(); 762 namelen = i; 763 dirsize = i + 2; 764 stopIt=TRUE; 765 break; 766 } 767 case 'v': 768 #ifdef CONFIG_FEATURE_MINIX2 769 version2 = 1; 629 opt = getopt32(argv, "ci:l:n:v", &str_i, &listfile, &str_n); 630 argv += optind; 631 //if (opt & 1) -c 632 if (opt & 2) G.req_nr_inodes = xatoul(str_i); // -i 633 //if (opt & 4) -l 634 if (opt & 8) { // -n 635 G.namelen = xatoi_u(str_n); 636 if (G.namelen == 14) G.magic = MINIX1_SUPER_MAGIC; 637 else if (G.namelen == 30) G.magic = MINIX1_SUPER_MAGIC2; 638 else bb_show_usage(); 639 G.dirsize = G.namelen + 2; 640 } 641 if (opt & 0x10) { // -v 642 #if ENABLE_FEATURE_MINIX2 643 version2 = 1; 770 644 #else 771 bb_error_msg("%s: not compiled with minix v2 support", 772 device_name); 773 exit(-1); 774 #endif 775 break; 776 case '-': 777 case 'h': 778 default: 779 goodbye: 780 bb_show_usage(); 781 } 782 } 783 } else { 784 if (device_name == NULL) 785 device_name = *argv; 786 else if (BLOCKS == 0) 787 BLOCKS = strtol(*argv, &tmp, 0); 788 else { 789 goto goodbye; 790 } 791 } 792 argv++; 793 } 794 795 if (device_name && !BLOCKS) 796 BLOCKS = get_size(device_name) / 1024; 797 if (!device_name || BLOCKS < 10) { 645 bb_error_msg_and_die("not compiled with minix v2 support"); 646 #endif 647 } 648 649 G.device_name = *argv++; 650 if (!G.device_name) 798 651 bb_show_usage(); 799 } 800 #ifdef CONFIG_FEATURE_MINIX2 652 if (*argv) 653 G.total_blocks = xatou32(*argv); 654 else 655 G.total_blocks = get_size(G.device_name) / 1024; 656 657 if (G.total_blocks < 10) 658 bb_error_msg_and_die("must have at least 10 blocks"); 659 801 660 if (version2) { 802 if (namelen == 14) 803 magic = MINIX2_SUPER_MAGIC; 804 else 805 magic = MINIX2_SUPER_MAGIC2; 806 } else 807 #endif 808 if (BLOCKS > 65535) 809 BLOCKS = 65535; 810 check_mount(); /* is it already mounted? */ 811 tmp = root_block; 661 G.magic = MINIX2_SUPER_MAGIC2; 662 if (G.namelen == 14) 663 G.magic = MINIX2_SUPER_MAGIC; 664 } else if (G.total_blocks > 65535) 665 G.total_blocks = 65535; 666 667 /* Check if it is mounted */ 668 mp = find_mount_point(G.device_name, NULL); 669 if (mp && strcmp(G.device_name, mp->mnt_fsname) == 0) 670 bb_error_msg_and_die("%s is mounted on %s; " 671 "refusing to make a filesystem", 672 G.device_name, mp->mnt_dir); 673 674 G.dev_fd = xopen(G.device_name, O_RDWR); 675 if (fstat(G.dev_fd, &statbuf) < 0) 676 bb_error_msg_and_die("cannot stat %s", G.device_name); 677 if (!S_ISBLK(statbuf.st_mode)) 678 opt &= ~1; // clear -c (check) 679 680 /* I don't know why someone has special code to prevent mkfs.minix 681 * on IDE devices. Why IDE but not SCSI, etc?... */ 682 #if 0 683 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) 684 /* what is this? */ 685 bb_error_msg_and_die("will not try " 686 "to make filesystem on '%s'", G.device_name); 687 #endif 688 689 tmp = G.root_block; 812 690 *(short *) tmp = 1; 813 691 strcpy(tmp + 2, "."); 814 tmp += dirsize;692 tmp += G.dirsize; 815 693 *(short *) tmp = 1; 816 694 strcpy(tmp + 2, ".."); 817 tmp += dirsize;695 tmp += G.dirsize; 818 696 *(short *) tmp = 2; 819 697 strcpy(tmp + 2, ".badblocks"); 820 DEV = bb_xopen3(device_name, O_RDWR, 0); 821 if (fstat(DEV, &statbuf) < 0) 822 bb_error_msg_and_die("unable to stat %s", device_name); 823 if (!S_ISBLK(statbuf.st_mode)) 824 check = 0; 825 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) 826 bb_error_msg_and_die("will not try to make filesystem on '%s'", device_name); 698 827 699 setup_tables(); 828 if (check) 700 701 if (opt & 1) // -c ? 829 702 check_blocks(); 830 703 else if (listfile) 831 704 get_list_blocks(listfile); 832 #ifdef CONFIG_FEATURE_MINIX2 705 833 706 if (version2) { 834 707 make_root_inode2(); 835 708 make_bad_inode2(); 836 } else 837 #endif 838 { 709 } else { 839 710 make_root_inode(); 840 711 make_bad_inode(); 841 712 } 713 842 714 mark_good_blocks(); 843 715 write_tables(); 844 716 return 0; 845 846 } 717 } -
branches/stable/mindi-busybox/util-linux/mkswap.c
r821 r1770 1 1 /* vi: set sw=4 ts=4: */ 2 /* 3 * mkswap.c - set up a linux swap device 2 /* mkswap.c - format swap device (Linux v1 only) 4 3 * 5 * (C) 1991 Linus Torvalds. This file may be redistributed as per 6 * the Linux copyright. 4 * Copyright 2006 Rob Landley <rob@landley.net> 5 * 6 * Licensed under GPL version 2, see file LICENSE in this tarball for details. 7 7 */ 8 8 9 /* 10 * 20.12.91 - time began. Got VM working yesterday by doing this by hand. 11 * 12 * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks] 13 * 14 * -c for readability checking. (Use it unless you are SURE!) 15 * -vN for swap areas version N. (Only N=0,1 known today.) 16 * -f for forcing swap creation even if it would smash partition table. 17 * 18 * The device may be a block device or an image of one, but this isn't 19 * enforced (but it's not much fun on a character device :-). 20 * 21 * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the 22 * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995. 23 * 24 * Version 1 swap area code (for kernel 2.1.117), aeb, 981010. 25 * 26 * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb. 27 * V1_MAX_PAGES fixes, jj, 990325. 28 * 29 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org> 30 * - added Native Language Support 31 * 32 * from util-linux -- adapted for busybox by 33 * Erik Andersen <andersen@codepoet.org>. I ripped out Native Language 34 * Support, made some stuff smaller, and fitted for life in busybox. 35 * 36 */ 9 #include "libbb.h" 37 10 38 #include "busybox.h" 39 #include <unistd.h> 40 #include <string.h> 41 #include <fcntl.h> 42 #include <sys/ioctl.h> /* for _IO */ 43 #include <sys/utsname.h> 44 #include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */ 45 /* we also get PAGE_SIZE via getpagesize() */ 46 47 static char *device_name = NULL; 48 static int DEV = -1; 49 static long PAGES = 0; 50 static int check = 0; 51 static int badpages = 0; 52 #if ENABLE_FEATURE_MKSWAP_V0 53 static int version = -1; 54 #else 55 #define version 1 56 /* and make sure that we optimize away anything which would deal with checking 57 * the kernel revision as we have v1 support only anyway. 58 */ 59 #undef KERNEL_VERSION 60 #define KERNEL_VERSION(p,q,r) 1 61 #define get_linux_version_code() 1 62 #endif 63 64 /* 65 * The definition of the union swap_header uses the constant PAGE_SIZE. 66 * Unfortunately, on some architectures this depends on the hardware model, 67 * and can only be found at run time -- we use getpagesize(). 68 */ 69 70 static int pagesize; 71 static unsigned int *signature_page; 72 73 static struct swap_header_v1 { 74 char bootbits[1024]; /* Space for disklabel etc. */ 75 unsigned int swap_version; 76 unsigned int last_page; 77 unsigned int nr_badpages; 78 unsigned int padding[125]; 79 unsigned int badpages[1]; 80 } *p; 81 82 static inline void init_signature_page(void) 83 { 84 pagesize = getpagesize(); 85 86 #ifdef PAGE_SIZE 87 if (pagesize != PAGE_SIZE) 88 bb_error_msg("Assuming pages of size %d", pagesize); 89 #endif 90 signature_page = (unsigned int *) xmalloc(pagesize); 91 memset(signature_page, 0, pagesize); 92 p = (struct swap_header_v1 *) signature_page; 93 } 94 95 static inline void write_signature(char *sig) 96 { 97 char *sp = (char *) signature_page; 98 99 strncpy(sp + pagesize - 10, sig, 10); 100 } 101 102 #define V0_MAX_PAGES (8 * (pagesize - 10)) 103 /* Before 2.2.0pre9 */ 104 #define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1) 105 /* Since 2.2.0pre9: 106 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL)) 107 with variations on 108 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8)) 109 #define SWP_OFFSET(entry) ((entry) >> 8) 110 on the various architectures. Below the result - yuk. 111 112 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2 113 i386 2^12 o<<8 e>>8 1<<24 1<<19 114 mips 2^12 o<<15 e>>15 1<<17 1<<19 115 alpha 2^13 o<<40 e>>40 1<<24 1<<18 116 m68k 2^12 o<<12 e>>12 1<<20 1<<19 117 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18} 118 sparc64 2^13 o<<13 e>>13 1<<51 1<<18 119 ppc 2^12 o<<8 e>>8 1<<24 1<<19 120 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16} 121 armv 2^12 o<<9 e>>9 1<<23 1<<19 122 123 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere. 124 125 The bad part is that we need to know this since the kernel will 126 refuse a swap space if it is too large. 127 */ 128 /* patch from jj - why does this differ from the above? */ 129 #if defined(__alpha__) 130 #define V1_MAX_PAGES ((1 << 24) - 1) 131 #elif defined(__mips__) 132 #define V1_MAX_PAGES ((1 << 17) - 1) 133 #elif defined(__sparc_v9__) 134 #define V1_MAX_PAGES ((3 << 29) - 1) 135 #elif defined(__sparc__) 136 #define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1)) 137 #else 138 #define V1_MAX_PAGES V1_OLD_MAX_PAGES 139 #endif 140 /* man page now says: 141 The maximum useful size of a swap area now depends on the architecture. 142 It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips, 143 128GB on alpha and 3TB on sparc64. 144 */ 145 146 #define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int)) 147 148 static inline void bit_set(unsigned int *addr, unsigned int nr) 149 { 150 unsigned int r, m; 151 152 addr += nr / (8 * sizeof(int)); 153 154 r = *addr; 155 m = 1 << (nr & (8 * sizeof(int) - 1)); 156 157 *addr = r | m; 158 } 159 160 static int bit_test_and_clear(unsigned int *addr, unsigned int nr) 161 { 162 unsigned int r, m; 163 164 addr += nr / (8 * sizeof(int)); 165 166 r = *addr; 167 m = 1 << (nr & (8 * sizeof(int) - 1)); 168 169 *addr = r & ~m; 170 return (r & m) != 0; 171 } 172 173 static void page_ok(int page) 174 { 175 if (ENABLE_FEATURE_MKSWAP_V0) { 176 bit_set(signature_page, page); 177 } 178 } 179 180 static void check_blocks(void) 181 { 182 unsigned int current_page; 183 int do_seek = 1; 184 char *buffer; 185 186 buffer = xmalloc(pagesize); 187 current_page = 0; 188 while (current_page < PAGES) { 189 if (!check && version == 0) { 190 page_ok(current_page++); 191 continue; 192 } 193 if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) != 194 current_page * pagesize) 195 bb_error_msg_and_die("seek failed in check_blocks"); 196 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) { 197 current_page++; 198 if (version == 0) 199 bit_test_and_clear(signature_page, current_page); 200 else { 201 if (badpages == MAX_BADPAGES) 202 bb_error_msg_and_die("too many bad pages"); 203 p->badpages[badpages] = current_page; 204 } 205 badpages++; 206 continue; 207 } 208 page_ok(current_page++); 209 } 210 if (ENABLE_FEATURE_CLEAN_UP) 211 free(buffer); 212 if (badpages > 0) 213 printf("%d bad page%s\n", badpages, (badpages==1)?"":"s"); 214 } 215 216 static long valid_offset(int fd, int offset) 217 { 218 char ch; 219 220 if (lseek(fd, offset, 0) < 0) 221 return 0; 222 if (read(fd, &ch, 1) < 1) 223 return 0; 224 return 1; 225 } 226 227 static int find_size(int fd) 228 { 229 unsigned int high, low; 230 231 low = 0; 232 for (high = 1; high > 0 && valid_offset(fd, high); high *= 2) 233 low = high; 234 while (low < high - 1) { 235 const int mid = (low + high) / 2; 236 237 if (valid_offset(fd, mid)) 238 low = mid; 239 else 240 high = mid; 241 } 242 return (low + 1); 243 } 244 245 /* return size in pages, to avoid integer overflow */ 246 static inline long get_size(const char *file) 247 { 248 int fd; 249 long size; 250 251 fd = bb_xopen3(file, O_RDONLY, 0); 252 if (ioctl(fd, BLKGETSIZE, &size) >= 0) { 253 size /= pagesize / 512; 254 } else { 255 size = find_size(fd) / pagesize; 256 } 257 close(fd); 258 return size; 259 } 260 11 int mkswap_main(int argc, char **argv); 261 12 int mkswap_main(int argc, char **argv) 262 13 { 263 char *tmp; 264 struct stat statbuf; 265 int sz; 266 int maxpages; 267 int goodpages; 268 #ifdef __sparc__ 269 int force = 0; 270 #endif 14 int fd, pagesize; 15 off_t len; 16 unsigned int hdr[129]; 271 17 272 init_signature_page(); /* get pagesize */18 // No options supported. 273 19 274 bb_opt_complementally = "?"; /* call bb_show_usage internally */ 275 sz = bb_getopt_ulflags(argc, argv, "+cfv:", &tmp); 276 if (sz & 1) 277 check = 1; 278 #ifdef __sparc__ 279 if (sz & 2) 280 force = 1; 281 #endif 282 #if ENABLE_FEATURE_MKSWAP_V0 283 if (sz & 4) { 284 version = bb_xgetlarg(tmp, 10, 0, 1); 285 } else { 286 if (get_linux_version_code() < KERNEL_VERSION(2, 1, 117)) 287 version = 0; 288 else 289 version = 1; 290 } 291 #endif 20 if (argc != 2) bb_show_usage(); 292 21 293 argv += optind; 294 argc -= optind; 22 // Figure out how big the device is and announce our intentions. 295 23 296 goodpages = pagesize / 1024; /* cache division */ 297 while (argc--) { 298 if (device_name) { 299 PAGES = bb_xgetlarg(argv[0], 0, 10, sz * goodpages) / goodpages; 300 argc = 0; /* ignore any surplus args.. */ 301 } else { 302 device_name = argv[0]; 303 sz = get_size(device_name); 304 argv++; 305 } 306 } 24 fd = xopen(argv[1], O_RDWR); 25 len = fdlength(fd); 26 pagesize = getpagesize(); 27 printf("Setting up swapspace version 1, size = %"OFF_FMT"d bytes\n", 28 len - pagesize); 307 29 308 if (!device_name) { 309 bb_error_msg_and_die("error: Nowhere to set up swap on?"); 310 } 311 if (!PAGES) { 312 PAGES = sz; 313 } 30 // Make a header. 314 31 315 #if 0 316 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES); 317 #else 318 if (!version) 319 maxpages = V0_MAX_PAGES; 320 else if (get_linux_version_code() >= KERNEL_VERSION(2,2,1)) 321 maxpages = V1_MAX_PAGES; 322 else { 323 maxpages = V1_OLD_MAX_PAGES; 324 if (maxpages > V1_MAX_PAGES) 325 maxpages = V1_MAX_PAGES; 326 } 327 #endif 328 if (PAGES > maxpages) { 329 PAGES = maxpages; 330 bb_error_msg("warning: truncating swap area to %ldkB", 331 PAGES * goodpages); 332 } 32 memset(hdr, 0, sizeof(hdr)); 33 hdr[0] = 1; 34 hdr[1] = (len / pagesize) - 1; 333 35 334 DEV = bb_xopen3(device_name, O_RDWR, 0); 335 if (fstat(DEV, &statbuf) < 0) 336 bb_perror_msg_and_die("%s", device_name); 337 if (!S_ISBLK(statbuf.st_mode)) 338 check = 0; 339 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) 340 bb_error_msg_and_die("Will not try to make swapdevice on '%s'", device_name); 36 // Write the header. Sync to disk because some kernel versions check 37 // signature on disk (not in cache) during swapon. 341 38 342 #ifdef __sparc__ 343 if (!force && version == 0) {344 /* Don't overwrite partition table unless forced */345 unsigned char *buffer = (unsigned char *) signature_page;346 unsigned short *q, sum;39 xlseek(fd, 1024, SEEK_SET); 40 xwrite(fd, hdr, sizeof(hdr)); 41 xlseek(fd, pagesize-10, SEEK_SET); 42 xwrite(fd, "SWAPSPACE2", 10); 43 fsync(fd); 347 44 348 if (read(DEV, buffer, 512) != 512) 349 bb_error_msg_and_die("fatal: first page unreadable"); 350 if (buffer[508] == 0xDA && buffer[509] == 0xBE) { 351 q = (unsigned short *) (buffer + 510); 352 for (sum = 0; q >= (unsigned short *) buffer;) 353 sum ^= *q--; 354 if (!sum) { 355 bb_error_msg("Device '%s' contains a valid Sun disklabel.\n" 356 "This probably means creating v0 swap would destroy your partition table\n" 357 "No swap created. If you really want to create swap v0 on that device, use\n" 358 "the -f option to force it.", device_name); 359 return EXIT_FAILURE; 360 } 361 } 362 } 363 #endif 45 if (ENABLE_FEATURE_CLEAN_UP) close(fd); 364 46 365 if (version == 0 || check) 366 check_blocks(); 367 if (version == 0 && !bit_test_and_clear(signature_page, 0)) 368 bb_error_msg_and_die("fatal: first page unreadable"); 369 if (version == 1) { 370 p->swap_version = version; 371 p->last_page = PAGES - 1; 372 p->nr_badpages = badpages; 373 } 374 375 goodpages = PAGES - badpages - 1; 376 if (goodpages <= 0) 377 bb_error_msg_and_die("Unable to set up swap-space: unreadable"); 378 printf("Setting up swapspace version %d, size = %ld bytes\n", 379 version, (long) (goodpages * pagesize)); 380 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2"); 381 382 sz = ((version == 0) ? 0 : 1024); /* offset */ 383 if (lseek(DEV, sz, SEEK_SET) != sz) 384 bb_error_msg_and_die("unable to rewind swap-device"); 385 goodpages = pagesize - sz; /* cache substraction */ 386 if (write(DEV, (char *) signature_page + sz, goodpages) 387 != goodpages) 388 bb_error_msg_and_die("unable to write signature page"); 389 390 /* 391 * A subsequent swapon() will fail if the signature 392 * is not actually on disk. (This is a kernel bug.) 393 */ 394 if (fsync(DEV)) 395 bb_error_msg_and_die("fsync failed"); 396 if (ENABLE_FEATURE_CLEAN_UP) { 397 close(DEV); 398 free(signature_page); 399 } 400 return EXIT_SUCCESS; 47 return 0; 401 48 } -
branches/stable/mindi-busybox/util-linux/more.c
r821 r1770 12 12 * Termios corrects by Vladimir Oleynik <dzo@simtreas.ru> 13 13 * 14 * This program is free software; you can redistribute it and/or modify 15 * it under the terms of the GNU General Public License as published by 16 * the Free Software Foundation; either version 2 of the License, or 17 * (at your option) any later version. 18 * 19 * This program is distributed in the hope that it will be useful, 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 * General Public License for more details. 23 * 24 * You should have received a copy of the GNU General Public License 25 * along with this program; if not, write to the Free Software 26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 * 14 * Licensed under GPLv2 or later, see file License in this tarball for details. 28 15 */ 29 16 30 #include <stdio.h> 31 #include <fcntl.h> 32 #include <signal.h> 33 #include <stdlib.h> 34 #include <unistd.h> 35 #include <sys/ioctl.h> 36 #include "busybox.h" 37 38 39 #ifdef CONFIG_FEATURE_USE_TERMIOS 40 static int cin_fileno; 17 #include "libbb.h" 18 #if ENABLE_FEATURE_USE_TERMIOS 41 19 #include <termios.h> 42 #define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp) 43 #define getTermSettings(fd,argp) tcgetattr(fd, argp); 44 45 static struct termios initial_settings, new_settings; 46 47 static void set_tty_to_initial_mode(void) 48 { 49 setTermSettings(cin_fileno, &initial_settings); 50 } 20 #endif /* FEATURE_USE_TERMIOS */ 21 22 23 #if ENABLE_FEATURE_USE_TERMIOS 24 25 struct globals { 26 int cin_fileno; 27 struct termios initial_settings; 28 struct termios new_settings; 29 }; 30 #define G (*(struct globals*)bb_common_bufsiz1) 31 //#define G (*ptr_to_globals) 32 #define INIT_G() ((void)0) 33 //#define INIT_G() PTR_TO_GLOBALS = xzalloc(sizeof(G)) 34 #define initial_settings (G.initial_settings) 35 #define new_settings (G.new_settings ) 36 #define cin_fileno (G.cin_fileno ) 37 38 #define setTermSettings(fd, argp) tcsetattr(fd, TCSANOW, argp) 39 #define getTermSettings(fd, argp) tcgetattr(fd, argp) 51 40 52 41 static void gotsig(int sig) 53 42 { 54 43 putchar('\n'); 44 setTermSettings(cin_fileno, &initial_settings); 55 45 exit(EXIT_FAILURE); 56 46 } 57 #endif /* CONFIG_FEATURE_USE_TERMIOS */ 58 59 47 48 #else /* !FEATURE_USE_TERMIOS */ 49 #define INIT_G() ((void)0) 50 #define setTermSettings(fd, argp) ((void)0) 51 #endif /* FEATURE_USE_TERMIOS */ 52 53 #define CONVERTED_TAB_SIZE 8 54 55 int more_main(int argc, char **argv); 60 56 int more_main(int argc, char **argv) 61 57 { 62 int c, lines, input = 0; 63 int please_display_more_prompt = 0; 58 int c = c; /* for gcc */ 59 int lines; 60 int input = 0; 61 int spaces = 0; 62 int please_display_more_prompt; 64 63 struct stat st; 65 64 FILE *file; 66 65 FILE *cin; 67 int len , page_height;66 int len; 68 67 int terminal_width; 69 68 int terminal_height; 70 69 71 argc--; 70 INIT_G(); 71 72 72 argv++; 73 74 75 /* not use inputing from terminal if usage: more > outfile */ 76 if(isatty(STDOUT_FILENO)) { 77 cin = fopen(CURRENT_TTY, "r"); 78 if (!cin) 79 cin = bb_xfopen(CONSOLE_DEV, "r"); 80 please_display_more_prompt = 2; 81 #ifdef CONFIG_FEATURE_USE_TERMIOS 82 cin_fileno = fileno(cin); 83 getTermSettings(cin_fileno, &initial_settings); 84 new_settings = initial_settings; 85 new_settings.c_lflag &= ~ICANON; 86 new_settings.c_lflag &= ~ECHO; 87 new_settings.c_cc[VMIN] = 1; 88 new_settings.c_cc[VTIME] = 0; 89 setTermSettings(cin_fileno, &new_settings); 90 atexit(set_tty_to_initial_mode); 91 (void) signal(SIGINT, gotsig); 92 (void) signal(SIGQUIT, gotsig); 93 (void) signal(SIGTERM, gotsig); 73 /* Another popular pager, most, detects when stdout 74 * is not a tty and turns into cat. This makes sense. */ 75 if (!isatty(STDOUT_FILENO)) 76 return bb_cat(argv); 77 cin = fopen(CURRENT_TTY, "r"); 78 if (!cin) 79 return bb_cat(argv); 80 81 #if ENABLE_FEATURE_USE_TERMIOS 82 cin_fileno = fileno(cin); 83 getTermSettings(cin_fileno, &initial_settings); 84 new_settings = initial_settings; 85 new_settings.c_lflag &= ~ICANON; 86 new_settings.c_lflag &= ~ECHO; 87 new_settings.c_cc[VMIN] = 1; 88 new_settings.c_cc[VTIME] = 0; 89 setTermSettings(cin_fileno, &new_settings); 90 signal(SIGINT, gotsig); 91 signal(SIGQUIT, gotsig); 92 signal(SIGTERM, gotsig); 94 93 #endif 95 } else {96 cin = stdin;97 }98 94 99 95 do { 100 if (argc == 0) { 101 file = stdin; 102 } else 103 file = bb_wfopen(*argv, "r"); 104 if(file==0) 105 goto loop; 106 96 file = stdin; 97 if (*argv) { 98 file = fopen_or_warn(*argv, "r"); 99 if (!file) 100 continue; 101 } 107 102 st.st_size = 0; 108 103 fstat(fileno(file), &st); 109 104 110 please_display_more_prompt &= ~1;111 105 please_display_more_prompt = 0; 106 /* never returns w, h <= 1 */ 112 107 get_terminal_width_height(fileno(cin), &terminal_width, &terminal_height); 113 if (terminal_height > 4) 114 terminal_height -= 2; 115 if (terminal_width > 0) 116 terminal_width -= 1; 117 118 len=0; 108 terminal_height -= 1; 109 110 len = 0; 119 111 lines = 0; 120 page_height = terminal_height; 121 while ((c = getc(file)) != EOF) { 122 123 if ((please_display_more_prompt & 3) == 3) { 112 while (spaces || (c = getc(file)) != EOF) { 113 int wrap; 114 if (spaces) 115 spaces--; 116 loop_top: 117 if (input != 'r' && please_display_more_prompt) { 124 118 len = printf("--More-- "); 125 if (file != stdin && st.st_size > 0) { 126 #if _FILE_OFFSET_BITS == 64 127 len += printf("(%d%% of %lld bytes)", 128 (int) (100 * ((double) ftell(file) / 129 (double) st.st_size)), (long long)st.st_size); 130 #else 131 len += printf("(%d%% of %ld bytes)", 132 (int) (100 * ((double) ftell(file) / 133 (double) st.st_size)), (long)st.st_size); 134 #endif 119 if (st.st_size > 0) { 120 len += printf("(%d%% of %"OFF_FMT"d bytes)", 121 (int) (ftello(file)*100 / st.st_size), 122 st.st_size); 135 123 } 136 137 124 fflush(stdout); 138 125 … … 141 128 * to get input from the user. 142 129 */ 143 input = getc(cin); 144 #ifndef CONFIG_FEATURE_USE_TERMIOS 145 printf("\033[A"); /* up cursor */ 130 for (;;) { 131 input = getc(cin); 132 input = tolower(input); 133 #if !ENABLE_FEATURE_USE_TERMIOS 134 printf("\033[A"); /* up cursor */ 146 135 #endif 147 /* Erase the "More" message */ 148 putc('\r', stdout); 149 while (--len >= 0) 150 putc(' ', stdout); 151 putc('\r', stdout); 152 len=0; 136 /* Erase the last message */ 137 printf("\r%*s\r", len, ""); 138 139 /* Due to various multibyte escape 140 * sequences, it's not ok to accept 141 * any input as a command to scroll 142 * the screen. We only allow known 143 * commands, else we show help msg. */ 144 if (input == ' ' || input == '\n' || input == 'q' || input == 'r') 145 break; 146 len = printf("(Enter:next line Space:next page Q:quit R:show the rest)"); 147 } 148 len = 0; 153 149 lines = 0; 154 page_height = terminal_height; 155 please_display_more_prompt &= ~1; 150 please_display_more_prompt = 0; 156 151 157 152 if (input == 'q') 158 153 goto end; 154 155 /* The user may have resized the terminal. 156 * Re-read the dimensions. */ 157 #if ENABLE_FEATURE_USE_TERMIOS 158 get_terminal_width_height(cin_fileno, &terminal_width, &terminal_height); 159 terminal_height -= 1; 160 #endif 159 161 } 162 163 /* Crudely convert tabs into spaces, which are 164 * a bajillion times easier to deal with. */ 165 if (c == '\t') { 166 spaces = CONVERTED_TAB_SIZE - 1; 167 c = ' '; 168 } 160 169 161 170 /* 162 171 * There are two input streams to worry about here: 163 172 * 164 * c 165 * input 173 * c : the character we are reading from the file being "mored" 174 * input: a character received from the keyboard 166 175 * 167 176 * If we hit a newline in the _file_ stream, we want to test and … … 169 178 * allows the user to quit while in the middle of a file. 170 179 */ 171 if (c == '\n') { 172 /* increment by just one line if we are at 173 * the end of this line */ 174 if (input == '\n') 175 please_display_more_prompt |= 1; 176 /* Adjust the terminal height for any overlap, so that 177 * no lines get lost off the top. */ 178 if (len >= terminal_width) { 179 int quot, rem; 180 quot = len / terminal_width; 181 rem = len - (quot * terminal_width); 182 if (quot) { 183 if (rem) 184 page_height-=quot; 185 else 186 page_height-=(quot-1); 187 } 188 } 189 if (++lines >= page_height) { 190 please_display_more_prompt |= 1; 191 } 192 len=0; 180 wrap = (++len > terminal_width); 181 if (c == '\n' || wrap) { 182 /* Then outputting this character 183 * will move us to a new line. */ 184 if (++lines >= terminal_height || input == '\n') 185 please_display_more_prompt = 1; 186 len = 0; 193 187 } 194 /* 195 * If we just read a newline from the file being 'mored' and any 196 * key other than a return is hit, scroll by one page 197 */ 198 putc(c, stdout); 199 len++; 188 if (c != '\n' && wrap) { 189 /* Then outputting this will also put a character on 190 * the beginning of that new line. Thus we first want to 191 * display the prompt (if any), so we skip the putchar() 192 * and go back to the top of the loop, without reading 193 * a new character. */ 194 goto loop_top; 195 } 196 /* My small mind cannot fathom backspaces and UTF-8 */ 197 putchar(c); 200 198 } 201 199 fclose(file); 202 200 fflush(stdout); 203 loop: 204 argv++; 205 } while (--argc > 0); 206 end: 201 } while (*argv && *++argv); 202 end: 203 setTermSettings(cin_fileno, &initial_settings); 207 204 return 0; 208 205 } -
branches/stable/mindi-busybox/util-linux/mount.c
r902 r1770 10 10 */ 11 11 12 /* todo:13 * bb_getopt_ulflags();14 */15 16 12 /* Design notes: There is no spec for mount. Remind me to write one. 17 13 … … 23 19 */ 24 20 25 #include "busybox.h" 26 #include <unistd.h> 27 #include <errno.h> 28 #include <string.h> 21 #include "libbb.h" 29 22 #include <mntent.h> 30 #include <ctype.h> 31 #include <fcntl.h> // for CONFIG_FEATURE_MOUNT_LOOP 32 #include <sys/ioctl.h> // for CONFIG_FEATURE_MOUNT_LOOP 33 34 // These two aren't always defined in old headers 35 #ifndef MS_BIND 36 #define MS_BIND 4096 23 24 /* Needed for nfs support only... */ 25 #include <syslog.h> 26 #include <sys/utsname.h> 27 #undef TRUE 28 #undef FALSE 29 #include <rpc/rpc.h> 30 #include <rpc/pmap_prot.h> 31 #include <rpc/pmap_clnt.h> 32 33 34 #if defined(__dietlibc__) 35 /* 16.12.2006, Sampo Kellomaki (sampo@iki.fi) 36 * dietlibc-0.30 does not have implementation of getmntent_r() */ 37 /* OTOH: why we use getmntent_r instead of getmntent? TODO... */ 38 struct mntent *getmntent_r(FILE* stream, struct mntent* result, char* buffer, int bufsize) 39 { 40 /* *** XXX FIXME WARNING: This hack is NOT thread safe. --Sampo */ 41 struct mntent* ment = getmntent(stream); 42 memcpy(result, ment, sizeof(struct mntent)); 43 return result; 44 } 37 45 #endif 38 #ifndef MS_MOVE 39 #define MS_MOVE 8192 40 #endif 41 #ifndef MS_SILENT 42 #define MS_SILENT 32768 43 #endif 46 44 47 45 48 // Not real flags, but we want to be able to check for this. 46 #define MOUNT_NOAUTO (1<<29) 47 #define MOUNT_SWAP (1<<30) 49 enum { 50 MOUNT_USERS = (1<<28)*ENABLE_DESKTOP, 51 MOUNT_NOAUTO = (1<<29), 52 MOUNT_SWAP = (1<<30), 53 }; 54 // TODO: more "user" flag compatibility. 55 // "user" option (from mount manpage): 56 // Only the user that mounted a filesystem can unmount it again. 57 // If any user should be able to unmount, then use users instead of user 58 // in the fstab line. The owner option is similar to the user option, 59 // with the restriction that the user must be the owner of the special file. 60 // This may be useful e.g. for /dev/fd if a login script makes 61 // the console user owner of this device. 62 48 63 /* Standard mount options (from -o options or --options), with corresponding 49 64 * flags */ … … 52 67 const char *name; 53 68 long flags; 54 } static const mount_options[] = { 55 // NOP flags. 56 57 {"loop", 0}, 58 {"defaults", 0}, 59 {"quiet", 0}, 60 61 // vfs flags 62 63 {"ro", MS_RDONLY}, 64 {"rw", ~MS_RDONLY}, 65 {"nosuid", MS_NOSUID}, 66 {"suid", ~MS_NOSUID}, 67 {"dev", ~MS_NODEV}, 68 {"nodev", MS_NODEV}, 69 {"exec", ~MS_NOEXEC}, 70 {"noexec", MS_NOEXEC}, 71 {"sync", MS_SYNCHRONOUS}, 72 {"async", ~MS_SYNCHRONOUS}, 73 {"atime", ~MS_NOATIME}, 74 {"noatime", MS_NOATIME}, 75 {"diratime", ~MS_NODIRATIME}, 76 {"nodiratime", MS_NODIRATIME}, 77 {"loud", ~MS_SILENT}, 78 79 // action flags 80 81 {"remount", MS_REMOUNT}, 82 {"bind", MS_BIND}, 83 {"move", MS_MOVE}, 84 {"noauto",MOUNT_NOAUTO}, 85 {"swap",MOUNT_SWAP} 69 } static mount_options[] = { 70 // MS_FLAGS set a bit. ~MS_FLAGS disable that bit. 0 flags are NOPs. 71 72 USE_FEATURE_MOUNT_LOOP( 73 {"loop", 0}, 74 ) 75 76 USE_FEATURE_MOUNT_FSTAB( 77 {"defaults", 0}, 78 /* {"quiet", 0}, - do not filter out, vfat wants to see it */ 79 {"noauto", MOUNT_NOAUTO}, 80 {"sw", MOUNT_SWAP}, 81 {"swap", MOUNT_SWAP}, 82 USE_DESKTOP({"user", MOUNT_USERS},) 83 USE_DESKTOP({"users", MOUNT_USERS},) 84 ) 85 86 USE_FEATURE_MOUNT_FLAGS( 87 // vfs flags 88 {"nosuid", MS_NOSUID}, 89 {"suid", ~MS_NOSUID}, 90 {"dev", ~MS_NODEV}, 91 {"nodev", MS_NODEV}, 92 {"exec", ~MS_NOEXEC}, 93 {"noexec", MS_NOEXEC}, 94 {"sync", MS_SYNCHRONOUS}, 95 {"async", ~MS_SYNCHRONOUS}, 96 {"atime", ~MS_NOATIME}, 97 {"noatime", MS_NOATIME}, 98 {"diratime", ~MS_NODIRATIME}, 99 {"nodiratime", MS_NODIRATIME}, 100 {"loud", ~MS_SILENT}, 101 102 // action flags 103 104 {"bind", MS_BIND}, 105 {"move", MS_MOVE}, 106 {"shared", MS_SHARED}, 107 {"slave", MS_SLAVE}, 108 {"private", MS_PRIVATE}, 109 {"unbindable", MS_UNBINDABLE}, 110 {"rshared", MS_SHARED|MS_RECURSIVE}, 111 {"rslave", MS_SLAVE|MS_RECURSIVE}, 112 {"rprivate", MS_SLAVE|MS_RECURSIVE}, 113 {"runbindable", MS_UNBINDABLE|MS_RECURSIVE}, 114 ) 115 116 // Always understood. 117 118 {"ro", MS_RDONLY}, // vfs flag 119 {"rw", ~MS_RDONLY}, // vfs flag 120 {"remount", MS_REMOUNT}, // action flag 86 121 }; 87 122 123 88 124 /* Append mount options to string */ 89 static void append_mount_options(char **oldopts, char *newopts) 90 { 91 if(*oldopts && **oldopts) { 92 char *temp=bb_xasprintf("%s,%s",*oldopts,newopts); 93 free(*oldopts); 94 *oldopts=temp; 125 static void append_mount_options(char **oldopts, const char *newopts) 126 { 127 if (*oldopts && **oldopts) { 128 /* do not insert options which are already there */ 129 while (newopts[0]) { 130 char *p; 131 int len = strlen(newopts); 132 p = strchr(newopts, ','); 133 if (p) len = p - newopts; 134 p = *oldopts; 135 while (1) { 136 if (!strncmp(p, newopts, len) 137 && (p[len]==',' || p[len]==0)) 138 goto skip; 139 p = strchr(p,','); 140 if (!p) break; 141 p++; 142 } 143 p = xasprintf("%s,%.*s", *oldopts, len, newopts); 144 free(*oldopts); 145 *oldopts = p; 146 skip: 147 newopts += len; 148 while (newopts[0] == ',') newopts++; 149 } 95 150 } else { 96 151 if (ENABLE_FEATURE_CLEAN_UP) free(*oldopts); 97 *oldopts = bb_xstrdup(newopts);152 *oldopts = xstrdup(newopts); 98 153 } 99 154 } 100 155 101 156 /* Use the mount_options list to parse options into flags. 102 * Return list of unrecognized options in *strflags if strflags!=NULL */157 * Also return list of unrecognized options if unrecognized!=NULL */ 103 158 static int parse_mount_options(char *options, char **unrecognized) 104 159 { … … 113 168 114 169 // Find this option in mount_options 115 for (i = 0; i < (sizeof(mount_options) / sizeof(*mount_options)); i++) {170 for (i = 0; i < ARRAY_SIZE(mount_options); i++) { 116 171 if (!strcasecmp(mount_options[i].name, options)) { 117 172 long fl = mount_options[i].flags; 118 if (fl < 0) flags &= fl;173 if (fl < 0) flags &= fl; 119 174 else flags |= fl; 120 175 break; … … 122 177 } 123 178 // If unrecognized not NULL, append unrecognized mount options */ 124 if (unrecognized 125 && i == (sizeof(mount_options) / sizeof(*mount_options))) 126 { 179 if (unrecognized && i == ARRAY_SIZE(mount_options)) { 127 180 // Add it to strflags, to pass on to kernel 128 181 i = *unrecognized ? strlen(*unrecognized) : 0; … … 135 188 136 189 // Advance to next option, or finish 137 if (comma) {190 if (comma) { 138 191 *comma = ','; 139 192 options = ++comma; … … 148 201 static llist_t *get_block_backed_filesystems(void) 149 202 { 150 char *fs, *buf, 151 *filesystems[] = {"/etc/filesystems", "/proc/filesystems", 0}; 203 static const char filesystems[2][sizeof("/proc/filesystems")] = { 204 "/etc/filesystems", 205 "/proc/filesystems", 206 }; 207 char *fs, *buf; 152 208 llist_t *list = 0; 153 209 int i; 154 210 FILE *f; 155 211 156 for(i = 0; filesystems[i]; i++) { 157 if(!(f = fopen(filesystems[i], "r"))) continue; 158 159 for(fs = buf = 0; (fs = buf = bb_get_chomped_line_from_file(f)); 160 free(buf)) 161 { 162 if(!strncmp(buf,"nodev",5) && isspace(buf[5])) continue; 163 164 while(isspace(*fs)) fs++; 165 if(*fs=='#' || *fs=='*') continue; 166 if(!*fs) continue; 167 168 llist_add_to_end(&list,bb_xstrdup(fs)); 212 for (i = 0; i < 2; i++) { 213 f = fopen(filesystems[i], "r"); 214 if (!f) continue; 215 216 while ((buf = xmalloc_getline(f)) != 0) { 217 if (!strncmp(buf, "nodev", 5) && isspace(buf[5])) 218 continue; 219 fs = skip_whitespace(buf); 220 if (*fs=='#' || *fs=='*' || !*fs) continue; 221 222 llist_add_to_end(&list, xstrdup(fs)); 223 free(buf); 169 224 } 170 225 if (ENABLE_FEATURE_CLEAN_UP) fclose(f); … … 186 241 187 242 #if ENABLE_FEATURE_MTAB_SUPPORT 188 static int useMtab ;243 static int useMtab = 1; 189 244 static int fakeIt; 190 245 #else … … 194 249 195 250 // Perform actual mount of specific filesystem at specific location. 196 251 // NB: mp->xxx fields may be trashed on exit 197 252 static int mount_it_now(struct mntent *mp, int vfsflags, char *filteropts) 198 253 { 199 int rc ;200 201 if (fakeIt) { return 0; }254 int rc = 0; 255 256 if (fakeIt) goto mtab; 202 257 203 258 // Mount, with fallback to read-only if necessary. 204 259 205 for (;;) {260 for (;;) { 206 261 rc = mount(mp->mnt_fsname, mp->mnt_dir, mp->mnt_type, 207 262 vfsflags, filteropts); 208 if (!rc || (vfsflags&MS_RDONLY) || (errno!=EACCES && errno!=EROFS))263 if (!rc || (vfsflags&MS_RDONLY) || (errno!=EACCES && errno!=EROFS)) 209 264 break; 210 265 bb_error_msg("%s is write-protected, mounting read-only", … … 220 275 /* If the mount was successful, and we're maintaining an old-style 221 276 * mtab file by hand, add the new entry to it now. */ 222 223 if(ENABLE_FEATURE_MTAB_SUPPORT && useMtab && !rc) { 277 mtab: 278 if (ENABLE_FEATURE_MTAB_SUPPORT && useMtab && !rc && !(vfsflags & MS_REMOUNT)) { 279 char *fsname; 224 280 FILE *mountTable = setmntent(bb_path_mtab_file, "a+"); 225 281 int i; 226 282 227 if(!mountTable) 228 bb_error_msg("No %s\n",bb_path_mtab_file); 283 if (!mountTable) { 284 bb_error_msg("no %s",bb_path_mtab_file); 285 goto ret; 286 } 229 287 230 288 // Add vfs string flags 231 289 232 for(i=0; mount_options[i].flags != MS_REMOUNT; i++) 233 if (mount_options[i].flags > 0) 234 append_mount_options(&(mp->mnt_opts), 235 // Shut up about the darn const. It's not important. I don't care. 236 (char *)mount_options[i].name); 290 for (i=0; mount_options[i].flags != MS_REMOUNT; i++) 291 if (mount_options[i].flags > 0 && (mount_options[i].flags & vfsflags)) 292 append_mount_options(&(mp->mnt_opts), mount_options[i].name); 237 293 238 294 // Remove trailing / (if any) from directory we mounted on 239 295 240 i = strlen(mp->mnt_dir); 241 if(i>1 && mp->mnt_dir[i-1] == '/') mp->mnt_dir[i-1] = 0; 296 i = strlen(mp->mnt_dir) - 1; 297 if (i > 0 && mp->mnt_dir[i] == '/') mp->mnt_dir[i] = 0; 298 299 // Convert to canonical pathnames as needed 300 301 mp->mnt_dir = bb_simplify_path(mp->mnt_dir); 302 fsname = 0; 303 if (!mp->mnt_type || !*mp->mnt_type) { /* bind mount */ 304 mp->mnt_fsname = fsname = bb_simplify_path(mp->mnt_fsname); 305 mp->mnt_type = (char*)"bind"; 306 } 307 mp->mnt_freq = mp->mnt_passno = 0; 242 308 243 309 // Write and close. 244 310 245 if(!mp->mnt_type || !*mp->mnt_type) mp->mnt_type="--bind";246 311 addmntent(mountTable, mp); 247 312 endmntent(mountTable); 248 if (ENABLE_FEATURE_CLEAN_UP) 249 if(strcmp(mp->mnt_type,"--bind")) mp->mnt_type = 0; 250 } 251 313 if (ENABLE_FEATURE_CLEAN_UP) { 314 free(mp->mnt_dir); 315 free(fsname); 316 } 317 } 318 ret: 252 319 return rc; 253 320 } 254 321 255 256 // Mount one directory. Handles NFS, loopback, autobind, and filesystem type 257 // detection. Returns 0 for success, nonzero for failure. 258 322 #if ENABLE_FEATURE_MOUNT_NFS 323 324 /* 325 * Linux NFS mount 326 * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com> 327 * 328 * Licensed under GPLv2, see file LICENSE in this tarball for details. 329 * 330 * Wed Feb 8 12:51:48 1995, biro@yggdrasil.com (Ross Biro): allow all port 331 * numbers to be specified on the command line. 332 * 333 * Fri, 8 Mar 1996 18:01:39, Swen Thuemmler <swen@uni-paderborn.de>: 334 * Omit the call to connect() for Linux version 1.3.11 or later. 335 * 336 * Wed Oct 1 23:55:28 1997: Dick Streefland <dick_streefland@tasking.com> 337 * Implemented the "bg", "fg" and "retry" mount options for NFS. 338 * 339 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org> 340 * - added Native Language Support 341 * 342 * Modified by Olaf Kirch and Trond Myklebust for new NFS code, 343 * plus NFSv3 stuff. 344 */ 345 346 /* This is just a warning of a common mistake. Possibly this should be a 347 * uclibc faq entry rather than in busybox... */ 348 #if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__) 349 #error "You need to build uClibc with UCLIBC_HAS_RPC for NFS support." 350 #endif 351 352 #define MOUNTPORT 635 353 #define MNTPATHLEN 1024 354 #define MNTNAMLEN 255 355 #define FHSIZE 32 356 #define FHSIZE3 64 357 358 typedef char fhandle[FHSIZE]; 359 360 typedef struct { 361 unsigned int fhandle3_len; 362 char *fhandle3_val; 363 } fhandle3; 364 365 enum mountstat3 { 366 MNT_OK = 0, 367 MNT3ERR_PERM = 1, 368 MNT3ERR_NOENT = 2, 369 MNT3ERR_IO = 5, 370 MNT3ERR_ACCES = 13, 371 MNT3ERR_NOTDIR = 20, 372 MNT3ERR_INVAL = 22, 373 MNT3ERR_NAMETOOLONG = 63, 374 MNT3ERR_NOTSUPP = 10004, 375 MNT3ERR_SERVERFAULT = 10006, 376 }; 377 typedef enum mountstat3 mountstat3; 378 379 struct fhstatus { 380 unsigned int fhs_status; 381 union { 382 fhandle fhs_fhandle; 383 } fhstatus_u; 384 }; 385 typedef struct fhstatus fhstatus; 386 387 struct mountres3_ok { 388 fhandle3 fhandle; 389 struct { 390 unsigned int auth_flavours_len; 391 char *auth_flavours_val; 392 } auth_flavours; 393 }; 394 typedef struct mountres3_ok mountres3_ok; 395 396 struct mountres3 { 397 mountstat3 fhs_status; 398 union { 399 mountres3_ok mountinfo; 400 } mountres3_u; 401 }; 402 typedef struct mountres3 mountres3; 403 404 typedef char *dirpath; 405 406 typedef char *name; 407 408 typedef struct mountbody *mountlist; 409 410 struct mountbody { 411 name ml_hostname; 412 dirpath ml_directory; 413 mountlist ml_next; 414 }; 415 typedef struct mountbody mountbody; 416 417 typedef struct groupnode *groups; 418 419 struct groupnode { 420 name gr_name; 421 groups gr_next; 422 }; 423 typedef struct groupnode groupnode; 424 425 typedef struct exportnode *exports; 426 427 struct exportnode { 428 dirpath ex_dir; 429 groups ex_groups; 430 exports ex_next; 431 }; 432 typedef struct exportnode exportnode; 433 434 struct ppathcnf { 435 int pc_link_max; 436 short pc_max_canon; 437 short pc_max_input; 438 short pc_name_max; 439 short pc_path_max; 440 short pc_pipe_buf; 441 uint8_t pc_vdisable; 442 char pc_xxx; 443 short pc_mask[2]; 444 }; 445 typedef struct ppathcnf ppathcnf; 446 447 #define MOUNTPROG 100005 448 #define MOUNTVERS 1 449 450 #define MOUNTPROC_NULL 0 451 #define MOUNTPROC_MNT 1 452 #define MOUNTPROC_DUMP 2 453 #define MOUNTPROC_UMNT 3 454 #define MOUNTPROC_UMNTALL 4 455 #define MOUNTPROC_EXPORT 5 456 #define MOUNTPROC_EXPORTALL 6 457 458 #define MOUNTVERS_POSIX 2 459 460 #define MOUNTPROC_PATHCONF 7 461 462 #define MOUNT_V3 3 463 464 #define MOUNTPROC3_NULL 0 465 #define MOUNTPROC3_MNT 1 466 #define MOUNTPROC3_DUMP 2 467 #define MOUNTPROC3_UMNT 3 468 #define MOUNTPROC3_UMNTALL 4 469 #define MOUNTPROC3_EXPORT 5 470 471 enum { 472 #ifndef NFS_FHSIZE 473 NFS_FHSIZE = 32, 474 #endif 475 #ifndef NFS_PORT 476 NFS_PORT = 2049 477 #endif 478 }; 479 480 /* 481 * We want to be able to compile mount on old kernels in such a way 482 * that the binary will work well on more recent kernels. 483 * Thus, if necessary we teach nfsmount.c the structure of new fields 484 * that will come later. 485 * 486 * Moreover, the new kernel includes conflict with glibc includes 487 * so it is easiest to ignore the kernel altogether (at compile time). 488 */ 489 490 struct nfs2_fh { 491 char data[32]; 492 }; 493 struct nfs3_fh { 494 unsigned short size; 495 unsigned char data[64]; 496 }; 497 498 struct nfs_mount_data { 499 int version; /* 1 */ 500 int fd; /* 1 */ 501 struct nfs2_fh old_root; /* 1 */ 502 int flags; /* 1 */ 503 int rsize; /* 1 */ 504 int wsize; /* 1 */ 505 int timeo; /* 1 */ 506 int retrans; /* 1 */ 507 int acregmin; /* 1 */ 508 int acregmax; /* 1 */ 509 int acdirmin; /* 1 */ 510 int acdirmax; /* 1 */ 511 struct sockaddr_in addr; /* 1 */ 512 char hostname[256]; /* 1 */ 513 int namlen; /* 2 */ 514 unsigned int bsize; /* 3 */ 515 struct nfs3_fh root; /* 4 */ 516 }; 517 518 /* bits in the flags field */ 519 enum { 520 NFS_MOUNT_SOFT = 0x0001, /* 1 */ 521 NFS_MOUNT_INTR = 0x0002, /* 1 */ 522 NFS_MOUNT_SECURE = 0x0004, /* 1 */ 523 NFS_MOUNT_POSIX = 0x0008, /* 1 */ 524 NFS_MOUNT_NOCTO = 0x0010, /* 1 */ 525 NFS_MOUNT_NOAC = 0x0020, /* 1 */ 526 NFS_MOUNT_TCP = 0x0040, /* 2 */ 527 NFS_MOUNT_VER3 = 0x0080, /* 3 */ 528 NFS_MOUNT_KERBEROS = 0x0100, /* 3 */ 529 NFS_MOUNT_NONLM = 0x0200 /* 3 */ 530 }; 531 532 533 /* 534 * We need to translate between nfs status return values and 535 * the local errno values which may not be the same. 536 * 537 * Andreas Schwab <schwab@LS5.informatik.uni-dortmund.de>: change errno: 538 * "after #include <errno.h> the symbol errno is reserved for any use, 539 * it cannot even be used as a struct tag or field name". 540 */ 541 542 #ifndef EDQUOT 543 #define EDQUOT ENOSPC 544 #endif 545 546 // Convert each NFSERR_BLAH into EBLAH 547 548 static const struct { 549 int stat; 550 int errnum; 551 } nfs_errtbl[] = { 552 {0,0}, {1,EPERM}, {2,ENOENT}, {5,EIO}, {6,ENXIO}, {13,EACCES}, {17,EEXIST}, 553 {19,ENODEV}, {20,ENOTDIR}, {21,EISDIR}, {22,EINVAL}, {27,EFBIG}, 554 {28,ENOSPC}, {30,EROFS}, {63,ENAMETOOLONG}, {66,ENOTEMPTY}, {69,EDQUOT}, 555 {70,ESTALE}, {71,EREMOTE}, {-1,EIO} 556 }; 557 558 static char *nfs_strerror(int status) 559 { 560 int i; 561 static char buf[sizeof("unknown nfs status return value: ") + sizeof(int)*3]; 562 563 for (i = 0; nfs_errtbl[i].stat != -1; i++) { 564 if (nfs_errtbl[i].stat == status) 565 return strerror(nfs_errtbl[i].errnum); 566 } 567 sprintf(buf, "unknown nfs status return value: %d", status); 568 return buf; 569 } 570 571 static bool_t xdr_fhandle(XDR *xdrs, fhandle objp) 572 { 573 if (!xdr_opaque(xdrs, objp, FHSIZE)) 574 return FALSE; 575 return TRUE; 576 } 577 578 static bool_t xdr_fhstatus(XDR *xdrs, fhstatus *objp) 579 { 580 if (!xdr_u_int(xdrs, &objp->fhs_status)) 581 return FALSE; 582 switch (objp->fhs_status) { 583 case 0: 584 if (!xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle)) 585 return FALSE; 586 break; 587 default: 588 break; 589 } 590 return TRUE; 591 } 592 593 static bool_t xdr_dirpath(XDR *xdrs, dirpath *objp) 594 { 595 if (!xdr_string(xdrs, objp, MNTPATHLEN)) 596 return FALSE; 597 return TRUE; 598 } 599 600 static bool_t xdr_fhandle3(XDR *xdrs, fhandle3 *objp) 601 { 602 if (!xdr_bytes(xdrs, (char **)&objp->fhandle3_val, (unsigned int *) &objp->fhandle3_len, FHSIZE3)) 603 return FALSE; 604 return TRUE; 605 } 606 607 static bool_t xdr_mountres3_ok(XDR *xdrs, mountres3_ok *objp) 608 { 609 if (!xdr_fhandle3(xdrs, &objp->fhandle)) 610 return FALSE; 611 if (!xdr_array(xdrs, &(objp->auth_flavours.auth_flavours_val), &(objp->auth_flavours.auth_flavours_len), ~0, 612 sizeof (int), (xdrproc_t) xdr_int)) 613 return FALSE; 614 return TRUE; 615 } 616 617 static bool_t xdr_mountstat3(XDR *xdrs, mountstat3 *objp) 618 { 619 if (!xdr_enum(xdrs, (enum_t *) objp)) 620 return FALSE; 621 return TRUE; 622 } 623 624 static bool_t xdr_mountres3(XDR *xdrs, mountres3 *objp) 625 { 626 if (!xdr_mountstat3(xdrs, &objp->fhs_status)) 627 return FALSE; 628 switch (objp->fhs_status) { 629 case MNT_OK: 630 if (!xdr_mountres3_ok(xdrs, &objp->mountres3_u.mountinfo)) 631 return FALSE; 632 break; 633 default: 634 break; 635 } 636 return TRUE; 637 } 638 639 #define MAX_NFSPROT ((nfs_mount_version >= 4) ? 3 : 2) 640 641 /* 642 * nfs_mount_version according to the sources seen at compile time. 643 */ 644 static int nfs_mount_version; 645 static int kernel_version; 646 647 /* 648 * Unfortunately, the kernel prints annoying console messages 649 * in case of an unexpected nfs mount version (instead of 650 * just returning some error). Therefore we'll have to try 651 * and figure out what version the kernel expects. 652 * 653 * Variables: 654 * KERNEL_NFS_MOUNT_VERSION: kernel sources at compile time 655 * NFS_MOUNT_VERSION: these nfsmount sources at compile time 656 * nfs_mount_version: version this source and running kernel can handle 657 */ 658 static void 659 find_kernel_nfs_mount_version(void) 660 { 661 if (kernel_version) 662 return; 663 664 nfs_mount_version = 4; /* default */ 665 666 kernel_version = get_linux_version_code(); 667 if (kernel_version) { 668 if (kernel_version < KERNEL_VERSION(2,1,32)) 669 nfs_mount_version = 1; 670 else if (kernel_version < KERNEL_VERSION(2,2,18) || 671 (kernel_version >= KERNEL_VERSION(2,3,0) && 672 kernel_version < KERNEL_VERSION(2,3,99))) 673 nfs_mount_version = 3; 674 /* else v4 since 2.3.99pre4 */ 675 } 676 } 677 678 static struct pmap * 679 get_mountport(struct sockaddr_in *server_addr, 680 long unsigned prog, 681 long unsigned version, 682 long unsigned proto, 683 long unsigned port) 684 { 685 struct pmaplist *pmap; 686 static struct pmap p = {0, 0, 0, 0}; 687 688 server_addr->sin_port = PMAPPORT; 689 /* glibc 2.4 (still) has pmap_getmaps(struct sockaddr_in *). 690 * I understand it like "IPv6 for this is not 100% ready" */ 691 pmap = pmap_getmaps(server_addr); 692 693 if (version > MAX_NFSPROT) 694 version = MAX_NFSPROT; 695 if (!prog) 696 prog = MOUNTPROG; 697 p.pm_prog = prog; 698 p.pm_vers = version; 699 p.pm_prot = proto; 700 p.pm_port = port; 701 702 while (pmap) { 703 if (pmap->pml_map.pm_prog != prog) 704 goto next; 705 if (!version && p.pm_vers > pmap->pml_map.pm_vers) 706 goto next; 707 if (version > 2 && pmap->pml_map.pm_vers != version) 708 goto next; 709 if (version && version <= 2 && pmap->pml_map.pm_vers > 2) 710 goto next; 711 if (pmap->pml_map.pm_vers > MAX_NFSPROT || 712 (proto && p.pm_prot && pmap->pml_map.pm_prot != proto) || 713 (port && pmap->pml_map.pm_port != port)) 714 goto next; 715 memcpy(&p, &pmap->pml_map, sizeof(p)); 716 next: 717 pmap = pmap->pml_next; 718 } 719 if (!p.pm_vers) 720 p.pm_vers = MOUNTVERS; 721 if (!p.pm_port) 722 p.pm_port = MOUNTPORT; 723 if (!p.pm_prot) 724 p.pm_prot = IPPROTO_TCP; 725 return &p; 726 } 727 728 static int daemonize(void) 729 { 730 int fd; 731 int pid = fork(); 732 if (pid < 0) /* error */ 733 return -errno; 734 if (pid > 0) /* parent */ 735 return 0; 736 /* child */ 737 fd = xopen(bb_dev_null, O_RDWR); 738 dup2(fd, 0); 739 dup2(fd, 1); 740 dup2(fd, 2); 741 while (fd > 2) close(fd--); 742 setsid(); 743 openlog(applet_name, LOG_PID, LOG_DAEMON); 744 logmode = LOGMODE_SYSLOG; 745 return 1; 746 } 747 748 // TODO 749 static inline int we_saw_this_host_before(const char *hostname) 750 { 751 return 0; 752 } 753 754 /* RPC strerror analogs are terminally idiotic: 755 * *mandatory* prefix and \n at end. 756 * This hopefully helps. Usage: 757 * error_msg_rpc(clnt_*error*(" ")) */ 758 static void error_msg_rpc(const char *msg) 759 { 760 int len; 761 while (msg[0] == ' ' || msg[0] == ':') msg++; 762 len = strlen(msg); 763 while (len && msg[len-1] == '\n') len--; 764 bb_error_msg("%.*s", len, msg); 765 } 766 767 // NB: mp->xxx fields may be trashed on exit 768 static int nfsmount(struct mntent *mp, int vfsflags, char *filteropts) 769 { 770 CLIENT *mclient; 771 char *hostname; 772 char *pathname; 773 char *mounthost; 774 struct nfs_mount_data data; 775 char *opt; 776 struct hostent *hp; 777 struct sockaddr_in server_addr; 778 struct sockaddr_in mount_server_addr; 779 int msock, fsock; 780 union { 781 struct fhstatus nfsv2; 782 struct mountres3 nfsv3; 783 } status; 784 int daemonized; 785 char *s; 786 int port; 787 int mountport; 788 int proto; 789 int bg; 790 int soft; 791 int intr; 792 int posix; 793 int nocto; 794 int noac; 795 int nolock; 796 int retry; 797 int tcp; 798 int mountprog; 799 int mountvers; 800 int nfsprog; 801 int nfsvers; 802 int retval; 803 804 find_kernel_nfs_mount_version(); 805 806 daemonized = 0; 807 mounthost = NULL; 808 retval = ETIMEDOUT; 809 msock = fsock = -1; 810 mclient = NULL; 811 812 /* NB: hostname, mounthost, filteropts must be free()d prior to return */ 813 814 filteropts = xstrdup(filteropts); /* going to trash it later... */ 815 816 hostname = xstrdup(mp->mnt_fsname); 817 /* mount_main() guarantees that ':' is there */ 818 s = strchr(hostname, ':'); 819 pathname = s + 1; 820 *s = '\0'; 821 /* Ignore all but first hostname in replicated mounts 822 until they can be fully supported. (mack@sgi.com) */ 823 s = strchr(hostname, ','); 824 if (s) { 825 *s = '\0'; 826 bb_error_msg("warning: multiple hostnames not supported"); 827 } 828 829 server_addr.sin_family = AF_INET; 830 if (!inet_aton(hostname, &server_addr.sin_addr)) { 831 hp = gethostbyname(hostname); 832 if (hp == NULL) { 833 bb_herror_msg("%s", hostname); 834 goto fail; 835 } 836 if (hp->h_length > sizeof(struct in_addr)) { 837 bb_error_msg("got bad hp->h_length"); 838 hp->h_length = sizeof(struct in_addr); 839 } 840 memcpy(&server_addr.sin_addr, 841 hp->h_addr, hp->h_length); 842 } 843 844 memcpy(&mount_server_addr, &server_addr, sizeof(mount_server_addr)); 845 846 /* add IP address to mtab options for use when unmounting */ 847 848 if (!mp->mnt_opts) { /* TODO: actually mp->mnt_opts is never NULL */ 849 mp->mnt_opts = xasprintf("addr=%s", inet_ntoa(server_addr.sin_addr)); 850 } else { 851 char *tmp = xasprintf("%s%saddr=%s", mp->mnt_opts, 852 mp->mnt_opts[0] ? "," : "", 853 inet_ntoa(server_addr.sin_addr)); 854 free(mp->mnt_opts); 855 mp->mnt_opts = tmp; 856 } 857 858 /* Set default options. 859 * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to 860 * let the kernel decide. 861 * timeo is filled in after we know whether it'll be TCP or UDP. */ 862 memset(&data, 0, sizeof(data)); 863 data.retrans = 3; 864 data.acregmin = 3; 865 data.acregmax = 60; 866 data.acdirmin = 30; 867 data.acdirmax = 60; 868 data.namlen = NAME_MAX; 869 870 bg = 0; 871 soft = 0; 872 intr = 0; 873 posix = 0; 874 nocto = 0; 875 nolock = 0; 876 noac = 0; 877 retry = 10000; /* 10000 minutes ~ 1 week */ 878 tcp = 0; 879 880 mountprog = MOUNTPROG; 881 mountvers = 0; 882 port = 0; 883 mountport = 0; 884 nfsprog = 100003; 885 nfsvers = 0; 886 887 /* parse options */ 888 if (filteropts) for (opt = strtok(filteropts, ","); opt; opt = strtok(NULL, ",")) { 889 char *opteq = strchr(opt, '='); 890 if (opteq) { 891 static const char options[] ALIGN1 = 892 /* 0 */ "rsize\0" 893 /* 1 */ "wsize\0" 894 /* 2 */ "timeo\0" 895 /* 3 */ "retrans\0" 896 /* 4 */ "acregmin\0" 897 /* 5 */ "acregmax\0" 898 /* 6 */ "acdirmin\0" 899 /* 7 */ "acdirmax\0" 900 /* 8 */ "actimeo\0" 901 /* 9 */ "retry\0" 902 /* 10 */ "port\0" 903 /* 11 */ "mountport\0" 904 /* 12 */ "mounthost\0" 905 /* 13 */ "mountprog\0" 906 /* 14 */ "mountvers\0" 907 /* 15 */ "nfsprog\0" 908 /* 16 */ "nfsvers\0" 909 /* 17 */ "vers\0" 910 /* 18 */ "proto\0" 911 /* 19 */ "namlen\0" 912 /* 20 */ "addr\0"; 913 int val = xatoi_u(opteq + 1); 914 *opteq = '\0'; 915 switch (index_in_strings(options, opt)) { 916 case 0: // "rsize" 917 data.rsize = val; 918 break; 919 case 1: // "wsize" 920 data.wsize = val; 921 break; 922 case 2: // "timeo" 923 data.timeo = val; 924 break; 925 case 3: // "retrans" 926 data.retrans = val; 927 break; 928 case 4: // "acregmin" 929 data.acregmin = val; 930 break; 931 case 5: // "acregmax" 932 data.acregmax = val; 933 break; 934 case 6: // "acdirmin" 935 data.acdirmin = val; 936 break; 937 case 7: // "acdirmax" 938 data.acdirmax = val; 939 break; 940 case 8: // "actimeo" 941 data.acregmin = val; 942 data.acregmax = val; 943 data.acdirmin = val; 944 data.acdirmax = val; 945 break; 946 case 9: // "retry" 947 retry = val; 948 break; 949 case 10: // "port" 950 port = val; 951 break; 952 case 11: // "mountport" 953 mountport = val; 954 break; 955 case 12: // "mounthost" 956 mounthost = xstrndup(opteq+1, 957 strcspn(opteq+1," \t\n\r,")); 958 break; 959 case 13: // "mountprog" 960 mountprog = val; 961 break; 962 case 14: // "mountvers" 963 mountvers = val; 964 break; 965 case 15: // "nfsprog" 966 nfsprog = val; 967 break; 968 case 16: // "nfsvers" 969 case 17: // "vers" 970 nfsvers = val; 971 break; 972 case 18: // "proto" 973 if (!strncmp(opteq+1, "tcp", 3)) 974 tcp = 1; 975 else if (!strncmp(opteq+1, "udp", 3)) 976 tcp = 0; 977 else 978 bb_error_msg("warning: unrecognized proto= option"); 979 break; 980 case 19: // "namlen" 981 if (nfs_mount_version >= 2) 982 data.namlen = val; 983 else 984 bb_error_msg("warning: option namlen is not supported\n"); 985 break; 986 case 20: // "addr" - ignore 987 break; 988 default: 989 bb_error_msg("unknown nfs mount parameter: %s=%d", opt, val); 990 goto fail; 991 } 992 } 993 else { 994 static const char options[] ALIGN1 = 995 "bg\0" 996 "fg\0" 997 "soft\0" 998 "hard\0" 999 "intr\0" 1000 "posix\0" 1001 "cto\0" 1002 "ac\0" 1003 "tcp\0" 1004 "udp\0" 1005 "lock\0"; 1006 int val = 1; 1007 if (!strncmp(opt, "no", 2)) { 1008 val = 0; 1009 opt += 2; 1010 } 1011 switch (index_in_strings(options, opt)) { 1012 case 0: // "bg" 1013 bg = val; 1014 break; 1015 case 1: // "fg" 1016 bg = !val; 1017 break; 1018 case 2: // "soft" 1019 soft = val; 1020 break; 1021 case 3: // "hard" 1022 soft = !val; 1023 break; 1024 case 4: // "intr" 1025 intr = val; 1026 break; 1027 case 5: // "posix" 1028 posix = val; 1029 break; 1030 case 6: // "cto" 1031 nocto = !val; 1032 break; 1033 case 7: // "ac" 1034 noac = !val; 1035 break; 1036 case 8: // "tcp" 1037 tcp = val; 1038 break; 1039 case 9: // "udp" 1040 tcp = !val; 1041 break; 1042 case 10: // "lock" 1043 if (nfs_mount_version >= 3) 1044 nolock = !val; 1045 else 1046 bb_error_msg("warning: option nolock is not supported"); 1047 break; 1048 default: 1049 bb_error_msg("unknown nfs mount option: %s%s", val ? "" : "no", opt); 1050 goto fail; 1051 } 1052 } 1053 } 1054 proto = (tcp) ? IPPROTO_TCP : IPPROTO_UDP; 1055 1056 data.flags = (soft ? NFS_MOUNT_SOFT : 0) 1057 | (intr ? NFS_MOUNT_INTR : 0) 1058 | (posix ? NFS_MOUNT_POSIX : 0) 1059 | (nocto ? NFS_MOUNT_NOCTO : 0) 1060 | (noac ? NFS_MOUNT_NOAC : 0); 1061 if (nfs_mount_version >= 2) 1062 data.flags |= (tcp ? NFS_MOUNT_TCP : 0); 1063 if (nfs_mount_version >= 3) 1064 data.flags |= (nolock ? NFS_MOUNT_NONLM : 0); 1065 if (nfsvers > MAX_NFSPROT || mountvers > MAX_NFSPROT) { 1066 bb_error_msg("NFSv%d not supported", nfsvers); 1067 goto fail; 1068 } 1069 if (nfsvers && !mountvers) 1070 mountvers = (nfsvers < 3) ? 1 : nfsvers; 1071 if (nfsvers && nfsvers < mountvers) { 1072 mountvers = nfsvers; 1073 } 1074 1075 /* Adjust options if none specified */ 1076 if (!data.timeo) 1077 data.timeo = tcp ? 70 : 7; 1078 1079 data.version = nfs_mount_version; 1080 1081 if (vfsflags & MS_REMOUNT) 1082 goto do_mount; 1083 1084 /* 1085 * If the previous mount operation on the same host was 1086 * backgrounded, and the "bg" for this mount is also set, 1087 * give up immediately, to avoid the initial timeout. 1088 */ 1089 if (bg && we_saw_this_host_before(hostname)) { 1090 daemonized = daemonize(); /* parent or error */ 1091 if (daemonized <= 0) { /* parent or error */ 1092 retval = -daemonized; 1093 goto ret; 1094 } 1095 } 1096 1097 /* create mount daemon client */ 1098 /* See if the nfs host = mount host. */ 1099 if (mounthost) { 1100 if (mounthost[0] >= '0' && mounthost[0] <= '9') { 1101 mount_server_addr.sin_family = AF_INET; 1102 mount_server_addr.sin_addr.s_addr = inet_addr(hostname); 1103 } else { 1104 hp = gethostbyname(mounthost); 1105 if (hp == NULL) { 1106 bb_herror_msg("%s", mounthost); 1107 goto fail; 1108 } else { 1109 if (hp->h_length > sizeof(struct in_addr)) { 1110 bb_error_msg("got bad hp->h_length?"); 1111 hp->h_length = sizeof(struct in_addr); 1112 } 1113 mount_server_addr.sin_family = AF_INET; 1114 memcpy(&mount_server_addr.sin_addr, 1115 hp->h_addr, hp->h_length); 1116 } 1117 } 1118 } 1119 1120 /* 1121 * The following loop implements the mount retries. When the mount 1122 * times out, and the "bg" option is set, we background ourself 1123 * and continue trying. 1124 * 1125 * The case where the mount point is not present and the "bg" 1126 * option is set, is treated as a timeout. This is done to 1127 * support nested mounts. 1128 * 1129 * The "retry" count specified by the user is the number of 1130 * minutes to retry before giving up. 1131 */ 1132 { 1133 struct timeval total_timeout; 1134 struct timeval retry_timeout; 1135 struct pmap* pm_mnt; 1136 time_t t; 1137 time_t prevt; 1138 time_t timeout; 1139 1140 retry_timeout.tv_sec = 3; 1141 retry_timeout.tv_usec = 0; 1142 total_timeout.tv_sec = 20; 1143 total_timeout.tv_usec = 0; 1144 timeout = time(NULL) + 60 * retry; 1145 prevt = 0; 1146 t = 30; 1147 retry: 1148 /* be careful not to use too many CPU cycles */ 1149 if (t - prevt < 30) 1150 sleep(30); 1151 1152 pm_mnt = get_mountport(&mount_server_addr, 1153 mountprog, 1154 mountvers, 1155 proto, 1156 mountport); 1157 nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers; 1158 1159 /* contact the mount daemon via TCP */ 1160 mount_server_addr.sin_port = htons(pm_mnt->pm_port); 1161 msock = RPC_ANYSOCK; 1162 1163 switch (pm_mnt->pm_prot) { 1164 case IPPROTO_UDP: 1165 mclient = clntudp_create(&mount_server_addr, 1166 pm_mnt->pm_prog, 1167 pm_mnt->pm_vers, 1168 retry_timeout, 1169 &msock); 1170 if (mclient) 1171 break; 1172 mount_server_addr.sin_port = htons(pm_mnt->pm_port); 1173 msock = RPC_ANYSOCK; 1174 case IPPROTO_TCP: 1175 mclient = clnttcp_create(&mount_server_addr, 1176 pm_mnt->pm_prog, 1177 pm_mnt->pm_vers, 1178 &msock, 0, 0); 1179 break; 1180 default: 1181 mclient = 0; 1182 } 1183 if (!mclient) { 1184 if (!daemonized && prevt == 0) 1185 error_msg_rpc(clnt_spcreateerror(" ")); 1186 } else { 1187 enum clnt_stat clnt_stat; 1188 /* try to mount hostname:pathname */ 1189 mclient->cl_auth = authunix_create_default(); 1190 1191 /* make pointers in xdr_mountres3 NULL so 1192 * that xdr_array allocates memory for us 1193 */ 1194 memset(&status, 0, sizeof(status)); 1195 1196 if (pm_mnt->pm_vers == 3) 1197 clnt_stat = clnt_call(mclient, MOUNTPROC3_MNT, 1198 (xdrproc_t) xdr_dirpath, 1199 (caddr_t) &pathname, 1200 (xdrproc_t) xdr_mountres3, 1201 (caddr_t) &status, 1202 total_timeout); 1203 else 1204 clnt_stat = clnt_call(mclient, MOUNTPROC_MNT, 1205 (xdrproc_t) xdr_dirpath, 1206 (caddr_t) &pathname, 1207 (xdrproc_t) xdr_fhstatus, 1208 (caddr_t) &status, 1209 total_timeout); 1210 1211 if (clnt_stat == RPC_SUCCESS) 1212 goto prepare_kernel_data; /* we're done */ 1213 if (errno != ECONNREFUSED) { 1214 error_msg_rpc(clnt_sperror(mclient, " ")); 1215 goto fail; /* don't retry */ 1216 } 1217 /* Connection refused */ 1218 if (!daemonized && prevt == 0) /* print just once */ 1219 error_msg_rpc(clnt_sperror(mclient, " ")); 1220 auth_destroy(mclient->cl_auth); 1221 clnt_destroy(mclient); 1222 mclient = 0; 1223 close(msock); 1224 } 1225 1226 /* Timeout. We are going to retry... maybe */ 1227 1228 if (!bg) 1229 goto fail; 1230 if (!daemonized) { 1231 daemonized = daemonize(); 1232 if (daemonized <= 0) { /* parent or error */ 1233 retval = -daemonized; 1234 goto ret; 1235 } 1236 } 1237 prevt = t; 1238 t = time(NULL); 1239 if (t >= timeout) 1240 /* TODO error message */ 1241 goto fail; 1242 1243 goto retry; 1244 } 1245 1246 prepare_kernel_data: 1247 1248 if (nfsvers == 2) { 1249 if (status.nfsv2.fhs_status != 0) { 1250 bb_error_msg("%s:%s failed, reason given by server: %s", 1251 hostname, pathname, 1252 nfs_strerror(status.nfsv2.fhs_status)); 1253 goto fail; 1254 } 1255 memcpy(data.root.data, 1256 (char *) status.nfsv2.fhstatus_u.fhs_fhandle, 1257 NFS_FHSIZE); 1258 data.root.size = NFS_FHSIZE; 1259 memcpy(data.old_root.data, 1260 (char *) status.nfsv2.fhstatus_u.fhs_fhandle, 1261 NFS_FHSIZE); 1262 } else { 1263 fhandle3 *my_fhandle; 1264 if (status.nfsv3.fhs_status != 0) { 1265 bb_error_msg("%s:%s failed, reason given by server: %s", 1266 hostname, pathname, 1267 nfs_strerror(status.nfsv3.fhs_status)); 1268 goto fail; 1269 } 1270 my_fhandle = &status.nfsv3.mountres3_u.mountinfo.fhandle; 1271 memset(data.old_root.data, 0, NFS_FHSIZE); 1272 memset(&data.root, 0, sizeof(data.root)); 1273 data.root.size = my_fhandle->fhandle3_len; 1274 memcpy(data.root.data, 1275 (char *) my_fhandle->fhandle3_val, 1276 my_fhandle->fhandle3_len); 1277 1278 data.flags |= NFS_MOUNT_VER3; 1279 } 1280 1281 /* create nfs socket for kernel */ 1282 1283 if (tcp) { 1284 if (nfs_mount_version < 3) { 1285 bb_error_msg("NFS over TCP is not supported"); 1286 goto fail; 1287 } 1288 fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 1289 } else 1290 fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 1291 if (fsock < 0) { 1292 bb_perror_msg("nfs socket"); 1293 goto fail; 1294 } 1295 if (bindresvport(fsock, 0) < 0) { 1296 bb_perror_msg("nfs bindresvport"); 1297 goto fail; 1298 } 1299 if (port == 0) { 1300 server_addr.sin_port = PMAPPORT; 1301 port = pmap_getport(&server_addr, nfsprog, nfsvers, 1302 tcp ? IPPROTO_TCP : IPPROTO_UDP); 1303 if (port == 0) 1304 port = NFS_PORT; 1305 } 1306 server_addr.sin_port = htons(port); 1307 1308 /* prepare data structure for kernel */ 1309 1310 data.fd = fsock; 1311 memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr)); 1312 strncpy(data.hostname, hostname, sizeof(data.hostname)); 1313 1314 /* clean up */ 1315 1316 auth_destroy(mclient->cl_auth); 1317 clnt_destroy(mclient); 1318 close(msock); 1319 1320 if (bg) { 1321 /* We must wait until mount directory is available */ 1322 struct stat statbuf; 1323 int delay = 1; 1324 while (stat(mp->mnt_dir, &statbuf) == -1) { 1325 if (!daemonized) { 1326 daemonized = daemonize(); 1327 if (daemonized <= 0) { /* parent or error */ 1328 retval = -daemonized; 1329 goto ret; 1330 } 1331 } 1332 sleep(delay); /* 1, 2, 4, 8, 16, 30, ... */ 1333 delay *= 2; 1334 if (delay > 30) 1335 delay = 30; 1336 } 1337 } 1338 1339 do_mount: /* perform actual mount */ 1340 1341 mp->mnt_type = (char*)"nfs"; 1342 retval = mount_it_now(mp, vfsflags, (char*)&data); 1343 goto ret; 1344 1345 fail: /* abort */ 1346 1347 if (msock != -1) { 1348 if (mclient) { 1349 auth_destroy(mclient->cl_auth); 1350 clnt_destroy(mclient); 1351 } 1352 close(msock); 1353 } 1354 if (fsock != -1) 1355 close(fsock); 1356 1357 ret: 1358 free(hostname); 1359 free(mounthost); 1360 free(filteropts); 1361 return retval; 1362 } 1363 1364 #else /* !ENABLE_FEATURE_MOUNT_NFS */ 1365 1366 /* Never called. Call should be optimized out. */ 1367 int nfsmount(struct mntent *mp, int vfsflags, char *filteropts); 1368 1369 #endif /* !ENABLE_FEATURE_MOUNT_NFS */ 1370 1371 // Mount one directory. Handles CIFS, NFS, loopback, autobind, and filesystem 1372 // type detection. Returns 0 for success, nonzero for failure. 1373 // NB: mp->xxx fields may be trashed on exit 259 1374 static int singlemount(struct mntent *mp, int ignore_busy) 260 1375 { … … 268 1383 // Treat fstype "auto" as unspecified. 269 1384 270 if (mp->mnt_type && !strcmp(mp->mnt_type,"auto")) mp->mnt_type = 0; 1385 if (mp->mnt_type && strcmp(mp->mnt_type,"auto") == 0) 1386 mp->mnt_type = 0; 1387 1388 // Might this be an CIFS filesystem? 1389 1390 if (ENABLE_FEATURE_MOUNT_CIFS 1391 && (!mp->mnt_type || strcmp(mp->mnt_type,"cifs") == 0) 1392 && (mp->mnt_fsname[0]=='/' || mp->mnt_fsname[0]=='\\') 1393 && mp->mnt_fsname[0]==mp->mnt_fsname[1] 1394 ) { 1395 len_and_sockaddr *lsa; 1396 char *ip, *dotted; 1397 char *s; 1398 1399 rc = 1; 1400 // Replace '/' with '\' and verify that unc points to "//server/share". 1401 1402 for (s = mp->mnt_fsname; *s; ++s) 1403 if (*s == '/') *s = '\\'; 1404 1405 // get server IP 1406 1407 s = strrchr(mp->mnt_fsname, '\\'); 1408 if (s <= mp->mnt_fsname+1) goto report_error; 1409 *s = '\0'; 1410 lsa = host2sockaddr(mp->mnt_fsname+2, 0); 1411 *s = '\\'; 1412 if (!lsa) goto report_error; 1413 1414 // insert ip=... option into string flags. 1415 1416 dotted = xmalloc_sockaddr2dotted_noport(&lsa->sa); 1417 ip = xasprintf("ip=%s", dotted); 1418 parse_mount_options(ip, &filteropts); 1419 1420 // compose new unc '\\server-ip\share' 1421 // (s => slash after hostname) 1422 1423 mp->mnt_fsname = xasprintf("\\\\%s%s", dotted, s); 1424 1425 // lock is required 1426 vfsflags |= MS_MANDLOCK; 1427 1428 mp->mnt_type = (char*)"cifs"; 1429 rc = mount_it_now(mp, vfsflags, filteropts); 1430 if (ENABLE_FEATURE_CLEAN_UP) { 1431 free(mp->mnt_fsname); 1432 free(ip); 1433 free(dotted); 1434 free(lsa); 1435 } 1436 goto report_error; 1437 } 271 1438 272 1439 // Might this be an NFS filesystem? 273 1440 274 if (ENABLE_FEATURE_MOUNT_NFS && 275 (!mp->mnt_type || !strcmp(mp->mnt_type,"nfs")) && 276 strchr(mp->mnt_fsname, ':') != NULL) 277 { 278 if (nfsmount(mp->mnt_fsname, mp->mnt_dir, &vfsflags, &filteropts, 1)) { 279 bb_perror_msg("nfsmount failed"); 280 goto report_error; 281 } else { 282 // Strangely enough, nfsmount() doesn't actually mount() anything. 283 mp->mnt_type = "nfs"; 284 rc = mount_it_now(mp, vfsflags, filteropts); 285 if (ENABLE_FEATURE_CLEAN_UP) free(filteropts); 286 287 goto report_error; 288 } 1441 if (ENABLE_FEATURE_MOUNT_NFS 1442 && (!mp->mnt_type || !strcmp(mp->mnt_type, "nfs")) 1443 && strchr(mp->mnt_fsname, ':') != NULL 1444 ) { 1445 rc = nfsmount(mp, vfsflags, filteropts); 1446 goto report_error; 289 1447 } 290 1448 291 1449 // Look at the file. (Not found isn't a failure for remount, or for 292 1450 // a synthetic filesystem like proc or sysfs.) 293 294 if (stat(mp->mnt_fsname, &st)); 295 else if (!(vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE))) { 1451 // (We use stat, not lstat, in order to allow 1452 // mount symlink_to_file_or_blkdev dir) 1453 1454 if (!stat(mp->mnt_fsname, &st) 1455 && !(vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE)) 1456 ) { 296 1457 // Do we need to allocate a loopback device for it? 297 1458 298 1459 if (ENABLE_FEATURE_MOUNT_LOOP && S_ISREG(st.st_mode)) { 299 1460 loopFile = bb_simplify_path(mp->mnt_fsname); 300 mp->mnt_fsname = 0; 301 switch(set_loop(&(mp->mnt_fsname), loopFile, 0)) { 302 case 0: 303 case 1: 304 break; 305 default: 306 bb_error_msg( errno == EPERM || errno == EACCES 307 ? bb_msg_perm_denied_are_you_root 308 : "Couldn't setup loop device"); 309 return errno; 1461 mp->mnt_fsname = NULL; /* will receive malloced loop dev name */ 1462 if (set_loop(&(mp->mnt_fsname), loopFile, 0) < 0) { 1463 if (errno == EPERM || errno == EACCES) 1464 bb_error_msg(bb_msg_perm_denied_are_you_root); 1465 else 1466 bb_perror_msg("cannot setup loop device"); 1467 return errno; 310 1468 } 311 1469 312 1470 // Autodetect bind mounts 313 1471 314 } else if (S_ISDIR(st.st_mode) && !mp->mnt_type) vfsflags |= MS_BIND; 1472 } else if (S_ISDIR(st.st_mode) && !mp->mnt_type) 1473 vfsflags |= MS_BIND; 315 1474 } 316 1475 … … 320 1479 if (mp->mnt_type || (vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE))) 321 1480 rc = mount_it_now(mp, vfsflags, filteropts); 322 323 // Loop through filesystem types until mount succeeds or we run out324 325 1481 else { 1482 // Loop through filesystem types until mount succeeds 1483 // or we run out 326 1484 327 1485 /* Initialize list of block backed filesystems. This has to be … … 337 1495 for (fl = fslist; fl; fl = fl->link) { 338 1496 mp->mnt_type = fl->data; 339 340 if (!(rc = mount_it_now(mp,vfsflags, filteropts))) break; 341 342 mp->mnt_type = 0; 343 } 344 } 345 346 if (ENABLE_FEATURE_CLEAN_UP) free(filteropts); 1497 rc = mount_it_now(mp, vfsflags, filteropts); 1498 if (!rc) break; 1499 } 1500 } 347 1501 348 1502 // If mount failed, clean up loop file (if any). … … 355 1509 } 356 1510 } 357 report_error: 358 if (rc && errno == EBUSY && ignore_busy) rc = 0; 1511 1512 report_error: 1513 if (ENABLE_FEATURE_CLEAN_UP) 1514 free(filteropts); 1515 1516 if (rc && errno == EBUSY && ignore_busy) 1517 rc = 0; 359 1518 if (rc < 0) 360 bb_perror_msg(" Mounting %s on %s failed", mp->mnt_fsname, mp->mnt_dir);1519 bb_perror_msg("mounting %s on %s failed", mp->mnt_fsname, mp->mnt_dir); 361 1520 362 1521 return rc; … … 366 1525 // each directory to be mounted. 367 1526 1527 static const char must_be_root[] ALIGN1 = "you must be root"; 1528 1529 int mount_main(int argc, char **argv); 368 1530 int mount_main(int argc, char **argv) 369 1531 { 370 char *cmdopts = bb_xstrdup(""), *fstabname, *fstype=0, *storage_path=0; 1532 enum { OPT_ALL = 0x10 }; 1533 1534 char *cmdopts = xstrdup(""), *fstype=0, *storage_path=0; 1535 char *opt_o; 1536 const char *fstabname; 371 1537 FILE *fstab; 372 int i, opt, all = FALSE, rc = 0; 1538 int i, j, rc = 0; 1539 unsigned opt; 373 1540 struct mntent mtpair[2], *mtcur = mtpair; 1541 SKIP_DESKTOP(const int nonroot = 0;) 1542 USE_DESKTOP( int nonroot = (getuid() != 0);) 374 1543 375 1544 /* parse long options, like --bind and --move. Note that -o option 376 1545 * and --option are synonymous. Yes, this means --remount,rw works. */ 377 1546 378 for (i = opt= 0; i < argc; i++) {1547 for (i = j = 0; i < argc; i++) { 379 1548 if (argv[i][0] == '-' && argv[i][1] == '-') { 380 append_mount_options(&cmdopts,argv[i]+2); 381 } else argv[opt++] = argv[i]; 382 } 383 argc = opt; 1549 append_mount_options(&cmdopts, argv[i]+2); 1550 } else argv[j++] = argv[i]; 1551 } 1552 argv[j] = 0; 1553 argc = j; 384 1554 385 1555 // Parse remaining options 386 1556 387 while ((opt = getopt(argc, argv, "o:t:rwavnf")) > 0) { 388 switch (opt) { 389 case 'o': 390 append_mount_options(&cmdopts, optarg); 391 break; 392 case 't': 393 fstype = optarg; 394 break; 395 case 'r': 396 append_mount_options(&cmdopts, "ro"); 397 break; 398 case 'w': 399 append_mount_options(&cmdopts, "rw"); 400 break; 401 case 'a': 402 all = TRUE; 403 break; 404 case 'n': 405 USE_FEATURE_MTAB_SUPPORT(useMtab = FALSE;) 406 break; 407 case 'f': 408 USE_FEATURE_MTAB_SUPPORT(fakeIt = FALSE;) 409 break; 410 case 'v': 411 break; // ignore -v 412 default: 413 bb_show_usage(); 414 } 415 } 1557 opt = getopt32(argv, "o:t:rwanfvs", &opt_o, &fstype); 1558 if (opt & 0x1) append_mount_options(&cmdopts, opt_o); // -o 1559 //if (opt & 0x2) // -t 1560 if (opt & 0x4) append_mount_options(&cmdopts, "ro"); // -r 1561 if (opt & 0x8) append_mount_options(&cmdopts, "rw"); // -w 1562 //if (opt & 0x10) // -a 1563 if (opt & 0x20) USE_FEATURE_MTAB_SUPPORT(useMtab = 0); // -n 1564 if (opt & 0x40) USE_FEATURE_MTAB_SUPPORT(fakeIt = 1); // -f 1565 //if (opt & 0x80) // -v: verbose (ignore) 1566 //if (opt & 0x100) // -s: sloppy (ignore) 1567 argv += optind; 1568 argc -= optind; 416 1569 417 1570 // Three or more non-option arguments? Die with a usage message. 418 1571 419 if ( optind-argc>2) bb_show_usage();1572 if (argc > 2) bb_show_usage(); 420 1573 421 1574 // If we have no arguments, show currently mounted filesystems 422 1575 423 if ( optind ==argc) {424 if (! all) {1576 if (!argc) { 1577 if (!(opt & OPT_ALL)) { 425 1578 FILE *mountTable = setmntent(bb_path_mtab_file, "r"); 426 1579 427 if (!mountTable) bb_error_msg_and_die("No %s",bb_path_mtab_file);428 429 while (getmntent_r(mountTable, mtpair,bb_common_bufsiz1,1580 if (!mountTable) bb_error_msg_and_die("no %s", bb_path_mtab_file); 1581 1582 while (getmntent_r(mountTable, mtpair, bb_common_bufsiz1, 430 1583 sizeof(bb_common_bufsiz1))) 431 1584 { 432 // Don't show rootfs. 433 if (!strcmp(mtpair->mnt_fsname, "rootfs")) continue; 1585 // Don't show rootfs. FIXME: why?? 1586 // util-linux 2.12a happily shows rootfs... 1587 //if (!strcmp(mtpair->mnt_fsname, "rootfs")) continue; 434 1588 435 1589 if (!fstype || !strcmp(mtpair->mnt_type, fstype)) … … 441 1595 return EXIT_SUCCESS; 442 1596 } 443 } 1597 } else storage_path = bb_simplify_path(argv[0]); 444 1598 445 1599 // When we have two arguments, the second is the directory and we can … … 447 1601 // argument when we get it. 448 1602 449 if (optind+2 == argc) { 450 mtpair->mnt_fsname = argv[optind]; 451 mtpair->mnt_dir = argv[optind+1]; 1603 if (argc == 2) { 1604 if (nonroot) 1605 bb_error_msg_and_die(must_be_root); 1606 mtpair->mnt_fsname = argv[0]; 1607 mtpair->mnt_dir = argv[1]; 452 1608 mtpair->mnt_type = fstype; 453 1609 mtpair->mnt_opts = cmdopts; … … 456 1612 } 457 1613 458 // If we have at least one argument, it's the storage location 459 460 if (optind < argc) storage_path = bb_simplify_path(argv[optind]); 1614 i = parse_mount_options(cmdopts, 0); 1615 if (nonroot && (i & ~MS_SILENT)) // Non-root users cannot specify flags 1616 bb_error_msg_and_die(must_be_root); 1617 1618 // If we have a shared subtree flag, don't worry about fstab or mtab. 1619 1620 if (ENABLE_FEATURE_MOUNT_FLAGS 1621 && (i & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) 1622 ) { 1623 rc = mount("", argv[0], "", i, ""); 1624 if (rc) bb_perror_msg_and_die("%s", argv[0]); 1625 goto clean_up; 1626 } 461 1627 462 1628 // Open either fstab or mtab 463 1629 464 if (parse_mount_options(cmdopts,0) & MS_REMOUNT) 465 fstabname = (char *)bb_path_mtab_file; // Again with the evil const. 466 else fstabname="/etc/fstab"; 467 468 if (!(fstab=setmntent(fstabname,"r"))) 469 bb_perror_msg_and_die("Cannot read %s",fstabname); 1630 fstabname = "/etc/fstab"; 1631 if (i & MS_REMOUNT) { 1632 fstabname = bb_path_mtab_file; 1633 } 1634 fstab = setmntent(fstabname, "r"); 1635 if (!fstab) 1636 bb_perror_msg_and_die("cannot read %s", fstabname); 470 1637 471 1638 // Loop through entries until we find what we're looking for. 472 1639 473 memset(mtpair, 0,sizeof(mtpair));1640 memset(mtpair, 0, sizeof(mtpair)); 474 1641 for (;;) { 475 struct mntent *mtnext = mtpair + (mtcur==mtpair ? 1 : 0);1642 struct mntent *mtnext = (mtcur==mtpair ? mtpair+1 : mtpair); 476 1643 477 1644 // Get next fstab entry … … 483 1650 // Were we looking for something specific? 484 1651 485 if ( optind !=argc) {1652 if (argc) { 486 1653 487 1654 // If we didn't find anything, complain. 488 1655 489 1656 if (!mtnext->mnt_fsname) 490 bb_error_msg_and_die("Can't find %s in %s", 491 argv[optind], fstabname); 1657 bb_error_msg_and_die("can't find %s in %s", 1658 argv[0], fstabname); 1659 1660 mtcur = mtnext; 1661 if (nonroot) { 1662 // fstab must have "users" or "user" 1663 if (!(parse_mount_options(mtcur->mnt_opts, 0) & MOUNT_USERS)) 1664 bb_error_msg_and_die(must_be_root); 1665 } 492 1666 493 1667 // Mount the last thing we found. 494 1668 495 mtcur = mtnext; 496 mtcur->mnt_opts=bb_xstrdup(mtcur->mnt_opts); 497 append_mount_options(&(mtcur->mnt_opts),cmdopts); 1669 mtcur->mnt_opts = xstrdup(mtcur->mnt_opts); 1670 append_mount_options(&(mtcur->mnt_opts), cmdopts); 498 1671 rc = singlemount(mtcur, 0); 499 1672 free(mtcur->mnt_opts); … … 506 1679 * "proc") or a full path from root */ 507 1680 508 if ( optind !=argc) {1681 if (argc) { 509 1682 510 1683 // Is this what we're looking for? 511 1684 512 if (strcmp(argv[optind],mtcur->mnt_fsname) &&513 strcmp(storage_path, mtcur->mnt_fsname) &&514 strcmp(argv[ optind],mtcur->mnt_dir) &&515 strcmp(storage_path, mtcur->mnt_dir)) continue;1685 if (strcmp(argv[0], mtcur->mnt_fsname) && 1686 strcmp(storage_path, mtcur->mnt_fsname) && 1687 strcmp(argv[0], mtcur->mnt_dir) && 1688 strcmp(storage_path, mtcur->mnt_dir)) continue; 516 1689 517 1690 // Remember this entry. Something later may have overmounted … … 523 1696 524 1697 } else { 525 526 1698 // Do we need to match a filesystem type? 527 if (fstype && strcmp(mtcur->mnt_type,fstype)) continue;1699 if (fstype && match_fstype(mtcur, fstype)) continue; 528 1700 529 1701 // Skip noauto and swap anyway. 530 1702 531 if (parse_mount_options(mtcur->mnt_opts, 0)1703 if (parse_mount_options(mtcur->mnt_opts, 0) 532 1704 & (MOUNT_NOAUTO | MOUNT_SWAP)) continue; 533 1705 1706 // No, mount -a won't mount anything, 1707 // even user mounts, for mere humans. 1708 1709 if (nonroot) 1710 bb_error_msg_and_die(must_be_root); 1711 534 1712 // Mount this thing. 535 1713 1714 // NFS mounts want this to be xrealloc-able 1715 mtcur->mnt_opts = xstrdup(mtcur->mnt_opts); 536 1716 if (singlemount(mtcur, 1)) { 537 1717 /* Count number of failed mounts */ 538 1718 rc++; 539 1719 } 1720 free(mtcur->mnt_opts); 540 1721 } 541 1722 } -
branches/stable/mindi-busybox/util-linux/pivot_root.c
r821 r1770 7 7 * regardless of the kernel being used. 8 8 * 9 * Licensed under GPL v2 or later, see file LICENSE in this tarball for details.9 * Licensed under GPL version 2, see file LICENSE in this tarball for details. 10 10 */ 11 #include <stdlib.h> 12 #include <stdio.h> 13 #include <errno.h> 14 #include "busybox.h" 11 #include "libbb.h" 15 12 16 13 extern int pivot_root(const char * new_root,const char * put_old); 17 14 15 int pivot_root_main(int argc, char **argv); 18 16 int pivot_root_main(int argc, char **argv) 19 17 { 20 21 bb_show_usage();18 if (argc != 3) 19 bb_show_usage(); 22 20 23 if (pivot_root(argv[1],argv[2]) < 0) 24 bb_perror_msg_and_die("pivot_root"); 21 if (pivot_root(argv[1], argv[2]) < 0) { 22 /* prints "pivot_root: <strerror text>" */ 23 bb_perror_nomsg_and_die(); 24 } 25 25 26 return EXIT_SUCCESS; 27 26 return EXIT_SUCCESS; 28 27 } -
branches/stable/mindi-busybox/util-linux/rdate.c
r821 r1770 9 9 */ 10 10 11 #include <sys/types.h> 12 #include <sys/socket.h> 13 #include <netinet/in.h> 14 #include <netdb.h> 15 #include <stdio.h> 16 #include <string.h> 17 #include <time.h> 18 #include <stdlib.h> 19 #include <unistd.h> 20 #include <signal.h> 11 #include "libbb.h" 21 12 22 #include "busybox.h" 23 24 25 static const int RFC_868_BIAS = 2208988800UL; 13 enum { RFC_868_BIAS = 2208988800UL }; 26 14 27 15 static void socket_timeout(int sig) … … 32 20 static time_t askremotedate(const char *host) 33 21 { 34 unsigned long nett; 35 struct sockaddr_in s_in; 22 uint32_t nett; 36 23 int fd; 37 38 bb_lookup_host(&s_in, host);39 s_in.sin_port = bb_lookup_port("time", "tcp", 37);40 24 41 25 /* Add a timeout for dead or inaccessible servers */ … … 43 27 signal(SIGALRM, socket_timeout); 44 28 45 fd = xconnect(&s_in);29 fd = create_and_connect_stream_or_die(host, bb_lookup_port("time", "tcp", 37)); 46 30 47 31 if (safe_read(fd, (void *)&nett, 4) != 4) /* read time from server */ … … 51 35 /* convert from network byte order to local byte order. 52 36 * RFC 868 time is the number of seconds 53 * 54 * 55 * Subtract the RFC 868 time 37 * since 00:00 (midnight) 1 January 1900 GMT 38 * the RFC 868 time 2,208,988,800 corresponds to 00:00 1 Jan 1970 GMT 39 * Subtract the RFC 868 time to get Linux epoch 56 40 */ 57 41 58 return (ntohl(nett) - RFC_868_BIAS);42 return ntohl(nett) - RFC_868_BIAS; 59 43 } 60 44 45 int rdate_main(int argc, char **argv); 61 46 int rdate_main(int argc, char **argv) 62 47 { … … 64 49 unsigned long flags; 65 50 66 bb_opt_complementally = "-1";67 flags = bb_getopt_ulflags(argc,argv, "sp");51 opt_complementary = "-1"; 52 flags = getopt32(argv, "sp"); 68 53 69 54 remote_time = askremotedate(argv[optind]); … … 74 59 time(¤t_time); 75 60 if (current_time == remote_time) 76 bb_error_msg(" Current time matches remote time.");61 bb_error_msg("current time matches remote time"); 77 62 else 78 63 if (stime(&remote_time) < 0) 79 bb_perror_msg_and_die(" Couldnot set time of day");64 bb_perror_msg_and_die("cannot set time of day"); 80 65 } 81 66 -
branches/stable/mindi-busybox/util-linux/readprofile.c
r902 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 3 * readprofile.c - used to read /proc/profile … … 4 5 * Copyright (C) 1994,1996 Alessandro Rubini (rubini@ipvvis.unipv.it) 5 6 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 19 8 */ 20 9 … … 44 33 */ 45 34 46 #include <errno.h> 47 #include <stdio.h> 48 #include <fcntl.h> 49 #include <stdlib.h> 50 #include <unistd.h> 51 #include <string.h> 52 #include <sys/types.h> 53 #include <sys/stat.h> 35 #include "libbb.h" 54 36 #include <sys/utsname.h> 55 37 56 #include "busybox.h"57 58 38 #define S_LEN 128 59 39 60 40 /* These are the defaults */ 61 static const char defaultmap[]="/boot/System.map"; 62 static const char defaultpro[]="/proc/profile"; 63 41 static const char defaultmap[] ALIGN1 = "/boot/System.map"; 42 static const char defaultpro[] ALIGN1 = "/proc/profile"; 43 44 int readprofile_main(int argc, char **argv); 64 45 int readprofile_main(int argc, char **argv) 65 46 { 66 47 FILE *map; 67 int proFd;68 const char *mapFile, *proFile, *mult=0;69 unsigned long len=0, indx=1;70 uint64_t add0 =0;48 const char *mapFile, *proFile, *mult = 0; 49 unsigned long indx = 1; 50 size_t len; 51 uint64_t add0 = 0; 71 52 unsigned int step; 72 53 unsigned int *buf, total, fn_len; 73 unsigned long long fn_add, next_add; 54 unsigned long long fn_add, next_add; /* current and next address */ 74 55 char fn_name[S_LEN], next_name[S_LEN]; /* current and next name */ 56 char mapline[S_LEN]; 75 57 char mode[8]; 76 int c; 77 int optAll=0, optInfo=0, optReset=0, optVerbose=0, optNative=0; 78 int optBins=0, optSub=0; 79 char mapline[S_LEN]; 80 int maplineno=1; 58 int optAll = 0, optInfo = 0, optReset = 0; 59 int optVerbose = 0, optNative = 0; 60 int optBins = 0, optSub = 0; 61 int maplineno = 1; 81 62 int header_printed; 82 63 … … 86 67 mapFile = defaultmap; 87 68 88 while ((c = getopt(argc, argv, "M:m:np:itvarVbs")) != -1) { 89 switch(c) { 90 case 'm': 91 mapFile = optarg; 92 break; 93 case 'n': 94 optNative++; 95 break; 96 case 'p': 97 proFile = optarg; 98 break; 99 case 'a': 100 optAll++; 101 break; 102 case 'b': 103 optBins++; 104 break; 105 case 's': 106 optSub++; 107 break; 108 case 'i': 109 optInfo++; 110 break; 111 case 'M': 112 mult = optarg; 113 break; 114 case 'r': 115 optReset++; 116 break; 117 case 'v': 118 optVerbose++; 119 break; 120 default: 121 bb_show_usage(); 122 } 123 } 69 opt_complementary = "nn:aa:bb:ss:ii:rr:vv"; 70 getopt32(argv, "M:m:p:nabsirv", 71 &mult, &mapFile, &proFile, 72 &optNative, &optAll, &optBins, &optSub, 73 &optInfo, &optReset, &optVerbose); 124 74 125 75 if (optReset || mult) { … … 131 81 */ 132 82 if (mult) { 133 multiplier = strtoul(mult, 0, 10);83 multiplier = xatoi_u(mult); 134 84 to_write = sizeof(int); 135 85 } else { … … 138 88 } 139 89 140 fd = bb_xopen(defaultpro,O_WRONLY);141 142 if ( write(fd, &multiplier, to_write) != to_write)90 fd = xopen(defaultpro, O_WRONLY); 91 92 if (full_write(fd, &multiplier, to_write) != to_write) 143 93 bb_perror_msg_and_die("error writing %s", defaultpro); 144 94 … … 150 100 * Use an fd for the profiling buffer, to skip stdio overhead 151 101 */ 152 153 proFd = bb_xopen(proFile,O_RDONLY); 154 155 if (((int)(len=lseek(proFd,0,SEEK_END)) < 0) 156 || (lseek(proFd,0,SEEK_SET) < 0)) 157 bb_perror_msg_and_die(proFile); 158 159 buf = xmalloc(len); 160 161 if (read(proFd,buf,len) != len) 162 bb_perror_msg_and_die(proFile); 163 164 close(proFd); 165 102 len = MAXINT(ssize_t); 103 buf = xmalloc_open_read_close(proFile, &len); 166 104 if (!optNative) { 167 105 int entries = len/sizeof(*buf); 168 int big = 0, small = 0,i;106 int big = 0, small = 0, i; 169 107 unsigned *p; 170 108 … … 176 114 } 177 115 if (big > small) { 178 bb_error_msg(" Assuming reversed byte order."179 " Use -n to force native byte order.");116 bb_error_msg("assuming reversed byte order, " 117 "use -n to force native byte order"); 180 118 for (p = buf; p < buf+entries; p++) 181 119 for (i = 0; i < sizeof(*buf)/2; i++) { … … 198 136 total = 0; 199 137 200 map = bb_xfopen(mapFile, "r");201 202 while (fgets(mapline, S_LEN,map)) {203 if (sscanf(mapline, "%llx %s %s",&fn_add,mode,fn_name) != 3)138 map = xfopen(mapFile, "r"); 139 140 while (fgets(mapline, S_LEN, map)) { 141 if (sscanf(mapline, "%llx %s %s", &fn_add, mode, fn_name) != 3) 204 142 bb_error_msg_and_die("%s(%i): wrong map line", 205 143 mapFile, maplineno); 206 144 207 if (!strcmp(fn_name, "_stext")) /* only elf works like this */ {145 if (!strcmp(fn_name, "_stext")) /* only elf works like this */ { 208 146 add0 = fn_add; 209 147 break; … … 218 156 * Main loop. 219 157 */ 220 while (fgets(mapline, S_LEN,map)) {158 while (fgets(mapline, S_LEN, map)) { 221 159 unsigned int this = 0; 222 160 223 if (sscanf(mapline, "%llx %s %s",&next_add,mode,next_name) != 3)161 if (sscanf(mapline, "%llx %s %s", &next_add, mode, next_name) != 3) 224 162 bb_error_msg_and_die("%s(%i): wrong map line", 225 163 mapFile, maplineno); 226 164 227 165 header_printed = 0; … … 241 179 if (optBins && (buf[indx] || optAll)) { 242 180 if (!header_printed) { 243 printf 181 printf("%s:\n", fn_name); 244 182 header_printed = 1; 245 183 } 246 printf 184 printf("\t%"PRIx64"\t%u\n", (indx - 1)*step + add0, buf[indx]); 247 185 } 248 186 this += buf[indx++]; … … 252 190 if (optBins) { 253 191 if (optVerbose || this > 0) 254 printf 192 printf(" total\t\t\t\t%u\n", this); 255 193 } else if ((this || optAll) && 256 194 (fn_len = next_add-fn_add) != 0) { 257 195 if (optVerbose) 258 196 printf("%016llx %-40s %6i %8.4f\n", fn_add, 259 fn_name, this,this/(double)fn_len);197 fn_name, this, this/(double)fn_len); 260 198 else 261 199 printf("%6i %-40s %8.4f\n", 262 this, fn_name,this/(double)fn_len);200 this, fn_name, this/(double)fn_len); 263 201 if (optSub) { 264 202 unsigned long long scan; … … 277 215 278 216 fn_add = next_add; 279 strcpy(fn_name, next_name);217 strcpy(fn_name, next_name); 280 218 281 219 maplineno++; … … 288 226 if (optVerbose) 289 227 printf("%016x %-40s %6i %8.4f\n", 290 0, "total",total,total/(double)(fn_add-add0));228 0, "total", total, total/(double)(fn_add-add0)); 291 229 else 292 230 printf("%6i %-40s %8.4f\n", 293 total, "total",total/(double)(fn_add-add0));231 total, "total", total/(double)(fn_add-add0)); 294 232 295 233 fclose(map); -
branches/stable/mindi-busybox/util-linux/setarch.c
r821 r1770 8 8 */ 9 9 10 #include <stdlib.h>11 #include <unistd.h>12 #include <string.h>13 #include <errno.h>14 #include <stdio.h>15 10 #include <sys/personality.h> 16 11 17 #include " busybox.h"12 #include "libbb.h" 18 13 14 int setarch_main(int ATTRIBUTE_UNUSED argc, char **argv); 19 15 int setarch_main(int ATTRIBUTE_UNUSED argc, char **argv) 20 16 { … … 46 42 47 43 /* Try to execute the program */ 48 execvp(argv[0], argv);44 BB_EXECVP(argv[0], argv); 49 45 } 50 46 -
branches/stable/mindi-busybox/util-linux/swaponoff.c
r821 r1770 5 5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> 6 6 * 7 * Licensed under the GPL v 2, see the file LICENSE in this tarball.7 * Licensed under the GPL version 2, see the file LICENSE in this tarball. 8 8 */ 9 9 10 #include " busybox.h"10 #include "libbb.h" 11 11 #include <mntent.h> 12 #include <dirent.h>13 #include <errno.h>14 #include <string.h>15 12 #include <sys/swap.h> 16 13 17 18 static int swap_enable_disable(const char *device) 14 static int swap_enable_disable(char *device) 19 15 { 20 16 int status; … … 23 19 xstat(device, &st); 24 20 21 #if ENABLE_DESKTOP 25 22 /* test for holes */ 26 23 if (S_ISREG(st.st_mode)) 27 24 if (st.st_blocks * 512 < st.st_size) 28 bb_error_msg_and_die("swap file has holes"); 25 bb_error_msg("warning: swap file has holes"); 26 #endif 29 27 30 if ( bb_applet_name[5] == 'n')28 if (applet_name[5] == 'n') 31 29 status = swapon(device, 0); 32 30 else … … 61 59 } 62 60 63 #define DO_ALL 0x01 64 61 int swap_on_off_main(int argc, char **argv); 65 62 int swap_on_off_main(int argc, char **argv) 66 63 { … … 70 67 bb_show_usage(); 71 68 72 ret = bb_getopt_ulflags(argc,argv, "a");73 if (ret & DO_ALL)69 ret = getopt32(argv, "a"); 70 if (ret) 74 71 return do_em_all(); 75 72 76 ret = 0;73 /* ret = 0; redundant */ 77 74 while (*++argv) 78 75 ret += swap_enable_disable(*argv); -
branches/stable/mindi-busybox/util-linux/switch_root.c
r821 r1770 1 /* vi: set ts=4:*/1 /* vi: set sw=4 ts=4: */ 2 2 /* Copyright 2005 Rob Landley <rob@landley.net> 3 3 * 4 4 * Switch from rootfs to another filesystem as the root of the mount tree. 5 5 * 6 * Licensed under GPL v2 or later, see file LICENSE in this tarball for details.6 * Licensed under GPL version 2, see file LICENSE in this tarball for details. 7 7 */ 8 8 9 #include "busybox.h" 10 #include <fcntl.h> 11 #include <string.h> 9 #include "libbb.h" 12 10 #include <sys/vfs.h> 13 #include <unistd.h>14 11 15 12 … … 28 25 #endif 29 26 30 dev_t rootdev;27 static dev_t rootdev; 31 28 32 29 // Recursively delete contents of rootfs. 33 30 34 static void delete_contents(c har *directory)31 static void delete_contents(const char *directory) 35 32 { 36 33 DIR *dir; … … 39 36 40 37 // Don't descend into other filesystems 41 if (lstat(directory, &st) || st.st_dev != rootdev) return;38 if (lstat(directory, &st) || st.st_dev != rootdev) return; 42 39 43 40 // Recursively delete the contents of directories. 44 41 if (S_ISDIR(st.st_mode)) { 45 if((dir = opendir(directory))) { 42 dir = opendir(directory); 43 if (dir) { 46 44 while ((d = readdir(dir))) { 47 char *newdir =d->d_name;45 char *newdir = d->d_name; 48 46 49 47 // Skip . and .. 50 if (*newdir=='.' && (!newdir[1] || (newdir[1]=='.' && !newdir[2])))48 if (*newdir=='.' && (!newdir[1] || (newdir[1]=='.' && !newdir[2]))) 51 49 continue; 52 50 … … 67 65 } 68 66 69 int switch_root_main(int argc, char *argv[]) 67 int switch_root_main(int argc, char **argv); 68 int switch_root_main(int argc, char **argv) 70 69 { 71 char *newroot, *console =NULL;70 char *newroot, *console = NULL; 72 71 struct stat st1, st2; 73 72 struct statfs stfs; … … 75 74 // Parse args (-c console) 76 75 77 bb_opt_complementally="-2"; 78 bb_getopt_ulflags(argc,argv,"c:",&console); 76 opt_complementary = "-2"; 77 getopt32(argv, "c:", &console); 78 argv += optind; 79 79 80 80 // Change to new root directory and verify it's a different fs. 81 81 82 newroot =argv[optind++];82 newroot = *argv++; 83 83 84 if (chdir(newroot) || lstat(".", &st1) || lstat("/", &st2) || 85 st1.st_dev == st2.st_dev) 86 { 87 bb_error_msg_and_die("bad newroot %s",newroot); 84 xchdir(newroot); 85 if (lstat(".", &st1) || lstat("/", &st2) || st1.st_dev == st2.st_dev) { 86 bb_error_msg_and_die("bad newroot %s", newroot); 88 87 } 89 rootdev =st2.st_dev;88 rootdev = st2.st_dev; 90 89 91 90 // Additional sanity checks: we're about to rm -rf /, so be REALLY SURE 92 91 // we mean it. (I could make this a CONFIG option, but I would get email 93 // from all the people who WILL eat their filesystems s.)92 // from all the people who WILL eat their filesystems.) 94 93 95 94 if (lstat("/init", &st1) || !S_ISREG(st1.st_mode) || statfs("/", &stfs) || … … 107 106 // recalculate "." and ".." links. 108 107 109 if (mount(".", "/", NULL, MS_MOVE, NULL) || chroot(".") || chdir("/")) 110 bb_error_msg_and_die("moving root"); 108 if (mount(".", "/", NULL, MS_MOVE, NULL) || chroot(".")) 109 bb_error_msg_and_die("error moving root"); 110 xchdir("/"); 111 111 112 112 // If a new console specified, redirect stdin/stdout/stderr to that. … … 114 114 if (console) { 115 115 close(0); 116 if(open(console, O_RDWR) < 0) 117 bb_error_msg_and_die("Bad console '%s'",console); 116 xopen(console, O_RDWR); 118 117 dup2(0, 1); 119 118 dup2(0, 2); … … 121 120 122 121 // Exec real init. (This is why we must be pid 1.) 123 execv(argv[ optind],argv+optind);124 bb_ error_msg_and_die("Bad init '%s'",argv[optind]);122 execv(argv[0], argv); 123 bb_perror_msg_and_die("bad init %s", argv[0]); 125 124 } -
branches/stable/mindi-busybox/util-linux/umount.c
r902 r1770 6 6 * Copyright (C) 2005 by Rob Landley <rob@landley.net> 7 7 * 8 * This program is licensed under the GNU General Public license (GPL) 9 * version 2 or later, see http://www.fsf.org/licensing/licenses/gpl.html 10 * or the file "LICENSE" in the busybox source tarball for the full text. 11 * 8 * Licensed under GPL version 2, see file LICENSE in this tarball for details. 12 9 */ 13 10 14 #include "busybox.h"15 11 #include <mntent.h> 16 #include <errno.h>17 12 #include <getopt.h> 13 #include "libbb.h" 18 14 19 #define OPTION_STRING "flDnravd "15 #define OPTION_STRING "flDnravdt:" 20 16 #define OPT_FORCE 1 21 17 #define OPT_LAZY 2 … … 25 21 #define OPT_ALL (ENABLE_FEATURE_UMOUNT_ALL ? 32 : 0) 26 22 23 int umount_main(int argc, char **argv); 27 24 int umount_main(int argc, char **argv) 28 25 { … … 31 28 struct mntent me; 32 29 FILE *fp; 30 char *fstype = 0; 33 31 int status = EXIT_SUCCESS; 34 unsigned longopt;32 unsigned opt; 35 33 struct mtab_list { 36 34 char *dir; … … 41 39 /* Parse any options */ 42 40 43 opt = bb_getopt_ulflags(argc, argv, OPTION_STRING);41 opt = getopt32(argv, OPTION_STRING, &fstype); 44 42 45 43 argc -= optind; … … 59 57 * the argument list should be empty (which will match all). */ 60 58 61 if (!(fp = setmntent(bb_path_mtab_file, "r"))) { 59 fp = setmntent(bb_path_mtab_file, "r"); 60 if (!fp) { 62 61 if (opt & OPT_ALL) 63 bb_error_msg_and_die("Cannot open %s", bb_path_mtab_file); 64 } else while (getmntent_r(fp,&me,path,sizeof(path))) { 65 m = xmalloc(sizeof(struct mtab_list)); 66 m->next = mtl; 67 m->device = bb_xstrdup(me.mnt_fsname); 68 m->dir = bb_xstrdup(me.mnt_dir); 69 mtl = m; 62 bb_error_msg_and_die("cannot open %s", bb_path_mtab_file); 63 } else { 64 while (getmntent_r(fp, &me, path, sizeof(path))) { 65 /* Match fstype if passed */ 66 if (fstype && match_fstype(&me, fstype)) 67 continue; 68 m = xmalloc(sizeof(struct mtab_list)); 69 m->next = mtl; 70 m->device = xstrdup(me.mnt_fsname); 71 m->dir = xstrdup(me.mnt_dir); 72 mtl = m; 73 } 74 endmntent(fp); 70 75 } 71 endmntent(fp);72 76 73 /* If we're not mounting all, we need at least one argument. */74 if (!(opt & OPT_ALL) ) {77 /* If we're not umounting all, we need at least one argument. */ 78 if (!(opt & OPT_ALL) && !fstype) { 75 79 m = 0; 76 80 if (!argc) bb_show_usage(); 77 81 } 78 82 79 83 // Loop through everything we're supposed to umount, and do so. 80 84 for (;;) { … … 107 111 curstat = umount2(zapit, doForce); 108 112 if (curstat) 109 bb_error_msg _and_die("forced umount of %s failed!", zapit);113 bb_error_msg("forced umount of %s failed!", zapit); 110 114 } 111 115 … … 113 117 if (curstat && (opt & OPT_REMOUNT) && errno == EBUSY && m) { 114 118 curstat = mount(m->device, zapit, NULL, MS_REMOUNT|MS_RDONLY, NULL); 115 bb_error_msg(curstat ? " Cannot remount %s read-only" :119 bb_error_msg(curstat ? "cannot remount %s read-only" : 116 120 "%s busy - remounted read-only", m->device); 117 121 } … … 119 123 if (curstat) { 120 124 status = EXIT_FAILURE; 121 bb_perror_msg(" Couldn't umount %s", zapit);125 bb_perror_msg("cannot umount %s", zapit); 122 126 } else { 123 127 /* De-allocate the loop device. This ioctl should be ignored on … … 133 137 // of /dev/blah, not just the most recent. 134 138 while (m && (m = m->next)) 135 if ((opt & OPT_ALL) || !strcmp(path, m->device))139 if ((opt & OPT_ALL) || !strcmp(path, m->device)) 136 140 break; 137 141 } … … 145 149 free(mtl->dir); 146 150 free(mtl); 147 mtl =m;151 mtl = m; 148 152 } 149 153 }
Note:
See TracChangeset
for help on using the changeset viewer.