123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- /* Owner/group mapping for tar
- Copyright 2015-2019 Free Software Foundation, Inc.
- This file is part of GNU tar.
- GNU tar 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 3 of the License, or
- (at your option) any later version.
- GNU tar 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, see <http://www.gnu.org/licenses/>. */
- #include <system.h>
- #include "common.h"
- #include "wordsplit.h"
- #include <hash.h>
- #include <pwd.h>
- struct mapentry
- {
- uintmax_t orig_id;
- uintmax_t new_id;
- char *new_name;
- };
- static size_t
- map_hash (void const *entry, size_t nbuckets)
- {
- struct mapentry const *map = entry;
- return map->orig_id % nbuckets;
- }
- static bool
- map_compare (void const *entry1, void const *entry2)
- {
- struct mapentry const *map1 = entry1;
- struct mapentry const *map2 = entry2;
- return map1->orig_id == map2->orig_id;
- }
- static int
- parse_id (uintmax_t *retval,
- char const *arg, char const *what, uintmax_t maxval,
- char const *file, unsigned line)
- {
- uintmax_t v;
- char *p;
-
- errno = 0;
- v = strtoumax (arg, &p, 10);
- if (*p || errno)
- {
- error (0, 0, _("%s:%u: invalid %s: %s"), file, line, what, arg);
- return -1;
- }
- if (v > maxval)
- {
- error (0, 0, _("%s:%u: %s out of range: %s"), file, line, what, arg);
- return -1;
- }
- *retval = v;
- return 0;
- }
- static void
- map_read (Hash_table **ptab, char const *file,
- uintmax_t (*name_to_id) (char const *), char const *what,
- uintmax_t maxval)
- {
- FILE *fp;
- char *buf = NULL;
- size_t bufsize = 0;
- ssize_t n;
- struct wordsplit ws;
- int wsopt;
- unsigned line;
- int err = 0;
-
- fp = fopen (file, "r");
- if (!fp)
- open_fatal (file);
- ws.ws_comment = "#";
- wsopt = WRDSF_COMMENT | WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_SQUEEZE_DELIMS
- | WRDSF_QUOTE;
- line = 0;
- while ((n = getline (&buf, &bufsize, fp)) > 0)
- {
- struct mapentry *ent;
- uintmax_t orig_id, new_id;
- char *name = NULL;
- char *colon;
-
- ++line;
- if (wordsplit (buf, &ws, wsopt))
- FATAL_ERROR ((0, 0, _("%s:%u: cannot split line: %s"),
- file, line, wordsplit_strerror (&ws)));
- wsopt |= WRDSF_REUSE;
- if (ws.ws_wordc == 0)
- continue;
- if (ws.ws_wordc != 2)
- {
- error (0, 0, _("%s:%u: malformed line"), file, line);
- err = 1;
- continue;
- }
- if (ws.ws_wordv[0][0] == '+')
- {
- if (parse_id (&orig_id, ws.ws_wordv[0]+1, what, maxval, file, line))
- {
- err = 1;
- continue;
- }
- }
- else if (name_to_id)
- {
- orig_id = name_to_id (ws.ws_wordv[0]);
- if (orig_id == UINTMAX_MAX)
- {
- error (0, 0, _("%s:%u: can't obtain %s of %s"),
- file, line, what, ws.ws_wordv[0]);
- err = 1;
- continue;
- }
- }
- colon = strchr (ws.ws_wordv[1], ':');
- if (colon)
- {
- if (colon > ws.ws_wordv[1])
- name = ws.ws_wordv[1];
- *colon++ = 0;
- if (parse_id (&new_id, colon, what, maxval, file, line))
- {
- err = 1;
- continue;
- }
- }
- else if (ws.ws_wordv[1][0] == '+')
- {
- if (parse_id (&new_id, ws.ws_wordv[1], what, maxval, file, line))
- {
- err = 1;
- continue;
- }
- }
- else
- {
- name = ws.ws_wordv[1];
- new_id = name_to_id (ws.ws_wordv[1]);
- if (new_id == UINTMAX_MAX)
- {
- error (0, 0, _("%s:%u: can't obtain %s of %s"),
- file, line, what, ws.ws_wordv[1]);
- err = 1;
- continue;
- }
- }
- ent = xmalloc (sizeof (*ent));
- ent->orig_id = orig_id;
- ent->new_id = new_id;
- ent->new_name = name ? xstrdup (name) : NULL;
-
- if (!((*ptab
- || (*ptab = hash_initialize (0, 0, map_hash, map_compare, 0)))
- && hash_insert (*ptab, ent)))
- xalloc_die ();
- }
- if (wsopt & WRDSF_REUSE)
- wordsplit_free (&ws);
- fclose (fp);
- if (err)
- FATAL_ERROR ((0, 0, _("errors reading map file")));
- }
- /* UID translation */
- static Hash_table *owner_map;
- static uintmax_t
- name_to_uid (char const *name)
- {
- struct passwd *pw = getpwnam (name);
- return pw ? pw->pw_uid : UINTMAX_MAX;
- }
- void
- owner_map_read (char const *file)
- {
- map_read (&owner_map, file, name_to_uid, "UID", TYPE_MAXIMUM (uid_t));
- }
- int
- owner_map_translate (uid_t uid, uid_t *new_uid, char const **new_name)
- {
- int rc = 1;
-
- if (owner_map)
- {
- struct mapentry ent, *res;
-
- ent.orig_id = uid;
- res = hash_lookup (owner_map, &ent);
- if (res)
- {
- *new_uid = res->new_id;
- *new_name = res->new_name;
- return 0;
- }
- }
- if (owner_option != (uid_t) -1)
- {
- *new_uid = owner_option;
- rc = 0;
- }
- if (owner_name_option)
- {
- *new_name = owner_name_option;
- rc = 0;
- }
- return rc;
- }
- /* GID translation */
- static Hash_table *group_map;
- static uintmax_t
- name_to_gid (char const *name)
- {
- struct group *gr = getgrnam (name);
- return gr ? gr->gr_gid : UINTMAX_MAX;
- }
- void
- group_map_read (char const *file)
- {
- map_read (&group_map, file, name_to_gid, "GID", TYPE_MAXIMUM (gid_t));
- }
- int
- group_map_translate (gid_t gid, gid_t *new_gid, char const **new_name)
- {
- int rc = 1;
-
- if (group_map)
- {
- struct mapentry ent, *res;
-
- ent.orig_id = gid;
- res = hash_lookup (group_map, &ent);
- if (res)
- {
- *new_gid = res->new_id;
- *new_name = res->new_name;
- return 0;
- }
- }
- if (group_option != (uid_t) -1)
- {
- *new_gid = group_option;
- rc = 0;
- }
- if (group_name_option)
- {
- *new_name = group_name_option;
- rc = 0;
- }
-
- return rc;
- }
|