Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/libpwdgrp/pwd_grp.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/libpwdgrp/pwd_grp.c
r1765 r2725 1 1 /* vi: set sw=4 ts=4: */ 2 /* 2 /* Copyright (C) 2003 Manuel Novoa III 3 3 * 4 * Licensed under GPL v2, or later. See file LICENSE in this tarball.4 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 5 5 */ 6 6 7 /* 7 /* Nov 6, 2003 Initial version. 8 8 * 9 * 9 * NOTE: This implementation is quite strict about requiring all 10 10 * field seperators. It also does not allow leading whitespace 11 11 * except when processing the numeric fields. glibc is more 12 12 * lenient. See the various glibc difference comments below. 13 13 * 14 * 14 * TODO: 15 15 * Move to dynamic allocation of (currently statically allocated) 16 16 * buffers; especially for the group-related functions since 17 17 * large group member lists will cause error returns. 18 *19 18 */ 20 19 21 20 #include "libbb.h" 22 #include <features.h>23 21 #include <assert.h> 24 22 25 23 #ifndef _PATH_SHADOW 26 #define 24 #define _PATH_SHADOW "/etc/shadow" 27 25 #endif 28 26 #ifndef _PATH_PASSWD 29 #define 27 #define _PATH_PASSWD "/etc/passwd" 30 28 #endif 31 29 #ifndef _PATH_GROUP 32 #define 30 #define _PATH_GROUP "/etc/group" 33 31 #endif 34 32 … … 44 42 /* Prototypes for internal functions. */ 45 43 46 static int bb__pgsreader(int (*parserfunc)(void *d, char *line), void *data, 47 char *__restrict line_buff, size_t buflen, FILE *f); 48 49 static int bb__parsepwent(void *pw, char *line); 50 static int bb__parsegrent(void *gr, char *line); 44 static int bb__pgsreader( 45 int FAST_FUNC (*parserfunc)(void *d, char *line), 46 void *data, 47 char *__restrict line_buff, 48 size_t buflen, 49 FILE *f); 50 51 static int FAST_FUNC bb__parsepwent(void *pw, char *line); 52 static int FAST_FUNC bb__parsegrent(void *gr, char *line); 51 53 #if ENABLE_USE_BB_SHADOW 52 static int bb__parsespent(void *sp, char *line);54 static int FAST_FUNC bb__parsespent(void *sp, char *line); 53 55 #endif 54 56 … … 162 164 163 165 #if ENABLE_USE_BB_SHADOW 166 #ifdef UNUSED_FOR_NOW 164 167 int fgetspent_r(FILE *__restrict stream, struct spwd *__restrict resultbuf, 165 168 char *__restrict buffer, size_t buflen, … … 178 181 } 179 182 #endif 183 #endif 180 184 181 185 /**********************************************************************/ … … 185 189 /**********************************************************************/ 186 190 187 #if 0191 #ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS 188 192 struct passwd *fgetpwent(FILE *stream) 189 193 { … … 210 214 211 215 #if ENABLE_USE_BB_SHADOW 212 #if 0216 #ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS 213 217 struct spwd *fgetspent(FILE *stream) 214 218 { … … 223 227 #endif 224 228 229 #ifdef UNUSED_FOR_NOW 225 230 int sgetspent_r(const char *string, struct spwd *result_buf, 226 231 char *buffer, size_t buflen, struct spwd **result) … … 231 236 232 237 if (buflen < PWD_BUFFER_SIZE) { 233 234 errno =rv;238 DO_ERANGE: 239 errno = rv; 235 240 goto DONE; 236 241 } … … 252 257 } 253 258 #endif 259 #endif /* ENABLE_USE_BB_SHADOW */ 254 260 255 261 /**********************************************************************/ … … 397 403 #endif 398 404 399 /* This one doesn't use static buffers */400 int getpw(uid_t uid, char *buf)401 {402 struct passwd resultbuf;403 struct passwd *result;404 char buffer[PWD_BUFFER_SIZE];405 406 if (!buf) {407 errno = EINVAL;408 } else if (!getpwuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result)) {409 if (sprintf(buf, "%s:%s:%lu:%lu:%s:%s:%s\n",410 resultbuf.pw_name, resultbuf.pw_passwd,411 (unsigned long)(resultbuf.pw_uid),412 (unsigned long)(resultbuf.pw_gid),413 resultbuf.pw_gecos, resultbuf.pw_dir,414 resultbuf.pw_shell) >= 0415 ) {416 return 0;417 }418 }419 420 return -1;421 }422 423 405 /**********************************************************************/ 424 406 … … 465 447 466 448 if (!pwf) { 467 pwf = fopen (_PATH_PASSWD, "r");449 pwf = fopen_for_read(_PATH_PASSWD); 468 450 if (!pwf) { 469 451 rv = errno; … … 512 494 513 495 if (!grf) { 514 grf = fopen (_PATH_GROUP, "r");496 grf = fopen_for_read(_PATH_GROUP); 515 497 if (!grf) { 516 498 rv = errno; … … 529 511 } 530 512 513 #ifdef UNUSED_FOR_NOW 531 514 #if ENABLE_USE_BB_SHADOW 532 515 static FILE *spf /*= NULL*/; … … 559 542 560 543 if (!spf) { 561 spf = fopen (_PATH_SHADOW, "r");544 spf = fopen_for_read(_PATH_SHADOW); 562 545 if (!spf) { 563 546 rv = errno; … … 576 559 } 577 560 #endif 578 579 #if 0 561 #endif /* UNUSED_FOR_NOW */ 562 563 #ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS 580 564 struct passwd *getpwent(void) 581 565 { … … 597 581 return result; 598 582 } 599 #endif 600 601 #if 0 //ENABLE_USE_BB_SHADOW 583 584 #if ENABLE_USE_BB_SHADOW 602 585 struct spwd *getspent(void) 603 586 { … … 620 603 } 621 604 #endif 622 623 int initgroups(const char *user, gid_t gid) 605 #endif /* UNUSED_SINCE_WE_AVOID_STATIC_BUFS */ 606 607 static gid_t *getgrouplist_internal(int *ngroups_ptr, const char *user, gid_t gid) 624 608 { 625 609 FILE *grfile; 626 610 gid_t *group_list; 627 int num_groups, rv; 628 char **m; 611 int ngroups; 629 612 struct group group; 630 613 char buff[PWD_BUFFER_SIZE]; 631 614 632 rv = -1;633 634 615 /* We alloc space for 8 gids at a time. */ 635 group_list = (gid_t *) malloc(8*sizeof(gid_t *)); 636 if (group_list 637 && ((grfile = fopen(_PATH_GROUP, "r")) != NULL) 616 group_list = xmalloc(8 * sizeof(group_list[0])); 617 group_list[0] = gid; 618 ngroups = 1; 619 620 grfile = fopen_for_read(_PATH_GROUP); 621 if (grfile) { 622 while (!bb__pgsreader(bb__parsegrent, &group, buff, sizeof(buff), grfile)) { 623 char **m; 624 assert(group.gr_mem); /* Must have at least a NULL terminator. */ 625 if (group.gr_gid == gid) 626 continue; 627 for (m = group.gr_mem; *m; m++) { 628 if (strcmp(*m, user) != 0) 629 continue; 630 group_list = xrealloc_vector(group_list, /*8=2^3:*/ 3, ngroups); 631 group_list[ngroups++] = group.gr_gid; 632 break; 633 } 634 } 635 fclose(grfile); 636 } 637 *ngroups_ptr = ngroups; 638 return group_list; 639 } 640 641 int initgroups(const char *user, gid_t gid) 642 { 643 int ngroups; 644 gid_t *group_list = getgrouplist_internal(&ngroups, user, gid); 645 646 ngroups = setgroups(ngroups, group_list); 647 free(group_list); 648 return ngroups; 649 } 650 651 int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups) 652 { 653 int ngroups_old = *ngroups; 654 gid_t *group_list = getgrouplist_internal(ngroups, user, gid); 655 656 if (*ngroups <= ngroups_old) { 657 ngroups_old = *ngroups; 658 memcpy(groups, group_list, ngroups_old * sizeof(groups[0])); 659 } else { 660 ngroups_old = -1; 661 } 662 free(group_list); 663 return ngroups_old; 664 } 665 666 #ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS 667 int putpwent(const struct passwd *__restrict p, FILE *__restrict f) 668 { 669 int rv = -1; 670 671 #if 0 672 /* glibc does this check */ 673 if (!p || !f) { 674 errno = EINVAL; 675 return rv; 676 } 677 #endif 678 679 /* No extra thread locking is needed above what fprintf does. */ 680 if (fprintf(f, "%s:%s:%lu:%lu:%s:%s:%s\n", 681 p->pw_name, p->pw_passwd, 682 (unsigned long)(p->pw_uid), 683 (unsigned long)(p->pw_gid), 684 p->pw_gecos, p->pw_dir, p->pw_shell) >= 0 685 ) { 686 rv = 0; 687 } 688 689 return rv; 690 } 691 692 int putgrent(const struct group *__restrict p, FILE *__restrict f) 693 { 694 int rv = -1; 695 696 #if 0 697 /* glibc does this check */ 698 if (!p || !f) { 699 errno = EINVAL; 700 return rv; 701 } 702 #endif 703 704 if (fprintf(f, "%s:%s:%lu:", 705 p->gr_name, p->gr_passwd, 706 (unsigned long)(p->gr_gid)) >= 0 638 707 ) { 639 *group_list = gid; 640 num_groups = 1; 641 642 while (!bb__pgsreader(bb__parsegrent, &group, buff, sizeof(buff), grfile)) { 643 assert(group.gr_mem); /* Must have at least a NULL terminator. */ 644 if (group.gr_gid != gid) { 645 for (m = group.gr_mem; *m; m++) { 646 if (!strcmp(*m, user)) { 647 if (!(num_groups & 7)) { 648 gid_t *tmp = (gid_t *) 649 realloc(group_list, 650 (num_groups+8) * sizeof(gid_t *)); 651 if (!tmp) { 652 rv = -1; 653 goto DO_CLOSE; 654 } 655 group_list = tmp; 656 } 657 group_list[num_groups++] = group.gr_gid; 658 break; 659 } 708 static const char format[] ALIGN1 = ",%s"; 709 710 char **m; 711 const char *fmt; 712 713 fmt = format + 1; 714 715 assert(p->gr_mem); 716 m = p->gr_mem; 717 718 while (1) { 719 if (!*m) { 720 if (fputc('\n', f) >= 0) { 721 rv = 0; 660 722 } 661 } 662 } 663 664 rv = setgroups(num_groups, group_list); 665 DO_CLOSE: 666 fclose(grfile); 667 } 668 669 /* group_list will be NULL if initial malloc failed, which may trigger 670 * warnings from various malloc debuggers. */ 671 free(group_list); 672 return rv; 673 } 674 675 int putpwent(const struct passwd *__restrict p, FILE *__restrict f) 676 { 677 int rv = -1; 678 679 if (!p || !f) { 680 errno=EINVAL; 681 } else { 682 /* No extra thread locking is needed above what fprintf does. */ 683 if (fprintf(f, "%s:%s:%lu:%lu:%s:%s:%s\n", 684 p->pw_name, p->pw_passwd, 685 (unsigned long)(p->pw_uid), 686 (unsigned long)(p->pw_gid), 687 p->pw_gecos, p->pw_dir, p->pw_shell) >= 0 688 ) { 689 rv = 0; 690 } 691 } 692 693 return rv; 694 } 695 696 int putgrent(const struct group *__restrict p, FILE *__restrict f) 697 { 698 static const char format[] ALIGN1 = ",%s"; 699 700 char **m; 701 const char *fmt; 702 int rv = -1; 703 704 if (!p || !f) { /* Sigh... glibc checks. */ 705 errno=EINVAL; 706 } else { 707 if (fprintf(f, "%s:%s:%lu:", 708 p->gr_name, p->gr_passwd, 709 (unsigned long)(p->gr_gid)) >= 0 710 ) { 711 712 fmt = format + 1; 713 714 assert(p->gr_mem); 715 m = p->gr_mem; 716 717 do { 718 if (!*m) { 719 if (fputc('\n', f) >= 0) { 720 rv = 0; 721 } 722 break; 723 } 724 if (fprintf(f, fmt, *m) < 0) { 725 break; 726 } 727 ++m; 728 fmt = format; 729 } while (1); 730 731 } 732 733 } 734 735 return rv; 736 } 723 break; 724 } 725 if (fprintf(f, fmt, *m) < 0) { 726 break; 727 } 728 m++; 729 fmt = format; 730 } 731 } 732 733 return rv; 734 } 735 #endif 737 736 738 737 #if ENABLE_USE_BB_SHADOW 739 static const unsigned char _sp_off[] ALIGN1 = { 738 #ifdef UNUSED_FOR_NOW 739 static const unsigned char put_sp_off[] ALIGN1 = { 740 740 offsetof(struct spwd, sp_lstchg), /* 2 - not a char ptr */ 741 741 offsetof(struct spwd, sp_min), /* 3 - not a char ptr */ … … 748 748 int putspent(const struct spwd *p, FILE *stream) 749 749 { 750 static const char ld_format[] ALIGN1 = "%ld:"; 751 752 const char *f; 750 const char *fmt; 753 751 long x; 754 752 int i; … … 762 760 } 763 761 764 for (i = 0; i < sizeof( _sp_off); i++) {765 f = ld_format;766 x = *( const long *)(((const char *) p) +_sp_off[i]);762 for (i = 0; i < sizeof(put_sp_off); i++) { 763 fmt = "%ld:"; 764 x = *(long *)((char *)p + put_sp_off[i]); 767 765 if (x == -1) { 768 f += 3;769 } 770 if (fprintf(stream, f , x) < 0) {766 fmt += 3; 767 } 768 if (fprintf(stream, fmt, x) < 0) { 771 769 goto DO_UNLOCK; 772 770 } … … 781 779 } 782 780 783 DO_UNLOCK: 784 return rv; 785 } 786 #endif 787 788 /**********************************************************************/ 789 /* Internal uClibc functions. */ 781 DO_UNLOCK: 782 return rv; 783 } 784 #endif 785 #endif /* USE_BB_SHADOW */ 786 787 /**********************************************************************/ 788 /* Internal functions */ 790 789 /**********************************************************************/ 791 790 … … 800 799 }; 801 800 802 static int bb__parsepwent(void *data, char *line)801 static int FAST_FUNC bb__parsepwent(void *data, char *line) 803 802 { 804 803 char *endptr; … … 807 806 808 807 i = 0; 809 do{810 p = ( (char *) ((struct passwd *) data))+ pw_off[i];811 812 if ( (i & 6) ^ 2) { /* i!=2 and i!=3 */808 while (1) { 809 p = (char *) data + pw_off[i]; 810 811 if (i < 2 || i > 3) { 813 812 *((char **) p) = line; 814 if (i ==6) {813 if (i == 6) { 815 814 return 0; 816 815 } … … 839 838 } 840 839 841 *line++ = 0;842 ++i;843 } while (1);840 *line++ = '\0'; 841 i++; 842 } /* while (1) */ 844 843 845 844 return -1; … … 854 853 }; 855 854 856 static int bb__parsegrent(void *data, char *line)855 static int FAST_FUNC bb__parsegrent(void *data, char *line) 857 856 { 858 857 char *endptr; … … 864 863 end_of_buf = ((struct group *) data)->gr_name; /* Evil hack! */ 865 864 i = 0; 866 do{867 p = ( (char *) ((struct group *) data))+ gr_off[i];865 while (1) { 866 p = (char *) data + gr_off[i]; 868 867 869 868 if (i < 2) { … … 873 872 break; 874 873 } 875 *line++ = 0;876 ++i;874 *line++ = '\0'; 875 i++; 877 876 } else { 878 877 *((gid_t *) p) = strtoul(line, &endptr, 10); … … 894 893 if (p[1]) { /* We have a member list to process. */ 895 894 /* Overwrite the last ':' with a ',' before counting. 896 * This allows us to test for initial ',' and adds897 * one ',' so that the ',' count equals the member898 * count. */895 * This allows us to (1) test for initial ',' 896 * and (2) adds one ',' so that the number of commas 897 * equals the member count. */ 899 898 *p = ','; 900 899 do { … … 927 926 if (--i) { 928 927 p = endptr; /* Pointing to char prior to first member. */ 929 do{928 while (1) { 930 929 *members++ = ++p; 931 if (!--i) break; 932 while (*++p) {} 933 } while (1); 930 if (!--i) 931 break; 932 while (*++p) 933 continue; 934 } 934 935 } 935 936 *members = NULL; … … 937 938 return 0; 938 939 } 939 } while (1);940 } /* while (1) */ 940 941 941 942 ERR: … … 947 948 #if ENABLE_USE_BB_SHADOW 948 949 static const unsigned char sp_off[] ALIGN1 = { 949 offsetof(struct spwd, sp_namp), /* 0 */950 offsetof(struct spwd, sp_pwdp), /* 1 */951 offsetof(struct spwd, sp_lstchg), /* 2 - not a char ptr*/952 offsetof(struct spwd, sp_min), /* 3 - not a char ptr*/953 offsetof(struct spwd, sp_max), /* 4 - not a char ptr*/954 offsetof(struct spwd, sp_warn), /* 5 - not a char ptr*/955 offsetof(struct spwd, sp_inact), /* 6 - not a char ptr*/956 offsetof(struct spwd, sp_expire), /* 7 - not a char ptr*/957 offsetof(struct spwd, sp_flag) /* 8 - not a char ptr*/950 offsetof(struct spwd, sp_namp), /* 0: char* */ 951 offsetof(struct spwd, sp_pwdp), /* 1: char* */ 952 offsetof(struct spwd, sp_lstchg), /* 2: long */ 953 offsetof(struct spwd, sp_min), /* 3: long */ 954 offsetof(struct spwd, sp_max), /* 4: long */ 955 offsetof(struct spwd, sp_warn), /* 5: long */ 956 offsetof(struct spwd, sp_inact), /* 6: long */ 957 offsetof(struct spwd, sp_expire), /* 7: long */ 958 offsetof(struct spwd, sp_flag) /* 8: unsigned long */ 958 959 }; 959 960 960 static int bb__parsespent(void *data, char *line)961 static int FAST_FUNC bb__parsespent(void *data, char *line) 961 962 { 962 963 char *endptr; … … 965 966 966 967 i = 0; 967 do{968 p = ( (char *) ((struct spwd *) data))+ sp_off[i];968 while (1) { 969 p = (char *) data + sp_off[i]; 969 970 if (i < 2) { 970 971 *((char **) p) = line; 971 972 line = strchr(line, ':'); 972 973 if (!line) { 973 break; 974 break; /* error */ 974 975 } 975 976 } else { 976 *((long *) p) = (long) strtoul(line, &endptr, 10); 977 977 *((long *) p) = strtoul(line, &endptr, 10); 978 978 if (endptr == line) { 979 *((long *) p) = ((i != 8) ? -1L : ((long)(~0UL))); 980 } 981 979 *((long *) p) = -1L; 980 } 982 981 line = endptr; 983 984 982 if (i == 8) { 985 if ( !*endptr) {986 return 0;983 if (*line != '\0') { 984 break; /* error */ 987 985 } 988 break; 989 } 990 991 if (*endptr != ':') { 992 break; 993 } 994 995 } 996 997 *line++ = 0; 998 ++i; 999 } while (1); 986 return 0; /* all ok */ 987 } 988 if (*line != ':') { 989 break; /* error */ 990 } 991 } 992 *line++ = '\0'; 993 i++; 994 } 1000 995 1001 996 return EINVAL; … … 1005 1000 /**********************************************************************/ 1006 1001 1007 /* Reads until if EOF, or until iffinds a line which fits in the buffer1002 /* Reads until EOF, or until it finds a line which fits in the buffer 1008 1003 * and for which the parser function succeeds. 1009 1004 * 1010 * Returns 0 on success and ENOENT for end-of-file (glibc con cession).1005 * Returns 0 on success and ENOENT for end-of-file (glibc convention). 1011 1006 */ 1012 1013 static int bb__pgsreader(int (*parserfunc)(void *d, char *line), void *data, 1014 char *__restrict line_buff, size_t buflen, FILE *f) 1015 { 1016 int line_len; 1007 static int bb__pgsreader( 1008 int FAST_FUNC (*parserfunc)(void *d, char *line), 1009 void *data, 1010 char *__restrict line_buff, 1011 size_t buflen, 1012 FILE *f) 1013 { 1017 1014 int skip; 1018 1015 int rv = ERANGE; … … 1020 1017 if (buflen < PWD_BUFFER_SIZE) { 1021 1018 errno = rv; 1022 } else { 1023 skip = 0; 1024 do { 1025 if (!fgets(line_buff, buflen, f)) { 1026 if (feof(f)) { 1027 rv = ENOENT; 1028 } 1019 return rv; 1020 } 1021 1022 skip = 0; 1023 while (1) { 1024 if (!fgets(line_buff, buflen, f)) { 1025 if (feof(f)) { 1026 rv = ENOENT; 1027 } 1028 break; 1029 } 1030 1031 { 1032 int line_len = strlen(line_buff) - 1; 1033 if (line_len >= 0 && line_buff[line_len] == '\n') { 1034 line_buff[line_len] = '\0'; 1035 } else 1036 if (line_len + 2 == buflen) { 1037 /* A start (or continuation) of overlong line */ 1038 skip = 1; 1039 continue; 1040 } /* else: a last line in the file, and it has no '\n' */ 1041 } 1042 1043 if (skip) { 1044 /* This "line" is a remainder of overlong line, ignore */ 1045 skip = 0; 1046 continue; 1047 } 1048 1049 /* NOTE: glibc difference - glibc strips leading whitespace from 1050 * records. We do not allow leading whitespace. */ 1051 1052 /* Skip empty lines, comment lines, and lines with leading 1053 * whitespace. */ 1054 if (line_buff[0] != '\0' && line_buff[0] != '#' && !isspace(line_buff[0])) { 1055 if (parserfunc == bb__parsegrent) { 1056 /* Do evil group hack: 1057 * The group entry parsing function needs to know where 1058 * the end of the buffer is so that it can construct the 1059 * group member ptr table. */ 1060 ((struct group *) data)->gr_name = line_buff + buflen; 1061 } 1062 if (parserfunc(data, line_buff) == 0) { 1063 rv = 0; 1029 1064 break; 1030 1065 } 1031 1032 line_len = strlen(line_buff) - 1; /* strlen() must be > 0. */ 1033 if (line_buff[line_len] == '\n') { 1034 line_buff[line_len] = 0; 1035 } else if (line_len + 2 == buflen) { /* line too long */ 1036 ++skip; 1037 continue; 1038 } 1039 1040 if (skip) { 1041 --skip; 1042 continue; 1043 } 1044 1045 /* NOTE: glibc difference - glibc strips leading whitespace from 1046 * records. We do not allow leading whitespace. */ 1047 1048 /* Skip empty lines, comment lines, and lines with leading 1049 * whitespace. */ 1050 if (*line_buff && (*line_buff != '#') && !isspace(*line_buff)) { 1051 if (parserfunc == bb__parsegrent) { /* Do evil group hack. */ 1052 /* The group entry parsing function needs to know where 1053 * the end of the buffer is so that it can construct the 1054 * group member ptr table. */ 1055 ((struct group *) data)->gr_name = line_buff + buflen; 1056 } 1057 1058 if (!parserfunc(data, line_buff)) { 1059 rv = 0; 1060 break; 1061 } 1062 } 1063 } while (1); 1064 1065 } 1066 1067 return rv; 1068 } 1066 } 1067 } /* while (1) */ 1068 1069 return rv; 1070 }
Note:
See TracChangeset
for help on using the changeset viewer.