bug-coreutils
[Top][All Lists]
Advanced

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

Re: a bugger on the pwd code


From: 杨光辉
Subject: Re: a bugger on the pwd code
Date: Thu, 15 Nov 2007 08:49:47 +0800

I don't know how to reply you. My english is terrible. I have to send the
code to you. The code is complete from the coreutils code. You can compile
the code using the gcc compiler.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#include <stdio.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <stdbool.h>
#include <errno.h>

#ifndef _D_EXACT_NAMLEN
# define _D_EXACT_NAMLEN(dp) strlen ((dp)->d_name)
#endif

#ifndef MIN
# define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif

#define D_INO(dp) (dp)->d_ino

#define ISSLASH(c)    ((c) == '/')

# define SAME_INODE(Stat_buf_1, Stat_buf_2) \
   ((Stat_buf_1).st_ino == (Stat_buf_2).st_ino \
    && (Stat_buf_1).st_dev == (Stat_buf_2).st_dev)

struct file_name
{
    char *buf;
    size_t n_alloc;
    char *start;
};

void
xalloc_die (void)
{
  fprintf(stderr, "memory exhausted\n");
  exit(1);
}

void *
xmalloc (size_t n)
{
  void *p = malloc (n);
  if (!p && n != 0)
    xalloc_die ();
  return p;
}

void *
xnmalloc (size_t n, size_t s)
{
  return xmalloc (n * s);
}

bool
dot_or_dotdot (char const *file_name)
{
  if (file_name[0] == '.')
    {
      char sep = file_name[(file_name[1] == '.') + 1];
      return (! sep || ISSLASH (sep));
    }
  else
    return false;
}

struct dirent const *
readdir_ignoring_dot_and_dotdot (DIR *dirp)
{
  while (1)
    {
      struct dirent const *dp = readdir (dirp);
      if (dp == NULL || ! dot_or_dotdot (dp->d_name))
    return dp;
    }
}


void
file_name_free (struct file_name *p)
{
    free (p->buf);
    free (p);
}

struct file_name *
file_name_init(void)
{
    struct file_name *p = xmalloc(sizeof *p);

    p->n_alloc = MIN (2 * PATH_MAX, 32 * 1024);

    p->buf = xmalloc (p->n_alloc);
    p->start = p->buf + (p->n_alloc - 1);
    p->start[0] = '\0';

    return p;
}

void
file_name_prepend (struct file_name *p, char const *s, size_t s_len)
{
    size_t n_free = p->start - p->buf;
    if (n_free < 1 + s_len)
    {
    size_t half = p->n_alloc + 1 + s_len;
    char *q = xnmalloc(2, half);
    size_t n_used = p->n_alloc - n_free;

    p->start = q + 2 * half - n_used;
    memcpy (p->start, p->buf + n_free, n_used);
    free (p->buf);
    p->buf = q;
    p->n_alloc = 2 * half;
    }

    p->start -= 1 + s_len;
    p->start[0] = '/';
    memcpy (p->start + 1, s, s_len);
}

char *
nth_parent (size_t n)
{
  char *buf = xnmalloc (3, n);
  char *p = buf;
  size_t i;

  for (i = 0; i < n; i++)
    {
      memcpy (p, "../", 3);
      p += 3;
    }
  p[-1] = '\0';
  return buf;
}

void
find_dir_entry (struct stat *dot_sb, struct file_name *file_name,
        size_t parent_height)
{
  DIR *dirp;
  int fd;
  struct stat parent_sb;
  bool use_lstat;
  bool found;

  dirp = opendir ("..");
  if (dirp == NULL)
    fprintf(stderr,"cannot open directory %s\n",nth_parent (parent_height));

  fd = dirfd (dirp);
  if ((0 <= fd ? fchdir (fd) : chdir ("..")) < 0)
    fprintf(stderr,"failed to chdir to %s\n",nth_parent (parent_height));

  if ((0 <= fd ? fstat (fd, &parent_sb) : stat (".", &parent_sb)) < 0)
    fprintf(stderr, "failed to stat %s\n", nth_parent (parent_height));

  use_lstat = (parent_sb.st_dev != dot_sb->st_dev);

  found = false;
  while (1)
    {
      struct dirent const *dp;
      struct stat ent_sb;
      ino_t ino;

      errno = 0;
      if ((dp = readdir_ignoring_dot_and_dotdot (dirp)) == NULL)
    {
      if (errno)
        {
          int e = errno;
          closedir (dirp);
          errno = e;

          dirp = NULL;
        }
      break;
    }

      ino = D_INO (dp);

      if (use_lstat)
    {
      if (lstat (dp->d_name, &ent_sb) < 0)
        {
          continue;
        }
      ino = ent_sb.st_ino;
    }

      if (ino != dot_sb->st_ino)
    continue;

      if ( ! use_lstat || ent_sb.st_dev == dot_sb->st_dev)
    {
      file_name_prepend (file_name, dp->d_name, _D_EXACT_NAMLEN (dp));
      found = true;
      break;
    }
    }

  if (dirp == NULL || closedir (dirp) != 0)
    {
      fprintf(stderr,"reading directory %s\n",nth_parent (parent_height));
    }

  if ( ! found)
       fprintf(stderr, "couldn't find directory entry in %s with matching
i-node\n", nth_parent(parent_height));

  *dot_sb = parent_sb;
}

struct dev_ino *
get_root_dev_ino (struct dev_ino *root_d_i)
{
  struct stat statbuf;
  if (lstat ("/", &statbuf))
    return NULL;
  root_d_i->st_ino = statbuf.st_ino;
  root_d_i->st_dev = statbuf.st_dev;
  return root_d_i;
}

void
robust_getcwd (struct file_name *file_name)
{
  size_t height = 1;
  struct dev_ino dev_ino_buf;
  struct dev_ino *root_dev_ino = get_root_dev_ino (&dev_ino_buf);
  struct stat dot_sb;

  if (root_dev_ino == NULL)
    fprintf(stderr, "failed to get attributes of /\n");

  if (stat (".", &dot_sb) < 0)
    fprintf(stderr,"failed to stat .\n");

  while (1)
    {
      if (SAME_INODE (dot_sb, *root_dev_ino))
    break;

      find_dir_entry (&dot_sb, file_name, height++);
    }

  if (file_name->start[0] == '\0')
    file_name_prepend (file_name, "", 0);
}

int
main (int argc, char **argv)
{

  struct file_name *file_name = file_name_init ();
  robust_getcwd (file_name);
  puts (file_name->start);
  file_name_free (file_name);


  exit (EXIT_SUCCESS);
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
I compiled the code. The compiler output the error messages, like below.
pwd3.c: In function 'get_root_dev_ino':
pwd3.c:223: error: dereferencing pointer to incomplete type
pwd3.c:224: error: dereferencing pointer to incomplete type
pwd3.c: In function 'robust_getcwd':
pwd3.c:232: error: storage size of 'dev_ino_buf' isn't known
pwd3.c:244: error: dereferencing pointer to incomplete type
pwd3.c:244: error: dereferencing pointer to incomplete type
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Thank you! Thank you!

2007/11/15, Bob Proulx <address@hidden>:
>
> 杨光辉 wrote:
> > /*pwd.c on the coreutils-6.9*/
> >          static void
> >          robust_getcwd (struct file_name *file_name)
> >         {
> >           size_t height = 1;
> > 262    struct dev_ino dev_ino_buf;
> > 263    struct dev_ino *root_dev_ino = get_root_dev_ino (&dev_ino_buf);
> >
> >           .......
> >         }
> > The line 262 and 263 have something wrong. "dev_ino_buf " didn't
> allocate
> > memory. I compilered the pwd.c and found some buggers. Maybe I'm wrong.
>
> The dev_ino_buf variable is a local variable.  The compiler will
> reserve space for it on the stack.  In C this is an "automatic"
> variable.
>
> The get_root_dev_ino() routine returns the &dev_ino_buf parameter
> value as the return value of the function and it is assigned to the
> root_dev_ino variable.
>
> This is not "memory allocation" in the malloc() sense of memory
> allocation.  All of the variables are local variables and the C
> compiler will reserve local stack space for them.  What do you mean
> when you say "didn't allocate memory" for them?
>
> Are you having a problem with the coreutils pwd?
>
> Bob
>

reply via email to

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