home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / rsync221.zip / uidlist.c < prev    next >
C/C++ Source or Header  |  1999-03-04  |  6KB  |  292 lines

  1. /* 
  2.    Copyright (C) Andrew Tridgell 1996
  3.    Copyright (C) Paul Mackerras 1996
  4.    
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2 of the License, or
  8.    (at your option) any later version.
  9.    
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.    
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19.  
  20. /* handle the mapping of uid/gid and user/group names between systems.
  21.    If the source username/group does not exist on the target then use
  22.    the numeric ids. Never do any mapping for uid=0 or gid=0 as these
  23.    are special.
  24. */
  25.  
  26. #include "rsync.h"
  27.  
  28. extern int preserve_uid;
  29. extern int preserve_gid;
  30. extern int numeric_ids;
  31.  
  32. struct idlist {
  33.     struct idlist *next;
  34.     int id, id2;
  35.     char *name;
  36. };
  37.  
  38. static struct idlist *uidlist;
  39. static struct idlist *gidlist;
  40.  
  41. static struct idlist *add_list(int id, char *name)
  42. {
  43.     struct idlist *list = (struct idlist *)malloc(sizeof(list[0]));
  44.     if (!list) out_of_memory("add_list");
  45.     list->next = NULL;
  46.     list->name = strdup(name);
  47.     if (!list->name) out_of_memory("add_list");
  48.     list->id = (int)id;
  49.     return list;
  50. }
  51.  
  52.  
  53.  
  54. /* turn a uid into a user name */
  55. static char *uid_to_name(uid_t uid)
  56. {
  57.     struct passwd *pass = getpwuid(uid);
  58.     if (pass) return(pass->pw_name);
  59.     return NULL;
  60. }
  61.  
  62. /* turn a gid into a group name */
  63. static char *gid_to_name(gid_t gid)
  64. {
  65.     struct group *grp = getgrgid(gid);
  66.     if (grp) return(grp->gr_name);
  67.     return NULL;
  68. }
  69.  
  70. static int map_uid(int id, char *name)
  71. {
  72.     uid_t uid;
  73.     if (name_to_uid(name, &uid) && uid != 0)
  74.         return uid;
  75.     return id;
  76. }
  77.  
  78. static int map_gid(int id, char *name)
  79. {
  80.     gid_t gid;
  81.     if (name_to_gid(name, &gid) && gid != 0)
  82.         return gid;
  83.     return id;
  84. }
  85.  
  86. /* this function is a definate candidate for a faster algorithm */
  87. static uid_t match_uid(uid_t uid)
  88. {
  89.     static uid_t last_in, last_out;
  90.     struct idlist *list = uidlist;
  91.  
  92.     if (uid == last_in) return last_out;
  93.  
  94.     last_in = uid;
  95.  
  96.     while (list) {
  97.         if (list->id == (int)uid) {
  98.             last_out = (uid_t)list->id2;
  99.             return last_out;
  100.         }
  101.         list = list->next;
  102.     }
  103.     
  104.     last_out = uid;
  105.     return last_out;
  106. }
  107.  
  108. static gid_t match_gid(gid_t gid)
  109. {
  110.     static gid_t last_in, last_out;
  111.     struct idlist *list = gidlist;
  112.  
  113.     if (gid == last_in) return last_out;
  114.  
  115.     last_in = gid;
  116.  
  117.     while (list) {
  118.         if (list->id == (int)gid) {
  119.             last_out = (gid_t)list->id2;
  120.             return last_out;
  121.         }
  122.         list = list->next;
  123.     }
  124.     
  125.     last_out = gid;
  126.     return last_out;
  127. }
  128.  
  129. /* add a uid to the list of uids */
  130. void add_uid(uid_t uid)
  131. {
  132.     struct idlist *list = uidlist;
  133.     char *name;
  134.  
  135.     if (numeric_ids) return;
  136.  
  137.     /* don't map root */
  138.     if (uid==0) return;
  139.  
  140.     if (!list) {
  141.         if (!(name = uid_to_name(uid))) return;
  142.         uidlist = add_list((int)uid, name);
  143.         return;
  144.     }
  145.  
  146.     while (list->next) {
  147.         if (list->id == (int)uid) return;
  148.         list = list->next;
  149.     }
  150.  
  151.     if (list->id == (int)uid) return;
  152.  
  153.     if (!(name = uid_to_name(uid))) return;
  154.  
  155.     list->next = add_list((int)uid, name);
  156. }
  157.  
  158. /* add a gid to the list of gids */
  159. void add_gid(gid_t gid)
  160. {
  161.     struct idlist *list = gidlist;
  162.     char *name;
  163.  
  164.     if (numeric_ids) return;
  165.  
  166.     /* don't map root */
  167.     if (gid==0) return;
  168.  
  169.     if (!list) {
  170.         if (!(name = gid_to_name(gid))) return;
  171.         gidlist = add_list((int)gid, name);
  172.         return;
  173.     }
  174.  
  175.     while (list->next) {
  176.         if (list->id == (int)gid) return;
  177.         list = list->next;
  178.     }
  179.  
  180.     if (list->id == (int)gid) return;
  181.  
  182.     if (!(name = gid_to_name(gid))) return;
  183.  
  184.     list->next = add_list((int)gid, name);
  185. }
  186.  
  187.  
  188. /* send a complete uid/gid mapping to the peer */
  189. void send_uid_list(int f)
  190. {
  191.     struct idlist *list;
  192.  
  193.     if (numeric_ids) return;
  194.  
  195.     if (preserve_uid) {
  196.         /* we send sequences of uid/byte-length/name */
  197.         list = uidlist;
  198.         while (list) {
  199.             int len = strlen(list->name);
  200.             write_int(f, list->id);
  201.             write_byte(f, len);
  202.             write_buf(f, list->name, len);
  203.             list = list->next;
  204.         }
  205.  
  206.         /* terminate the uid list with a 0 uid. We explicitly exclude
  207.            0 from the list */
  208.         write_int(f, 0);
  209.     }
  210.  
  211.     if (preserve_gid) {
  212.         list = gidlist;
  213.         while (list) {
  214.             int len = strlen(list->name);
  215.             write_int(f, list->id);
  216.             write_byte(f, len);
  217.             write_buf(f, list->name, len);
  218.             list = list->next;
  219.         }
  220.         write_int(f, 0);
  221.     }
  222. }
  223.  
  224. /* recv a complete uid/gid mapping from the peer and map the uid/gid
  225.    in the file list to local names */
  226. void recv_uid_list(int f, struct file_list *flist)
  227. {
  228.     int id, i;
  229.     char *name;
  230.     struct idlist *list;
  231.  
  232.     if (numeric_ids) return;
  233.  
  234.     if (preserve_uid) {
  235.         /* read the uid list */
  236.         list = uidlist;
  237.         id = read_int(f);
  238.         while (id != 0) {
  239.             int len = read_byte(f);
  240.             name = (char *)malloc(len+1);
  241.             if (!name) out_of_memory("recv_uid_list");
  242.             read_sbuf(f, name, len);
  243.             if (!list) {
  244.                 uidlist = add_list(id, name);
  245.                 list = uidlist;
  246.             } else {
  247.                 list->next = add_list(id, name);
  248.                 list = list->next;
  249.             }
  250.             list->id2 = map_uid(id, name);
  251.             free(name);
  252.             id = read_int(f);
  253.         }
  254.     }
  255.  
  256.  
  257.     if (preserve_gid) {
  258.         /* and the gid list */
  259.         list = gidlist;
  260.         id = read_int(f);
  261.         while (id != 0) {
  262.             int len = read_byte(f);
  263.             name = (char *)malloc(len+1);
  264.             if (!name) out_of_memory("recv_uid_list");
  265.             read_sbuf(f, name, len);
  266.             if (!list) {
  267.                 gidlist = add_list(id, name);
  268.                 list = gidlist;
  269.             } else {
  270.                 list->next = add_list(id, name);
  271.                 list = list->next;
  272.             }
  273.             list->id2 = map_gid(id, name);
  274.             free(name);
  275.             id = read_int(f);
  276.         }
  277.     }
  278.  
  279.     if (!uidlist && !gidlist) return;
  280.  
  281.     /* now convert the uid/gid of all files in the list to the mapped
  282.        uid/gid */
  283.     for (i=0;i<flist->count;i++) {
  284.         if (preserve_uid && flist->files[i]->uid != 0) {
  285.             flist->files[i]->uid = match_uid(flist->files[i]->uid);
  286.         }
  287.         if (preserve_gid && flist->files[i]->gid != 0) {
  288.             flist->files[i]->gid = match_gid(flist->files[i]->gid);
  289.         }
  290.     }
  291. }
  292.