*** empty log message ***
authorAndrew Tridgell <tridge@samba.org>
Tue, 13 Jan 1998 15:57:26 +0000 (15:57 +0000)
committerAndrew Tridgell <tridge@samba.org>
Tue, 13 Jan 1998 15:57:26 +0000 (15:57 +0000)
Makefile.in
flist.c
main.c
rsync.h
uidlist.c [new file with mode: 0644]
version.h

index 6b93fea..585fee4 100644 (file)
@@ -21,7 +21,7 @@ SHELL=/bin/sh
 
 LIBOBJ=lib/getopt.o lib/fnmatch.o lib/zlib.o
 OBJS1=rsync.o exclude.o util.o md4.o main.o checksum.o match.o
-OBJS=$(OBJS1) flist.o io.o compat.o hlink.o token.o $(LIBOBJ)
+OBJS=$(OBJS1) flist.o io.o compat.o hlink.o token.o uidlist.o $(LIBOBJ)
 
 .c.o:
        $(CC) $(CFLAGS) -c $*.c -o $*.o
diff --git a/flist.c b/flist.c
index 40158fa..d438400 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -43,6 +43,7 @@ extern int preserve_gid;
 extern int preserve_times;
 extern int relative_paths;
 extern int copy_links;
+extern int remote_version;
 
 static char **local_exclude_list = NULL;
 
@@ -142,10 +143,14 @@ void send_file_entry_v11(struct file_struct *file,int f)
     write_int(f,(int)file->modtime);
   if (!(flags & SAME_MODE))
     write_int(f,(int)file->mode);
-  if (preserve_uid && !(flags & SAME_UID))
-    write_int(f,(int)file->uid);
-  if (preserve_gid && !(flags & SAME_GID))
-    write_int(f,(int)file->gid);
+  if (preserve_uid && !(flags & SAME_UID)) {
+         add_uid(file->uid);
+         write_int(f,(int)file->uid);
+  }
+  if (preserve_gid && !(flags & SAME_GID)) {
+         add_gid(file->gid);
+         write_int(f,(int)file->gid);
+  }
   if (preserve_devices && IS_DEVICE(file->mode) && !(flags & SAME_RDEV))
     write_int(f,(int)file->rdev);
 
@@ -502,6 +507,11 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
 
   clean_flist(flist);
 
+  /* now send the uid/gid list. This was introduced in protocol version 15 */
+  if (f != -1 && remote_version >= 15) {
+         send_uid_list(f);
+  }
+
   return flist;
 }
 
@@ -564,6 +574,11 @@ struct file_list *recv_file_list(int f)
     fprintf(FINFO,"done\n");
   }
 
+  /* now recv the uid/gid list. This was introduced in protocol version 15 */
+  if (f != -1 && remote_version >= 15) {
+         recv_uid_list(f, flist);
+  }
+
   return flist;
 
 oom:
diff --git a/main.c b/main.c
index 837d309..16f280d 100644 (file)
--- a/main.c
+++ b/main.c
@@ -52,6 +52,7 @@ int do_compression=0;
 int am_root=0;
 int orig_umask=0;
 int relative_paths=0;
+int numeric_ids = 0;
 
 extern int csum_length;
 
@@ -166,6 +167,9 @@ static void server_options(char **args,int *argc)
   if (delete_mode)
     args[ac++] = "--delete";
 
+  if (numeric_ids)
+    args[ac++] = "--numeric-ids";
+
   *argc = ac;
 }
 
@@ -434,6 +438,7 @@ static void usage(FILE *f)
   fprintf(f,"    --rsync-path PATH    specify path to rsync on the remote machine\n");
   fprintf(f,"-C, --cvs-exclude        auto ignore files in the same way CVS does\n");
   fprintf(f,"    --delete             delete files that don't exist on the sending side\n");
+  fprintf(f,"    --numeric-ids        don't map uid/gid values by user/group name\n");
   fprintf(f,"-I, --ignore-times       don't exclude files that match length and time\n");
   fprintf(f,"-z, --compress           compress file data\n");
   fprintf(f,"    --exclude FILE       exclude file FILE\n");
@@ -447,7 +452,7 @@ static void usage(FILE *f)
 }
 
 enum {OPT_VERSION,OPT_SUFFIX,OPT_SENDER,OPT_SERVER,OPT_EXCLUDE,
-      OPT_EXCLUDE_FROM,OPT_DELETE,OPT_RSYNC_PATH};
+      OPT_EXCLUDE_FROM,OPT_DELETE,OPT_NUMERIC_IDS,OPT_RSYNC_PATH};
 
 static char *short_options = "oblLWHpguDCtcahvrRIxnSe:B:z";
 
@@ -456,6 +461,7 @@ static struct option long_options[] = {
   {"server",      0,     0,    OPT_SERVER},
   {"sender",      0,     0,    OPT_SENDER},
   {"delete",      0,     0,    OPT_DELETE},
+  {"numeric-ids", 0,     0,    OPT_NUMERIC_IDS},
   {"exclude",     1,     0,    OPT_EXCLUDE},
   {"exclude-from",1,     0,    OPT_EXCLUDE_FROM},
   {"rsync-path",  1,     0,    OPT_RSYNC_PATH},
@@ -549,6 +555,10 @@ int main(int argc,char *argv[])
          delete_mode = 1;
          break;
 
+       case OPT_NUMERIC_IDS:
+         numeric_ids = 1;
+         break;
+
        case OPT_EXCLUDE:
          add_exclude(optarg);
          break;
diff --git a/rsync.h b/rsync.h
index 0b88103..836c67d 100644 (file)
--- a/rsync.h
+++ b/rsync.h
@@ -39,7 +39,7 @@
 #define SAME_TIME (1<<7)
 
 /* update this if you make incompatible changes */
-#define PROTOCOL_VERSION 14
+#define PROTOCOL_VERSION 15
 #define MIN_PROTOCOL_VERSION 10
 #define MAX_PROTOCOL_VERSION 20
 
 #include "lib/getopt.h"
 #endif
 
+/* these are needed for the uid/gid mapping code */
+#include <pwd.h>
+#include <grp.h>
+
 #ifndef S_IFLNK
 #define S_IFLNK  0120000
 #endif
diff --git a/uidlist.c b/uidlist.c
new file mode 100644 (file)
index 0000000..b7d84ce
--- /dev/null
+++ b/uidlist.c
@@ -0,0 +1,310 @@
+/* 
+   Copyright (C) Andrew Tridgell 1996
+   Copyright (C) Paul Mackerras 1996
+   
+   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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* handle the mapping of uid/gid and user/group names between systems.
+   If the source username/group does not exist on the target then use
+   the numeric ids. Never do any mapping for uid=0 or gid=0 as these
+   are special.
+*/
+
+#include "rsync.h"
+
+extern int preserve_uid;
+extern int preserve_gid;
+extern int numeric_ids;
+
+struct idlist {
+       struct idlist *next;
+       int id, id2;
+       char *name;
+};
+
+static struct idlist *uidlist;
+static struct idlist *gidlist;
+
+static struct idlist *add_list(int id, char *name)
+{
+       struct idlist *list = (struct idlist *)malloc(sizeof(list[0]));
+       if (!list) out_of_memory("add_list");
+       list->next = NULL;
+       list->name = strdup(name);
+       if (!list->name) out_of_memory("add_list");
+       list->id = (int)id;
+       return list;
+}
+
+
+
+/* turn a uid into a user name */
+static char *uid_to_name(uid_t uid)
+{
+       struct passwd *pass = getpwuid(uid);
+       if (pass) return(pass->pw_name);
+       return NULL;
+}
+
+/* turn a gid into a group name */
+static char *gid_to_name(gid_t gid)
+{
+       struct group *grp = getgrgid(gid);
+       if (grp) return(grp->gr_name);
+       return NULL;
+}
+
+
+/* turn a user name into a uid */
+static uid_t name_to_uid(char *name)
+{
+       struct passwd *pass;
+       if (!name || !*name) return 0;
+       pass = getpwnam(name);
+       if (pass) return(pass->pw_uid);
+       return 0;
+}
+
+/* turn a group name into a gid */
+static gid_t name_to_gid(char *name)
+{
+       struct group *grp;
+       if (!name || !*name) return 0;
+       grp = getgrnam(name);
+       if (grp) return(grp->gr_gid);
+       return 0;
+}
+
+static int map_uid(int id, char *name)
+{
+       uid_t uid = name_to_uid(name);
+       if (uid != 0) return uid;
+       return id;
+}
+
+static int map_gid(int id, char *name)
+{
+       gid_t gid = name_to_gid(name);
+       if (gid != 0) return gid;
+       return id;
+}
+
+/* this function is a definate candidate for a faster algorithm */
+static uid_t match_uid(uid_t uid)
+{
+       static uid_t last_in, last_out;
+       struct idlist *list = uidlist;
+
+       if (uid == last_in) return last_out;
+
+       last_in = uid;
+
+       while (list) {
+               if (list->id == (int)uid) {
+                       last_out = (uid_t)list->id2;
+                       return last_out;
+               }
+               list = list->next;
+       }
+       
+       last_out = uid;
+       return last_out;
+}
+
+static gid_t match_gid(gid_t gid)
+{
+       static gid_t last_in, last_out;
+       struct idlist *list = gidlist;
+
+       if (gid == last_in) return last_out;
+
+       last_in = gid;
+
+       while (list) {
+               if (list->id == (int)gid) {
+                       last_out = (gid_t)list->id2;
+                       return last_out;
+               }
+               list = list->next;
+       }
+       
+       last_out = gid;
+       return last_out;
+}
+
+/* add a uid to the list of uids */
+void add_uid(uid_t uid)
+{
+       struct idlist *list = uidlist;
+       char *name;
+
+       if (numeric_ids) return;
+
+       /* don't map root */
+       if (uid==0) return;
+
+       if (!list) {
+               if (!(name = uid_to_name(uid))) return;
+               uidlist = add_list((int)uid, name);
+               return;
+       }
+
+       while (list->next) {
+               if (list->id == (int)uid) return;
+               list = list->next;
+       }
+
+       if (list->id == (int)uid) return;
+
+       if (!(name = uid_to_name(uid))) return;
+
+       list->next = add_list((int)uid, name);
+}
+
+/* add a gid to the list of gids */
+void add_gid(gid_t gid)
+{
+       struct idlist *list = gidlist;
+       char *name;
+
+       if (numeric_ids) return;
+
+       /* don't map root */
+       if (gid==0) return;
+
+       if (!list) {
+               if (!(name = gid_to_name(gid))) return;
+               gidlist = add_list((int)gid, name);
+               return;
+       }
+
+       while (list->next) {
+               if (list->id == (int)gid) return;
+               list = list->next;
+       }
+
+       if (list->id == (int)gid) return;
+
+       if (!(name = gid_to_name(gid))) return;
+
+       list->next = add_list((int)gid, name);
+}
+
+
+/* send a complete uid/gid mapping to the peer */
+void send_uid_list(int f)
+{
+       struct idlist *list;
+
+       if (numeric_ids) return;
+
+       if (preserve_uid) {
+               /* we send sequences of uid/byte-length/name */
+               list = uidlist;
+               while (list) {
+                       int len = strlen(list->name);
+                       write_int(f, list->id);
+                       write_byte(f, len);
+                       write_buf(f, list->name, len);
+                       list = list->next;
+               }
+
+               /* terminate the uid list with a 0 uid. We explicitly exclude
+                  0 from the list */
+               write_int(f, 0);
+       }
+
+       if (preserve_gid) {
+               list = gidlist;
+               while (list) {
+                       int len = strlen(list->name);
+                       write_int(f, list->id);
+                       write_byte(f, len);
+                       write_buf(f, list->name, len);
+                       list = list->next;
+               }
+               write_int(f, 0);
+       }
+}
+
+/* recv a complete uid/gid mapping from the peer and map the uid/gid
+   in the file list to local names */
+void recv_uid_list(int f, struct file_list *flist)
+{
+       int id, i;
+       char *name;
+       struct idlist *list;
+
+       if (numeric_ids) return;
+
+       if (preserve_uid) {
+               /* read the uid list */
+               list = uidlist;
+               id = read_int(f);
+               while (id != 0) {
+                       int len = read_byte(f);
+                       name = (char *)malloc(len);
+                       if (!name) out_of_memory("recv_uid_list");
+                       read_buf(f, name, len);
+                       if (!list) {
+                               uidlist = add_list(id, name);
+                               list = uidlist;
+                       } else {
+                               list->next = add_list(id, name);
+                               list = list->next;
+                       }
+                       list->id2 = map_uid(id, name);
+                       free(name);
+                       id = read_int(f);
+               }
+       }
+
+
+       if (preserve_gid) {
+               /* and the gid list */
+               list = gidlist;
+               id = read_int(f);
+               while (id != 0) {
+                       int len = read_byte(f);
+                       name = (char *)malloc(len);
+                       if (!name) out_of_memory("recv_uid_list");
+                       read_buf(f, name, len);
+                       if (!list) {
+                               gidlist = add_list(id, name);
+                               list = gidlist;
+                       } else {
+                               list->next = add_list(id, name);
+                               list = list->next;
+                       }
+                       list->id2 = map_gid(id, name);
+                       free(name);
+                       id = read_int(f);
+               }
+       }
+
+       if (!uidlist && !gidlist) return;
+
+       /* now convert the uid/gid of all files in the list to the mapped
+          uid/gid */
+       for (i=0;i<flist->count;i++) {
+               if (preserve_uid && flist->files[i].uid != 0) {
+                       flist->files[i].uid = match_uid(flist->files[i].uid);
+               }
+               if (preserve_gid && flist->files[i].gid != 0) {
+                       flist->files[i].gid = match_gid(flist->files[i].gid);
+               }
+       }
+}
index 9f46e2d..24228d7 100644 (file)
--- a/version.h
+++ b/version.h
@@ -1 +1 @@
-#define VERSION "1.6.8"
+#define VERSION "1.6.9"