Ignore:
Timestamp:
Oct 29, 2017, 7:02:04 PM (8 years ago)
Author:
bird
Message:

kmk_install: added --dos2unix and --unix2dos flags.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/kmkbuiltin/install.c

    r3112 r3114  
    9191#include "kmkbuiltin.h"
    9292#include "k/kDefs.h"    /* for K_OS */
     93#include "dos2unix.h"
    9394
    9495
     
    102103#ifndef MAXBSIZE
    103104# define MAXBSIZE 0x20000
    104 #endif
    105 
    106 /* Bootstrap aid - this doesn't exist in most older releases */
    107 #ifndef MAP_FAILED
    108 #define MAP_FAILED ((void *)-1) /* from <sys/mman.h> */
    109105#endif
    110106
     
    137133static int ignore_perm_errors;
    138134static int hard_link_files_when_possible;
     135static int dos2unix;
    139136
    140137static struct option long_options[] =
     
    146143    { "hard-link-files-when-possible",                  no_argument, 0, 265 },
    147144    { "no-hard-link-files-when-possible",               no_argument, 0, 266 },
     145    { "dos2unix",                                       no_argument, 0, 267 },
     146    { "unix2dos",                                       no_argument, 0, 268 },
    148147    { 0, 0,     0, 0 },
    149148};
    150149
    151150
    152 static int      copy(int, const char *, int, const char *, off_t);
     151static int      copy(int, const char *, int *, const char *);
    153152static int      compare(int, const char *, size_t, int, const char *, size_t);
    154153static int      create_newfile(const char *, int, struct stat *);
     
    160159static int      usage(FILE *);
    161160static char    *last_slash(const char *);
     161static KBOOL    needs_dos2unix_conversion(const char *pszFilename);
     162static KBOOL    needs_unix2dos_conversion(const char *pszFilename);
    162163
    163164int
     
    173174        (void)envp;
    174175
    175         /* reinitialize globals */
    176         mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
    177         suffix = BACKUP_SUFFIX;
    178         gid = 0;
    179         uid = 0;
    180         dobackup = docompare = dodir = dopreserve = dostrip = nommap = safecopy = verbose = mode_given = 0;
     176        /* reinitialize globals */
     177        mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
     178        suffix = BACKUP_SUFFIX;
     179        gid = 0;
     180        uid = 0;
     181        dobackup = docompare = dodir = dopreserve = dostrip = nommap = safecopy = verbose = mode_given = 0;
    181182        ignore_perm_errors = geteuid() != 0;
    182         hard_link_files_when_possible = 0;
    183 
    184         /* reset getopt and set progname. */
    185         g_progname = argv[0];
    186         opterr = 1;
    187         optarg = NULL;
    188         optopt = 0;
    189         optind = 0; /* init */
     183        hard_link_files_when_possible = 0;
     184        dos2unix = 0;
     185
     186        /* reset getopt and set progname. */
     187        g_progname = argv[0];
     188        opterr = 1;
     189        optarg = NULL;
     190        optopt = 0;
     191        optind = 0; /* init */
    190192
    191193        iflags = 0;
     
    264266                        hard_link_files_when_possible = 0;
    265267                        break;
     268                case 267:
     269                        dos2unix = 1;
     270                        break;
     271                case 268:
     272                        dos2unix = -1;
     273                        break;
    266274                case '?':
    267275                default:
     
    280288        if (argc == 0 || (argc == 1 && !dodir))
    281289                return usage(stderr);
     290
     291        /*   and unix2dos doesn't combine well with a couple of other options. */
     292        if (dos2unix != 0) {
     293                if (docompare) {
     294                        warnx("-C/-p and --dos2unix/unix2dos may not be specified together");
     295                        return usage(stderr);
     296                }
     297                if (dostrip) {
     298                        warnx("-s and --dos2unix/unix2dos may not be specified together");
     299                        return usage(stderr);
     300                }
     301        }
    282302
    283303        /* need to make a temp copy so we can compare stripped version */
     
    478498                } else if (gid != (gid_t)-1 && gid != from_sb.st_gid) {
    479499                        why_not = "gid mismatch";
     500                } else if (dos2unix > 0 && needs_dos2unix_conversion(from_name)) {
     501                        why_not = "dos2unix";
     502                } else if (dos2unix < 0 && needs_unix2dos_conversion(from_name)) {
     503                        why_not = "unix2dos";
    480504                } else {
    481505                        int rcLink = link(from_name, to_name);
     
    544568                }
    545569                if (!devnull) {
    546                         rc = copy(from_fd, from_name, to_fd,
    547                                   tempcopy ? tempfile : to_name, from_sb.st_size);
     570                        rc = copy(from_fd, from_name, &to_fd, tempcopy ? tempfile : to_name);
    548571                        if (rc)
    549572                                goto l_done;
     
    880903
    881904/*
     905 * Write error handler.
     906 */
     907static int write_error(int *ptr_to_fd, const char *to_name, int nw)
     908{
     909    int serrno = errno;
     910    (void)close(*ptr_to_fd);
     911    *ptr_to_fd = -1;
     912    (void)unlink(to_name);
     913    errno = nw > 0 ? EIO : serrno;
     914    return err(EX_OSERR, "%s", to_name);
     915}
     916
     917/*
     918 * Read error handler.
     919 */
     920static int read_error(const char *from_name, int *ptr_to_fd, const char *to_name)
     921{
     922    int serrno = errno;
     923    (void)close(*ptr_to_fd);
     924    *ptr_to_fd = -1;
     925    (void)unlink(to_name);
     926    errno = serrno;
     927    return err(EX_OSERR, "%s", from_name);
     928}
     929
     930/*
    882931 * copy --
    883932 *      copy from one file to another
    884933 */
    885934static int
    886 copy(int from_fd, const char *from_name, int to_fd, const char *to_name,
    887     off_t size)
    888 {
     935copy(int from_fd, const char *from_name, int *ptr_to_fd, const char *to_name)
     936{
     937        KBOOL fPendingCr = K_FALSE;
     938        KSIZE cchDst;
    889939        int nr, nw;
    890         int serrno;
    891940        char buf[MAXBSIZE];
    892 
    893         (void)size;
     941        int to_fd = *ptr_to_fd;
    894942
    895943        /* Rewind file descriptors. */
     
    899947                return err(EX_OSERR, "lseek: %s", to_name);
    900948
    901         while ((nr = read(from_fd, buf, sizeof(buf))) > 0)
    902                 if ((nw = write(to_fd, buf, nr)) != nr) {
    903                         serrno = errno;
    904                         (void)unlink(to_name);
    905                         errno = nw > 0 ? EIO : serrno;
    906                         return err(EX_OSERR, "%s", to_name);
    907                 }
    908         if (nr != 0) {
    909                 serrno = errno;
    910                 (void)unlink(to_name);
    911                 errno = serrno;
    912                 return err(EX_OSERR, "%s", from_name);
    913         }
    914         return EX_OK;
     949        if (dos2unix == 0) {
     950                /*
     951                 * Copy bytes, no conversion.
     952                 */
     953                while ((nr = read(from_fd, buf, sizeof(buf))) > 0)
     954                        if ((nw = write(to_fd, buf, nr)) != nr)
     955                                return write_error(ptr_to_fd, to_name, nw);
     956        } else if (dos2unix > 0) {
     957                /*
     958                 * CRLF -> LF is a reduction, so we can work with full buffers.
     959                 */
     960                while ((nr = read(from_fd, buf, sizeof(buf))) > 0) {
     961                        if (   fPendingCr
     962                                && buf[0] != '\n'
     963                                && (nw = write(to_fd, "\r", 1)) != 1)
     964                                return write_error(ptr_to_fd, to_name, nw);
     965
     966                        fPendingCr = dos2unix_convert_to_unix(buf, nr, buf, &cchDst);
     967
     968                        nw = write(to_fd, buf, cchDst);
     969                        if (nw != (int)cchDst)
     970                                return write_error(ptr_to_fd, to_name, nw);
     971                }
     972        } else {
     973                /*
     974                 * LF -> CRLF is an expansion, so we work with half buffers, reading
     975                 * into the upper half of the buffer and expanding into the full buffer.
     976                 * The conversion will never expand to more than the double size.
     977                 *
     978                 * Note! We do not convert valid CRLF line endings.  This gives us
     979                 *       valid DOS text, but no round-trip conversion.
     980                 */
     981                char * const pchSrc = &buf[sizeof(buf) / 2];
     982                while ((nr = read(from_fd, pchSrc, sizeof(buf) / 2)) > 0) {
     983                        if (   fPendingCr
     984                                && pchSrc[0] != '\n'
     985                                && (nw = write(to_fd, "\r", 1))!= 1)
     986                                return write_error(ptr_to_fd, to_name, nw);
     987
     988                        fPendingCr = dos2unix_convert_to_dos(pchSrc, nr, buf, &cchDst);
     989
     990                        nw = write(to_fd, buf, cchDst);
     991                        if (nw != (int)cchDst)
     992                                return write_error(ptr_to_fd, to_name, nw);
     993                }
     994        }
     995
     996        /* Check for read error. */
     997        if (nr != 0)
     998                return read_error(from_name, ptr_to_fd, to_name);
     999
     1000        /* When converting, we might have a pending final CR to write. */
     1001    if (   fPendingCr
     1002                && (nw = write(to_fd, "\r", 1))!= 1)
     1003                return write_error(ptr_to_fd, to_name, nw);
     1004
     1005    return EX_OK;
    9151006}
    9161007
     
    10091100        fprintf(pf,
    10101101"usage: %s [-bCcpSsv] [--[no-]hard-link-files-when-possible]\n"
    1011 "            [--[no-]ignore-perm-errors] [-B suffix] [-f flags]\n"
    1012 "            [-g group] [-m mode] [-o owner] file1 file2\n"
     1102"            [--[no-]ignore-perm-errors] [-B suffix] [-f flags] [-g group]\n"
     1103"            [-m mode] [-o owner] [--dos2unix|--unix2dos] file1 file2\n"
    10131104"   or: %s [-bCcpSsv] [--[no-]ignore-perm-errors] [-B suffix] [-f flags]\n"
    10141105"            [-g group] [-m mode] [-o owner] file1 ... fileN directory\n"
     
    10441135}
    10451136
     1137/**
     1138 * Checks if @a pszFilename actually needs dos2unix conversion.
     1139 *
     1140 * @returns boolean.
     1141 * @param       pszFilename             The name of the file to check.
     1142 */
     1143static KBOOL needs_dos2unix_conversion(const char *pszFilename)
     1144{
     1145        KU32 fStyle = 0;
     1146        int iErr = dos2unix_analyze_file(pszFilename, &fStyle, NULL, NULL);
     1147        return iErr != 0
     1148                || (fStyle & (DOS2UNIX_STYLE_MASK | DOS2UNIX_F_BINARY)) != DOS2UNIX_STYLE_UNIX;
     1149}
     1150
     1151/**
     1152 * Checks if @a pszFilename actually needs unix2dos conversion.
     1153 *
     1154 * @returns boolean.
     1155 * @param       pszFilename             The name of the file to check.
     1156 */
     1157static KBOOL needs_unix2dos_conversion(const char *pszFilename)
     1158{
     1159        KU32 fStyle = 0;
     1160        int iErr = dos2unix_analyze_file(pszFilename, &fStyle, NULL, NULL);
     1161        return iErr != 0
     1162                || (fStyle & (DOS2UNIX_STYLE_MASK | DOS2UNIX_F_BINARY)) != DOS2UNIX_STYLE_DOS;
     1163}
     1164
Note: See TracChangeset for help on using the changeset viewer.