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

📄 ls.c

📁 Linux.Programming.by example 的源代码绝对经典
💻 C
📖 第 1 页 / 共 5 页
字号:
	case 2:		/* Second label character */	  if (*p)	    {	      label[1] = *(p++);	      state = 3;	    }	  else	    state = -1;	/* Error */	  break;	case 3:		/* Equal sign after indicator label */	  state = -1;	/* Assume failure... */	  if (*(p++) == '=')/* It *should* be... */	    {	      for (ind_no = 0; indicator_name[ind_no] != NULL; ++ind_no)		{		  if (STREQ (label, indicator_name[ind_no]))		    {		      color_indicator[ind_no].string = buf;		      state = ((color_indicator[ind_no].len =				get_funky_string (&buf, &p, 0)) < 0 ? -1 : 1);		      break;		    }		}	      if (state == -1)		error (0, 0, _("unrecognized prefix: %s"), quotearg (label));	    }	 break;	case 4:		/* Equal sign after *.ext */	  if (*(p++) == '=')	    {	      ext->seq.string = buf;	      state = (ext->seq.len =		       get_funky_string (&buf, &p, 0)) < 0 ? -1 : 1;	    }	  else	    state = -1;	  break;	}    }  if (state < 0)    {      struct color_ext_type *e;      struct color_ext_type *e2;      error (0, 0,	     _("unparsable value for LS_COLORS environment variable"));      free (color_buf);      for (e = color_ext_list; e != NULL; /* empty */)	{	  e2 = e;	  e = e->next;	  free (e2);	}      print_with_color = 0;    }  if (color_indicator[C_LINK].len == 6      && !strncmp (color_indicator[C_LINK].string, "target", 6))    color_symlink_as_referent = 1;}/* Request that the directory named NAME have its contents listed later.   If REALNAME is nonzero, it will be used instead of NAME when the   directory name is printed.  This allows symbolic links to directories   to be treated as regular directories but still be listed under their   real names.  NAME == NULL is used to insert a marker entry for the   directory named in REALNAME.   If F is non-NULL, we use its dev/ino information to save   a call to stat -- when doing a recursive (-R) traversal.  */static voidqueue_directory (const char *name, const char *realname){  struct pending *new;  new = XMALLOC (struct pending, 1);  new->realname = realname ? xstrdup (realname) : NULL;  new->name = name ? xstrdup (name) : NULL;  new->next = pending_dirs;  pending_dirs = new;}/* Read directory `name', and list the files in it.   If `realname' is nonzero, print its name instead of `name';   this is used for symbolic links to directories. */static voidprint_dir (const char *name, const char *realname){  register DIR *dirp;  register struct dirent *next;  register uintmax_t total_blocks = 0;  static int first = 1;  errno = 0;  dirp = opendir (name);  if (!dirp)    {      error (0, errno, "%s", quotearg_colon (name));      exit_status = 1;      return;    }  if (LOOP_DETECT)    {      struct stat dir_stat;      int fd = dirfd (dirp);      /* If dirfd failed, endure the overhead of using stat.  */      if ((0 <= fd	   ? fstat (fd, &dir_stat)	   : stat (name, &dir_stat)) < 0)	{	  error (0, errno, _("cannot determine device and inode of %s"),		 quotearg_colon (name));	  exit_status = 1;	  return;	}      /* If we've already visited this dev/inode pair, warn that	 we've found a loop, and do not process this directory.  */      if (visit_dir (dir_stat.st_dev, dir_stat.st_ino))	{	  error (0, 0, _("not listing already-listed directory: %s"),		 quotearg_colon (name));	  return;	}      DEV_INO_PUSH (dir_stat.st_dev, dir_stat.st_ino);    }  /* Read the directory entries, and insert the subfiles into the `files'     table.  */  clear_files ();  while (1)    {      /* Set errno to zero so we can distinguish between a readdir failure	 and when readdir simply finds that there are no more entries.  */      errno = 0;      if ((next = readdir (dirp)) == NULL)	{	  if (errno)	    {	      /* Save/restore errno across closedir call.  */	      int e = errno;	      closedir (dirp);	      errno = e;	      /* Arrange to give a diagnostic after exiting this loop.  */	      dirp = NULL;	    }	  break;	}      if (file_interesting (next))	{	  enum filetype type = unknown;#if HAVE_STRUCT_DIRENT_D_TYPE	  if (next->d_type == DT_BLK	      || next->d_type == DT_CHR	      || next->d_type == DT_DIR	      || next->d_type == DT_FIFO	      || next->d_type == DT_LNK	      || next->d_type == DT_REG	      || next->d_type == DT_SOCK)	    type = next->d_type;#endif	  total_blocks += gobble_file (next->d_name, type, 0, name);	}    }  if (dirp == NULL || CLOSEDIR (dirp))    {      error (0, errno, _("reading directory %s"), quotearg_colon (name));      exit_status = 1;      /* Don't return; print whatever we got. */    }  /* Sort the directory contents.  */  sort_files ();  /* If any member files are subdirectories, perhaps they should have their     contents listed rather than being mentioned here as files.  */  if (recursive)    extract_dirs_from_files (name, 1);  if (recursive || print_dir_name)    {      if (!first)	DIRED_PUTCHAR ('\n');      first = 0;      DIRED_INDENT ();      PUSH_CURRENT_DIRED_POS (&subdired_obstack);      dired_pos += quote_name (stdout, realname ? realname : name,			       dirname_quoting_options, NULL);      PUSH_CURRENT_DIRED_POS (&subdired_obstack);      DIRED_FPUTS_LITERAL (":\n", stdout);    }  if (format == long_format || print_block_size)    {      const char *p;      char buf[LONGEST_HUMAN_READABLE + 1];      DIRED_INDENT ();      p = _("total");      DIRED_FPUTS (p, stdout, strlen (p));      DIRED_PUTCHAR (' ');      p = human_readable (total_blocks, buf, human_output_opts,			  ST_NBLOCKSIZE, output_block_size);      DIRED_FPUTS (p, stdout, strlen (p));      DIRED_PUTCHAR ('\n');    }  if (files_index)    print_current_files ();}/* Add `pattern' to the list of patterns for which files that match are   not listed.  */static voidadd_ignore_pattern (const char *pattern){  register struct ignore_pattern *ignore;  ignore = XMALLOC (struct ignore_pattern, 1);  ignore->pattern = pattern;  /* Add it to the head of the linked list. */  ignore->next = ignore_patterns;  ignore_patterns = ignore;}/* Return nonzero if the file in `next' should be listed. */static intfile_interesting (const struct dirent *next){  register struct ignore_pattern *ignore;  for (ignore = ignore_patterns; ignore; ignore = ignore->next)    if (fnmatch (ignore->pattern, next->d_name, FNM_PERIOD) == 0)      return 0;  if (really_all_files      || next->d_name[0] != '.'      || (all_files	  && next->d_name[1] != '\0'	  && (next->d_name[1] != '.' || next->d_name[2] != '\0')))    return 1;  return 0;}/* Enter and remove entries in the table `files'.  *//* Empty the table of files. */static voidclear_files (void){  register int i;  for (i = 0; i < files_index; i++)    {      free (files[i].name);      if (files[i].linkname)	free (files[i].linkname);    }  files_index = 0;  block_size_size = 4;}/* Add a file to the current table of files.   Verify that the file exists, and print an error message if it does not.   Return the number of blocks that the file occupies.  */static uintmax_tgobble_file (const char *name, enum filetype type, int explicit_arg,	     const char *dirname){  register uintmax_t blocks;  register char *path;  if (files_index == nfiles)    {      nfiles *= 2;      files = XREALLOC (files, struct fileinfo, nfiles);    }  files[files_index].linkname = 0;  files[files_index].linkmode = 0;  files[files_index].linkok = 0;  if (explicit_arg      || format_needs_stat      || (format_needs_type	  && (type == unknown	      /* FIXME: remove this disjunct.		 I don't think we care about symlinks here, but for now		 this won't make a big performance difference.  */	      || type == symbolic_link	      /* --indicator-style=classify (aka -F)		 requires that we stat each regular file		 to see if it's executable.  */	      || (type == normal && (indicator_style == classify				     /* This is so that --color ends up					highlighting files with the executable					bit set even when options like -F are					not specified.  */				     || print_with_color)))))    {      /* `path' is the absolute pathname of this file. */      int err;      if (name[0] == '/' || dirname[0] == 0)	path = (char *) name;      else	{	  path = (char *) alloca (strlen (name) + strlen (dirname) + 2);	  attach (path, dirname, name);	}      switch (dereference)	{	case DEREF_ALWAYS:	  err = stat (path, &files[files_index].stat);	  break;	case DEREF_COMMAND_LINE_ARGUMENTS:	case DEREF_COMMAND_LINE_SYMLINK_TO_DIR:	  if (explicit_arg)	    {	      int need_lstat;	      err = stat (path, &files[files_index].stat);	      if (dereference == DEREF_COMMAND_LINE_ARGUMENTS)		break;	      need_lstat = (err < 0			    ? errno == ENOENT			    : ! S_ISDIR (files[files_index].stat.st_mode));	      if (!need_lstat)		break;	      /* stat failed because of ENOENT, maybe indicating a dangling		 symlink.  Or stat succeeded, PATH does not refer to a		 directory, and --dereference-command-line-symlink-to-dir is		 in effect.  Fall through so that we call lstat instead.  */	    }	default: /* DEREF_NEVER */	  err = lstat (path, &files[files_index].stat);	  break;	}      if (err < 0)	{	  error (0, errno, "%s", quotearg_colon (path));	  exit_status = 1;	  return 0;	}#if HAVE_ACL      if (format == long_format)	{	  int n = file_has_acl (path, &files[files_index].stat);	  files[files_index].have_acl = (0 < n);	  if (n < 0)	    error (0, errno, "%s", quotearg_colon (path));	}#endif      if (S_ISLNK (files[files_index].stat.st_mode)	  && (format == long_format || check_symlink_color))	{	  char *linkpath;	  struct stat linkstats;	  get_link_name (path, &files[files_index]);	  linkpath = make_link_path (path, files[files_index].linkname);	  /* Avoid following symbolic links when possible, ie, when	     they won't be traced and when no indicator is needed. */	  if (linkpath	      && (indicator_style != none || check_symlink_color)	      && stat (linkpath, &linkstats) == 0)	    {	      files[files_index].linkok = 1;	      /* Symbolic links to directories that are mentioned on the	         command line are automatically traced if not being	         listed as files.  */	      if (!explicit_arg || format == long_format		  || !S_ISDIR (linkstats.st_mode))		{		  /* Get the linked-to file's mode for the filetype indicator		     in long listings.  */		  files[files_index].linkmode = linkstats.st_mode;		  files[files_index].linkok = 1;		}	    }	  if (linkpath)	    free (linkpath);	}      if (S_ISLNK (files[files_index].stat.st_mode))	files[files_index].filetype = symbolic_link;      else if (S_ISDIR (files[files_index].stat.st_mode))	{	  if (explicit_arg && !immediate_dirs)	    files[files_index].filetype = arg_directory;	  else	    files[files_index].filetype = directory;	}      else	files[files_index].filetype = normal;      blocks = ST_NBLOCKS (files[files_index].stat);      {	char buf[LONGEST_HUMAN_READABLE + 1];	int len = strlen (human_readable (blocks, buf, human_output_opts,					  ST_NBLOCKSIZE, output_block_size));	if (block_size_size < len)	  block_size_size = len < 7 ? len : 7;      }    }  else    {      files[files_index].filetype = type;#if HAVE_STRUCT_DIRENT_D_TYPE      files[files_index].stat.st_mode = DTTOIF (type);#endif      blocks = 0;    }  files[files_index].name = xstrdup (name);  files_index++;  return blocks;}#ifdef S_ISLNK/* Put the name of the file that `filename' is a symbolic link to   into the `linkname' field of `f'. */static voidget_link_name (const char *filename, struct fileinfo *f){  f->linkname = xreadlink (filename);  if (f->linkname == NULL)    {      error (0, errno, _("cannot read symbolic link %s"),	     quotearg_colon (filename));      exit_status = 1;    }}/* If `linkname' is a relative path and `path' contains one or more   leading directories, return `linkname' with those directories   prepended; otherwise, return a copy of `linkname'.   If `linkname' is zero, return zero. */static char *make_link_path (const char *path, const char *linkname){  char *linkbuf;  size_t bufsiz;  if (linkname == 0)    return 0;  if (*linkname == '/')    return xstrdup (linkname);  /* The link is to a relative path.  Prepend any leading path     in `path' to the link name. */  linkbuf = strrchr (path, '/');  if (linkbuf == 0)    return xstrdup (linkname);  bufsiz = linkbuf - path + 1;  linkbuf = xmalloc (bufsiz + strlen (linkname) + 1);  strncpy (linkbuf, path, bufsiz);  strcpy (linkbuf + bufsiz, linkname);  return linkbuf;}#endif/* Return nonzero if base_name (NAME) ends in `.' or `..'   This is so we don't try to recurse on `././././. ...' */static intbasename_is_dot_or_dotdot (const char *n

⌨️ 快捷键说明

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