rem: struct stat file_stats; uid_t new_uid; gid_t new_gid; int errors = 0; int is_symlink; int is_directory;
add: char const *file_full_name = ent->fts_path; char const *file = ent->fts_accpath; struct stat const *file_stats; struct stat stat_buf; bool ok = true; bool do_chown; bool symlink_changed = true;
context: change_file_owner (int cmdline_arg, const char *file, uid_t uid, gid_t gid,		   uid_t old_uid, gid_t old_gid,		   struct Chown_option const *chopt){  struct stat file_stats;  uid_t new_uid;  gid_t new_gid;  int errors = 0;  int is_symlink;  int is_directory;  if (lstat (file, &file_stats))    {      if (chopt->force_silent == 0)	error (0, errno, _("failed to get attributes of %s"), quote (file));      return 1;    }  /* If it's a symlink and we're dereferencing, then use stat     to get the attributes of the referent.  */  if (S_ISLNK (file_stats.st_mode))    {      if (chopt->dereference == DEREF_ALWAYS	  && stat (file, &file_stats))	{	  if (chopt->force_silent == 0)	    error (0, errno, _("failed to get attributes of %s"), quote (file));	  return 1;	}      is_symlink = 1;      /* With -R, don't traverse through symlinks-to-directories.	 But of course, this will all change with POSIX's new	 -H, -L, -P options.  */      is_directory = 0;    }  else    {      is_symlink = 0;      is_directory = S_ISDIR (file_stats.st_mode);    }  if ((old_uid == (uid_t) -1 || file_stats.st_uid == old_uid)      && (old_gid == (gid_t) -1 || file_stats.st_gid == old_gid))    {      new_uid = (uid == (uid_t) -1 ? file_stats.st_uid : uid);      new_gid = (gid == (gid_t) -1 ? file_stats.st_gid : gid);      if (new_uid != file_stats.st_uid || new_gid != file_stats.st_gid)	{	  int fail;	  int symlink_changed = 1;	  int saved_errno;	  int called_lchown = 0;	  if (is_symlink)	    {	      if (chopt->dereference == DEREF_NEVER)		{		  called_lchown = 1;		  fail = lchown (file, new_uid, new_gid);		  /* Ignore the failure if it's due to lack of support (ENOSYS)		     and this is not a command line argument.  */		  if (!cmdline_arg && fail && errno == ENOSYS)		    {		      fail = 0;		      symlink_changed = 0;		    }		}	      else if (chopt->dereference == DEREF_ALWAYS)		{		  /* Applying chown to a symlink and expecting it to affect		     the referent is not portable.  So instead, open the		     file and use fchown on the resulting descriptor.  */		  int fd = open (file, O_RDONLY | O_NONBLOCK | O_NOCTTY);		  fail = (fd == -1 ? 1 : fchown (fd, new_uid, new_gid));		}	      else		{		  /* FIXME */		  abort ();		}	    }	  else	    {	      fail = chown (file, new_uid, new_gid);	    }	  saved_errno = errno;	  if (chopt->verbosity == V_high	      || (chopt->verbosity == V_changes_only && !fail))	    {	      enum Change_status ch_status = (! symlink_changed					      ? CH_NOT_APPLIED					      : (fail						 ? CH_FAILED : CH_SUCCEEDED));	      describe_change (file, ch_status,			       chopt->user_name, chopt->group_name);	    }	  if (fail)	    {	      if (chopt->force_silent == 0)		error (0, saved_errno, (uid != (uid_t) -1					? _("changing ownership of %s")					: _("changing group of %s")),		       quote (file));	      errors = 1;	    }	  else	    {	      /* The change succeeded.  On some systems, the chown function		 resets the `special' permission bits.  When run by a		 `privileged' user, this program must ensure that at least		 the set-uid and set-group ones are still set.  */	      if (file_stats.st_mode & ~(S_IFMT | S_IRWXUGO)		  /* If we called lchown above (which means this is a symlink),		     then skip it.  */		  && ! called_lchown)		{		  if (chmod (file, file_stats.st_mode))		    {		      error (0, saved_errno,			     _("unable to restore permissions of %s"),			     quote (file));		      fail = 1;		    }		}	    }	}      else if (chopt->verbosity == V_high)	{	  describe_change (file, CH_NO_CHANGE_REQUESTED,			   chopt->user_name, chopt->group_name);	}    }  if (chopt->recurse && is_directory)    errors |= change_dir_owner (file, uid, gid, old_uid, old_gid, chopt);  return errors;}