static struct vfs_s_inode * vfs_s_inode_from_path (struct vfs_class *me, const char *name, int flags) { struct vfs_s_super *super; struct vfs_s_inode *ino; char *q; if (!(q = vfs_s_get_path (me, name, &super, 0))) return NULL; ino = vfs_s_find_inode (me, super, q, flags & FL_FOLLOW ? LINK_FOLLOW : LINK_NO_FOLLOW, flags & ~FL_FOLLOW); if ((!ino) && (!*q)) /* We are asking about / directory of ftp server: assume it exists */ ino = vfs_s_find_inode (me, super, q, flags & FL_FOLLOW ? LINK_FOLLOW : LINK_NO_FOLLOW, FL_DIR | (flags & ~FL_FOLLOW)); g_free (q); return ino; }
static struct vfs_s_entry * vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root, const char *a_path, int follow, int flags) { struct vfs_s_entry *ent = NULL; char * const path = g_strdup (a_path); struct vfs_s_entry *retval = NULL; if (root->super->root != root) vfs_die ("We have to use _real_ root. Always. Sorry."); canonicalize_pathname (path); if (!(flags & FL_DIR)) { char *dirname, *name, *save; struct vfs_s_inode *ino; split_dir_name (me, path, &dirname, &name, &save); ino = vfs_s_find_inode (me, root->super, dirname, follow, flags | FL_DIR); if (save) *save = PATH_SEP; retval = vfs_s_find_entry_tree (me, ino, name, follow, flags); g_free (path); return retval; } for (ent = root->subdir; ent != NULL; ent = ent->next) if (!strcmp (ent->name, path)) break; if (ent && (!(MEDATA->dir_uptodate) (me, ent->ino))) { #if 1 print_vfs_message (_("Directory cache expired for %s"), path); #endif vfs_s_free_entry (me, ent); ent = NULL; } if (!ent) { struct vfs_s_inode *ino; ino = vfs_s_new_inode (me, root->super, vfs_s_default_stat (me, S_IFDIR | 0755)); ent = vfs_s_new_entry (me, path, ino); if ((MEDATA->dir_load) (me, ino, path) == -1) { vfs_s_free_entry (me, ent); g_free (path); return NULL; } vfs_s_insert_entry (me, root, ent); for (ent = root->subdir; ent != NULL; ent = ent->next) if (!strcmp (ent->name, path)) break; } if (!ent) vfs_die ("find_linear: success but directory is not there\n"); #if 0 if (!vfs_s_resolve_symlink (me, ent, follow)) { g_free (path); return NULL; } #endif g_free (path); return ent; }
/* * Return 1 for success, 0 if the checksum is bad, EOF on eof, * 2 for a record full of zeros (EOF marker). * */ static int read_header (vfs *me, vfs_s_super *archive, int tard) { register int i; register long sum, signed_sum, recsum; register char *p; register union record *header; char **longp; char *bp, *data; int size, written; static char *next_long_name = NULL, *next_long_link = NULL; char *current_file_name, *current_link_name; recurse: header = get_next_record (archive, tard); if (NULL == header) return EOF; recsum = from_oct (8, header->header.chksum); sum = 0; signed_sum = 0; p = header->charptr; for (i = sizeof (*header); --i >= 0;) { /* * We can't use unsigned char here because of old compilers, * e.g. V7. */ signed_sum += *p; sum += 0xFF & *p++; } /* Adjust checksum to count the "chksum" field as blanks. */ for (i = sizeof (header->header.chksum); --i >= 0;) { sum -= 0xFF & header->header.chksum[i]; signed_sum -= (char) header->header.chksum[i]; } sum += ' ' * sizeof header->header.chksum; signed_sum += ' ' * sizeof header->header.chksum; if (sum == 8 * ' ') { /* * This is a zeroed record...whole record is 0's except * for the 8 blanks we faked for the checksum field. */ return 2; } if (sum != recsum && signed_sum != recsum) return 0; /* * linkflag on BSDI tar (pax) always '\000' */ if(header->header.linkflag == '\000' && strlen(header->header.arch_name) && header->header.arch_name[strlen(header->header.arch_name) - 1] == '/') header->header.linkflag = LF_DIR; /* * Good record. Decode file size and return. */ if (header->header.linkflag == LF_LINK || header->header.linkflag == LF_DIR) hstat.st_size = 0; /* Links 0 size on tape */ else hstat.st_size = from_oct (1 + 12, header->header.size); header->header.arch_name[NAMSIZ - 1] = '\0'; if (header->header.linkflag == LF_LONGNAME || header->header.linkflag == LF_LONGLINK) { longp = ((header->header.linkflag == LF_LONGNAME) ? &next_long_name : &next_long_link); if (*longp) free (*longp); bp = *longp = (char *) xmalloc (hstat.st_size, "Tar: Long name"); for (size = hstat.st_size; size > 0; size -= written) { data = get_next_record (archive, tard)->charptr; if (data == NULL) { message_1s (1, MSG_ERROR, _("Unexpected EOF on archive file")); return 0; } written = RECORDSIZE; if (written > size) written = size; bcopy (data, bp, written); bp += written; } #if 0 if (hstat.st_size > 1) bp [hstat.st_size - 1] = 0; /* just to make sure */ #endif goto recurse; } else { struct stat st; struct vfs_s_entry *entry; struct vfs_s_inode *inode, *parent; long data_position; char *p, *q; int len; int isdir = 0; current_file_name = (next_long_name ? next_long_name : strdup (header->header.arch_name)); len = strlen (current_file_name); if (current_file_name[len - 1] == '/') { current_file_name[len - 1] = 0; isdir = 1; } current_link_name = (next_long_link ? next_long_link : strdup (header->header.arch_linkname)); len = strlen (current_link_name); if (len && current_link_name [len - 1] == '/') current_link_name[len - 1] = 0; next_long_link = next_long_name = NULL; data_position = current_tar_position; p = strrchr (current_file_name, '/'); if (p == NULL) { p = current_file_name; q = current_file_name + strlen (current_file_name); /* "" */ } else { *(p++) = 0; q = current_file_name; } parent = vfs_s_find_inode (me, archive->root, q, LINK_NO_FOLLOW, FL_MKDIR); if (parent == NULL) { message_1s (1, MSG_ERROR, _("Inconsistent tar archive")); return 0; } if (header->header.linkflag == LF_LINK) { parent = vfs_s_find_inode (me, archive->root, current_link_name, LINK_NO_FOLLOW, 0); if (parent == NULL) { message_1s (1, MSG_ERROR, _("Inconsistent tar archive")); } else { inode = parent; entry = vfs_s_new_entry(me, p, inode); vfs_s_insert_entry(me, parent, entry); free (current_link_name); goto done; } } fill_stat_from_header (me, &st, header); inode = vfs_s_new_inode (me, archive, &st); inode->u.tar.data_offset = data_position; if (*current_link_name) inode->linkname = current_link_name; entry = vfs_s_new_entry (me, p, inode); vfs_s_insert_entry (me, parent, entry); free (current_file_name); done: if (header->header.isextended) { while (get_next_record (archive, tard)->ext_hdr.isextended); inode->u.tar.data_offset = current_tar_position; } return 1; } }