diff --git a/src/arbits/output/slbt_ar_output_members.c b/src/arbits/output/slbt_ar_output_members.c index 66c8979..7388f38 100644 --- a/src/arbits/output/slbt_ar_output_members.c +++ b/src/arbits/output/slbt_ar_output_members.c @@ -4,6 +4,8 @@ /* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ /*******************************************************************/ +#include +#include #include #include #include "slibtool_driver_impl.h" @@ -15,6 +17,26 @@ | SLBT_PRETTY_POSIX \ | SLBT_PRETTY_HEXDATA) +const char slbt_ar_perm_strs[8][4] = { + {'-','-','-','\0'}, + {'-','-','x','\0'}, + {'-','w','-','\0'}, + {'-','w','x','\0'}, + {'r','-','-','\0'}, + {'r','-','x','\0'}, + {'r','w','-','\0'}, + {'r','w','x','\0'} +}; + +static unsigned slbt_ar_output_decimal_len_from_val(size_t val, unsigned min) +{ + unsigned ret; + + for (ret=0; val; ret++) + val /= 10; + + return (ret > min) ? ret : min; +} static int slbt_ar_output_one_member_posix( int fdout, @@ -25,6 +47,42 @@ static int slbt_ar_output_one_member_posix( memberp->ar_file_header.ar_member_name); } +static int slbt_ar_output_one_member_posix_verbose( + int fdout, + struct ar_meta_member_info * memberp, + const char * fmtstr, + locale_t arlocale) +{ + unsigned ownerbits; + unsigned groupbits; + unsigned worldbits; + time_t artimeval; + struct tm artimeloc; + char artimestr[64] = {0}; + + ownerbits = (memberp->ar_file_header.ar_file_mode & 0700) >> 6; + groupbits = (memberp->ar_file_header.ar_file_mode & 0070) >> 3; + worldbits = (memberp->ar_file_header.ar_file_mode & 0007); + artimeval = memberp->ar_file_header.ar_time_date_stamp; + + if (localtime_r(&artimeval,&artimeloc)) + strftime_l( + artimestr,sizeof(artimestr), + "%b %e %H:%M %Y",&artimeloc, + arlocale); + + return slbt_dprintf( + fdout,fmtstr, + slbt_ar_perm_strs[ownerbits], + slbt_ar_perm_strs[groupbits], + slbt_ar_perm_strs[worldbits], + memberp->ar_file_header.ar_uid, + memberp->ar_file_header.ar_gid, + memberp->ar_file_header.ar_file_size, + artimestr, + memberp->ar_file_header.ar_member_name); +} + static int slbt_ar_output_members_posix( const struct slbt_driver_ctx * dctx, const struct slbt_archive_meta * meta, @@ -32,8 +90,36 @@ static int slbt_ar_output_members_posix( { struct ar_meta_member_info ** memberp; int fdout; + size_t testval; + size_t sizelen; + size_t uidlen; + size_t gidlen; + locale_t arloc; + char fmtstr[64]; fdout = fdctx->fdout; + arloc = 0; + + if (dctx->cctx->fmtflags & SLBT_PRETTY_VERBOSE) { + for (sizelen=0,memberp=meta->a_memberv; *memberp; memberp++) + if ((testval = memberp[0]->ar_file_header.ar_file_size) > sizelen) + sizelen = testval; + + for (uidlen=0,memberp=meta->a_memberv; *memberp; memberp++) + if ((testval = memberp[0]->ar_file_header.ar_uid) > uidlen) + uidlen = testval; + + for (gidlen=0,memberp=meta->a_memberv; *memberp; memberp++) + if ((testval = memberp[0]->ar_file_header.ar_gid) > gidlen) + gidlen = testval; + + sizelen = slbt_ar_output_decimal_len_from_val(sizelen,6); + uidlen = slbt_ar_output_decimal_len_from_val(uidlen,1); + gidlen = slbt_ar_output_decimal_len_from_val(gidlen,1); + arloc = newlocale(LC_ALL,setlocale(LC_ALL,0),0); + + sprintf(fmtstr,"%%s%%s%%s %%%zuu/%%-%zuu %%%zuu %%s %%s\n",uidlen,gidlen,sizelen); + } for (memberp=meta->a_memberv; *memberp; memberp++) { switch ((*memberp)->ar_member_attr) { @@ -43,11 +129,21 @@ static int slbt_ar_output_members_posix( break; default: - if (slbt_ar_output_one_member_posix(fdout,*memberp) < 0) - return SLBT_SYSTEM_ERROR(dctx,0); + if (arloc) { + if (slbt_ar_output_one_member_posix_verbose( + fdout,*memberp,fmtstr,arloc) < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + } else { + if (slbt_ar_output_one_member_posix( + fdout,*memberp) < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + } } } + if (arloc) + freelocale(arloc); + return 0; }