char * xgetcwd () { char *cwd; char *ret; unsigned path_max; errno = 0; path_max = (unsigned) PATH_MAX; path_max += 2; /* The getcwd docs say to do this. */ cwd = tar_xmalloc (path_max); errno = 0; while ((ret = getcwd (cwd, path_max)) == NULL && errno == ERANGE) { path_max += PATH_INCR; cwd = tar_realloc (cwd, path_max); errno = 0; } if (ret == NULL) { int save_errno = errno; free (cwd); errno = save_errno; return NULL; } return cwd; }
static void fill_in_sparse_array (void) { int ind; /* Allocate space for our scratch space; it's initially 10 elements long, but can change in this routine if necessary. */ sp_array_size = 10; sparsearray = (struct sp_array *) tar_xmalloc (sp_array_size * sizeof (struct sp_array)); /* There are at most five of these structures in the header itself; read these in first. */ for (ind = 0; ind < SPARSE_IN_HDR; ind++) { /* Compare to 0, or use !(int)..., for Pyramid's dumb compiler. */ if (head->header.sp[ind].numbytes == 0) break; sparsearray[ind].offset = from_oct (1 + 12, head->header.sp[ind].offset); sparsearray[ind].numbytes = from_oct (1 + 12, head->header.sp[ind].numbytes); } /* If the header's extended, we gotta read in exhdr's till we're done. */ if (head->header.isextended) { /* How far into the sparsearray we are `so far'. */ static int so_far_ind = SPARSE_IN_HDR; union record *exhdr; while (1) { exhdr = findrec (); for (ind = 0; ind < SPARSE_EXT_HDR; ind++) { if (ind + so_far_ind > sp_array_size - 1) { /* We just ran out of room in our scratch area - realloc it. */ sp_array_size *= 2; sparsearray = (struct sp_array *) tar_realloc (sparsearray, sp_array_size * sizeof (struct sp_array)); } /* Convert the character strings into longs. */ sparsearray[ind + so_far_ind].offset = from_oct (1 + 12, exhdr->ext_hdr.sp[ind].offset); sparsearray[ind + so_far_ind].numbytes = from_oct (1 + 12, exhdr->ext_hdr.sp[ind].numbytes); } /* If this is the last extended header for this file, we can stop. */ if (!exhdr->ext_hdr.isextended) break; else { so_far_ind += SPARSE_EXT_HDR; userec (exhdr); } } /* Be sure to skip past the last one. */ userec (exhdr); } }
static void __tar_add_dir_name (char *p, int device) { char *new_buf; char *p_buf; char *namebuf; int buflen; register int len; int sublen; #if 0 voidstar the_buffer; char *buf; char **vec,**p_vec; int n_strs,n_size; #endif struct name *n; new_buf = __tar_get_dir_contents (p, device); for (n = namelist; n; n = n->next) { if (!strcmp (n->name, p)) { n->dir_contents = new_buf ? new_buf : "\0\0\0\0"; break; } } if (new_buf) { len = strlen (p); buflen = NAMSIZ <= len ? len + NAMSIZ : NAMSIZ; namebuf = tar_xmalloc ((size_t) (buflen + 1)); strcpy (namebuf, p); if (namebuf[len - 1] != '/') { namebuf[len++] = '/'; namebuf[len] = '\0'; } for (p_buf = new_buf; p_buf && *p_buf; p_buf += sublen + 1) { sublen = strlen (p_buf); if (*p_buf == 'D') { if (len + sublen >= buflen) { buflen += NAMSIZ; namebuf = (char *) tar_realloc (namebuf, (size_t) (buflen + 1)); } strcpy (namebuf + len, p_buf + 1); __tar_addname (namebuf); __tar_add_dir_name (namebuf, device); } } free (namebuf); } }
static void diff_sparse_files (int filesize) { int sparse_ind = 0; char *buf; int buf_size = RECORDSIZE; union record *datarec; int err; long numbytes; #if 0 int amt_read = 0; #endif int size = filesize; /* FIXME: `datarec' might be used uninitialized in this function. Reported by Bruno Haible. */ buf = (char *) tar_xmalloc (buf_size * sizeof (char)); fill_in_sparse_array (); while (size > 0) { datarec = findrec (); if (!sparsearray[sparse_ind].numbytes) break; /* `numbytes' is nicer to write than `sparsearray[sparse_ind].numbytes' all the time... */ numbytes = sparsearray[sparse_ind].numbytes; lseek (diff_fd, sparsearray[sparse_ind].offset, 0); /* Take care to not run out of room in our buffer. */ while (buf_size < numbytes) { buf_size *= 2; buf = (char *) tar_realloc (buf, buf_size * sizeof (char)); } while (numbytes > RECORDSIZE) { if (err = read (diff_fd, buf, RECORDSIZE), err != RECORDSIZE) { if (err < 0) WARN ((0, errno, _("Cannot read %s"), current_file_name)); else fprintf (stdlis, _("%s: Could only read %d of %ld bytes\n"), current_file_name, err, numbytes); break; } if (memcmp (buf, datarec->charptr, RECORDSIZE)) { different++; break; } numbytes -= err; size -= err; userec (datarec); datarec = findrec (); } if (err = read (diff_fd, buf, (size_t) numbytes), err != numbytes) { if (err < 0) WARN ((0, errno, _("Cannot read %s"), current_file_name)); else fprintf (stdlis, _("%s: Could only read %d of %ld bytes\n"), current_file_name, err, numbytes); break; } if (memcmp (buf, datarec->charptr, (size_t) numbytes)) { different++; break; } #if 0 amt_read += numbytes; if (amt_read >= RECORDSIZE) { amt_read = 0; userec (datarec); datarec = findrec (); } #endif userec (datarec); sparse_ind++; size -= numbytes; } /* If the number of bytes read isn't the number of bytes supposedly in the file, they're different. */ #if 0 if (amt_read != filesize) different++; #endif userec (datarec); free (sparsearray); if (different) { fprintf (stdlis, _("%s: Data differs\n"), current_file_name); if (exit_status == TAREXIT_SUCCESS) exit_status = TAREXIT_DIFFERS; } }
char * __tar_get_dir_contents (char *p, int device) { DIR *dirp; register struct dirent *d; char *new_buf; char *namebuf; int bufsiz; int len; voidstar the_buffer; char *buf; size_t n_strs; #if 0 int n_size; #endif char *p_buf; char **vec, **p_vec; errno = 0; dirp = opendir (p); bufsiz = strlen (p) + NAMSIZ; namebuf = tar_xmalloc ((size_t) (bufsiz + 2)); if (!dirp) { ERROR ((0, errno, _("Cannot open directory %s"), p)); new_buf = NULL; } else { struct dirname *dp; int all_children; dp = __tar_get_dir (p); all_children = dp ? dp->allnew : 0; strcpy (namebuf, p); if (p[strlen (p) - 1] != '/') strcat (namebuf, "/"); len = strlen (namebuf); the_buffer = __tar_init_buffer (); while (d = readdir (dirp), d) { struct stat hs; /* Skip `.' and `..'. */ if (__tar_is_dot_or_dotdot (d->d_name)) continue; if ((int) NAMLEN (d) + len >= bufsiz) { bufsiz += NAMSIZ; namebuf = (char *) tar_realloc (namebuf, (size_t) (bufsiz + 2)); } strcpy (namebuf + len, d->d_name); #ifdef AIX if (flag_follow_links ? statx (namebuf, &hs, STATSIZE, STX_HIDDEN) : statx (namebuf, &hs, STATSIZE, STX_HIDDEN | STX_LINK)) #else if (flag_follow_links ? stat (namebuf, &hs) : lstat (namebuf, &hs)) #endif { ERROR ((0, errno, _("Cannot stat %s"), namebuf)); continue; } if ((flag_local_filesys && device != hs.st_dev) || (flag_exclude && __tar_check_exclude (namebuf))) __tar_add_buffer (the_buffer, "N", 1); #ifdef AIX else if (S_ISHIDDEN (hs.st_mode)) { __tar_add_buffer (the_buffer, "D", 1); strcat (d->d_name, "A"); d->d_namlen++; } #endif /* AIX */ else if (S_ISDIR (hs.st_mode)) { if (dp = __tar_get_dir (namebuf), dp) { if (dp->dev != hs.st_dev || dp->ino != hs.st_ino) { if (flag_verbose) WARN ((0, 0, _("Directory %s has been renamed"), namebuf)); dp->allnew = 1; dp->dev = hs.st_dev; dp->ino = hs.st_ino; } dp->dir_text = ""; } else { if (flag_verbose) WARN ((0, 0, _("Directory %s is new"), namebuf)); __tar_add_dir (namebuf, hs.st_dev, hs.st_ino, ""); dp = __tar_get_dir (namebuf); dp->allnew = 1; } if (all_children && dp) dp->allnew = 1; __tar_add_buffer (the_buffer, "D", 1); } else if (!all_children && flag_new_files && new_time > hs.st_mtime && (flag_new_files > 1 || new_time > hs.st_ctime)) __tar_add_buffer (the_buffer, "N", 1); else __tar_add_buffer (the_buffer, "Y", 1); __tar_add_buffer (the_buffer, d->d_name, (int) (NAMLEN (d) + 1)); } __tar_add_buffer (the_buffer, "\000\000", 2); closedir (dirp); /* Well, we've read in the contents of the dir, now sort them. */ buf = __tar_get_buffer (the_buffer); if (buf[0] == '\0') { __tar_flush_buffer (the_buffer); new_buf = NULL; } else { n_strs = 0; for (p_buf = buf; *p_buf;) { int tmp; tmp = strlen (p_buf) + 1; n_strs++; p_buf += tmp; } vec = (char **) tar_xmalloc (sizeof (char *) * (n_strs + 1)); for (p_vec = vec, p_buf = buf; *p_buf; p_buf += strlen (p_buf) + 1) *p_vec++ = p_buf; *p_vec = 0; qsort ((voidstar) vec, n_strs, sizeof (char *), __tar_dirent_cmp); new_buf = (char *) tar_xmalloc ((size_t) (p_buf - buf + 2)); for (p_vec = vec, p_buf = new_buf; *p_vec; p_vec++) { char *p_tmp; for (p_tmp = *p_vec; (*p_buf++ = *p_tmp++); ) ; } *p_buf++ = '\0'; free (vec); __tar_flush_buffer (the_buffer); } } free (namebuf); return new_buf; }