📄 install.c
字号:
/* install - copy files and set attributes Copyright (C) 89, 90, 91, 1995-2002 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* Written by David MacKenzie <djm@gnu.ai.mit.edu> */#ifdef _AIX #pragma alloca#endif#include <config.h>#include <stdio.h>#include <getopt.h>#include <sys/types.h>#include <pwd.h>#include <grp.h>#include "system.h"#include "backupfile.h"#include "error.h"#include "cp-hash.h"#include "copy.h"#include "dirname.h"#include "makepath.h"#include "modechange.h"#include "path-concat.h"#include "quote.h"#include "xstrtol.h"/* The official name of this program (e.g., no `g' prefix). */#define PROGRAM_NAME "install"#define AUTHORS "David MacKenzie"#if HAVE_SYS_WAIT_H# include <sys/wait.h>#endifstruct passwd *getpwnam ();struct group *getgrnam ();#ifndef _POSIX_VERSIONuid_t getuid ();gid_t getgid ();#endif#if ! HAVE_ENDGRENT# define endgrent() ((void) 0)#endif#if ! HAVE_ENDPWENT# define endpwent() ((void) 0)#endif/* Initial number of entries in each hash table entry's table of inodes. */#define INITIAL_HASH_MODULE 100/* Initial number of entries in the inode hash table. */#define INITIAL_ENTRY_TAB_SIZE 70/* Number of bytes of a file to copy at a time. */#define READ_SIZE (32 * 1024)int isdir ();int stat ();static int change_timestamps (const char *from, const char *to);static int change_attributes (const char *path);static int copy_file (const char *from, const char *to, const struct cp_options *x);static int install_file_to_path (const char *from, const char *to, const struct cp_options *x);static int install_file_in_dir (const char *from, const char *to_dir, const struct cp_options *x);static int install_file_in_file (const char *from, const char *to, const struct cp_options *x);static void get_ids (void);static void strip (const char *path);void usage (int status);/* The name this program was run with, for error messages. */char *program_name;/* The user name that will own the files, or NULL to make the owner the current user ID. */static char *owner_name;/* The user ID corresponding to `owner_name'. */static uid_t owner_id;/* The group name that will own the files, or NULL to make the group the current group ID. */static char *group_name;/* The group ID corresponding to `group_name'. */static gid_t group_id;/* The permissions to which the files will be set. The umask has no effect. */static mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;/* If nonzero, strip executable files after copying them. */static int strip_files;/* If nonzero, install a directory instead of a regular file. */static int dir_arg;static struct option const long_options[] ={ {"backup", optional_argument, NULL, 'b'}, {"directory", no_argument, NULL, 'd'}, {"group", required_argument, NULL, 'g'}, {"mode", required_argument, NULL, 'm'}, {"owner", required_argument, NULL, 'o'}, {"preserve-timestamps", no_argument, NULL, 'p'}, {"strip", no_argument, NULL, 's'}, {"suffix", required_argument, NULL, 'S'}, {"version-control", required_argument, NULL, 'V'}, /* Deprecated. FIXME. */ {"verbose", no_argument, NULL, 'v'}, {GETOPT_HELP_OPTION_DECL}, {GETOPT_VERSION_OPTION_DECL}, {NULL, 0, NULL, 0}};static voidcp_option_init (struct cp_options *x){ x->copy_as_regular = 1; x->dereference = DEREF_ALWAYS; x->unlink_dest_before_opening = 1; x->unlink_dest_after_failed_open = 0; x->hard_link = 0; x->interactive = I_UNSPECIFIED; x->move_mode = 0; x->myeuid = geteuid (); x->one_file_system = 0; x->preserve_ownership = 0; x->preserve_links = 0; x->preserve_mode = 0; x->preserve_timestamps = 0; x->require_preserve = 0; x->recursive = 0; x->sparse_mode = SPARSE_AUTO; x->symbolic_link = 0; x->backup_type = none; /* Create destination files initially writable so we can run strip on them. Although GNU strip works fine on read-only files, some others would fail. */ x->set_mode = 1; x->mode = S_IRUSR | S_IWUSR; x->stdin_tty = 0; x->umask_kill = 0; x->update = 0; x->verbose = 0; x->xstat = stat; x->dest_info = NULL; x->src_info = NULL;}intmain (int argc, char **argv){ int optc; int errors = 0; const char *specified_mode = NULL; int make_backups = 0; char *backup_suffix_string; char *version_control_string = NULL; int mkdir_and_install = 0; struct cp_options x; int n_files; char **file; program_name = argv[0]; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); atexit (close_stdout); cp_option_init (&x); owner_name = NULL; group_name = NULL; strip_files = 0; dir_arg = 0; umask (0); /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless we'll actually use backup_suffix_string. */ backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); while ((optc = getopt_long (argc, argv, "bcsDdg:m:o:pvV:S:", long_options, NULL)) != -1) { switch (optc) { case 0: break; case 'V': /* FIXME: this is deprecated. Remove it in 2001. */ error (0, 0, _("warning: --version-control (-V) is obsolete; support for\ it\nwill be removed in some future release. Use --backup=%s instead." ), optarg); /* Fall through. */ case 'b': make_backups = 1; if (optarg) version_control_string = optarg; break; case 'c': break; case 's': strip_files = 1; break; case 'd': dir_arg = 1; break; case 'D': mkdir_and_install = 1; break; case 'v': x.verbose = 1; break; case 'g': group_name = optarg; break; case 'm': specified_mode = optarg; break; case 'o': owner_name = optarg; break; case 'p': x.preserve_timestamps = 1; break; case 'S': make_backups = 1; backup_suffix_string = optarg; break; case_GETOPT_HELP_CHAR; case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); default: usage (EXIT_FAILURE); } } /* Check for invalid combinations of arguments. */ if (dir_arg && strip_files) error (EXIT_FAILURE, 0, _("the strip option may not be used when installing a directory")); if (backup_suffix_string) simple_backup_suffix = xstrdup (backup_suffix_string); x.backup_type = (make_backups ? xget_version (_("backup type"), version_control_string) : none); n_files = argc - optind; file = argv + optind; if (n_files == 0 || (n_files == 1 && !dir_arg)) { error (0, 0, _("too few arguments")); usage (EXIT_FAILURE); } if (specified_mode) { struct mode_change *change = mode_compile (specified_mode, 0); if (change == MODE_INVALID) error (EXIT_FAILURE, 0, _("invalid mode %s"), quote (specified_mode)); else if (change == MODE_MEMORY_EXHAUSTED) xalloc_die (); mode = mode_adjust (0, change); } get_ids (); if (dir_arg) { int i; for (i = 0; i < n_files; i++) { errors |= make_path (file[i], mode, mode, owner_id, group_id, 0, (x.verbose ? _("creating directory %s") : NULL)); } } else { /* FIXME: it's a little gross that this initialization is required by copy.c::copy. */ hash_init (); if (n_files == 2) { if (mkdir_and_install) errors = install_file_to_path (file[0], file[1], &x); else if (!isdir (file[1])) errors = install_file_in_file (file[0], file[1], &x); else errors = install_file_in_dir (file[0], file[1], &x); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -