⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rm.c

📁 HLPDK V10.0+ System Extension Library
💻 C
📖 第 1 页 / 共 2 页
字号:

  if (verbose)
    printf ("  %s\n", pathname);

  err = clear_directory (statp);
  if (err == 0)
    {
      if (interactive)
	{
	  fprintf (stderr, "%s: remove directory `%s'? ",
		   program_name, pathname);
	  if (!yesno ())
	    return 1;
	}
      err = rmdir (pathname) != 0;
      if (err != 0)
	error (0, errno, "%s", pathname);
    }
  return err;
}

/* An element in a stack of pointers into `pathname'.
   `pathp' points to where in `pathname' the terminating '\0' goes
   for this level's directory name. */
struct pathstack
{
  struct pathstack *next;
  char *pathp;
  ino_t inum;
};

/* Linked list of pathnames of directories in progress in recursive rm.
   The entries actually contain pointers into `pathname'.
   `pathstack' is the current deepest level. */
static struct pathstack *pathstack = NULL;

/* Read directory `pathname' and remove all of its entries,
   avoiding use of chdir.
   On entry, STATP points to the results of stat on `pathname'.
   Return 0 for success, error count for failure.
   Upon return, `pathname' will have the same contents as before,
   but its address might be different; in that case, `pnsize' will
   be larger, as well. */

int
clear_directory (statp)
     struct stat *statp;
{
  DIR *dirp;
  struct direct *dp;
  char *name_space;		/* Copy of directory's filenames. */
  char *namep;			/* Current entry in `name_space'. */
  unsigned name_size;		/* Bytes allocated for `name_space'. */
  ino_t *inode_space;		/* Copy of directory's inodes. */
  ino_t *inodep;		/* Current entry in `inode_space'. */
  unsigned inode_size;		/* Bytes allocated for `inode_space'. */
  int name_length;		/* Length of filename in `namep' plus '\0'. */
  int pathname_length;		/* Length of `pathname'. */
  int err = 0;			/* Return status. */
  struct pathstack pathframe;	/* New top of stack. */
  struct pathstack *pp;		/* Temporary. */

  errno = 0;
  dirp = opendir (pathname);
  if (dirp == NULL)
    {
      error (0, errno, "%s", pathname);
      return 1;
    }

#ifdef MSDOS				/* stat () it ourselves ... */
  statp->st_size = 0L;
  for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp))
	statp->st_size += strlen(dp->d_name) + 1;
  seekdir(dirp, 0L);
#endif /* MSDOS */

  name_size = statp->st_size;
  name_space = (char *) xmalloc (name_size);
  namep = name_space;

#ifndef MSDOS
  inode_size = statp->st_size;
  inode_space = (ino_t *) xmalloc (inode_size);
  inodep = inode_space;
#endif /* not MSDOS */

  while ((dp = readdir (dirp)) != NULL)
    {
      /* Skip "." and ".." (some NFS filesystems' directories lack them). */
      if (dp->d_name[0] != '.'
	  || (dp->d_name[1] != '\0'
	      && (dp->d_name[1] != '.' || dp->d_name[2] != '\0')))
	{
	  unsigned size_needed = (namep - name_space) + NLENGTH (dp) + 2;

	  if (size_needed > name_size)
	    {
	      char *new_name_space;

	      while (size_needed > name_size)
		name_size += 1024;

	      new_name_space = xrealloc (name_space, name_size);
	      namep += new_name_space - name_space;
	      name_space = new_name_space;
	    }
	  namep = stpcpy (namep, dp->d_name) + 1;

#ifndef MSDOS
	  if (inodep == inode_space + inode_size)
	    {
	      ino_t *new_inode_space;

	      inode_size += 1024;
	      new_inode_space = (ino_t *) xrealloc (inode_space, inode_size);
	      inodep += new_inode_space - inode_space;
	      inode_space = new_inode_space;
	    }
	  *inodep++ = dp->d_ino;
#endif /* not MSDOS */
	}
    }
  *namep = '\0';
  closedir (dirp);
  
  pathname_length = strlen (pathname);

  for (namep = name_space, inodep = inode_space; *namep != '\0';
       namep += name_length, inodep++)
    {
      name_length = strlen (namep) + 1;

      /* Satisfy GNU requirement that filenames can be arbitrarily long. */
      if (pathname_length + 1 + name_length > pnsize)
	{
	  char *new_pathname;

	  pnsize = (pathname_length + 1 + name_length) * 2;
	  new_pathname = xrealloc (pathname, pnsize);
	  /* Update the all the pointers in the stack to use the new area. */
	  for (pp = pathstack; pp != NULL; pp = pp->next)
	    pp->pathp += new_pathname - pathname;
	  pathname = new_pathname;
	}

      /* Add a new frame to the top of the path stack. */
      pathframe.pathp = pathname + pathname_length;
      pathframe.inum = *inodep;
      pathframe.next = pathstack;
      pathstack = &pathframe;

      /* Append '/' and the filename to current pathname, take care of the
	 file (which could result in recursive calls), and take the filename
	 back off. */

      *pathstack->pathp = '/';
      strcpy (pathstack->pathp + 1, namep);

      /* If the i-number has already appeared, there's an error. */
      if (check_stack (pathstack->next, pathstack->inum) || rm ())
	err++;

      *pathstack->pathp = '\0';
      pathstack = pathstack->next;	/* Pop the stack. */
    }
  free (name_space);
#ifndef MSDOS
  free (inode_space);
#endif /* not MSDOS */
  return err;
}

#ifndef MSDOS
/* If STACK does not already have an entry with the same i-number as INUM,
   return 0. Otherwise, ask the user whether to continue;
   if yes, return 1, and if no, exit.
   This assumes that no one tries to remove filesystem mount points;
   doing so could cause duplication of i-numbers that would not indicate
   a corrupted file system. */

int
check_stack (stack, inum)
     struct pathstack *stack;
     ino_t inum;
{
  struct pathstack *p;

  for (p = stack; p != NULL; p = p->next)
    {
      if (p->inum == inum)
	{
	  fprintf (stderr, "\
%s: WARNING: Circular directory structure.\n\
This almost certainly means that you have a corrupted file system.\n\
NOTIFY YOUR SYSTEM MANAGER.\n\
Cycle detected:\n\
%s\n\
is the same file as\n", program_name, pathname);
	  *p->pathp = '\0';	/* Truncate pathname. */
	  fprintf (stderr, "%s\n", pathname);
	  *p->pathp = '/';	/* Put it back. */
	  fprintf (stderr, "%s: continue? ", program_name);
	  if (!yesno ())
	    exit (1);
	  return 1;
	}
    }
  return 0;
}
#endif /* !MSDOS */

/* Query the user for a line from the keyboard;
   return 1 if yes, 0 otherwise. */

int
yesno ()
{
  int c, c2;

  fflush (stderr);
  c = getchar ();
  if (c == '\n')
    return 0;
  while ((c2 = getchar ()) != '\n' && c2 != EOF)
    ;

  return c == 'y' || c == 'Y';
}

/* Remove trailing slashes from PATH; they cause some system calls to fail. */

#ifdef MSDOS
#undef strip_trailing_slashes

void
strip_trailing_slashes (char **path)
{
  char *new_path = _fullpath (NULL, *path, 0);
  free (*path);
  *path = msdos_format_filename (new_path);
}

#else /* not MSDOS */

void
strip_trailing_slashes (path)
     char *path;
{
  int last;

  last = strlen (path) - 1;
  while (last > 0 && path[last] == '/')
    path[last--] = '\0';
}

char *
xmalloc (n)
     unsigned n;
{
  char *p;

  p = malloc (n);
  if (p == 0)
    error (2, 0, "virtual memory exhausted");
  return p;
}

char *
xrealloc (p, n)
     char *p;
     unsigned n;
{
  p = realloc (p, n);
  if (p == 0)
    error (2, 0, "virtual memory exhausted");
  return p;
}

#endif /* not MSDOS */

/* Return NAME with any leading path stripped off.  */

char *
basename (name)
     char *name;
{
  char *base;

  base = rindex (name, '/');
  return base ? base + 1 : name;
}

/* Copy SOURCE into DEST, stopping after copying the first '\0', and
   return a pointer to the '\0' at the end of DEST;
   in other words, return DEST + strlen (SOURCE). */

char *
stpcpy (dest, source)
     char *dest;
     char *source;
{
  while ((*dest++ = *source++) != 0)
    /* Do nothing. */ ;
  return dest - 1;
}

void
usage ()
{
#ifdef MSDOS
  fprintf (stderr, "\
Usage: %s [-dfirvR] [+directory] [+force] [+interactive] [+recursive]\n\
       [+verbose] [+copying] [+version] path...\n",
#else /* not MSDOS */
  fprintf (stderr, "\
Usage: %s [-dfirvR] [+directory] [+force] [+interactive] [+recursive]\n\
       [+verbose] path...\n",
#endif /* not MSDOS */
	   program_name);
  exit (1);
}

#ifdef MSDOS
int
force_unlink(char *filename)
{
  if (access( filename, 2))			/* read only */
    if (chmod( filename, S_IREAD|S_IWRITE))
      error (0, errno, "can't force write permission for %s", filename);

#undef unlink					/* nasty tricks ... */
  return unlink (filename);
}
#endif /* MSDOS */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -