[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: wc 'Is a directory' output

From: Jim Meyering
Subject: Re: wc 'Is a directory' output
Date: Mon, 14 May 2012 08:49:36 +0200

Christopher Jordan-Squire wrote:
> Hi--I was playing around with using awk on wc output and discovered
> that when wc prints "wc: DIR: Is a directory", where DIR is the
> appropriate directory name, it doesn't seem to be printing to stdout.
> If I redirect the output of, say, wc -l ./* to a text file with '>'
> then I don't get the "wc: DIRE: Is a directory" statements. That's
> also causing some weird issues when I pipe wc's output to awk.
> I was trying to understand how wc prints the "Is a directory" line.
> But I haven't been able to figure it out after looking through the
> source for 45 minutes. (I'm a very inexperienced C coder, though. So I
> could have missed something easy.) Could anyone tell me what wc is
> doing and where this shows up in the source?

The easiest/quickest way to answer a question like that is via gdb:
[This is using Fedora 17/x86_64]


Run gdb with --args, the program name, and any arguments ("."):

    $ gdb --args wc .
    Reading symbols from /usr/bin/wc...(no debugging symbols found)...done.
    Missing separate debuginfos, use: debuginfo-install \
    (gdb) q

That warning is relevant, so I'll get out of gdb and run the suggested command:
(without debuginfo, you wouldn't see some line number and file name
information in the backtrace)

    $ sudo debuginfo-install coreutils-8.15-6.fc17.x86_64
    $ gdb --args wc .
    Reading symbols from /usr/bin/wc...Reading symbols from \
    (gdb) b write
    Function "write" not defined.
    Make breakpoint pending on future shared library load? (y or [n]) y

    Breakpoint 1 (write) pending.
    (gdb) run
    Starting program: /usr/bin/wc .

    Breakpoint 1, write () at ../sysdeps/unix/syscall-template.S:82
    (gdb) backtrace
    #0  write () at ../sysdeps/unix/syscall-template.S:82
    #1  0x0000003134676793 in _IO_new_file_write (f=0x31349b1180,
        data=<optimized out>, n=13) at fileops.c:1289
    #2  0x0000003134676672 in new_do_write (fp=fp@entry=0x31349b1180,
        data=data@entry=0x7fffffff6e20 "/usr/bin/wc: ", to_do=to_do@entry=13)
        at fileops.c:543
    #3  0x00000031346772fe in _IO_new_file_xsputn (n=13, data=<optimized out>,
        f=0x31349b1180) at fileops.c:1383
    #4  _IO_new_file_xsputn (f=0x31349b1180, data=<optimized out>, n=13)
        at fileops.c:1305
    #5  0x000000313464b744 in buffered_vfprintf (s=s@entry=0x31349b1180,
        format=format@entry=0x3134777ad1 "%s: ", args=args@entry=0x7fffffff94a8)
        at vfprintf.c:2258
    #6  0x000000313464656e in _IO_vfprintf_internal (s=s@entry=0x31349b1180,
        format=format@entry=0x3134777ad1 "%s: ", ap=ap@entry=0x7fffffff94a8)
        at vfprintf.c:1258
    #7  0x000000313466b632 in __fxprintf (fp=0x31349b1180, fp@entry=0x0,
        fmt=fmt@entry=0x3134777ad1 "%s: ") at fxprintf.c:51
    #8  0x00000031346f0ae2 in __error (status=status@entry=0, errnum=21,
        message=message@entry=0x406135 "%s") at error.c:241
    #9  0x0000000000402d40 in wc (fd=fd@entry=7,
        file_x=file_x@entry=0x7fffffffde4d ".", fstatus=fstatus@entry=0x6090a0)
        at wc.c:434
    #10 0x0000000000402df6 in wc_file (file=file@entry=0x7fffffffde4d ".",
        fstatus=fstatus@entry=0x6090a0) at wc.c:516
    #11 0x0000000000401e80 in wc_file (fstatus=0x6090a0, file=0x7fffffffde4d 
        at wc.c:499
    #12 main (argc=<optimized out>, argv=<optimized out>) at wc.c:777

That shows the write was via a use of the error function in wc.c,
9 frames up the stack.  Go up the stack 9 levels and list the source:

    (gdb) up 9
    #9  0x0000000000402d40 in wc (fd=fd@entry=7,
        file_x=file_x@entry=0x7fffffffde4d ".", fstatus=fstatus@entry=0x6090a0)
        at wc.c:434
    434                   error (0, errno, "%s", file);
    (gdb) list
    429           while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
    430             {
    431               const char *p = buf;
    432               if (bytes_read == SAFE_READ_ERROR)
    433                 {
    434                   error (0, errno, "%s", file);
    435                   ok = false;
    436                   break;
    437                 }

What is wc doing?
The read syscall (via safe_read) failed with errno=EISDIR.
The error function uses that errno value to print the diagnostic you saw.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]