X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/75f162e46fe7c14d3f65bfd5d895332373ec56d2..9863bdbc936f730dda710742dfa65aabc034a6c7:/flist.c diff --git a/flist.c b/flist.c index e9fc97b6..d694b451 100644 --- a/flist.c +++ b/flist.c @@ -89,6 +89,18 @@ int flist_cnt = 0; /* how many (non-tmp) file list objects exist */ int file_total = 0; /* total of all active items over all file-lists */ int flist_eof = 0; /* all the file-lists are now known */ +/* Starting from protocol version 26, we always use 64-bit ino_t and dev_t + * internally, even if this platform does not allow files to have 64-bit inums. + * The only exception is if we're on a platform with no 64-bit type at all. + * + * Because we use read_longint() to get these off the wire, if you transfer + * devices or (for protocols < 30) hardlinks with dev or inum > 2**32 to a + * machine with no 64-bit types then you will get an overflow error. + * + * Note that if you transfer devices from a 64-bit-devt machine (say, Solaris) + * to a 32-bit-devt machine (say, Linux-2.2/x86) then the device numbers will + * be truncated. But it's a kind of silly thing to do anyhow. */ + /* The tmp_* vars are used as a cache area by make_file() to store data * that the sender doesn't need to remember in its file list. The data * will survive just long enough to be used by send_file_entry(). */ @@ -296,7 +308,7 @@ static void flist_expand(struct file_list *flist, int extra) flist->malloced); if (verbose >= 2 && flist->malloced != FLIST_START) { - rprintf(FCLIENT, "[%s] expand file_list to %.0f bytes, did%s move\n", + rprintf(FCLIENT, "[%s] expand file_list pointer array to %.0f bytes, did%s move\n", who_am_i(), (double)sizeof flist->files[0] * flist->malloced, (new_ptr == flist->files) ? " not" : ""); @@ -450,7 +462,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx) #ifdef SUPPORT_HARD_LINKS if (tmp_dev != 0) { if (protocol_version >= 30) { - struct idev_node *np = idev_node(tmp_dev, tmp_ino); + struct ht_int64_node *np = idev_find(tmp_dev, tmp_ino); first_hlink_ndx = (int32)(long)np->data - 1; if (first_hlink_ndx < 0) { np->data = (void*)(long)(ndx + 1); @@ -504,7 +516,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx) write_buf(f, fname + l1, l2); if (first_hlink_ndx >= 0) { - write_varint30(f, first_hlink_ndx); + write_varint(f, first_hlink_ndx); goto the_end; } @@ -694,7 +706,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist, if (protocol_version >= 30 && BITS_SETnUNSET(xflags, XMIT_HLINKED, XMIT_HLINK_FIRST)) { struct file_struct *first; - first_hlink_ndx = read_varint30(f); + first_hlink_ndx = read_varint(f); if (first_hlink_ndx < 0 || first_hlink_ndx >= flist->used) { rprintf(FERROR, "hard-link reference out of range: %d (%d)\n", @@ -929,7 +941,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist, ? flist->used : first_hlink_ndx; } else { static int32 cnt = 0; - struct idev_node *np; + struct ht_int64_node *np; int64 ino; int32 ndx; if (protocol_version < 26) { @@ -940,7 +952,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist, dev = read_longint(f); ino = read_longint(f); } - np = idev_node(dev, ino); + np = idev_find(dev, ino); ndx = (int32)(long)np->data - 1; if (ndx < 0) { ndx = cnt++; @@ -980,34 +992,24 @@ static struct file_struct *recv_file_entry(struct file_list *flist, return file; } -/** - * Create a file_struct for a named file by reading its stat() - * information and performing extensive checks against global - * options. +/* Create a file_struct for a named file by reading its stat() information + * and performing extensive checks against global options. * - * @return the new file, or NULL if there was an error or this file - * should be excluded. - * - * @todo There is a small optimization opportunity here to avoid - * stat()ing the file in some circumstances, which has a certain cost. - * We are called immediately after doing readdir(), and so we may - * already know the d_type of the file. We could for example avoid - * statting directories if we're not recursing, but this is not a very - * important case. Some systems may not have d_type. - **/ + * Returns a pointer to the new file struct, or NULL if there was an error + * or this file should be excluded. */ struct file_struct *make_file(const char *fname, struct file_list *flist, STRUCT_STAT *stp, int flags, int filter_level) { static char *lastdir; static int lastdir_len = -1; struct file_struct *file; - STRUCT_STAT st; char thisname[MAXPATHLEN]; char linkname[MAXPATHLEN]; int alloc_len, basename_len, linkname_len; int extra_len = file_extra_cnt * EXTRA_LEN; const char *basename; alloc_pool_t *pool; + STRUCT_STAT st; char *bp; if (strlcpy(thisname, fname, sizeof thisname) >= sizeof thisname) { @@ -1962,13 +1964,13 @@ struct file_list *recv_file_list(int f) start_read = stats.total_read; - flist = flist_new(0, "recv_file_list"); - #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && protocol_version < 30) init_hard_links(); #endif + flist = flist_new(0, "recv_file_list"); + if (inc_recurse) { if (flist->ndx_start == 0) dir_flist = flist_new(FLIST_TEMP, "recv_file_list"); @@ -2174,12 +2176,10 @@ struct file_list *flist_new(int flags, char *msg) { struct file_list *flist; - flist = new(struct file_list); + flist = new0(struct file_list); if (!flist) out_of_memory(msg); - memset(flist, 0, sizeof flist[0]); - if (flags & FLIST_TEMP) { if (!(flist->file_pool = pool_create(SMALL_EXTENT, 0, out_of_memory, POOL_INTERN)))