archive_entry_stat.c revision 228759
1243789Sdim/*- 2243789Sdim * Copyright (c) 2003-2007 Tim Kientzle 3243789Sdim * All rights reserved. 4243789Sdim * 5243789Sdim * Redistribution and use in source and binary forms, with or without 6243789Sdim * modification, are permitted provided that the following conditions 7243789Sdim * are met: 8243789Sdim * 1. Redistributions of source code must retain the above copyright 9243789Sdim * notice, this list of conditions and the following disclaimer. 10243789Sdim * 2. Redistributions in binary form must reproduce the above copyright 11243789Sdim * notice, this list of conditions and the following disclaimer in the 12243789Sdim * documentation and/or other materials provided with the distribution. 13243789Sdim * 14243789Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15243789Sdim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16243789Sdim * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17243789Sdim * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18243789Sdim * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19243789Sdim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20243789Sdim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21243789Sdim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22243789Sdim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23243789Sdim * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24243789Sdim */ 25249423Sdim 26243789Sdim#include "archive_platform.h" 27243789Sdim__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_stat.c 201100 2009-12-28 03:05:31Z kientzle $"); 28243789Sdim 29243789Sdim#ifdef HAVE_SYS_STAT_H 30243789Sdim#include <sys/stat.h> 31243789Sdim#endif 32243789Sdim#ifdef HAVE_STDLIB_H 33249423Sdim#include <stdlib.h> 34249423Sdim#endif 35243789Sdim 36249423Sdim#include "archive_entry.h" 37243789Sdim#include "archive_entry_private.h" 38243789Sdim 39249423Sdimconst struct stat * 40243789Sdimarchive_entry_stat(struct archive_entry *entry) 41243789Sdim{ 42249423Sdim struct stat *st; 43243789Sdim if (entry->stat == NULL) { 44243789Sdim entry->stat = malloc(sizeof(*st)); 45263508Sdim if (entry->stat == NULL) 46243789Sdim return (NULL); 47243789Sdim entry->stat_valid = 0; 48249423Sdim } 49249423Sdim 50249423Sdim /* 51243789Sdim * If none of the underlying fields have been changed, we 52243789Sdim * don't need to regenerate. In theory, we could use a bitmap 53243789Sdim * here to flag only those items that have changed, but the 54243789Sdim * extra complexity probably isn't worth it. It will be very 55249423Sdim * rare for anyone to change just one field then request a new 56249423Sdim * stat structure. 57243789Sdim */ 58243789Sdim if (entry->stat_valid) 59243789Sdim return (entry->stat); 60243789Sdim 61243789Sdim st = entry->stat; 62243789Sdim /* 63243789Sdim * Use the public interfaces to extract items, so that 64243789Sdim * the appropriate conversions get invoked. 65243789Sdim */ 66243789Sdim st->st_atime = archive_entry_atime(entry); 67243789Sdim#if HAVE_STRUCT_STAT_ST_BIRTHTIME 68243789Sdim st->st_birthtime = archive_entry_birthtime(entry); 69243789Sdim#endif 70243789Sdim st->st_ctime = archive_entry_ctime(entry); 71249423Sdim st->st_mtime = archive_entry_mtime(entry); 72249423Sdim st->st_dev = archive_entry_dev(entry); 73249423Sdim st->st_gid = archive_entry_gid(entry); 74243789Sdim st->st_uid = archive_entry_uid(entry); 75243789Sdim st->st_ino = archive_entry_ino64(entry); 76243789Sdim st->st_nlink = archive_entry_nlink(entry); 77243789Sdim st->st_rdev = archive_entry_rdev(entry); 78249423Sdim st->st_size = archive_entry_size(entry); 79243789Sdim st->st_mode = archive_entry_mode(entry); 80243789Sdim 81243789Sdim /* 82243789Sdim * On systems that support high-res timestamps, copy that 83243789Sdim * information into struct stat. 84243789Sdim */ 85243789Sdim#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 86243789Sdim st->st_atimespec.tv_nsec = archive_entry_atime_nsec(entry); 87243789Sdim st->st_ctimespec.tv_nsec = archive_entry_ctime_nsec(entry); 88243789Sdim st->st_mtimespec.tv_nsec = archive_entry_mtime_nsec(entry); 89243789Sdim#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 90243789Sdim st->st_atim.tv_nsec = archive_entry_atime_nsec(entry); 91243789Sdim st->st_ctim.tv_nsec = archive_entry_ctime_nsec(entry); 92243789Sdim st->st_mtim.tv_nsec = archive_entry_mtime_nsec(entry); 93243789Sdim#elif HAVE_STRUCT_STAT_ST_MTIME_N 94243789Sdim st->st_atime_n = archive_entry_atime_nsec(entry); 95243789Sdim st->st_ctime_n = archive_entry_ctime_nsec(entry); 96243789Sdim st->st_mtime_n = archive_entry_mtime_nsec(entry); 97243789Sdim#elif HAVE_STRUCT_STAT_ST_UMTIME 98243789Sdim st->st_uatime = archive_entry_atime_nsec(entry) / 1000; 99243789Sdim st->st_uctime = archive_entry_ctime_nsec(entry) / 1000; 100243789Sdim st->st_umtime = archive_entry_mtime_nsec(entry) / 1000; 101243789Sdim#elif HAVE_STRUCT_STAT_ST_MTIME_USEC 102243789Sdim st->st_atime_usec = archive_entry_atime_nsec(entry) / 1000; 103243789Sdim st->st_ctime_usec = archive_entry_ctime_nsec(entry) / 1000; 104243789Sdim st->st_mtime_usec = archive_entry_mtime_nsec(entry) / 1000; 105243789Sdim#endif 106249423Sdim#if HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 107249423Sdim st->st_birthtimespec.tv_nsec = archive_entry_birthtime_nsec(entry); 108243789Sdim#endif 109243789Sdim 110249423Sdim /* 111243789Sdim * TODO: On Linux, store 32 or 64 here depending on whether 112249423Sdim * the cached stat structure is a stat32 or a stat64. This 113243789Sdim * will allow us to support both variants interchangably. 114243789Sdim */ 115243789Sdim entry->stat_valid = 1; 116243789Sdim 117243789Sdim return (st); 118243789Sdim} 119243789Sdim