strncpy help (long)

Discussion in 'C Programming' started by fybar, Oct 21, 2004.

  1. fybar

    fybar Guest

    Hi, I am in the progress of writing a program that will read in the
    contents of a directory and then do some stuff to some of the files. So
    far I am getting the contents of the directory but I get a strange
    result from one file. Here is my program, feel free to critique:

    #include <sys/types.h>
    #include <dirent.h>
    #include <stdio.h>


    void main(int argc, char *argv[])
    {
    int i;
    int j;
    int array_size;
    DIR *dirp;
    struct dirent *direntp;
    char filename[NAME_MAX];

    /* print usage */
    switch(argc) {
    case 1:
    printf("Usage: %s path\n\n", argv[0]);
    exit(1);
    break;
    /* print out dir contents */
    default :
    for ( i=1; i < argc; i++){
    dirp = opendir( argv );
    printf("This is the dir %s.\n\n", argv);
    while ( (direntp = readdir( dirp )) != NULL )
    {
    printf( "1. strlen from raw {%d}\n", strlen(direntp->d_name) );
    printf( "2. raw from pointer {%s}\n",direntp->d_name );
    strncpy(filename,direntp->d_name,strlen(direntp->d_name));
    array_size=strlen(filename);
    printf("This is the string length %d\n", array_size);
    if ( strncmp( filename, "r",1 )==0 ){
    printf( "3. Modified string {%s}\n",filename );
    }
    for ( j=1; j <= array_size; j++ ) {
    filename[j]=0;
    }
    }
    }
    break;
    }

    closedir( dirp );
    exit(0);
    }
    I call the program:
    myprog /usr/data/r*

    I get data like this:
    This is the dir /usr/data/rui19.

    1. strlen from raw {1}
    2. raw from pointer {.}
    This is the string length 6
    1. strlen from raw {2}
    2. raw from pointer {..}
    This is the string length 2
    1. strlen from raw {14}
    2. raw from pointer {rui19.ils.0001}
    This is the string length 14
    3. Modified string {rui19.ils.0001}

    However one file gives me this:

    1. strlen from raw {18}
    2. raw from pointer {rui22.ils.0052.bak}
    This is the string length 22
    3. Modified string {rui22.ils.0052.baM-@M-^?^C}

    What is that on the end of the file name? This file was created from a
    winder's version of edt, vms guy just won't let go, and saved over a
    Samba share to a Tru64 box. I don't know if some characters were
    concatenated to the end of the filename, but an ls shows the filename
    properly. Is there something in the filename or is my program to blame?
    I have not tried removing or renaming the file as I don't want to lose
    this behaviour until I undestand it. The odd part is that if I print
    out the name directly from the dirent struct I don't see a problem, I
    only see it after the strncpy. This is the only file that does this.

    Also, I created the array_size variable because this wouldn't work.
    What is wrong with this statement?

    for ( j=1; j <= strlen(filename); j++

    Thanks!

    fyb
    --
    This is my sig
     
    fybar, Oct 21, 2004
    #1
    1. Advertising


  2. >"fybar" <> wrote > Hi, I am in the progress of

    writing a program that will read in the
    > contents of a directory and then do some stuff to some of the files. So
    > far I am getting the contents of the directory but I get a strange
    > result from one file. Here is my program, feel free to critique:
    >
    > #include <sys/types.h>
    > #include <dirent.h>

    [snip]

    I don't believe that these are header files that are kosher around here. I
    wouldn't know unix from a boomerang (haven't used either). Maybe other
    people can point you in the right direction. MPJ
     
    Merrill & Michele, Oct 22, 2004
    #2
    1. Advertising

  3. In article <>,
    (fybar) wrote:

    > What is that on the end of the file name? This file was created from a
    > winder's version of edt, vms guy just won't let go, and saved over a
    > Samba share to a Tru64 box. I don't know if some characters were
    > concatenated to the end of the filename, but an ls shows the filename
    > properly. Is there something in the filename or is my program to blame?
    > I have not tried removing or renaming the file as I don't want to lose
    > this behaviour until I undestand it. The odd part is that if I print
    > out the name directly from the dirent struct I don't see a problem, I
    > only see it after the strncpy. This is the only file that does this.


    You don't want strncpy() -- you want strcpy(). strncpy() does not
    '\0'-terminate the string if it's third argument is <= the length of
    the second argument. You've carefully made sure that it is ==.

    - jonathan
     
    Jonathan Adams, Oct 22, 2004
    #3
  4. fybar

    dandelion Guest

    "Jonathan Adams" <> wrote in message
    news:...
    <snip>

    > You don't want strncpy() -- you want strcpy(). strncpy() does not
    > '\0'-terminate the string if it's third argument is <= the length of
    > the second argument. You've carefully made sure that it is ==.


    In that case strcpy will cause a buffer-overrun and allow hostile code to be
    executed. I'd suggest using strncpy and checking the results.
     
    dandelion, Oct 22, 2004
    #4
  5. In article <4178b962$0$143$4all.nl>,
    "dandelion" <> wrote:

    > "Jonathan Adams" <> wrote in message
    > news:...
    > <snip>
    >
    > > You don't want strncpy() -- you want strcpy(). strncpy() does not
    > > '\0'-terminate the string if it's third argument is <= the length of
    > > the second argument. You've carefully made sure that it is ==.

    >
    > In that case strcpy will cause a buffer-overrun and allow hostile code to be
    > executed. I'd suggest using strncpy and checking the results.


    His use of strncpy() is wrong, and checking the results would not help
    him:

    ....
    char filename[NAME_MAX];
    ....
    strncpy(filename,direntp->d_name,strlen(direntp->d_name));
    ....

    It is just as susceptible to buffer overflows as strcpy() would be.
    What the OP actually wants is strlcpy():

    char filename[NAME_MAX];
    ....
    if (strlcpy(filename, direntp->d_name, sizeof (filename)) >=
    sizeof(filename)) {
    /* overflow */
    }
    ....

    size_t
    strlcpy(char *out, const char *in, size_t len)
    {
    size_t ret = strlen(in);

    if (ret < len) {
    (void) strcpy(out, in);
    } else {
    (void) strncpy(out, in, len - 1);
    out[len - 1] = '\0';
    }
    return (ret);
    }

    (yes, there are more efficient ways of writing strlcpy())

    Cheers,
    - jonathan
     
    Jonathan Adams, Oct 22, 2004
    #5
  6. fybar

    dandelion Guest

    "Jonathan Adams" <> wrote in message
    news:...
    > In article <4178b962$0$143$4all.nl>,
    > "dandelion" <> wrote:
    >
    > > "Jonathan Adams" <> wrote in message
    > > news:...
    > > <snip>
    > >
    > > > You don't want strncpy() -- you want strcpy(). strncpy() does not
    > > > '\0'-terminate the string if it's third argument is <= the length of
    > > > the second argument. You've carefully made sure that it is ==.

    > >
    > > In that case strcpy will cause a buffer-overrun and allow hostile code

    to be
    > > executed. I'd suggest using strncpy and checking the results.

    >
    > His use of strncpy() is wrong, and checking the results would not help
    > him:
    >
    > ...



    Ok. I checked and you're right.


    > char filename[NAME_MAX];
    > ...
    > strncpy(filename,direntp->d_name,strlen(direntp->d_name));



    strncpy(filename, direntp->d_name, NAME_MAX);

    And check the results.

    <snip>

    > (yes, there are more efficient ways of writing strlcpy())


    I'm glad you noticed.

    In fact, there aren't many sensible ways to implement it less efficient
    without deliberately trying.

    Cheers,

    dandelion.
     
    dandelion, Oct 22, 2004
    #6
  7. fybar

    dandelion Guest

    "Jonathan Adams" <> wrote in message
    news:...

    <snip>

    > size_t
    > strlcpy(char *out, const char *in, size_t len)
    > {
    > size_t ret = strlen(in);
    >
    > if (ret < len) {
    > (void) strcpy(out, in);
    > } else {
    > (void) strncpy(out, in, len - 1);
    > out[len - 1] = '\0';
    > }
    > return (ret);
    > }
    >
    > (yes, there are more efficient ways of writing strlcpy())


    size_t
    strlcpy(char *dst, const char *src, size_t len)
    {
    size_t cnt = 0;
    len--;

    while('\0' != src[cnt] && cnt < len)
    {
    dst[cnt] = src[cnt];
    cnt++;
    }

    out[cnt] = '\0';
    return cnt;
    }

    Cheers,
    dandelion.

    PS. The above is not tested and may contain errors.
     
    dandelion, Oct 22, 2004
    #7
  8. In article <4178ce89$0$88490$4all.nl>,
    "dandelion" <> wrote:

    > "Jonathan Adams" <> wrote in message
    > news:...
    >
    > <snip>
    >
    > > size_t
    > > strlcpy(char *out, const char *in, size_t len)
    > > {
    > > size_t ret = strlen(in);
    > >
    > > if (ret < len) {
    > > (void) strcpy(out, in);
    > > } else {
    > > (void) strncpy(out, in, len - 1);
    > > out[len - 1] = '\0';
    > > }
    > > return (ret);
    > > }
    > >
    > > (yes, there are more efficient ways of writing strlcpy())

    >
    > size_t
    > strlcpy(char *dst, const char *src, size_t len)
    > {
    > size_t cnt = 0;
    > len--;
    >
    > while('\0' != src[cnt] && cnt < len)
    > {
    > dst[cnt] = src[cnt];
    > cnt++;
    > }
    >
    > out[cnt] = '\0';
    > return cnt;
    > }
    >
    > Cheers,
    > dandelion.
    >
    > PS. The above is not tested and may contain errors.


    For example, it doesn't match the openbsd definition:

    The strlcpy and strlcat functions return the total length of
    the string they tried to create. For strlcpy that means the
    length of src.

    - jonathan
     
    Jonathan Adams, Oct 22, 2004
    #8
  9. fybar

    dandelion Guest

    "Jonathan Adams" <> wrote in message
    news:...
    > In article <4178ce89$0$88490$4all.nl>,
    > "dandelion" <> wrote:
    >
    > > "Jonathan Adams" <> wrote in message
    > > news:...
    > >
    > > <snip>
    > >
    > > > size_t
    > > > strlcpy(char *out, const char *in, size_t len)
    > > > {
    > > > size_t ret = strlen(in);
    > > >
    > > > if (ret < len) {
    > > > (void) strcpy(out, in);
    > > > } else {
    > > > (void) strncpy(out, in, len - 1);
    > > > out[len - 1] = '\0';
    > > > }
    > > > return (ret);
    > > > }
    > > >
    > > > (yes, there are more efficient ways of writing strlcpy())

    > >
    > > size_t
    > > strlcpy(char *dst, const char *src, size_t len)
    > > {
    > > size_t cnt = 0;
    > > len--;
    > >
    > > while('\0' != src[cnt] && cnt < len)
    > > {
    > > dst[cnt] = src[cnt];
    > > cnt++;
    > > }
    > >
    > > out[cnt] = '\0';
    > > return cnt;
    > > }
    > >
    > > Cheers,
    > > dandelion.
    > >
    > > PS. The above is not tested and may contain errors.

    >
    > For example, it doesn't match the openbsd definition:


    I'm no OpenBSD user, so don't expect me to know their standards.

    > The strlcpy and strlcat functions return the total length of
    > the string they tried to create. For strlcpy that means the
    > length of src.


    In this case I would say the OpenBSD definition sucks, since the src string
    is not guaranteed *) to be zero teriminated, in which case strlen will
    return a preposterous value if you do not SIGSEGV with an out-of-bounds
    pointer (you code).

    And if it is... Easy... Add a small extra loop counting till the '\0' comes
    home.

    I still prefer strncpy.

    *) it's a library function after all. I know that *in this case* it's
    guaranteed.
     
    dandelion, Oct 22, 2004
    #9
  10. fybar

    CBFalconer Guest

    Jonathan Adams wrote:
    >

    .... snip ...
    >
    > (yes, there are more efficient ways of writing strlcpy())


    For example (full file <http://cbfalconer.home.att.net/download>):

    #include "strlcpy.h"

    /* NOTE: these routines are deliberately designed to
    not require any assistance from the standard
    libraries. This makes them more useful in any
    embedded systems that must minimize the load size.

    Public domain, by C.B. Falconer
    bug reports to mailto:
    */

    /* ---------------------- */

    size_t strlcpy(char *dst, const char *src, size_t sz)
    {
    const char *start = src;

    if (src && sz--) {
    while ((*dst++ = *src))
    if (sz--) src++;
    else {
    *(--dst) = '\0';
    break;
    }
    }
    if (src) {
    while (*src++) continue;
    return src - start - 1;
    }
    else if (sz) *dst = '\0';
    return 0;
    } /* strlcpy */

    /* ---------------------- */

    size_t strlcat(char *dst, const char *src, size_t sz)
    {
    char *start = dst;

    while (*dst++) /* assumes sz >= strlen(dst) */
    if (sz) sz--; /* i.e. well formed string */
    dst--;
    return dst - start + strlcpy(dst, src, sz);
    } /* strlcat */

    --
    "I support the Red Sox and any team that beats the Yankees"
    "Any baby snookums can be a Yankee fan, it takes real moral
    fiber to be a Red Sox fan" - "I listened to Toronto come back
    from 3:0 in '42, I watched Boston come back from 3:0 in '04"
     
    CBFalconer, Oct 22, 2004
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. George Marsaglia

    Assigning unsigned long to unsigned long long

    George Marsaglia, Jul 8, 2003, in forum: C Programming
    Replies:
    1
    Views:
    683
    Eric Sosman
    Jul 8, 2003
  2. Daniel Rudy

    unsigned long long int to long double

    Daniel Rudy, Sep 19, 2005, in forum: C Programming
    Replies:
    5
    Views:
    1,195
    Peter Shaggy Haywood
    Sep 20, 2005
  3. Mathieu Dutour

    long long and long

    Mathieu Dutour, Jul 17, 2007, in forum: C Programming
    Replies:
    4
    Views:
    480
    santosh
    Jul 24, 2007
  4. Bart C

    Use of Long and Long Long

    Bart C, Jan 9, 2008, in forum: C Programming
    Replies:
    27
    Views:
    807
    Peter Nilsson
    Jan 15, 2008
  5. veryhotsausage
    Replies:
    1
    Views:
    1,810
    veryhotsausage
    Jul 4, 2008
Loading...

Share This Page