aboutsummaryrefslogtreecommitdiff
path: root/util-linux
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2020-01-08 12:30:49 +0000
committerRon Yorston <rmy@pobox.com>2020-01-08 12:30:49 +0000
commita9271a8e97e6e7be5285330d5f19352decabf807 (patch)
treebf3c4464c369a15a46454792dac167505f74769f /util-linux
parentb0b7ab792bc1f45963f4b84b94faaf05054e1613 (diff)
parent9ec836c033fc6e55e80f3309b3e05acdf09bb297 (diff)
downloadbusybox-w32-a9271a8e97e6e7be5285330d5f19352decabf807.tar.gz
busybox-w32-a9271a8e97e6e7be5285330d5f19352decabf807.tar.bz2
busybox-w32-a9271a8e97e6e7be5285330d5f19352decabf807.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'util-linux')
-rw-r--r--util-linux/fdisk.c33
-rw-r--r--util-linux/fdisk_aix.c40
-rw-r--r--util-linux/fdisk_gpt.c6
-rw-r--r--util-linux/fdisk_osf.c4
-rw-r--r--util-linux/fdisk_sgi.c12
-rw-r--r--util-linux/fdisk_sun.c16
-rw-r--r--util-linux/rdate.c8
-rw-r--r--util-linux/taskset.c140
8 files changed, 189 insertions, 70 deletions
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c
index f28d4fdd2..e58cb0fd1 100644
--- a/util-linux/fdisk.c
+++ b/util-linux/fdisk.c
@@ -299,9 +299,6 @@ static int get_boot(enum action what);
299static int get_boot(void); 299static int get_boot(void);
300#endif 300#endif
301 301
302#define PLURAL 0
303#define SINGULAR 1
304
305static sector_t get_start_sect(const struct partition *p); 302static sector_t get_start_sect(const struct partition *p);
306static sector_t get_nr_sects(const struct partition *p); 303static sector_t get_nr_sects(const struct partition *p);
307 304
@@ -591,18 +588,18 @@ partname(const char *dev, int pno, int lth)
591 return bufp; 588 return bufp;
592} 589}
593 590
591#if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_OSF_LABEL
594static ALWAYS_INLINE struct partition * 592static ALWAYS_INLINE struct partition *
595get_part_table(int i) 593get_part_table(int i)
596{ 594{
597 return ptes[i].part_table; 595 return ptes[i].part_table;
598} 596}
597#endif
599 598
600static const char * 599static ALWAYS_INLINE const char *
601str_units(int n) 600str_units(void)
602{ /* n==1: use singular */ 601{
603 if (n == 1) 602 return display_in_cyl_units ? "cylinder" : "sector";
604 return display_in_cyl_units ? "cylinder" : "sector";
605 return display_in_cyl_units ? "cylinders" : "sectors";
606} 603}
607 604
608static int 605static int
@@ -1778,8 +1775,8 @@ change_units(void)
1778{ 1775{
1779 display_in_cyl_units = !display_in_cyl_units; 1776 display_in_cyl_units = !display_in_cyl_units;
1780 update_units(); 1777 update_units();
1781 printf("Changing display/entry units to %s\n", 1778 printf("Changing display/entry units to %ss\n",
1782 str_units(PLURAL)); 1779 str_units());
1783} 1780}
1784 1781
1785static void 1782static void
@@ -2030,8 +2027,7 @@ check_consistency(const struct partition *p, int partition)
2030static void 2027static void
2031list_disk_geometry(void) 2028list_disk_geometry(void)
2032{ 2029{
2033 ullong bytes = ((ullong)total_number_of_sectors << 9); 2030 ullong xbytes = total_number_of_sectors / (1024*1024 / 512);
2034 ullong xbytes = bytes / (1024*1024);
2035 char x = 'M'; 2031 char x = 'M';
2036 2032
2037 if (xbytes >= 10000) { 2033 if (xbytes >= 10000) {
@@ -2041,11 +2037,12 @@ list_disk_geometry(void)
2041 } 2037 }
2042 printf("Disk %s: %llu %cB, %llu bytes, %"SECT_FMT"u sectors\n" 2038 printf("Disk %s: %llu %cB, %llu bytes, %"SECT_FMT"u sectors\n"
2043 "%u cylinders, %u heads, %u sectors/track\n" 2039 "%u cylinders, %u heads, %u sectors/track\n"
2044 "Units: %s of %u * %u = %u bytes\n\n", 2040 "Units: %ss of %u * %u = %u bytes\n"
2041 "\n",
2045 disk_device, xbytes, x, 2042 disk_device, xbytes, x,
2046 bytes, total_number_of_sectors, 2043 ((ullong)total_number_of_sectors * 512), total_number_of_sectors,
2047 g_cylinders, g_heads, g_sectors, 2044 g_cylinders, g_heads, g_sectors,
2048 str_units(PLURAL), 2045 str_units(),
2049 units_per_sector, sector_size, units_per_sector * sector_size 2046 units_per_sector, sector_size, units_per_sector * sector_size
2050 ); 2047 );
2051} 2048}
@@ -2486,7 +2483,7 @@ add_partition(int n, int sys)
2486 for (i = 0; i < g_partitions; i++) 2483 for (i = 0; i < g_partitions; i++)
2487 first[i] = (cround(first[i]) - 1) * units_per_sector; 2484 first[i] = (cround(first[i]) - 1) * units_per_sector;
2488 2485
2489 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR)); 2486 snprintf(mesg, sizeof(mesg), "First %s", str_units());
2490 do { 2487 do {
2491 temp = start; 2488 temp = start;
2492 for (i = 0; i < g_partitions; i++) { 2489 for (i = 0; i < g_partitions; i++) {
@@ -2548,7 +2545,7 @@ add_partition(int n, int sys)
2548 } else { 2545 } else {
2549 snprintf(mesg, sizeof(mesg), 2546 snprintf(mesg, sizeof(mesg),
2550 "Last %s or +size{,K,M,G,T}", 2547 "Last %s or +size{,K,M,G,T}",
2551 str_units(SINGULAR) 2548 str_units()
2552 ); 2549 );
2553 stop = read_int(cround(start), cround(limit), cround(limit), cround(start), mesg); 2550 stop = read_int(cround(start), cround(limit), cround(limit), cround(start), mesg);
2554 if (display_in_cyl_units) { 2551 if (display_in_cyl_units) {
diff --git a/util-linux/fdisk_aix.c b/util-linux/fdisk_aix.c
index ee5df50e5..0a5e818fe 100644
--- a/util-linux/fdisk_aix.c
+++ b/util-linux/fdisk_aix.c
@@ -6,10 +6,10 @@
6 */ 6 */
7 7
8typedef struct { 8typedef struct {
9 unsigned int magic; /* expect AIX_LABEL_MAGIC */ 9 uint32_t magic; /* expect AIX_LABEL_MAGIC */
10 unsigned int fillbytes1[124]; 10 uint32_t fillbytes1[124];
11 unsigned int physical_volume_id; 11 uint32_t physical_volume_id;
12 unsigned int fillbytes2[124]; 12 uint32_t fillbytes2[124];
13} aix_partition; 13} aix_partition;
14 14
15#define AIX_LABEL_MAGIC 0xc9c2d4c1 15#define AIX_LABEL_MAGIC 0xc9c2d4c1
@@ -17,20 +17,18 @@ typedef struct {
17#define AIX_INFO_MAGIC 0x00072959 17#define AIX_INFO_MAGIC 0x00072959
18#define AIX_INFO_MAGIC_SWAPPED 0x59290700 18#define AIX_INFO_MAGIC_SWAPPED 0x59290700
19 19
20#define aixlabel ((aix_partition *)MBRbuffer)
21
22
23/* 20/*
24 Changes: 21 * Changes:
25 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br> 22 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
26 * Internationalization 23 * Internationalization
27 * 24 *
28 * 2003-03-20 Phillip Kesling <pkesling@sgi.com> 25 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
29 * Some fixes 26 * Some fixes
30*/ 27 */
31 28
32static smallint aix_other_endian; /* bool */ 29// Write-only vars, unfinished code?
33static smallint aix_volumes = 1; /* max 15 */ 30//static smallint aix_other_endian; /* bool */
31//static smallint aix_volumes = 1; /* max 15 */
34 32
35/* 33/*
36 * only dealing with free blocks here 34 * only dealing with free blocks here
@@ -54,18 +52,20 @@ aix_info(void)
54static int 52static int
55check_aix_label(void) 53check_aix_label(void)
56{ 54{
55 aix_partition *aixlabel = (void*)MBRbuffer;
56
57 if (aixlabel->magic != AIX_LABEL_MAGIC 57 if (aixlabel->magic != AIX_LABEL_MAGIC
58 && aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED 58 && aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED
59 ) { 59 ) {
60 current_label_type = 0; 60 current_label_type = LABEL_DOS;
61 aix_other_endian = 0; 61// aix_other_endian = 0;
62 return 0; 62 return 0;
63 } 63 }
64 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED); 64// aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
65 update_units(); 65 update_units();
66 current_label_type = LABEL_AIX; 66 current_label_type = LABEL_AIX;
67 g_partitions = 1016; 67 g_partitions = 1016;
68 aix_volumes = 15; 68// aix_volumes = 15;
69 aix_info(); 69 aix_info();
70 /*aix_nolabel();*/ /* %% */ 70 /*aix_nolabel();*/ /* %% */
71 /*aix_label = 1;*/ /* %% */ 71 /*aix_label = 1;*/ /* %% */
diff --git a/util-linux/fdisk_gpt.c b/util-linux/fdisk_gpt.c
index dbe889f7c..e884e3dc1 100644
--- a/util-linux/fdisk_gpt.c
+++ b/util-linux/fdisk_gpt.c
@@ -161,7 +161,7 @@ check_gpt_label(void)
161 if (!valid_part_table_flag(MBRbuffer) 161 if (!valid_part_table_flag(MBRbuffer)
162 || first->sys_ind != LEGACY_GPT_TYPE 162 || first->sys_ind != LEGACY_GPT_TYPE
163 ) { 163 ) {
164 current_label_type = 0; 164 current_label_type = LABEL_DOS;
165 return 0; 165 return 0;
166 } 166 }
167 167
@@ -171,7 +171,7 @@ check_gpt_label(void)
171 gpt_hdr = (void *)pe.sectorbuffer; 171 gpt_hdr = (void *)pe.sectorbuffer;
172 172
173 if (gpt_hdr->magic != SWAP_LE64(GPT_MAGIC)) { 173 if (gpt_hdr->magic != SWAP_LE64(GPT_MAGIC)) {
174 current_label_type = 0; 174 current_label_type = LABEL_DOS;
175 return 0; 175 return 0;
176 } 176 }
177 177
@@ -194,7 +194,7 @@ check_gpt_label(void)
194 || SWAP_LE32(gpt_hdr->hdr_size) > sector_size 194 || SWAP_LE32(gpt_hdr->hdr_size) > sector_size
195 ) { 195 ) {
196 puts("\nwarning: unable to parse GPT disklabel\n"); 196 puts("\nwarning: unable to parse GPT disklabel\n");
197 current_label_type = 0; 197 current_label_type = LABEL_DOS;
198 return 0; 198 return 0;
199 } 199 }
200 200
diff --git a/util-linux/fdisk_osf.c b/util-linux/fdisk_osf.c
index 1328c1fcd..92180b2bc 100644
--- a/util-linux/fdisk_osf.c
+++ b/util-linux/fdisk_osf.c
@@ -470,7 +470,7 @@ xbsd_new_part(void)
470 end = xbsd_dlabel.d_secperunit - 1; 470 end = xbsd_dlabel.d_secperunit - 1;
471#endif 471#endif
472 472
473 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR)); 473 snprintf(mesg, sizeof(mesg), "First %s", str_units());
474 begin = read_int(bsd_cround(begin), bsd_cround(begin), bsd_cround(end), 474 begin = read_int(bsd_cround(begin), bsd_cround(begin), bsd_cround(end),
475 0, mesg); 475 0, mesg);
476 476
@@ -478,7 +478,7 @@ xbsd_new_part(void)
478 begin = (begin - 1) * xbsd_dlabel.d_secpercyl; 478 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
479 479
480 snprintf(mesg, sizeof(mesg), "Last %s or +size or +sizeM or +sizeK", 480 snprintf(mesg, sizeof(mesg), "Last %s or +size or +sizeM or +sizeK",
481 str_units(SINGULAR)); 481 str_units());
482 end = read_int(bsd_cround(begin), bsd_cround(end), bsd_cround(end), 482 end = read_int(bsd_cround(begin), bsd_cround(end), bsd_cround(end),
483 bsd_cround(begin), mesg); 483 bsd_cround(begin), mesg);
484 484
diff --git a/util-linux/fdisk_sgi.c b/util-linux/fdisk_sgi.c
index 0e5491a19..c90c801e2 100644
--- a/util-linux/fdisk_sgi.c
+++ b/util-linux/fdisk_sgi.c
@@ -295,19 +295,19 @@ sgi_list_table(int xtra)
295 "%u cylinders, %u physical cylinders\n" 295 "%u cylinders, %u physical cylinders\n"
296 "%u extra sects/cyl, interleave %u:1\n" 296 "%u extra sects/cyl, interleave %u:1\n"
297 "%s\n" 297 "%s\n"
298 "Units = %s of %u * 512 bytes\n\n", 298 "Units = %ss of %u * 512 bytes\n\n",
299 disk_device, g_heads, g_sectors, g_cylinders, 299 disk_device, g_heads, g_sectors, g_cylinders,
300 SGI_SSWAP16(sgiparam.pcylcount), 300 SGI_SSWAP16(sgiparam.pcylcount),
301 SGI_SSWAP16(sgiparam.sparecyl), 301 SGI_SSWAP16(sgiparam.sparecyl),
302 SGI_SSWAP16(sgiparam.ilfact), 302 SGI_SSWAP16(sgiparam.ilfact),
303 (char *)sgilabel, 303 (char *)sgilabel,
304 str_units(PLURAL), units_per_sector); 304 str_units(), units_per_sector);
305 } else { 305 } else {
306 printf("\nDisk %s (SGI disk label): " 306 printf("\nDisk %s (SGI disk label): "
307 "%u heads, %u sectors, %u cylinders\n" 307 "%u heads, %u sectors, %u cylinders\n"
308 "Units = %s of %u * 512 bytes\n\n", 308 "Units = %ss of %u * 512 bytes\n\n",
309 disk_device, g_heads, g_sectors, g_cylinders, 309 disk_device, g_heads, g_sectors, g_cylinders,
310 str_units(PLURAL), units_per_sector ); 310 str_units(), units_per_sector );
311 } 311 }
312 312
313 w = strlen(disk_device); 313 w = strlen(disk_device);
@@ -720,7 +720,7 @@ sgi_add_partition(int n, int sys)
720 printf("You got a partition overlap on the disk. Fix it first!\n"); 720 printf("You got a partition overlap on the disk. Fix it first!\n");
721 return; 721 return;
722 } 722 }
723 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR)); 723 snprintf(mesg, sizeof(mesg), "First %s", str_units());
724 while (1) { 724 while (1) {
725 if (sys == SGI_VOLUME) { 725 if (sys == SGI_VOLUME) {
726 last = sgi_get_lastblock(); 726 last = sgi_get_lastblock();
@@ -746,7 +746,7 @@ sgi_add_partition(int n, int sys)
746 printf("You will get a partition overlap on the disk. " 746 printf("You will get a partition overlap on the disk. "
747 "Fix it first!\n"); 747 "Fix it first!\n");
748 } 748 }
749 snprintf(mesg, sizeof(mesg), " Last %s", str_units(SINGULAR)); 749 snprintf(mesg, sizeof(mesg), " Last %s", str_units());
750 last = read_int(scround(first), scround(last)-1, scround(last)-1, 750 last = read_int(scround(first), scround(last)-1, scround(last)-1,
751 scround(first), mesg)+1; 751 scround(first), mesg)+1;
752 if (display_in_cyl_units) 752 if (display_in_cyl_units)
diff --git a/util-linux/fdisk_sun.c b/util-linux/fdisk_sun.c
index 3697a69b9..29d7c283a 100644
--- a/util-linux/fdisk_sun.c
+++ b/util-linux/fdisk_sun.c
@@ -491,7 +491,7 @@ add_sun_partition(int n, int sys)
491 return; 491 return;
492 } 492 }
493 } 493 }
494 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR)); 494 snprintf(mesg, sizeof(mesg), "First %s", str_units());
495 while (1) { 495 while (1) {
496 if (whole_disk) 496 if (whole_disk)
497 first = read_int(0, 0, 0, 0, mesg); 497 first = read_int(0, 0, 0, 0, mesg);
@@ -546,7 +546,7 @@ and is of type 'Whole disk'\n");
546 } 546 }
547 snprintf(mesg, sizeof(mesg), 547 snprintf(mesg, sizeof(mesg),
548 "Last %s or +size or +sizeM or +sizeK", 548 "Last %s or +size or +sizeM or +sizeK",
549 str_units(SINGULAR)); 549 str_units());
550 if (whole_disk) 550 if (whole_disk)
551 last = read_int(scround(stop2), scround(stop2), scround(stop2), 551 last = read_int(scround(stop2), scround(stop2), scround(stop2),
552 0, mesg); 552 0, mesg);
@@ -567,8 +567,8 @@ and is of type 'Whole disk'\n");
567"You haven't covered the whole disk with the 3rd partition,\n" 567"You haven't covered the whole disk with the 3rd partition,\n"
568"but your value %u %s covers some other partition.\n" 568"but your value %u %s covers some other partition.\n"
569"Your entry has been changed to %u %s\n", 569"Your entry has been changed to %u %s\n",
570 scround(last), str_units(SINGULAR), 570 scround(last), str_units(),
571 scround(stop), str_units(SINGULAR)); 571 scround(stop), str_units());
572 last = stop; 572 last = stop;
573 } 573 }
574 } else if (!whole_disk && last > stop) 574 } else if (!whole_disk && last > stop)
@@ -636,20 +636,20 @@ sun_list_table(int xtra)
636 "%u cylinders, %u alternate cylinders, %u physical cylinders\n" 636 "%u cylinders, %u alternate cylinders, %u physical cylinders\n"
637 "%u extra sects/cyl, interleave %u:1\n" 637 "%u extra sects/cyl, interleave %u:1\n"
638 "%s\n" 638 "%s\n"
639 "Units = %s of %u * 512 bytes\n\n", 639 "Units = %ss of %u * 512 bytes\n\n",
640 disk_device, g_heads, g_sectors, SUN_SSWAP16(sunlabel->rspeed), 640 disk_device, g_heads, g_sectors, SUN_SSWAP16(sunlabel->rspeed),
641 g_cylinders, SUN_SSWAP16(sunlabel->nacyl), 641 g_cylinders, SUN_SSWAP16(sunlabel->nacyl),
642 SUN_SSWAP16(sunlabel->pcylcount), 642 SUN_SSWAP16(sunlabel->pcylcount),
643 SUN_SSWAP16(sunlabel->sparecyl), 643 SUN_SSWAP16(sunlabel->sparecyl),
644 SUN_SSWAP16(sunlabel->ilfact), 644 SUN_SSWAP16(sunlabel->ilfact),
645 (char *)sunlabel, 645 (char *)sunlabel,
646 str_units(PLURAL), units_per_sector); 646 str_units(), units_per_sector);
647 else 647 else
648 printf( 648 printf(
649 "\nDisk %s (Sun disk label): %u heads, %u sectors, %u cylinders\n" 649 "\nDisk %s (Sun disk label): %u heads, %u sectors, %u cylinders\n"
650 "Units = %s of %u * 512 bytes\n\n", 650 "Units = %ss of %u * 512 bytes\n\n",
651 disk_device, g_heads, g_sectors, g_cylinders, 651 disk_device, g_heads, g_sectors, g_cylinders,
652 str_units(PLURAL), units_per_sector); 652 str_units(), units_per_sector);
653 653
654 printf("%*s Flag Start End Blocks Id System\n", 654 printf("%*s Flag Start End Blocks Id System\n",
655 w + 1, "Device"); 655 w + 1, "Device");
diff --git a/util-linux/rdate.c b/util-linux/rdate.c
index 41aade5ea..bb1dc519a 100644
--- a/util-linux/rdate.c
+++ b/util-linux/rdate.c
@@ -95,9 +95,13 @@ int rdate_main(int argc UNUSED_PARAM, char **argv)
95 if (!(flags & 2)) { /* no -p (-s may be present) */ 95 if (!(flags & 2)) { /* no -p (-s may be present) */
96 if (time(NULL) == remote_time) 96 if (time(NULL) == remote_time)
97 bb_simple_error_msg("current time matches remote time"); 97 bb_simple_error_msg("current time matches remote time");
98 else 98 else {
99 if (stime(&remote_time) < 0) 99 struct timespec ts;
100 ts.tv_sec = remote_time;
101 ts.tv_nsec = 0;
102 if (clock_settime(CLOCK_REALTIME, &ts) < 0)
100 bb_simple_perror_msg_and_die("can't set time of day"); 103 bb_simple_perror_msg_and_die("can't set time of day");
104 }
101 } 105 }
102 106
103 if (flags != 1) /* not lone -s */ 107 if (flags != 1) /* not lone -s */
diff --git a/util-linux/taskset.c b/util-linux/taskset.c
index ed8878ad4..b542f8c83 100644
--- a/util-linux/taskset.c
+++ b/util-linux/taskset.c
@@ -20,6 +20,14 @@
20//config: Needed for machines with more than 32-64 CPUs: 20//config: Needed for machines with more than 32-64 CPUs:
21//config: affinity parameter 0xHHHHHHHHHHHHHHHHHHHH can be arbitrarily long 21//config: affinity parameter 0xHHHHHHHHHHHHHHHHHHHH can be arbitrarily long
22//config: in this case. Otherwise, it is limited to sizeof(long). 22//config: in this case. Otherwise, it is limited to sizeof(long).
23//config:
24//config:config FEATURE_TASKSET_CPULIST
25//config: bool "CPU list support (-c option)"
26//config: default y
27//config: depends on FEATURE_TASKSET_FANCY
28//config: help
29//config: Add support for taking/printing affinity as CPU list when '-c'
30//config: option is used. For example, it prints '0-3,7' instead of mask '8f'.
23 31
24//applet:IF_TASKSET(APPLET_NOEXEC(taskset, taskset, BB_DIR_USR_BIN, BB_SUID_DROP, taskset)) 32//applet:IF_TASKSET(APPLET_NOEXEC(taskset, taskset, BB_DIR_USR_BIN, BB_SUID_DROP, taskset))
25 33
@@ -108,26 +116,120 @@ static unsigned long *get_aff(int pid, unsigned *sz)
108 return mask; 116 return mask;
109} 117}
110 118
119#if ENABLE_FEATURE_TASKSET_CPULIST
120/*
121 * Parse the CPU list and set the mask accordingly.
122 *
123 * The list element can be either a CPU index or a range of CPU indices.
124 * Example: "1,3,5-7". Stride can be specified: "0-7:2" is "0,2,4,6".
125 * Note: leading and trailing whitespace is not allowed.
126 * util-linux 2.31 allows leading and sometimes trailing whitespace:
127 * ok: taskset -c ' 1, 2'
128 * ok: taskset -c ' 1 , 2'
129 * ok: taskset -c ' 1-7: 2 ,8'
130 * not ok: taskset -c ' 1 '
131 * not ok: taskset -c ' 1-7: 2 '
132 */
133static void parse_cpulist(ul *mask, unsigned max, char *s)
134{
135 char *aff = s;
136 for (;;) {
137 unsigned bit, end;
138 unsigned stride = 1;
139
140 bit = end = bb_strtou(s, &s, 10);
141 if (*s == '-') {
142 s++;
143 end = bb_strtou(s, &s, 10);
144 if (*s == ':') {
145 s++;
146 stride = bb_strtou(s, &s, 10);
147 }
148 }
149 if ((*s != ',' && *s != '\0')
150 || bit > end
151 || end == UINT_MAX /* bb_strtou returns this on malformed / ERANGE numbers */
152 || (stride - 1) > (UINT_MAX / 4)
153 /* disallow 0, malformed input, and too large stride prone to overflows */
154 ) {
155 bb_error_msg_and_die("bad affinity '%s'", aff);
156 }
157 while (bit <= end && bit < max) {
158 mask[bit / BITS_UL] |= (1UL << (bit & MASK_UL));
159 bit += stride;
160 }
161 if (*s == '\0')
162 break;
163 s++;
164 }
165}
166static void print_cpulist(const ul *mask, unsigned mask_size_in_bytes)
167{
168 const ul *mask_end;
169 const char *delim;
170 unsigned pos;
171 ul bit;
172
173 mask_end = mask + mask_size_in_bytes / sizeof(mask[0]);
174 delim = "";
175 pos = 0;
176 bit = 1;
177 for (;;) {
178 if (*mask & bit) {
179 unsigned onebit = pos + 1;
180 printf("%s%u", delim, pos);
181 do {
182 pos++;
183 bit <<= 1;
184 if (bit == 0) {
185 mask++;
186 if (mask >= mask_end)
187 break;
188 bit = 1;
189 }
190 } while (*mask & bit);
191 if (onebit != pos)
192 printf("-%u", pos - 1);
193 delim = ",";
194 }
195 pos++;
196 bit <<= 1;
197 if (bit == 0) {
198 mask++;
199 if (mask >= mask_end)
200 break;
201 bit = 1;
202 }
203 }
204 bb_putchar('\n');
205}
206#endif
207
111int taskset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 208int taskset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
112int taskset_main(int argc UNUSED_PARAM, char **argv) 209int taskset_main(int argc UNUSED_PARAM, char **argv)
113{ 210{
114 ul *mask; 211 ul *mask;
115 unsigned mask_size_in_bytes; 212 unsigned mask_size_in_bytes;
116 pid_t pid = 0; 213 pid_t pid = 0;
117 unsigned opt_p;
118 const char *current_new; 214 const char *current_new;
119 char *aff; 215 char *aff;
216 unsigned opts;
217 enum {
218 OPT_p = 1 << 0,
219 OPT_c = (1 << 1) * ENABLE_FEATURE_TASKSET_CPULIST,
220 };
120 221
121 /* NB: we mimic util-linux's taskset: -p does not take 222 /* NB: we mimic util-linux's taskset: -p does not take
122 * an argument, i.e., "-pN" is NOT valid, only "-p N"! 223 * an argument, i.e., "-pN" is NOT valid, only "-p N"!
123 * Indeed, util-linux-2.13-pre7 uses: 224 * Indeed, util-linux-2.13-pre7 uses:
124 * getopt_long(argc, argv, "+pchV", ...), not "...p:..." */ 225 * getopt_long(argc, argv, "+pchV", ...), not "...p:..." */
125 226
126 opt_p = getopt32(argv, "^+" "p" "\0" "-1" /* at least 1 arg */); 227 opts = getopt32(argv, "^+" "p"IF_FEATURE_TASKSET_CPULIST("c")
228 "\0" "-1" /* at least 1 arg */);
127 argv += optind; 229 argv += optind;
128 230
129 aff = *argv++; 231 aff = *argv++;
130 if (opt_p) { 232 if (opts & OPT_p) {
131 char *pid_str = aff; 233 char *pid_str = aff;
132 if (*argv) { /* "-p <aff> <pid> ...rest.is.ignored..." */ 234 if (*argv) { /* "-p <aff> <pid> ...rest.is.ignored..." */
133 pid_str = *argv; /* NB: *argv != NULL in this case */ 235 pid_str = *argv; /* NB: *argv != NULL in this case */
@@ -144,8 +246,14 @@ int taskset_main(int argc UNUSED_PARAM, char **argv)
144 current_new = "current"; 246 current_new = "current";
145 print_aff: 247 print_aff:
146 mask = get_aff(pid, &mask_size_in_bytes); 248 mask = get_aff(pid, &mask_size_in_bytes);
147 if (opt_p) { 249 if (opts & OPT_p) {
148 printf("pid %d's %s affinity mask: "TASKSET_PRINTF_MASK"\n", 250#if ENABLE_FEATURE_TASKSET_CPULIST
251 if (opts & OPT_c) {
252 printf("pid %d's %s affinity list: ", pid, current_new);
253 print_cpulist(mask, mask_size_in_bytes);
254 } else
255#endif
256 printf("pid %d's %s affinity mask: "TASKSET_PRINTF_MASK"\n",
149 pid, current_new, from_mask(mask, mask_size_in_bytes)); 257 pid, current_new, from_mask(mask, mask_size_in_bytes));
150 if (*argv == NULL) { 258 if (*argv == NULL) {
151 /* Either it was just "-p <pid>", 259 /* Either it was just "-p <pid>",
@@ -158,17 +266,27 @@ int taskset_main(int argc UNUSED_PARAM, char **argv)
158 } 266 }
159 memset(mask, 0, mask_size_in_bytes); 267 memset(mask, 0, mask_size_in_bytes);
160 268
161 /* Affinity was specified, translate it into mask */
162 /* it is always in hex, skip "0x" if it exists */
163 if (aff[0] == '0' && (aff[1]|0x20) == 'x')
164 aff += 2;
165
166 if (!ENABLE_FEATURE_TASKSET_FANCY) { 269 if (!ENABLE_FEATURE_TASKSET_FANCY) {
270 /* Affinity was specified, translate it into mask */
271 /* it is always in hex, skip "0x" if it exists */
272 if (aff[0] == '0' && (aff[1]|0x20) == 'x')
273 aff += 2;
167 mask[0] = xstrtoul(aff, 16); 274 mask[0] = xstrtoul(aff, 16);
168 } else { 275 }
276#if ENABLE_FEATURE_TASKSET_CPULIST
277 else if (opts & OPT_c) {
278 parse_cpulist(mask, mask_size_in_bytes * 8, aff);
279 }
280#endif
281 else {
169 unsigned i; 282 unsigned i;
170 char *last_char; 283 char *last_char;
171 284
285 /* Affinity was specified, translate it into mask */
286 /* it is always in hex, skip "0x" if it exists */
287 if (aff[0] == '0' && (aff[1]|0x20) == 'x')
288 aff += 2;
289
172 i = 0; /* bit pos in mask[] */ 290 i = 0; /* bit pos in mask[] */
173 291
174 /* aff is ASCII hex string, accept very long masks in this form. 292 /* aff is ASCII hex string, accept very long masks in this form.