diff options
author | Jim Meyering <meyering@redhat.com> | 2011-04-10 11:22:59 +0200 |
---|---|---|
committer | Jim Meyering <meyering@redhat.com> | 2011-04-11 14:32:56 +0200 |
commit | 9288068ff8f3f749edc54c50f064eca9e6c83019 (patch) | |
tree | 6814c5637ffe8790f2eeae04c0ecd9ba5414cdf9 | |
parent | e6f4c3416721ae0b887fc0fee2f06967ba9a77b6 (diff) | |
download | coreutils-9288068ff8f3f749edc54c50f064eca9e6c83019.tar.xz |
maint: reorder install.c to eliminate declarations of static functions
* src/install.c: Remove static function declarations.
-rw-r--r-- | src/install.c | 671 |
1 files changed, 327 insertions, 344 deletions
diff --git a/src/install.c b/src/install.c index f4169968a..369547b36 100644 --- a/src/install.c +++ b/src/install.c @@ -68,23 +68,6 @@ static bool use_default_selinux_context = true; # define matchpathcon_init_prefix(a, p) /* empty */ #endif -static bool change_timestamps (struct stat const *from_sb, char const *to); -static bool change_attributes (char const *name); -static bool copy_file (const char *from, const char *to, - const struct cp_options *x); -static bool install_file_in_file_parents (char const *from, char *to, - struct cp_options *x); -static bool install_file_in_dir (const char *from, const char *to_dir, - const struct cp_options *x); -static bool install_file_in_file (const char *from, const char *to, - const struct cp_options *x); -static void get_ids (void); -static void strip (char const *name); -static void announce_mkdir (char const *dir, void *options); -static int make_ancestor (char const *dir, char const *component, - void *options); -void usage (int status); - /* The user name that will own the files, or NULL to make the owner the current user ID. */ static char *owner_name; @@ -407,6 +390,27 @@ target_directory_operand (char const *file) return is_a_dir; } +/* Report that directory DIR was made, if OPTIONS requests this. */ +static void +announce_mkdir (char const *dir, void *options) +{ + struct cp_options const *x = options; + if (x->verbose) + prog_fprintf (stdout, _("creating directory %s"), quote (dir)); +} + +/* Make ancestor directory DIR, whose last file name component is + COMPONENT, with options OPTIONS. Assume the working directory is + COMPONENT's parent. */ +static int +make_ancestor (char const *dir, char const *component, void *options) +{ + int r = mkdir (component, DEFAULT_MODE); + if (r == 0) + announce_mkdir (dir, options); + return r; +} + /* Process a command-line file name, for the -d option. */ static int process_dir (char *dir, struct savewd *wd, void *options) @@ -419,6 +423,312 @@ process_dir (char *dir, struct savewd *wd, void *options) : EXIT_FAILURE); } +/* Copy file FROM onto file TO, creating TO if necessary. + Return true if successful. */ + +static bool +copy_file (const char *from, const char *to, const struct cp_options *x) +{ + bool copy_into_self; + + if (copy_only_if_needed && !need_copy (from, to, x)) + return true; + + /* Allow installing from non-regular files like /dev/null. + Charles Karney reported that some Sun version of install allows that + and that sendmail's installation process relies on the behavior. + However, since !x->recursive, the call to "copy" will fail if FROM + is a directory. */ + + return copy (from, to, false, x, ©_into_self, NULL); +} + +/* Set the attributes of file or directory NAME. + Return true if successful. */ + +static bool +change_attributes (char const *name) +{ + bool ok = false; + /* chown must precede chmod because on some systems, + chown clears the set[ug]id bits for non-superusers, + resulting in incorrect permissions. + On System V, users can give away files with chown and then not + be able to chmod them. So don't give files away. + + We don't normally ignore errors from chown because the idea of + the install command is that the file is supposed to end up with + precisely the attributes that the user specified (or defaulted). + If the file doesn't end up with the group they asked for, they'll + want to know. */ + + if (! (owner_id == (uid_t) -1 && group_id == (gid_t) -1) + && lchown (name, owner_id, group_id) != 0) + error (0, errno, _("cannot change ownership of %s"), quote (name)); + else if (chmod (name, mode) != 0) + error (0, errno, _("cannot change permissions of %s"), quote (name)); + else + ok = true; + + if (use_default_selinux_context) + setdefaultfilecon (name); + + return ok; +} + +/* Set the timestamps of file DEST to match those of SRC_SB. + Return true if successful. */ + +static bool +change_timestamps (struct stat const *src_sb, char const *dest) +{ + struct timespec timespec[2]; + timespec[0] = get_stat_atime (src_sb); + timespec[1] = get_stat_mtime (src_sb); + + if (utimens (dest, timespec)) + { + error (0, errno, _("cannot set time stamps for %s"), quote (dest)); + return false; + } + return true; +} + +/* Strip the symbol table from the file NAME. + We could dig the magic number out of the file first to + determine whether to strip it, but the header files and + magic numbers vary so much from system to system that making + it portable would be very difficult. Not worth the effort. */ + +static void +strip (char const *name) +{ + int status; + pid_t pid = fork (); + + switch (pid) + { + case -1: + error (EXIT_FAILURE, errno, _("fork system call failed")); + break; + case 0: /* Child. */ + execlp (strip_program, strip_program, name, NULL); + error (EXIT_FAILURE, errno, _("cannot run %s"), strip_program); + break; + default: /* Parent. */ + if (waitpid (pid, &status, 0) < 0) + error (EXIT_FAILURE, errno, _("waiting for strip")); + else if (! WIFEXITED (status) || WEXITSTATUS (status)) + error (EXIT_FAILURE, 0, _("strip process terminated abnormally")); + break; + } +} + +/* Initialize the user and group ownership of the files to install. */ + +static void +get_ids (void) +{ + struct passwd *pw; + struct group *gr; + + if (owner_name) + { + pw = getpwnam (owner_name); + if (pw == NULL) + { + unsigned long int tmp; + if (xstrtoul (owner_name, NULL, 0, &tmp, NULL) != LONGINT_OK + || UID_T_MAX < tmp) + error (EXIT_FAILURE, 0, _("invalid user %s"), quote (owner_name)); + owner_id = tmp; + } + else + owner_id = pw->pw_uid; + endpwent (); + } + else + owner_id = (uid_t) -1; + + if (group_name) + { + gr = getgrnam (group_name); + if (gr == NULL) + { + unsigned long int tmp; + if (xstrtoul (group_name, NULL, 0, &tmp, NULL) != LONGINT_OK + || GID_T_MAX < tmp) + error (EXIT_FAILURE, 0, _("invalid group %s"), quote (group_name)); + group_id = tmp; + } + else + group_id = gr->gr_gid; + endgrent (); + } + else + group_id = (gid_t) -1; +} + +void +usage (int status) +{ + if (status != EXIT_SUCCESS) + fprintf (stderr, _("Try `%s --help' for more information.\n"), + program_name); + else + { + printf (_("\ +Usage: %s [OPTION]... [-T] SOURCE DEST\n\ + or: %s [OPTION]... SOURCE... DIRECTORY\n\ + or: %s [OPTION]... -t DIRECTORY SOURCE...\n\ + or: %s [OPTION]... -d DIRECTORY...\n\ +"), + program_name, program_name, program_name, program_name); + fputs (_("\ +\n\ +This install program copies files (often just compiled) into destination\n\ +locations you choose. If you want to download and install a ready-to-use\n\ +package on a GNU/Linux system, you should instead be using a package manager\n\ +like yum(1) or apt-get(1).\n\ +\n\ +In the first three forms, copy SOURCE to DEST or multiple SOURCE(s) to\n\ +the existing DIRECTORY, while setting permission modes and owner/group.\n\ +In the 4th form, create all components of the given DIRECTORY(ies).\n\ +\n\ +"), stdout); + fputs (_("\ +Mandatory arguments to long options are mandatory for short options too.\n\ +"), stdout); + fputs (_("\ + --backup[=CONTROL] make a backup of each existing destination file\n\ + -b like --backup but does not accept an argument\n\ + -c (ignored)\n\ + -C, --compare compare each pair of source and destination files, and\n\ + in some cases, do not modify the destination at all\n\ + -d, --directory treat all arguments as directory names; create all\n\ + components of the specified directories\n\ +"), stdout); + fputs (_("\ + -D create all leading components of DEST except the last,\n\ + then copy SOURCE to DEST\n\ + -g, --group=GROUP set group ownership, instead of process' current group\n\ + -m, --mode=MODE set permission mode (as in chmod), instead of rwxr-xr-x\n\ + -o, --owner=OWNER set ownership (super-user only)\n\ +"), stdout); + fputs (_("\ + -p, --preserve-timestamps apply access/modification times of SOURCE files\n\ + to corresponding destination files\n\ + -s, --strip strip symbol tables\n\ + --strip-program=PROGRAM program used to strip binaries\n\ + -S, --suffix=SUFFIX override the usual backup suffix\n\ + -t, --target-directory=DIRECTORY copy all SOURCE arguments into DIRECTORY\n\ + -T, --no-target-directory treat DEST as a normal file\n\ + -v, --verbose print the name of each directory as it is created\n\ +"), stdout); + fputs (_("\ + --preserve-context preserve SELinux security context\n\ + -Z, --context=CONTEXT set SELinux security context of files and directories\ +\n\ +"), stdout); + + fputs (HELP_OPTION_DESCRIPTION, stdout); + fputs (VERSION_OPTION_DESCRIPTION, stdout); + fputs (_("\ +\n\ +The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\ +The version control method may be selected via the --backup option or through\n\ +the VERSION_CONTROL environment variable. Here are the values:\n\ +\n\ +"), stdout); + fputs (_("\ + none, off never make backups (even if --backup is given)\n\ + numbered, t make numbered backups\n\ + existing, nil numbered if numbered backups exist, simple otherwise\n\ + simple, never always make simple backups\n\ +"), stdout); + emit_ancillary_info (); + } + exit (status); +} + +/* Copy file FROM onto file TO and give TO the appropriate + attributes. + Return true if successful. */ + +static bool +install_file_in_file (const char *from, const char *to, + const struct cp_options *x) +{ + struct stat from_sb; + if (x->preserve_timestamps && stat (from, &from_sb) != 0) + { + error (0, errno, _("cannot stat %s"), quote (from)); + return false; + } + if (! copy_file (from, to, x)) + return false; + if (strip_files) + strip (to); + if (x->preserve_timestamps && (strip_files || ! S_ISREG (from_sb.st_mode)) + && ! change_timestamps (&from_sb, to)) + return false; + return change_attributes (to); +} + +/* Copy file FROM onto file TO, creating any missing parent directories of TO. + Return true if successful. */ + +static bool +install_file_in_file_parents (char const *from, char *to, + struct cp_options *x) +{ + bool save_working_directory = + ! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to)); + int status = EXIT_SUCCESS; + + struct savewd wd; + savewd_init (&wd); + if (! save_working_directory) + savewd_finish (&wd); + + if (mkancesdirs (to, &wd, make_ancestor, x) == -1) + { + error (0, errno, _("cannot create directory %s"), to); + status = EXIT_FAILURE; + } + + if (save_working_directory) + { + int restore_result = savewd_restore (&wd, status); + int restore_errno = errno; + savewd_finish (&wd); + if (EXIT_SUCCESS < restore_result) + return false; + if (restore_result < 0 && status == EXIT_SUCCESS) + { + error (0, restore_errno, _("cannot create directory %s"), to); + return false; + } + } + + return (status == EXIT_SUCCESS && install_file_in_file (from, to, x)); +} + +/* Copy file FROM into directory TO_DIR, keeping its same name, + and give the copy the appropriate attributes. + Return true if successful. */ + +static bool +install_file_in_dir (const char *from, const char *to_dir, + const struct cp_options *x) +{ + const char *from_base = last_component (from); + char *to = file_name_concat (to_dir, from_base, NULL); + bool ret = install_file_in_file (from, to, x); + free (to); + return ret; +} + int main (int argc, char **argv) { @@ -681,330 +991,3 @@ main (int argc, char **argv) exit (exit_status); } - -/* Copy file FROM onto file TO, creating any missing parent directories of TO. - Return true if successful. */ - -static bool -install_file_in_file_parents (char const *from, char *to, - struct cp_options *x) -{ - bool save_working_directory = - ! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to)); - int status = EXIT_SUCCESS; - - struct savewd wd; - savewd_init (&wd); - if (! save_working_directory) - savewd_finish (&wd); - - if (mkancesdirs (to, &wd, make_ancestor, x) == -1) - { - error (0, errno, _("cannot create directory %s"), to); - status = EXIT_FAILURE; - } - - if (save_working_directory) - { - int restore_result = savewd_restore (&wd, status); - int restore_errno = errno; - savewd_finish (&wd); - if (EXIT_SUCCESS < restore_result) - return false; - if (restore_result < 0 && status == EXIT_SUCCESS) - { - error (0, restore_errno, _("cannot create directory %s"), to); - return false; - } - } - - return (status == EXIT_SUCCESS && install_file_in_file (from, to, x)); -} - -/* Copy file FROM onto file TO and give TO the appropriate - attributes. - Return true if successful. */ - -static bool -install_file_in_file (const char *from, const char *to, - const struct cp_options *x) -{ - struct stat from_sb; - if (x->preserve_timestamps && stat (from, &from_sb) != 0) - { - error (0, errno, _("cannot stat %s"), quote (from)); - return false; - } - if (! copy_file (from, to, x)) - return false; - if (strip_files) - strip (to); - if (x->preserve_timestamps && (strip_files || ! S_ISREG (from_sb.st_mode)) - && ! change_timestamps (&from_sb, to)) - return false; - return change_attributes (to); -} - -/* Copy file FROM into directory TO_DIR, keeping its same name, - and give the copy the appropriate attributes. - Return true if successful. */ - -static bool -install_file_in_dir (const char *from, const char *to_dir, - const struct cp_options *x) -{ - const char *from_base = last_component (from); - char *to = file_name_concat (to_dir, from_base, NULL); - bool ret = install_file_in_file (from, to, x); - free (to); - return ret; -} - -/* Copy file FROM onto file TO, creating TO if necessary. - Return true if successful. */ - -static bool -copy_file (const char *from, const char *to, const struct cp_options *x) -{ - bool copy_into_self; - - if (copy_only_if_needed && !need_copy (from, to, x)) - return true; - - /* Allow installing from non-regular files like /dev/null. - Charles Karney reported that some Sun version of install allows that - and that sendmail's installation process relies on the behavior. - However, since !x->recursive, the call to "copy" will fail if FROM - is a directory. */ - - return copy (from, to, false, x, ©_into_self, NULL); -} - -/* Set the attributes of file or directory NAME. - Return true if successful. */ - -static bool -change_attributes (char const *name) -{ - bool ok = false; - /* chown must precede chmod because on some systems, - chown clears the set[ug]id bits for non-superusers, - resulting in incorrect permissions. - On System V, users can give away files with chown and then not - be able to chmod them. So don't give files away. - - We don't normally ignore errors from chown because the idea of - the install command is that the file is supposed to end up with - precisely the attributes that the user specified (or defaulted). - If the file doesn't end up with the group they asked for, they'll - want to know. */ - - if (! (owner_id == (uid_t) -1 && group_id == (gid_t) -1) - && lchown (name, owner_id, group_id) != 0) - error (0, errno, _("cannot change ownership of %s"), quote (name)); - else if (chmod (name, mode) != 0) - error (0, errno, _("cannot change permissions of %s"), quote (name)); - else - ok = true; - - if (use_default_selinux_context) - setdefaultfilecon (name); - - return ok; -} - -/* Set the timestamps of file DEST to match those of SRC_SB. - Return true if successful. */ - -static bool -change_timestamps (struct stat const *src_sb, char const *dest) -{ - struct timespec timespec[2]; - timespec[0] = get_stat_atime (src_sb); - timespec[1] = get_stat_mtime (src_sb); - - if (utimens (dest, timespec)) - { - error (0, errno, _("cannot set time stamps for %s"), quote (dest)); - return false; - } - return true; -} - -/* Strip the symbol table from the file NAME. - We could dig the magic number out of the file first to - determine whether to strip it, but the header files and - magic numbers vary so much from system to system that making - it portable would be very difficult. Not worth the effort. */ - -static void -strip (char const *name) -{ - int status; - pid_t pid = fork (); - - switch (pid) - { - case -1: - error (EXIT_FAILURE, errno, _("fork system call failed")); - break; - case 0: /* Child. */ - execlp (strip_program, strip_program, name, NULL); - error (EXIT_FAILURE, errno, _("cannot run %s"), strip_program); - break; - default: /* Parent. */ - if (waitpid (pid, &status, 0) < 0) - error (EXIT_FAILURE, errno, _("waiting for strip")); - else if (! WIFEXITED (status) || WEXITSTATUS (status)) - error (EXIT_FAILURE, 0, _("strip process terminated abnormally")); - break; - } -} - -/* Initialize the user and group ownership of the files to install. */ - -static void -get_ids (void) -{ - struct passwd *pw; - struct group *gr; - - if (owner_name) - { - pw = getpwnam (owner_name); - if (pw == NULL) - { - unsigned long int tmp; - if (xstrtoul (owner_name, NULL, 0, &tmp, NULL) != LONGINT_OK - || UID_T_MAX < tmp) - error (EXIT_FAILURE, 0, _("invalid user %s"), quote (owner_name)); - owner_id = tmp; - } - else - owner_id = pw->pw_uid; - endpwent (); - } - else - owner_id = (uid_t) -1; - - if (group_name) - { - gr = getgrnam (group_name); - if (gr == NULL) - { - unsigned long int tmp; - if (xstrtoul (group_name, NULL, 0, &tmp, NULL) != LONGINT_OK - || GID_T_MAX < tmp) - error (EXIT_FAILURE, 0, _("invalid group %s"), quote (group_name)); - group_id = tmp; - } - else - group_id = gr->gr_gid; - endgrent (); - } - else - group_id = (gid_t) -1; -} - -/* Report that directory DIR was made, if OPTIONS requests this. */ -static void -announce_mkdir (char const *dir, void *options) -{ - struct cp_options const *x = options; - if (x->verbose) - prog_fprintf (stdout, _("creating directory %s"), quote (dir)); -} - -/* Make ancestor directory DIR, whose last file name component is - COMPONENT, with options OPTIONS. Assume the working directory is - COMPONENT's parent. */ -static int -make_ancestor (char const *dir, char const *component, void *options) -{ - int r = mkdir (component, DEFAULT_MODE); - if (r == 0) - announce_mkdir (dir, options); - return r; -} - -void -usage (int status) -{ - if (status != EXIT_SUCCESS) - fprintf (stderr, _("Try `%s --help' for more information.\n"), - program_name); - else - { - printf (_("\ -Usage: %s [OPTION]... [-T] SOURCE DEST\n\ - or: %s [OPTION]... SOURCE... DIRECTORY\n\ - or: %s [OPTION]... -t DIRECTORY SOURCE...\n\ - or: %s [OPTION]... -d DIRECTORY...\n\ -"), - program_name, program_name, program_name, program_name); - fputs (_("\ -\n\ -This install program copies files (often just compiled) into destination\n\ -locations you choose. If you want to download and install a ready-to-use\n\ -package on a GNU/Linux system, you should instead be using a package manager\n\ -like yum(1) or apt-get(1).\n\ -\n\ -In the first three forms, copy SOURCE to DEST or multiple SOURCE(s) to\n\ -the existing DIRECTORY, while setting permission modes and owner/group.\n\ -In the 4th form, create all components of the given DIRECTORY(ies).\n\ -\n\ -"), stdout); - fputs (_("\ -Mandatory arguments to long options are mandatory for short options too.\n\ -"), stdout); - fputs (_("\ - --backup[=CONTROL] make a backup of each existing destination file\n\ - -b like --backup but does not accept an argument\n\ - -c (ignored)\n\ - -C, --compare compare each pair of source and destination files, and\n\ - in some cases, do not modify the destination at all\n\ - -d, --directory treat all arguments as directory names; create all\n\ - components of the specified directories\n\ -"), stdout); - fputs (_("\ - -D create all leading components of DEST except the last,\n\ - then copy SOURCE to DEST\n\ - -g, --group=GROUP set group ownership, instead of process' current group\n\ - -m, --mode=MODE set permission mode (as in chmod), instead of rwxr-xr-x\n\ - -o, --owner=OWNER set ownership (super-user only)\n\ -"), stdout); - fputs (_("\ - -p, --preserve-timestamps apply access/modification times of SOURCE files\n\ - to corresponding destination files\n\ - -s, --strip strip symbol tables\n\ - --strip-program=PROGRAM program used to strip binaries\n\ - -S, --suffix=SUFFIX override the usual backup suffix\n\ - -t, --target-directory=DIRECTORY copy all SOURCE arguments into DIRECTORY\n\ - -T, --no-target-directory treat DEST as a normal file\n\ - -v, --verbose print the name of each directory as it is created\n\ -"), stdout); - fputs (_("\ - --preserve-context preserve SELinux security context\n\ - -Z, --context=CONTEXT set SELinux security context of files and directories\ -\n\ -"), stdout); - - fputs (HELP_OPTION_DESCRIPTION, stdout); - fputs (VERSION_OPTION_DESCRIPTION, stdout); - fputs (_("\ -\n\ -The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\ -The version control method may be selected via the --backup option or through\n\ -the VERSION_CONTROL environment variable. Here are the values:\n\ -\n\ -"), stdout); - fputs (_("\ - none, off never make backups (even if --backup is given)\n\ - numbered, t make numbered backups\n\ - existing, nil numbered if numbered backups exist, simple otherwise\n\ - simple, never always make simple backups\n\ -"), stdout); - emit_ancillary_info (); - } - exit (status); -} |