utils.c revision d84430702496f617c01c5e2d27d0e82e02390bb7
1/* 2 * lib/utils.c Utility Functions 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation version 2.1 7 * of the License. 8 * 9 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 10 */ 11 12/** 13 * @defgroup utils Utilities 14 * @{ 15 */ 16 17#include <netlink-local.h> 18#include <netlink/netlink.h> 19#include <netlink/utils.h> 20#include <linux/socket.h> 21 22/** 23 * Debug level 24 */ 25int nl_debug = 0; 26 27struct nl_dump_params nl_debug_dp = { 28 .dp_type = NL_DUMP_DETAILS, 29}; 30 31static void __init nl_debug_init(void) 32{ 33 char *nldbg, *end; 34 35 if ((nldbg = getenv("NLDBG"))) { 36 long level = strtol(nldbg, &end, 0); 37 if (nldbg != end) 38 nl_debug = level; 39 } 40 41 nl_debug_dp.dp_fd = stderr; 42} 43 44int __nl_read_num_str_file(const char *path, int (*cb)(long, const char *)) 45{ 46 FILE *fd; 47 char buf[128]; 48 49 fd = fopen(path, "r"); 50 if (fd == NULL) 51 return -nl_syserr2nlerr(errno); 52 53 while (fgets(buf, sizeof(buf), fd)) { 54 int goodlen, err; 55 long num; 56 char *end; 57 58 if (*buf == '#' || *buf == '\n' || *buf == '\r') 59 continue; 60 61 num = strtol(buf, &end, 0); 62 if (end == buf) 63 return -NLE_INVAL; 64 65 if (num == LONG_MIN || num == LONG_MAX) 66 return -NLE_RANGE; 67 68 while (*end == ' ' || *end == '\t') 69 end++; 70 71 goodlen = strcspn(end, "#\r\n\t "); 72 if (goodlen == 0) 73 return -NLE_INVAL; 74 75 end[goodlen] = '\0'; 76 77 err = cb(num, end); 78 if (err < 0) 79 return err; 80 } 81 82 fclose(fd); 83 84 return 0; 85} 86 87/** 88 * @name Unit Pretty-Printing 89 * @{ 90 */ 91 92/** 93 * Cancel down a byte counter 94 * @arg l byte counter 95 * @arg unit destination unit pointer 96 * 97 * Cancels down a byte counter until it reaches a reasonable 98 * unit. The chosen unit is assigned to \a unit. 99 * 100 * @return The cancelled down byte counter in the new unit. 101 */ 102double nl_cancel_down_bytes(unsigned long long l, char **unit) 103{ 104 if (l >= 1099511627776LL) { 105 *unit = "TiB"; 106 return ((double) l) / 1099511627776LL; 107 } else if (l >= 1073741824) { 108 *unit = "GiB"; 109 return ((double) l) / 1073741824; 110 } else if (l >= 1048576) { 111 *unit = "MiB"; 112 return ((double) l) / 1048576; 113 } else if (l >= 1024) { 114 *unit = "KiB"; 115 return ((double) l) / 1024; 116 } else { 117 *unit = "B"; 118 return (double) l; 119 } 120} 121 122/** 123 * Cancel down a bit counter 124 * @arg l bit counter 125 * @arg unit destination unit pointer 126 * 127 * Cancels downa bit counter until it reaches a reasonable 128 * unit. The chosen unit is assigned to \a unit. 129 * 130 * @return The cancelled down bit counter in the new unit. 131 */ 132double nl_cancel_down_bits(unsigned long long l, char **unit) 133{ 134 if (l >= 1099511627776ULL) { 135 *unit = "Tbit"; 136 return ((double) l) / 1099511627776ULL; 137 } else if (l >= 1073741824) { 138 *unit = "Gbit"; 139 return ((double) l) / 1073741824; 140 } else if (l >= 1048576) { 141 *unit = "Mbit"; 142 return ((double) l) / 1048576; 143 } else if (l >= 1024) { 144 *unit = "Kbit"; 145 return ((double) l) / 1024; 146 } else { 147 *unit = "bit"; 148 return (double) l; 149 } 150 151} 152 153/** 154 * Cancel down a micro second value 155 * @arg l micro seconds 156 * @arg unit destination unit pointer 157 * 158 * Cancels down a microsecond counter until it reaches a 159 * reasonable unit. The chosen unit is assigned to \a unit. 160 * 161 * @return The cancelled down microsecond in the new unit 162 */ 163double nl_cancel_down_us(uint32_t l, char **unit) 164{ 165 if (l >= 1000000) { 166 *unit = "s"; 167 return ((double) l) / 1000000; 168 } else if (l >= 1000) { 169 *unit = "ms"; 170 return ((double) l) / 1000; 171 } else { 172 *unit = "us"; 173 return (double) l; 174 } 175} 176 177/** @} */ 178 179/** 180 * @name Generic Unit Translations 181 * @{ 182 */ 183 184/** 185 * Convert a character string to a size 186 * @arg str size encoded as character string 187 * 188 * Converts the specified size as character to the corresponding 189 * number of bytes. 190 * 191 * Supported formats are: 192 * - b,kb/k,m/mb,gb/g for bytes 193 * - bit,kbit/mbit/gbit 194 * 195 * @return The number of bytes or -1 if the string is unparseable 196 */ 197long nl_size2int(const char *str) 198{ 199 char *p; 200 long l = strtol(str, &p, 0); 201 if (p == str) 202 return -NLE_INVAL; 203 204 if (*p) { 205 if (!strcasecmp(p, "kb") || !strcasecmp(p, "k")) 206 l *= 1024; 207 else if (!strcasecmp(p, "gb") || !strcasecmp(p, "g")) 208 l *= 1024*1024*1024; 209 else if (!strcasecmp(p, "gbit")) 210 l *= 1024*1024*1024/8; 211 else if (!strcasecmp(p, "mb") || !strcasecmp(p, "m")) 212 l *= 1024*1024; 213 else if (!strcasecmp(p, "mbit")) 214 l *= 1024*1024/8; 215 else if (!strcasecmp(p, "kbit")) 216 l *= 1024/8; 217 else if (!strcasecmp(p, "bit")) 218 l /= 8; 219 else if (strcasecmp(p, "b") != 0) 220 return -NLE_INVAL; 221 } 222 223 return l; 224} 225 226/** 227 * Convert a character string to a probability 228 * @arg str probability encoded as character string 229 * 230 * Converts the specified probability as character to the 231 * corresponding probability number. 232 * 233 * Supported formats are: 234 * - 0.0-1.0 235 * - 0%-100% 236 * 237 * @return The probability relative to NL_PROB_MIN and NL_PROB_MAX 238 */ 239long nl_prob2int(const char *str) 240{ 241 char *p; 242 double d = strtod(str, &p); 243 244 if (p == str) 245 return -NLE_INVAL; 246 247 if (d > 1.0) 248 d /= 100.0f; 249 250 if (d > 1.0f || d < 0.0f) 251 return -NLE_RANGE; 252 253 if (*p && strcmp(p, "%") != 0) 254 return -NLE_INVAL; 255 256 return rint(d * NL_PROB_MAX); 257} 258 259/** @} */ 260 261/** 262 * @name Time Translations 263 * @{ 264 */ 265 266#ifdef USER_HZ 267static uint32_t user_hz = USER_HZ; 268#else 269static uint32_t user_hz = 100; 270#endif 271 272static double ticks_per_usec = 1.0f; 273 274/* Retrieves the configured HZ and ticks/us value in the kernel. 275 * The value is cached. Supported ways of getting it: 276 * 277 * 1) environment variable 278 * 2) /proc/net/psched and sysconf 279 * 280 * Supports the environment variables: 281 * PROC_NET_PSCHED - may point to psched file in /proc 282 * PROC_ROOT - may point to /proc fs */ 283static void __init get_psched_settings(void) 284{ 285 char name[FILENAME_MAX]; 286 FILE *fd; 287 int got_hz = 0, got_tick = 0; 288 289 if (getenv("HZ")) { 290 long hz = strtol(getenv("HZ"), NULL, 0); 291 292 if (LONG_MIN != hz && LONG_MAX != hz) { 293 user_hz = hz; 294 got_hz = 1; 295 } 296 } 297 298 if (!got_hz) 299 user_hz = sysconf(_SC_CLK_TCK); 300 301 if (getenv("TICKS_PER_USEC")) { 302 double t = strtod(getenv("TICKS_PER_USEC"), NULL); 303 304 ticks_per_usec = t; 305 got_tick = 1; 306 } 307 308 309 if (getenv("PROC_NET_PSCHED")) 310 snprintf(name, sizeof(name), "%s", getenv("PROC_NET_PSCHED")); 311 else if (getenv("PROC_ROOT")) 312 snprintf(name, sizeof(name), "%s/net/psched", 313 getenv("PROC_ROOT")); 314 else 315 strncpy(name, "/proc/net/psched", sizeof(name) - 1); 316 317 if ((fd = fopen(name, "r"))) { 318 uint32_t tick, us, nom; 319 int r = fscanf(fd, "%08x%08x%08x%*08x", &tick, &us, &nom); 320 321 if (4 == r && nom == 1000000 && !got_tick) 322 ticks_per_usec = (double)tick/(double)us; 323 324 fclose(fd); 325 } 326} 327 328 329/** 330 * Return the value of HZ 331 */ 332int nl_get_hz(void) 333{ 334 return user_hz; 335} 336 337 338/** 339 * Convert micro seconds to ticks 340 * @arg us micro seconds 341 * @return number of ticks 342 */ 343uint32_t nl_us2ticks(uint32_t us) 344{ 345 return us * ticks_per_usec; 346} 347 348 349/** 350 * Convert ticks to micro seconds 351 * @arg ticks number of ticks 352 * @return microseconds 353 */ 354uint32_t nl_ticks2us(uint32_t ticks) 355{ 356 return ticks / ticks_per_usec; 357} 358 359long nl_time2int(const char *str) 360{ 361 char *p; 362 long l = strtol(str, &p, 0); 363 if (p == str) 364 return -NLE_INVAL; 365 366 if (*p) { 367 if (!strcasecmp(p, "min") == 0 || !strcasecmp(p, "m")) 368 l *= 60; 369 else if (!strcasecmp(p, "hour") || !strcasecmp(p, "h")) 370 l *= 60*60; 371 else if (!strcasecmp(p, "day") || !strcasecmp(p, "d")) 372 l *= 60*60*24; 373 else if (strcasecmp(p, "s") != 0) 374 return -NLE_INVAL; 375 } 376 377 return l; 378} 379 380/** 381 * Convert milliseconds to a character string 382 * @arg msec number of milliseconds 383 * @arg buf destination buffer 384 * @arg len buffer length 385 * 386 * Converts milliseconds to a character string split up in days, hours, 387 * minutes, seconds, and milliseconds and stores it in the specified 388 * destination buffer. 389 * 390 * @return The destination buffer. 391 */ 392char * nl_msec2str(uint64_t msec, char *buf, size_t len) 393{ 394 int i, split[5]; 395 char *units[] = {"d", "h", "m", "s", "msec"}; 396 397#define _SPLIT(idx, unit) if ((split[idx] = msec / unit) > 0) msec %= unit 398 _SPLIT(0, 86400000); /* days */ 399 _SPLIT(1, 3600000); /* hours */ 400 _SPLIT(2, 60000); /* minutes */ 401 _SPLIT(3, 1000); /* seconds */ 402#undef _SPLIT 403 split[4] = msec; 404 405 memset(buf, 0, len); 406 407 for (i = 0; i < ARRAY_SIZE(split); i++) { 408 if (split[i] > 0) { 409 char t[64]; 410 snprintf(t, sizeof(t), "%s%d%s", 411 strlen(buf) ? " " : "", split[i], units[i]); 412 strncat(buf, t, len - strlen(buf) - 1); 413 } 414 } 415 416 return buf; 417} 418 419/** @} */ 420 421/** 422 * @name Link Layer Protocol Translations 423 * @{ 424 */ 425 426static struct trans_tbl llprotos[] = { 427 {0, "generic"}, 428 __ADD(ARPHRD_ETHER,ether) 429 __ADD(ARPHRD_EETHER,eether) 430 __ADD(ARPHRD_AX25,ax25) 431 __ADD(ARPHRD_PRONET,pronet) 432 __ADD(ARPHRD_CHAOS,chaos) 433 __ADD(ARPHRD_IEEE802,ieee802) 434 __ADD(ARPHRD_ARCNET,arcnet) 435 __ADD(ARPHRD_APPLETLK,atalk) 436 __ADD(ARPHRD_DLCI,dlci) 437 __ADD(ARPHRD_ATM,atm) 438 __ADD(ARPHRD_METRICOM,metricom) 439 __ADD(ARPHRD_IEEE1394,ieee1394) 440#ifdef ARPHRD_EUI64 441 __ADD(ARPHRD_EUI64,eui64) 442#endif 443 __ADD(ARPHRD_INFINIBAND,infiniband) 444 __ADD(ARPHRD_SLIP,slip) 445 __ADD(ARPHRD_CSLIP,cslip) 446 __ADD(ARPHRD_SLIP6,slip6) 447 __ADD(ARPHRD_CSLIP6,cslip6) 448 __ADD(ARPHRD_RSRVD,rsrvd) 449 __ADD(ARPHRD_ADAPT,adapt) 450 __ADD(ARPHRD_ROSE,rose) 451 __ADD(ARPHRD_X25,x25) 452#ifdef ARPHRD_HWX25 453 __ADD(ARPHRD_HWX25,hwx25) 454#endif 455 __ADD(ARPHRD_PPP,ppp) 456 __ADD(ARPHRD_HDLC,hdlc) 457 __ADD(ARPHRD_LAPB,lapb) 458 __ADD(ARPHRD_DDCMP,ddcmp) 459 __ADD(ARPHRD_RAWHDLC,rawhdlc) 460 __ADD(ARPHRD_TUNNEL,ipip) 461 __ADD(ARPHRD_TUNNEL6,tunnel6) 462 __ADD(ARPHRD_FRAD,frad) 463 __ADD(ARPHRD_SKIP,skip) 464 __ADD(ARPHRD_LOOPBACK,loopback) 465 __ADD(ARPHRD_LOCALTLK,localtlk) 466 __ADD(ARPHRD_FDDI,fddi) 467 __ADD(ARPHRD_BIF,bif) 468 __ADD(ARPHRD_SIT,sit) 469 __ADD(ARPHRD_IPDDP,ip/ddp) 470 __ADD(ARPHRD_IPGRE,gre) 471 __ADD(ARPHRD_PIMREG,pimreg) 472 __ADD(ARPHRD_HIPPI,hippi) 473 __ADD(ARPHRD_ASH,ash) 474 __ADD(ARPHRD_ECONET,econet) 475 __ADD(ARPHRD_IRDA,irda) 476 __ADD(ARPHRD_FCPP,fcpp) 477 __ADD(ARPHRD_FCAL,fcal) 478 __ADD(ARPHRD_FCPL,fcpl) 479 __ADD(ARPHRD_FCFABRIC,fcfb_0) 480 __ADD(ARPHRD_FCFABRIC+1,fcfb_1) 481 __ADD(ARPHRD_FCFABRIC+2,fcfb_2) 482 __ADD(ARPHRD_FCFABRIC+3,fcfb_3) 483 __ADD(ARPHRD_FCFABRIC+4,fcfb_4) 484 __ADD(ARPHRD_FCFABRIC+5,fcfb_5) 485 __ADD(ARPHRD_FCFABRIC+6,fcfb_6) 486 __ADD(ARPHRD_FCFABRIC+7,fcfb_7) 487 __ADD(ARPHRD_FCFABRIC+8,fcfb_8) 488 __ADD(ARPHRD_FCFABRIC+9,fcfb_9) 489 __ADD(ARPHRD_FCFABRIC+10,fcfb_10) 490 __ADD(ARPHRD_FCFABRIC+11,fcfb_11) 491 __ADD(ARPHRD_FCFABRIC+12,fcfb_12) 492 __ADD(ARPHRD_IEEE802_TR,tr) 493 __ADD(ARPHRD_IEEE80211,ieee802.11) 494#ifdef ARPHRD_IEEE80211_PRISM 495 __ADD(ARPHRD_IEEE80211_PRISM, ieee802.11_prism) 496#endif 497#ifdef ARPHRD_VOID 498 __ADD(ARPHRD_VOID,void) 499#endif 500}; 501 502char * nl_llproto2str(int llproto, char *buf, size_t len) 503{ 504 return __type2str(llproto, buf, len, llprotos, ARRAY_SIZE(llprotos)); 505} 506 507int nl_str2llproto(const char *name) 508{ 509 return __str2type(name, llprotos, ARRAY_SIZE(llprotos)); 510} 511 512/** @} */ 513 514 515/** 516 * @name Ethernet Protocol Translations 517 * @{ 518 */ 519 520static struct trans_tbl ether_protos[] = { 521 __ADD(ETH_P_LOOP,loop) 522 __ADD(ETH_P_PUP,pup) 523 __ADD(ETH_P_PUPAT,pupat) 524 __ADD(ETH_P_IP,ip) 525 __ADD(ETH_P_X25,x25) 526 __ADD(ETH_P_ARP,arp) 527 __ADD(ETH_P_BPQ,bpq) 528 __ADD(ETH_P_IEEEPUP,ieeepup) 529 __ADD(ETH_P_IEEEPUPAT,ieeepupat) 530 __ADD(ETH_P_DEC,dec) 531 __ADD(ETH_P_DNA_DL,dna_dl) 532 __ADD(ETH_P_DNA_RC,dna_rc) 533 __ADD(ETH_P_DNA_RT,dna_rt) 534 __ADD(ETH_P_LAT,lat) 535 __ADD(ETH_P_DIAG,diag) 536 __ADD(ETH_P_CUST,cust) 537 __ADD(ETH_P_SCA,sca) 538 __ADD(ETH_P_RARP,rarp) 539 __ADD(ETH_P_ATALK,atalk) 540 __ADD(ETH_P_AARP,aarp) 541#ifdef ETH_P_8021Q 542 __ADD(ETH_P_8021Q,802.1q) 543#endif 544 __ADD(ETH_P_IPX,ipx) 545 __ADD(ETH_P_IPV6,ipv6) 546#ifdef ETH_P_WCCP 547 __ADD(ETH_P_WCCP,wccp) 548#endif 549 __ADD(ETH_P_PPP_DISC,ppp_disc) 550 __ADD(ETH_P_PPP_SES,ppp_ses) 551 __ADD(ETH_P_MPLS_UC,mpls_uc) 552 __ADD(ETH_P_MPLS_MC,mpls_mc) 553 __ADD(ETH_P_ATMMPOA,atmmpoa) 554 __ADD(ETH_P_ATMFATE,atmfate) 555 __ADD(ETH_P_EDP2,edp2) 556 __ADD(ETH_P_802_3,802.3) 557 __ADD(ETH_P_AX25,ax25) 558 __ADD(ETH_P_ALL,all) 559 __ADD(ETH_P_802_2,802.2) 560 __ADD(ETH_P_SNAP,snap) 561 __ADD(ETH_P_DDCMP,ddcmp) 562 __ADD(ETH_P_WAN_PPP,wan_ppp) 563 __ADD(ETH_P_PPP_MP,ppp_mp) 564 __ADD(ETH_P_LOCALTALK,localtalk) 565 __ADD(ETH_P_PPPTALK,ppptalk) 566 __ADD(ETH_P_TR_802_2,tr_802.2) 567 __ADD(ETH_P_MOBITEX,mobitex) 568 __ADD(ETH_P_CONTROL,control) 569 __ADD(ETH_P_IRDA,irda) 570 __ADD(ETH_P_ECONET,econet) 571 __ADD(ETH_P_HDLC,hdlc) 572}; 573 574char *nl_ether_proto2str(int eproto, char *buf, size_t len) 575{ 576 return __type2str(eproto, buf, len, ether_protos, 577 ARRAY_SIZE(ether_protos)); 578} 579 580int nl_str2ether_proto(const char *name) 581{ 582 return __str2type(name, ether_protos, ARRAY_SIZE(ether_protos)); 583} 584 585/** @} */ 586 587/** 588 * @name IP Protocol Translations 589 * @{ 590 */ 591 592char *nl_ip_proto2str(int proto, char *buf, size_t len) 593{ 594 struct protoent *p = getprotobynumber(proto); 595 596 if (p) { 597 snprintf(buf, len, "%s", p->p_name); 598 return buf; 599 } 600 601 snprintf(buf, len, "0x%x", proto); 602 return buf; 603} 604 605int nl_str2ip_proto(const char *name) 606{ 607 struct protoent *p = getprotobyname(name); 608 unsigned long l; 609 char *end; 610 611 if (p) 612 return p->p_proto; 613 614 l = strtoul(name, &end, 0); 615 if (l == ULONG_MAX || *end != '\0') 616 return -NLE_OBJ_NOTFOUND; 617 618 return (int) l; 619} 620 621/** @} */ 622 623/** 624 * @name Dumping Helpers 625 * @{ 626 */ 627 628/** 629 * Handle a new line while dumping 630 * @arg params Dumping parameters 631 * 632 * This function must be called before dumping any onto a 633 * new line. It will ensure proper prefixing as specified 634 * by the dumping parameters. 635 * 636 * @note This function will NOT dump any newlines itself 637 */ 638void nl_new_line(struct nl_dump_params *params) 639{ 640 params->dp_line++; 641 642 if (params->dp_prefix) { 643 int i; 644 for (i = 0; i < params->dp_prefix; i++) { 645 if (params->dp_fd) 646 fprintf(params->dp_fd, " "); 647 else if (params->dp_buf) 648 strncat(params->dp_buf, " ", 649 params->dp_buflen - 650 sizeof(params->dp_buf) - 1); 651 } 652 } 653 654 if (params->dp_nl_cb) 655 params->dp_nl_cb(params, params->dp_line); 656} 657 658static void dump_one(struct nl_dump_params *parms, const char *fmt, 659 va_list args) 660{ 661 if (parms->dp_fd) 662 vfprintf(parms->dp_fd, fmt, args); 663 else if (parms->dp_buf || parms->dp_cb) { 664 char *buf = NULL; 665 vasprintf(&buf, fmt, args); 666 if (parms->dp_cb) 667 parms->dp_cb(parms, buf); 668 else 669 strncat(parms->dp_buf, buf, 670 parms->dp_buflen - strlen(parms->dp_buf) - 1); 671 free(buf); 672 } 673} 674 675 676/** 677 * Dump a formatted character string 678 * @arg params Dumping parameters 679 * @arg fmt printf style formatting string 680 * @arg ... Arguments to formatting string 681 * 682 * Dumps a printf style formatting string to the output device 683 * as specified by the dumping parameters. 684 */ 685void nl_dump(struct nl_dump_params *params, const char *fmt, ...) 686{ 687 va_list args; 688 689 va_start(args, fmt); 690 dump_one(params, fmt, args); 691 va_end(args); 692} 693 694void nl_dump_line(struct nl_dump_params *parms, const char *fmt, ...) 695{ 696 va_list args; 697 698 nl_new_line(parms); 699 700 va_start(args, fmt); 701 dump_one(parms, fmt, args); 702 va_end(args); 703} 704 705 706/** @} */ 707 708/** @cond SKIP */ 709 710int __trans_list_add(int i, const char *a, struct nl_list_head *head) 711{ 712 struct trans_list *tl; 713 714 tl = calloc(1, sizeof(*tl)); 715 if (!tl) 716 return -NLE_NOMEM; 717 718 tl->i = i; 719 tl->a = strdup(a); 720 721 nl_list_add_tail(&tl->list, head); 722 723 return 0; 724} 725 726void __trans_list_clear(struct nl_list_head *head) 727{ 728 struct trans_list *tl, *next; 729 730 nl_list_for_each_entry_safe(tl, next, head, list) { 731 free(tl->a); 732 free(tl); 733 } 734} 735 736char *__type2str(int type, char *buf, size_t len, struct trans_tbl *tbl, 737 size_t tbl_len) 738{ 739 int i; 740 for (i = 0; i < tbl_len; i++) { 741 if (tbl[i].i == type) { 742 snprintf(buf, len, "%s", tbl[i].a); 743 return buf; 744 } 745 } 746 747 snprintf(buf, len, "0x%x", type); 748 return buf; 749} 750 751char *__list_type2str(int type, char *buf, size_t len, 752 struct nl_list_head *head) 753{ 754 struct trans_list *tl; 755 756 nl_list_for_each_entry(tl, head, list) { 757 if (tl->i == type) { 758 snprintf(buf, len, "%s", tl->a); 759 return buf; 760 } 761 } 762 763 snprintf(buf, len, "0x%x", type); 764 return buf; 765} 766 767char *__flags2str(int flags, char *buf, size_t len, 768 struct trans_tbl *tbl, size_t tbl_len) 769{ 770 int i; 771 int tmp = flags; 772 773 memset(buf, 0, len); 774 775 for (i = 0; i < tbl_len; i++) { 776 if (tbl[i].i & tmp) { 777 tmp &= ~tbl[i].i; 778 strncat(buf, tbl[i].a, len - strlen(buf) - 1); 779 if ((tmp & flags)) 780 strncat(buf, ",", len - strlen(buf) - 1); 781 } 782 } 783 784 return buf; 785} 786 787int __str2type(const char *buf, struct trans_tbl *tbl, size_t tbl_len) 788{ 789 unsigned long l; 790 char *end; 791 int i; 792 793 if (*buf == '\0') 794 return -NLE_INVAL; 795 796 for (i = 0; i < tbl_len; i++) 797 if (!strcasecmp(tbl[i].a, buf)) 798 return tbl[i].i; 799 800 l = strtoul(buf, &end, 0); 801 if (l == ULONG_MAX || *end != '\0') 802 return -NLE_OBJ_NOTFOUND; 803 804 return (int) l; 805} 806 807int __list_str2type(const char *buf, struct nl_list_head *head) 808{ 809 struct trans_list *tl; 810 unsigned long l; 811 char *end; 812 813 if (*buf == '\0') 814 return -NLE_INVAL; 815 816 nl_list_for_each_entry(tl, head, list) { 817 if (!strcasecmp(tl->a, buf)) 818 return tl->i; 819 } 820 821 l = strtoul(buf, &end, 0); 822 if (l == ULONG_MAX || *end != '\0') 823 return -NLE_OBJ_NOTFOUND; 824 825 return (int) l; 826} 827 828int __str2flags(const char *buf, struct trans_tbl *tbl, size_t tbl_len) 829{ 830 int i, flags = 0, len; 831 char *p = (char *) buf, *t; 832 833 for (;;) { 834 if (*p == ' ') 835 p++; 836 837 t = strchr(p, ','); 838 len = t ? t - p : strlen(p); 839 for (i = 0; i < tbl_len; i++) 840 if (!strncasecmp(tbl[i].a, p, len)) 841 flags |= tbl[i].i; 842 843 if (!t) 844 return flags; 845 846 p = ++t; 847 } 848 849 return 0; 850} 851 852void dump_from_ops(struct nl_object *obj, struct nl_dump_params *params) 853{ 854 int type = params->dp_type; 855 856 if (type < 0 || type > NL_DUMP_MAX) 857 BUG(); 858 859 params->dp_line = 0; 860 861 if (params->dp_dump_msgtype) { 862#if 0 863 /* XXX */ 864 char buf[64]; 865 866 dp_dump_line(params, 0, "%s ", 867 nl_cache_mngt_type2name(obj->ce_ops, 868 obj->ce_ops->co_protocol, 869 obj->ce_msgtype, 870 buf, sizeof(buf))); 871#endif 872 params->dp_pre_dump = 1; 873 } 874 875 if (obj->ce_ops->oo_dump[type]) 876 obj->ce_ops->oo_dump[type](obj, params); 877} 878 879/** @endcond */ 880 881/** @} */ 882