Print this page
8175/8183: memory leak fixes + incorrect test of dereferenced pointer


 215         struct ditem *myancinfo;        /* this directory's ancestry info */
 216         struct dchain *dc_next; /* next directory in the chain */
 217 };
 218 
 219 /*
 220  * A numbuf_t is used when converting a number to a string representation
 221  */
 222 typedef char numbuf_t[NUMBER_WIDTH];
 223 
 224 static struct dchain *dfirst;   /* start of the dir chain */
 225 static struct dchain *cdfirst;  /* start of the current dir chain */
 226 static struct dchain *dtemp;    /* temporary - used for linking */
 227 static char *curdir;            /* the current directory */
 228 
 229 static int      first = 1;      /* true if first line is not yet printed */
 230 static int      nfiles = 0;     /* number of flist entries in current use */
 231 static int      nargs = 0;      /* number of flist entries used for arguments */
 232 static int      maxfils = 0;    /* number of flist/lbuf entries allocated */
 233 static int      maxn = 0;       /* number of flist entries with lbufs asigned */
 234 static int      quantn = 64;    /* allocation growth quantum */

 235 
 236 static struct lbuf      *nxtlbf;        /* ptr to next lbuf to be assigned */

 237 static struct lbuf      **flist;        /* ptr to list of lbuf pointers */
 238 static struct lbuf      *gstat(char *, int, struct ditem *);
 239 static char             *getname(uid_t);
 240 static char             *getgroup(gid_t);
 241 static char             *makename(char *, char *);
 242 static void             pentry(struct lbuf *);
 243 static void             column(void);
 244 static void             pmode(mode_t aflag);
 245 static void             selection(int *);
 246 static void             new_line(void);
 247 static void             rddir(char *, struct ditem *);
 248 static int              strcol(unsigned char *);
 249 static void             pem(struct lbuf **, struct lbuf **, int);
 250 static void             pdirectory(char *, int, int, int, struct ditem *);
 251 static struct cachenode *findincache(struct cachenode **, long);

 252 static void             csi_pprintf(unsigned char *);
 253 static void             pprintf(char *, char *);
 254 static int              compar(struct lbuf **pp1, struct lbuf **pp2);
 255 static char             *number_to_scaled_string(numbuf_t buf,
 256                             unsigned long long number,
 257                             long scale);
 258 static void             record_ancestry(char *, struct stat *, struct lbuf *,
 259                             int, struct ditem *);
 260 static void             ls_color_init(void);
 261 static ls_color_t       *ls_color_find(const char *, mode_t);
 262 static void             ls_start_color(ls_color_t *);
 263 static void             ls_end_color(void);
 264 
 265 static int              aflg;
 266 static int              atflg;
 267 static int              bflg;
 268 static int              cflg;
 269 static int              dflg;
 270 static int              eflg;
 271 static int              fflg;


 396         { "block-size", required_argument, NULL, 0 },
 397         { "full-time", no_argument, NULL, 0 },
 398         { "si", no_argument, NULL, 0 },
 399         { "color", optional_argument, NULL, 0 },
 400         { "colour", optional_argument, NULL, 0},
 401         { "file-type", no_argument, NULL, 0 },
 402         { "time-style", required_argument, NULL, 0 },
 403 
 404         {0, 0, 0, 0}
 405 };
 406 
 407 int
 408 main(int argc, char *argv[])
 409 {
 410         int             c;
 411         int             i;
 412         int             width;
 413         int             amino = 0;
 414         int             opterr = 0;
 415         int             option_index = 0;

 416         struct lbuf     *ep;
 417         struct lbuf     lb;
 418         struct ditem    *myinfo = NULL;
 419 
 420         (void) setlocale(LC_ALL, "");
 421 #if !defined(TEXT_DOMAIN)       /* Should be defined by cc -D */
 422 #define TEXT_DOMAIN "SYS_TEST"  /* Use this only if it weren't */
 423 #endif
 424         (void) textdomain(TEXT_DOMAIN);
 425 #ifdef STANDALONE
 426         if (argv[0][0] == '\0')
 427                 argc = getargv("ls", &argv, 0);
 428 #endif
 429 
 430         lb.lmtime.tv_sec = time(NULL);
 431         lb.lmtime.tv_nsec = 0;
 432         year = lb.lmtime.tv_sec - 6L*30L*24L*60L*60L; /* 6 months ago */
 433         now = lb.lmtime.tv_sec + 60;
 434         if (isatty(1)) {
 435                 Cflg = 1;


 617                                         eflg = 0;
 618                                         time_fmt_old = FORMAT_ISO_LONG;
 619                                         time_fmt_new = FORMAT_ISO_LONG;
 620                                         continue;
 621                                 }
 622                                 if (strcmp(optarg, "iso") == 0) {
 623                                         statreq++;
 624                                         Eflg = 0;
 625                                         eflg = 0;
 626                                         time_fmt_old = FORMAT_ISO_OLD;
 627                                         time_fmt_new = FORMAT_ISO_NEW;
 628                                         continue;
 629                                 }
 630                                 /* should be the default */
 631                                 if (strcmp(optarg, "locale") == 0) {
 632                                         time_fmt_old = FORMAT_OLD;
 633                                         time_fmt_new = FORMAT_NEW;
 634                                         continue;
 635                                 }
 636                                 if (optarg[0] == '+') {
 637                                         char    *told, *tnew;
 638                                         char    *p;
 639                                         size_t  timelen = strlen(optarg);
 640 
 641                                         p = strchr(optarg, '\n');
 642                                         if (p != NULL)
 643                                                 *p++ = '\0';
 644 
 645                                         /*
 646                                          * Time format requires a leading and
 647                                          * trailing space
 648                                          * Add room for 3 spaces + 2 nulls
 649                                          * The + in optarg is replaced with
 650                                          * a space.
 651                                          */
 652                                         timelen += 2 + 3;
 653                                         told = malloc(timelen);
 654                                         if (told == NULL) {
 655                                                 perror("ls");
 656                                                 exit(2);
 657                                         }
 658 
 659                                         (void) memset(told, 0, timelen);
 660                                         told[0] = ' ';
 661                                         (void) strlcat(told, &optarg[1],
 662                                             timelen);
 663                                         (void) strlcat(told, " ", timelen);
 664 
 665                                         if (p != NULL) {
 666                                                 size_t tnew_len;

 667 
 668                                                 tnew = told + strlen(told) + 1;
 669                                                 tnew_len = timelen -
 670                                                     strlen(told) - 1;
 671 
 672                                                 tnew[0] = ' ';
 673                                                 (void) strlcat(tnew, p,
 674                                                     tnew_len);
 675                                                 (void) strlcat(tnew, " ",
 676                                                     tnew_len);
 677                                                 time_fmt_new =
 678                                                     (const char *)tnew;
 679                                         } else {
 680                                                 time_fmt_new =
 681                                                     (const char *)told;
 682                                         }
 683 
 684                                         time_fmt_old = (const char *)told;
 685                                         time_custom = 1;
 686                                         continue;
 687                                 }
 688                                 continue;
 689                         }
 690 


1005          * When certain options (-f, or -U and -1, and not -l, etc.) are
1006          * specified, don't cache each dirent as it's read.  This 'noflist'
1007          * option is set when there's no need to cache those dirents; instead,
1008          * print them out as they're read.
1009          */
1010         if ((Uflg || fflg) && !Cflg && !lflg && !iflg && statreq == 0)
1011                 noflist = 1;
1012 
1013         if (num_cols < 20 || num_cols > 1000)
1014                 /* assume it is an error */
1015                 num_cols = 80;
1016 
1017         /* allocate space for flist and the associated  */
1018         /* data structures (lbufs)                      */
1019         maxfils = quantn;
1020         if (((flist = malloc(maxfils * sizeof (struct lbuf *))) == NULL) ||
1021             ((nxtlbf = malloc(quantn * sizeof (struct lbuf))) == NULL)) {
1022                 perror("ls");
1023                 exit(2);
1024         }





1025         if ((amino = (argc-optind)) == 0) {
1026                                         /*
1027                                          * case when no names are given
1028                                          * in ls-command and current
1029                                          * directory is to be used
1030                                          */
1031                 argv[optind] = dotp;
1032         }
1033 
1034         if (colorflg)
1035                 ls_color_init();
1036 
1037         for (i = 0; i < (amino ? amino : 1); i++) {
1038 
1039                 /*
1040                  * If we are recursing, we need to make sure we don't
1041                  * get into an endless loop.  To keep track of the inodes
1042                  * (actually, just the directories) visited, we
1043                  * maintain a directory ancestry list for a file
1044                  * hierarchy.  As we go deeper into the hierarchy,


1112                         /* Place direct subdirs on front in right order */
1113                         while (cdfirst) {
1114                                 /* reverse cdfirst onto front of dfirst */
1115                                 dtemp = cdfirst;
1116                                 cdfirst = cdfirst -> dc_next;
1117                                 dtemp -> dc_next = dfirst;
1118                                 dfirst = dtemp;
1119                         }
1120                         /* take off first dir on dfirst & print it */
1121                         dtemp = dfirst;
1122                         dfirst = dfirst->dc_next;
1123                         pdirectory(dtemp->dc_name, 1, nargs,
1124                             dtemp->cycle_detected, dtemp->myancinfo);
1125                         if (nomocore)
1126                                 exit(2);
1127                         free(dtemp->dc_name);
1128                         free(dtemp);
1129                 }
1130         }
1131 








1132         return (err);
1133 }
1134 
1135 /*
1136  * pdirectory: print the directory name, labelling it if title is
1137  * nonzero, using lp as the place to start reading in the dir.
1138  */
1139 static void
1140 pdirectory(char *name, int title, int lp, int cdetect, struct ditem *myinfo)
1141 {
1142         struct dchain *dp;
1143         struct lbuf *ap;
1144         char *pname;
1145         int j;
1146 
1147         filewidth = 0;
1148         curdir = name;
1149         if (title) {
1150                 if (!first)
1151                         (void) putc('\n', stdout);


1780         o_mode_t groupperm, mask;
1781         int grouppermfound, maskfound;
1782 
1783         if (nomocore)
1784                 return (NULL);
1785 
1786         if (nfiles >= maxfils) {
1787                 /*
1788                  * all flist/lbuf pair assigned files, time to get some
1789                  * more space
1790                  */
1791                 maxfils += quantn;
1792                 if (((flist = realloc(flist,
1793                     maxfils * sizeof (struct lbuf *))) == NULL) ||
1794                     ((nxtlbf = malloc(quantn *
1795                     sizeof (struct lbuf))) == NULL)) {
1796                         perror("ls");
1797                         nomocore = 1;
1798                         return (NULL);
1799                 }




1800         }


1801 
1802         /*
1803          * nfiles is reset to nargs for each directory
1804          * that is given as an argument maxn is checked
1805          * to prevent the assignment of an lbuf to a flist entry
1806          * that already has one assigned.
1807          */
1808         if (nfiles >= maxn) {
1809                 rep = nxtlbf++;
1810                 flist[nfiles++] = rep;
1811                 maxn = nfiles;
1812         } else {
1813                 rep = flist[nfiles++];
1814         }
1815 
1816         /* Clear the lbuf */
1817         (void) memset((void *) rep, 0, sizeof (struct lbuf));
1818 
1819         /*
1820          * When noflist is set, none of the extra information about the dirent


2204                 } else if (val < c->val) {
2205                         parent = &c->lesschild;
2206                         c = c->lesschild;
2207                 } else {
2208                         parent = &c->grtrchild;
2209                         c = c->grtrchild;
2210                 }
2211         }
2212 
2213         /* not in the cache, make a new entry for it */
2214         c = calloc(1, sizeof (struct cachenode));
2215         if (c == NULL) {
2216                 perror("ls");
2217                 exit(2);
2218         }
2219         *parent = c;
2220         c->val = val;
2221         return (c);
2222 }
2223 






























2224 /*
2225  * get name from cache, or passwd file for a given uid;
2226  * lastuid is set to uid.
2227  */
2228 static char *
2229 getname(uid_t uid)
2230 {
2231         struct passwd *pwent;
2232         struct cachenode *c;
2233 
2234         if ((uid == lastuid) && lastuname)
2235                 return (lastuname);
2236 
2237         c = findincache(&names, uid);
2238         if (c->initted == 0) {
2239                 if ((pwent = getpwuid(uid)) != NULL) {
2240                         SCPYN(&c->name[0], pwent->pw_name);
2241                 } else {
2242                         (void) sprintf(&c->name[0], "%-8u", (int)uid);
2243                 }


2606                                             opt, len + 1);
2607                                 else
2608                                         (void) strlcpy(rep->exttr[fattr].name,
2609                                             "-", len + 1);
2610                         }
2611                 }
2612         }
2613 }
2614 
2615 /* Set extended system attribute timestamp display */
2616 
2617 void
2618 set_sysattrtm_display(char *name, struct lbuf *rep)
2619 {
2620         uint_t          nelem;
2621         uint64_t        *value;
2622         int             i;
2623         size_t          len;
2624 
2625         if (nvpair_value_uint64_array(pair, &value, &nelem) == 0) {
2626                 if (*value != NULL) {
2627                         len = strlen(name);
2628                         i = 0;
2629                         while (rep->extm[i].stm != 0 && i < sacnt)
2630                                 i++;
2631                         rep->extm[i].stm = value[0];
2632                         rep->extm[i].nstm = value[1];
2633                         rep->extm[i].name = xmalloc(len + 1, rep);
2634                         (void) strlcpy(rep->extm[i].name, name, len + 1);
2635                 }
2636         }
2637 }
2638 
2639 void
2640 format_time(time_t sec, time_t nsec)
2641 {
2642         const char *fstr = time_fmt_new;
2643         char fmt_buf[FMTSIZE];
2644 
2645         if (Eflg) {
2646                 (void) snprintf(fmt_buf, FMTSIZE, fstr, nsec);




 215         struct ditem *myancinfo;        /* this directory's ancestry info */
 216         struct dchain *dc_next; /* next directory in the chain */
 217 };
 218 
 219 /*
 220  * A numbuf_t is used when converting a number to a string representation
 221  */
 222 typedef char numbuf_t[NUMBER_WIDTH];
 223 
 224 static struct dchain *dfirst;   /* start of the dir chain */
 225 static struct dchain *cdfirst;  /* start of the current dir chain */
 226 static struct dchain *dtemp;    /* temporary - used for linking */
 227 static char *curdir;            /* the current directory */
 228 
 229 static int      first = 1;      /* true if first line is not yet printed */
 230 static int      nfiles = 0;     /* number of flist entries in current use */
 231 static int      nargs = 0;      /* number of flist entries used for arguments */
 232 static int      maxfils = 0;    /* number of flist/lbuf entries allocated */
 233 static int      maxn = 0;       /* number of flist entries with lbufs asigned */
 234 static int      quantn = 64;    /* allocation growth quantum */
 235 static size_t   hlbfsz = 1;
 236 
 237 static struct lbuf      *nxtlbf;        /* ptr to next lbuf to be assigned */
 238 static struct lbuf      **hlbf;         /* lbuf bookkeeping */
 239 static struct lbuf      **flist;        /* ptr to list of lbuf pointers */
 240 static struct lbuf      *gstat(char *, int, struct ditem *);
 241 static char             *getname(uid_t);
 242 static char             *getgroup(gid_t);
 243 static char             *makename(char *, char *);
 244 static void             pentry(struct lbuf *);
 245 static void             column(void);
 246 static void             pmode(mode_t aflag);
 247 static void             selection(int *);
 248 static void             new_line(void);
 249 static void             rddir(char *, struct ditem *);
 250 static int              strcol(unsigned char *);
 251 static void             pem(struct lbuf **, struct lbuf **, int);
 252 static void             pdirectory(char *, int, int, int, struct ditem *);
 253 static struct cachenode *findincache(struct cachenode **, long);
 254 static void             freecachenodes(void);
 255 static void             csi_pprintf(unsigned char *);
 256 static void             pprintf(char *, char *);
 257 static int              compar(struct lbuf **pp1, struct lbuf **pp2);
 258 static char             *number_to_scaled_string(numbuf_t buf,
 259                             unsigned long long number,
 260                             long scale);
 261 static void             record_ancestry(char *, struct stat *, struct lbuf *,
 262                             int, struct ditem *);
 263 static void             ls_color_init(void);
 264 static ls_color_t       *ls_color_find(const char *, mode_t);
 265 static void             ls_start_color(ls_color_t *);
 266 static void             ls_end_color(void);
 267 
 268 static int              aflg;
 269 static int              atflg;
 270 static int              bflg;
 271 static int              cflg;
 272 static int              dflg;
 273 static int              eflg;
 274 static int              fflg;


 399         { "block-size", required_argument, NULL, 0 },
 400         { "full-time", no_argument, NULL, 0 },
 401         { "si", no_argument, NULL, 0 },
 402         { "color", optional_argument, NULL, 0 },
 403         { "colour", optional_argument, NULL, 0},
 404         { "file-type", no_argument, NULL, 0 },
 405         { "time-style", required_argument, NULL, 0 },
 406 
 407         {0, 0, 0, 0}
 408 };
 409 
 410 int
 411 main(int argc, char *argv[])
 412 {
 413         int             c;
 414         int             i;
 415         int             width;
 416         int             amino = 0;
 417         int             opterr = 0;
 418         int             option_index = 0;
 419         char            *told = NULL;
 420         struct lbuf     *ep;
 421         struct lbuf     lb;
 422         struct ditem    *myinfo = NULL;
 423 
 424         (void) setlocale(LC_ALL, "");
 425 #if !defined(TEXT_DOMAIN)       /* Should be defined by cc -D */
 426 #define TEXT_DOMAIN "SYS_TEST"  /* Use this only if it weren't */
 427 #endif
 428         (void) textdomain(TEXT_DOMAIN);
 429 #ifdef STANDALONE
 430         if (argv[0][0] == '\0')
 431                 argc = getargv("ls", &argv, 0);
 432 #endif
 433 
 434         lb.lmtime.tv_sec = time(NULL);
 435         lb.lmtime.tv_nsec = 0;
 436         year = lb.lmtime.tv_sec - 6L*30L*24L*60L*60L; /* 6 months ago */
 437         now = lb.lmtime.tv_sec + 60;
 438         if (isatty(1)) {
 439                 Cflg = 1;


 621                                         eflg = 0;
 622                                         time_fmt_old = FORMAT_ISO_LONG;
 623                                         time_fmt_new = FORMAT_ISO_LONG;
 624                                         continue;
 625                                 }
 626                                 if (strcmp(optarg, "iso") == 0) {
 627                                         statreq++;
 628                                         Eflg = 0;
 629                                         eflg = 0;
 630                                         time_fmt_old = FORMAT_ISO_OLD;
 631                                         time_fmt_new = FORMAT_ISO_NEW;
 632                                         continue;
 633                                 }
 634                                 /* should be the default */
 635                                 if (strcmp(optarg, "locale") == 0) {
 636                                         time_fmt_old = FORMAT_OLD;
 637                                         time_fmt_new = FORMAT_NEW;
 638                                         continue;
 639                                 }
 640                                 if (optarg[0] == '+') {
 641                                         char    *tnew;
 642                                         char    *p;
 643                                         size_t  timelen = strlen(optarg);
 644 
 645                                         p = strchr(optarg, '\n');
 646                                         if (p != NULL)
 647                                                 *p++ = '\0';
 648 
 649                                         /*
 650                                          * Time format requires a leading and
 651                                          * trailing space
 652                                          * Add room for 3 spaces + 2 nulls
 653                                          * The + in optarg is replaced with
 654                                          * a space.
 655                                          */
 656                                         timelen += 2 + 3;
 657                                         told = realloc(told, timelen);
 658                                         if (told == NULL) {
 659                                                 perror("ls");
 660                                                 exit(2);
 661                                         }
 662 
 663                                         (void) memset(told, 0, timelen);
 664                                         told[0] = ' ';
 665                                         (void) strlcat(told, &optarg[1],
 666                                             timelen);
 667                                         (void) strlcat(told, " ", timelen);
 668 
 669                                         if (p != NULL) {
 670                                                 size_t tnew_len;
 671                                                 size_t told_len =strlen(told);
 672 
 673                                                 tnew = told + told_len + 1;
 674                                                 tnew_len = timelen -
 675                                                     told_len - 1;
 676 
 677                                                 tnew[0] = ' ';
 678                                                 (void) strlcat(tnew, p,
 679                                                     tnew_len);
 680                                                 (void) strlcat(tnew, " ",
 681                                                     tnew_len);
 682                                                 time_fmt_new =
 683                                                     (const char *)tnew;
 684                                         } else {
 685                                                 time_fmt_new =
 686                                                     (const char *)told;
 687                                         }
 688 
 689                                         time_fmt_old = (const char *)told;
 690                                         time_custom = 1;
 691                                         continue;
 692                                 }
 693                                 continue;
 694                         }
 695 


1010          * When certain options (-f, or -U and -1, and not -l, etc.) are
1011          * specified, don't cache each dirent as it's read.  This 'noflist'
1012          * option is set when there's no need to cache those dirents; instead,
1013          * print them out as they're read.
1014          */
1015         if ((Uflg || fflg) && !Cflg && !lflg && !iflg && statreq == 0)
1016                 noflist = 1;
1017 
1018         if (num_cols < 20 || num_cols > 1000)
1019                 /* assume it is an error */
1020                 num_cols = 80;
1021 
1022         /* allocate space for flist and the associated  */
1023         /* data structures (lbufs)                      */
1024         maxfils = quantn;
1025         if (((flist = malloc(maxfils * sizeof (struct lbuf *))) == NULL) ||
1026             ((nxtlbf = malloc(quantn * sizeof (struct lbuf))) == NULL)) {
1027                 perror("ls");
1028                 exit(2);
1029         }
1030         if ((hlbf = malloc(sizeof(*hlbf))) == NULL) {
1031                 perror("ls");
1032                 exit(2);
1033         }
1034         hlbf[0] = nxtlbf;
1035         if ((amino = (argc-optind)) == 0) {
1036                                         /*
1037                                          * case when no names are given
1038                                          * in ls-command and current
1039                                          * directory is to be used
1040                                          */
1041                 argv[optind] = dotp;
1042         }
1043 
1044         if (colorflg)
1045                 ls_color_init();
1046 
1047         for (i = 0; i < (amino ? amino : 1); i++) {
1048 
1049                 /*
1050                  * If we are recursing, we need to make sure we don't
1051                  * get into an endless loop.  To keep track of the inodes
1052                  * (actually, just the directories) visited, we
1053                  * maintain a directory ancestry list for a file
1054                  * hierarchy.  As we go deeper into the hierarchy,


1122                         /* Place direct subdirs on front in right order */
1123                         while (cdfirst) {
1124                                 /* reverse cdfirst onto front of dfirst */
1125                                 dtemp = cdfirst;
1126                                 cdfirst = cdfirst -> dc_next;
1127                                 dtemp -> dc_next = dfirst;
1128                                 dfirst = dtemp;
1129                         }
1130                         /* take off first dir on dfirst & print it */
1131                         dtemp = dfirst;
1132                         dfirst = dfirst->dc_next;
1133                         pdirectory(dtemp->dc_name, 1, nargs,
1134                             dtemp->cycle_detected, dtemp->myancinfo);
1135                         if (nomocore)
1136                                 exit(2);
1137                         free(dtemp->dc_name);
1138                         free(dtemp);
1139                 }
1140         }
1141 
1142         for (i = 0; i < hlbfsz; i ++)
1143                 free(hlbf[i]);
1144 
1145         free(told);
1146         free(hlbf);
1147         free(flist);
1148         freecachenodes();
1149 
1150         return (err);
1151 }
1152 
1153 /*
1154  * pdirectory: print the directory name, labelling it if title is
1155  * nonzero, using lp as the place to start reading in the dir.
1156  */
1157 static void
1158 pdirectory(char *name, int title, int lp, int cdetect, struct ditem *myinfo)
1159 {
1160         struct dchain *dp;
1161         struct lbuf *ap;
1162         char *pname;
1163         int j;
1164 
1165         filewidth = 0;
1166         curdir = name;
1167         if (title) {
1168                 if (!first)
1169                         (void) putc('\n', stdout);


1798         o_mode_t groupperm, mask;
1799         int grouppermfound, maskfound;
1800 
1801         if (nomocore)
1802                 return (NULL);
1803 
1804         if (nfiles >= maxfils) {
1805                 /*
1806                  * all flist/lbuf pair assigned files, time to get some
1807                  * more space
1808                  */
1809                 maxfils += quantn;
1810                 if (((flist = realloc(flist,
1811                     maxfils * sizeof (struct lbuf *))) == NULL) ||
1812                     ((nxtlbf = malloc(quantn *
1813                     sizeof (struct lbuf))) == NULL)) {
1814                         perror("ls");
1815                         nomocore = 1;
1816                         return (NULL);
1817                 }
1818                 if ((hlbf = realloc(hlbf, sizeof(*hlbf) * (hlbfsz + 1))) == NULL) {
1819                         perror("ls");
1820                         nomocore = 1;
1821                         return (NULL);
1822                 }
1823                 hlbf[hlbfsz++] = nxtlbf;
1824         }
1825 
1826         /*
1827          * nfiles is reset to nargs for each directory
1828          * that is given as an argument maxn is checked
1829          * to prevent the assignment of an lbuf to a flist entry
1830          * that already has one assigned.
1831          */
1832         if (nfiles >= maxn) {
1833                 rep = nxtlbf++;
1834                 flist[nfiles++] = rep;
1835                 maxn = nfiles;
1836         } else {
1837                 rep = flist[nfiles++];
1838         }
1839 
1840         /* Clear the lbuf */
1841         (void) memset((void *) rep, 0, sizeof (struct lbuf));
1842 
1843         /*
1844          * When noflist is set, none of the extra information about the dirent


2228                 } else if (val < c->val) {
2229                         parent = &c->lesschild;
2230                         c = c->lesschild;
2231                 } else {
2232                         parent = &c->grtrchild;
2233                         c = c->grtrchild;
2234                 }
2235         }
2236 
2237         /* not in the cache, make a new entry for it */
2238         c = calloc(1, sizeof (struct cachenode));
2239         if (c == NULL) {
2240                 perror("ls");
2241                 exit(2);
2242         }
2243         *parent = c;
2244         c->val = val;
2245         return (c);
2246 }
2247 
2248 void
2249 freecachenode(struct cachenode *node)
2250 {
2251         struct cachenode *current = node;
2252         if (current != NULL) {
2253                 struct cachenode *grt = NULL;
2254                 struct cachenode *lss = NULL;
2255 
2256                 if (current->grtrchild != NULL) {
2257                         grt = current->grtrchild;
2258                         freecachenode(grt);
2259                 }
2260                 if (current->lesschild != NULL) {
2261                         lss = current->lesschild;
2262                         freecachenode(lss);
2263                 }
2264 
2265                 free(current);
2266                 current = NULL;
2267         }
2268 }
2269 
2270 void
2271 freecachenodes(void)
2272 {
2273         freecachenode(groups);
2274         freecachenode(names);
2275 }
2276 
2277 
2278 /*
2279  * get name from cache, or passwd file for a given uid;
2280  * lastuid is set to uid.
2281  */
2282 static char *
2283 getname(uid_t uid)
2284 {
2285         struct passwd *pwent;
2286         struct cachenode *c;
2287 
2288         if ((uid == lastuid) && lastuname)
2289                 return (lastuname);
2290 
2291         c = findincache(&names, uid);
2292         if (c->initted == 0) {
2293                 if ((pwent = getpwuid(uid)) != NULL) {
2294                         SCPYN(&c->name[0], pwent->pw_name);
2295                 } else {
2296                         (void) sprintf(&c->name[0], "%-8u", (int)uid);
2297                 }


2660                                             opt, len + 1);
2661                                 else
2662                                         (void) strlcpy(rep->exttr[fattr].name,
2663                                             "-", len + 1);
2664                         }
2665                 }
2666         }
2667 }
2668 
2669 /* Set extended system attribute timestamp display */
2670 
2671 void
2672 set_sysattrtm_display(char *name, struct lbuf *rep)
2673 {
2674         uint_t          nelem;
2675         uint64_t        *value;
2676         int             i;
2677         size_t          len;
2678 
2679         if (nvpair_value_uint64_array(pair, &value, &nelem) == 0) {
2680                 if (value != NULL) {
2681                         len = strlen(name);
2682                         i = 0;
2683                         while (rep->extm[i].stm != 0 && i < sacnt)
2684                                 i++;
2685                         rep->extm[i].stm = value[0];
2686                         rep->extm[i].nstm = value[1];
2687                         rep->extm[i].name = xmalloc(len + 1, rep);
2688                         (void) strlcpy(rep->extm[i].name, name, len + 1);
2689                 }
2690         }
2691 }
2692 
2693 void
2694 format_time(time_t sec, time_t nsec)
2695 {
2696         const char *fstr = time_fmt_new;
2697         char fmt_buf[FMTSIZE];
2698 
2699         if (Eflg) {
2700                 (void) snprintf(fmt_buf, FMTSIZE, fstr, nsec);