#define _FILE_OFFSET_BITS 64
#include "config.h"
#ifndef HAVE_ASPRINTF
#include "asprintf.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <libxml/hash.h>
#include <libxml/xmlstring.h>
#ifdef HAVE_SYS_ACL_H
#include <sys/acl.h>
#endif
#include "xar.h"
#include "arcmod.h"
#include "archive.h"
#include "util.h"
#ifndef LLONG_MIN
#define LLONG_MIN LONG_LONG_MIN
#endif
#ifndef LLONG_MAX
#define LLONG_MAX LONG_LONG_MAX
#endif
static struct {
const char *name;
mode_t type;
} filetypes [] = {
{ "file", S_IFREG },
{ "directory", S_IFDIR },
{ "symlink", S_IFLNK },
{ "fifo", S_IFIFO },
{ "character special", S_IFCHR },
{ "block special", S_IFBLK },
{ "socket", S_IFSOCK },
#ifdef S_IFWHT
{ "whiteout", S_IFWHT },
#endif
{ NULL, 0 }
};
static const char * filetype_name (mode_t mode) {
unsigned int i;
for (i = 0; filetypes[i].name; i++)
if (mode == filetypes[i].type)
return (filetypes[i].name);
return ("unknown");
}
static xar_file_t xar_link_lookup(xar_t x, dev_t dev, ino_t ino, xar_file_t f) {
char key[32];
xar_file_t ret;
memset(key, 0, sizeof(key));
snprintf(key, sizeof(key)-1, "%08" DEV_HEXSTRING "%08" INO_HEXSTRING, DEV_CAST dev, INO_CAST ino);
ret = xmlHashLookup(XAR(x)->ino_hash, BAD_CAST(key));
if( ret == NULL ) {
xmlHashAddEntry(XAR(x)->ino_hash, BAD_CAST(key), XAR_FILE(f));
return NULL;
}
return ret;
}
static int32_t aacls(xar_t x, xar_file_t f, const char *file) {
#ifdef HAVE_SYS_ACL_H
#if !defined(__APPLE__)
acl_t a;
const char *type;
xar_prop_get(f, "type", &type);
if( !type || (strcmp(type, "symlink") == 0) )
return 0;
if( !xar_check_prop(x, "acl") )
return 0;
a = acl_get_file(file, ACL_TYPE_DEFAULT);
if( a ) {
char *t;
acl_entry_t e;
if( acl_get_entry(a, ACL_FIRST_ENTRY, &e) != 1 )
goto NEXT;
t = acl_to_text(a, NULL);
if( t ) {
xar_prop_set(f, "acl/default", t);
acl_free(t);
}
acl_free(a);
}
NEXT:
a = acl_get_file(file, ACL_TYPE_ACCESS);
if( a ) {
char *t;
acl_entry_t e;
if( acl_get_entry(a, ACL_FIRST_ENTRY, &e) != 1 )
goto DONE;
t = acl_to_text(a, NULL);
if( t ) {
xar_prop_set(f, "acl/access", t);
acl_free(t);
}
acl_free(a);
}
DONE:
#else
acl_entry_t e = NULL;
acl_t a;
int i;
if( !xar_check_prop(x, "acl") )
return 0;
a = acl_get_file(file, ACL_TYPE_EXTENDED);
if( !a )
return 0;
for( i = 0; acl_get_entry(a, e == NULL ? ACL_FIRST_ENTRY : ACL_NEXT_ENTRY, &e) == 0; i++ ) {
char *t;
t = acl_to_text(a, NULL);
if( t ) {
xar_prop_set(f, "acl/appleextended", t);
acl_free(t);
}
}
acl_free(a);
#endif
#endif
return 0;
}
static int32_t eacls(xar_t x, xar_file_t f, const char *file) {
#ifdef HAVE_SYS_ACL_H
#if !defined(__APPLE__)
const char *t;
acl_t a;
const char *type;
xar_prop_get(f, "type", &type);
if( !type || (strcmp(type, "symlink") == 0) )
return 0;
xar_prop_get(f, "acl/default", &t);
if( t ) {
a = acl_from_text(t);
if( !a ) {
xar_err_new(x);
xar_err_set_errno(x, errno);
xar_err_set_string(x, "Error extracting default acl from toc");
xar_err_set_file(x, f);
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
} else {
if( acl_set_file(file, ACL_TYPE_DEFAULT, a) != 0 ) {
xar_err_new(x);
xar_err_set_errno(x, errno);
xar_err_set_string(x, "Error setting default acl");
xar_err_set_file(x, f);
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
}
}
}
xar_prop_get(f, "acl/access", &t);
if( t ) {
a = acl_from_text(t);
if( !a ) {
xar_err_new(x);
xar_err_set_errno(x, errno);
xar_err_set_string(x, "Error extracting access acl from toc");
xar_err_set_file(x, f);
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
} else {
if( acl_set_file(file, ACL_TYPE_ACCESS, a) != 0 ) {
xar_err_new(x);
xar_err_set_errno(x, errno);
xar_err_set_string(x, "Error setting access acl");
xar_err_set_file(x, f);
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
}
acl_free(a);
}
}
#else
const char *t;
acl_t a;
xar_prop_get(f, "acl/appleextended", &t);
if( t ) {
a = acl_from_text(t);
if( !a ) {
xar_err_new(x);
xar_err_set_errno(x, errno);
xar_err_set_string(x, "Error extracting access acl from toc");
xar_err_set_file(x, f);
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
} else {
if( acl_set_file(file, ACL_TYPE_ACCESS, a) != 0 ) {
xar_err_new(x);
xar_err_set_errno(x, errno);
xar_err_set_string(x, "Error setting access acl");
xar_err_set_file(x, f);
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
}
acl_free(a);
}
}
#endif
#endif
return 0;
}
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
#define XAR_FLAG_FORK "flags"
static void x_addflag(xar_file_t f, const char *name) {
char opt[1024];
memset(opt, 0, sizeof(opt));
snprintf(opt, sizeof(opt)-1, "%s/%s", XAR_FLAG_FORK, name);
xar_prop_set(f, opt, NULL);
return;
}
#endif
static int32_t flags_archive(xar_t x, xar_file_t f, const struct stat *sb) {
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
if( !sb->st_flags )
return 0;
if( !xar_check_prop(x, XAR_FLAG_FORK) )
return 0;
#ifdef UF_NODUMP
if( sb->st_flags & UF_NODUMP )
x_addflag(f, "UserNoDump");
#endif
#ifdef UF_IMMUTABLE
if( sb->st_flags & UF_IMMUTABLE )
x_addflag(f, "UserImmutable");
#endif
#ifdef UF_APPEND
if( sb->st_flags & UF_APPEND )
x_addflag(f, "UserAppend");
#endif
#ifdef UF_OPAQUE
if( sb->st_flags & UF_OPAQUE )
x_addflag(f, "UserOpaque");
#endif
#ifdef SF_ARCHIVED
if( sb->st_flags & SF_ARCHIVED )
x_addflag(f, "SystemArchived");
#endif
#ifdef SF_IMMUTABLE
if( sb->st_flags & SF_IMMUTABLE )
x_addflag(f, "SystemImmutable");
#endif
#ifdef SF_APPEND
if( sb->st_flags & SF_APPEND )
x_addflag(f, "SystemAppend");
#endif
#endif
return 0;
}
#ifdef HAVE_CHFLAGS
static int32_t x_getprop(xar_file_t f, const char *name, char **value) {
char v[1024];
memset(v, 0, sizeof(v));
snprintf(v, sizeof(v)-1, "%s/%s", XAR_FLAG_FORK, name);
return xar_prop_get(f, v, (const char **)value);
}
#endif
int32_t xar_flags_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) {
#ifdef HAVE_CHFLAGS
char *tmp;
u_int flags = 0;
if( xar_prop_get(f, XAR_FLAG_FORK, NULL) )
return 0;
#ifdef UF_NODUMP
if( x_getprop(f, "UserNoDump", (char **)&tmp) == 0 )
flags |= UF_NODUMP;
#endif
#ifdef UF_IMMUTABLE
if( x_getprop(f, "UserImmutable", (char **)&tmp) == 0 )
flags |= UF_IMMUTABLE;
#endif
#ifdef UF_APPEND
if( x_getprop(f, "UserAppend", (char **)&tmp) == 0 )
flags |= UF_APPEND;
#endif
#ifdef UF_OPAQUE
if( x_getprop(f, "UserOpaque", (char **)&tmp) == 0 )
flags |= UF_OPAQUE;
#endif
#ifdef SF_ARCHIVED
if( x_getprop(f, "SystemArchived", (char **)&tmp) == 0 )
flags |= SF_ARCHIVED;
#endif
#ifdef SF_IMMUTABLE
if( x_getprop(f, "SystemImmutable", (char **)&tmp) == 0 )
flags |= SF_IMMUTABLE;
#endif
#ifdef SF_APPEND
if( x_getprop(f, "SystemAppend", (char **)&tmp) == 0 )
flags |= SF_APPEND;
#endif
if( !flags )
return 0;
if( chflags(file, flags) != 0 ) {
char e[1024];
memset(e, 0, sizeof(e));
snprintf(e, sizeof(e)-1, "chflags: %s", strerror(errno));
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, e);
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
#endif
return 0;
}
int32_t xar_stat_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) {
char *tmpstr;
struct passwd *pw;
struct group *gr;
char time[128];
struct tm t;
const char *type;
if(len){
if( xar_check_prop(x, "type") )
xar_prop_set(f, "type", "file");
return 0;
}
if( S_ISREG(XAR(x)->sbcache.st_mode) && (XAR(x)->sbcache.st_nlink > 1) ) {
xar_file_t tmpf;
const char *id = xar_attr_get(f, NULL, "id");
if( !id ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "stat: No file id for file");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_CREATION);
return -1;
}
tmpf = xar_link_lookup(x, XAR(x)->sbcache.st_dev, XAR(x)->sbcache.st_ino, f);
if( xar_check_prop(x, "type") ) {
xar_prop_set(f, "type", "hardlink");
if( tmpf ) {
const char *id;
id = xar_attr_get(tmpf, NULL, "id");
xar_attr_set(f, "type", "link", id);
} else {
xar_attr_set(f, "type", "link", "original");
}
}
} else {
type = filetype_name(XAR(x)->sbcache.st_mode & S_IFMT);
if( xar_check_prop(x, "type") )
xar_prop_set(f, "type", type);
}
if( xar_check_prop(x, "device") && (S_ISBLK(XAR(x)->sbcache.st_mode) || S_ISCHR(XAR(x)->sbcache.st_mode))) {
uint32_t major, minor;
char tmpstr[12];
xar_devmake(XAR(x)->sbcache.st_rdev, &major, &minor);
memset(tmpstr, 0, sizeof(tmpstr));
snprintf(tmpstr, sizeof(tmpstr)-1, "%u", major);
xar_prop_set(f, "device/major", tmpstr);
memset(tmpstr, 0, sizeof(tmpstr));
snprintf(tmpstr, sizeof(tmpstr)-1, "%u", minor);
xar_prop_set(f, "device/minor", tmpstr);
}
if( S_ISLNK(XAR(x)->sbcache.st_mode) ) {
char link[4096];
struct stat lsb;
memset(link, 0, sizeof(link));
readlink(file, link, sizeof(link)-1);
xar_prop_set(f, "link", link);
if( stat(file, &lsb) != 0 ) {
xar_attr_set(f, "link", "type", "broken");
} else {
type = filetype_name(lsb.st_mode & S_IFMT);
xar_attr_set(f, "link", "type", type);
}
}
if( xar_check_prop(x, "inode") ) {
asprintf(&tmpstr, "%"INO_STRING, XAR(x)->sbcache.st_ino);
xar_prop_set(f, "inode", tmpstr);
free(tmpstr);
}
if( xar_check_prop(x, "deviceno") ) {
asprintf(&tmpstr, "%"DEV_STRING, XAR(x)->sbcache.st_dev);
xar_prop_set(f, "deviceno", tmpstr);
free(tmpstr);
}
if( xar_check_prop(x, "mode") ) {
asprintf(&tmpstr, "%04o", XAR(x)->sbcache.st_mode & (~S_IFMT));
xar_prop_set(f, "mode", tmpstr);
free(tmpstr);
}
if( xar_check_prop(x, "uid") ) {
asprintf(&tmpstr, "%"PRIu64, (uint64_t)XAR(x)->sbcache.st_uid);
xar_prop_set(f, "uid", tmpstr);
free(tmpstr);
}
if( xar_check_prop(x, "user") ) {
pw = getpwuid(XAR(x)->sbcache.st_uid);
if( pw )
xar_prop_set(f, "user", pw->pw_name);
}
if( xar_check_prop(x, "gid") ) {
asprintf(&tmpstr, "%"PRIu64, (uint64_t)XAR(x)->sbcache.st_gid);
xar_prop_set(f, "gid", tmpstr);
free(tmpstr);
}
if( xar_check_prop(x, "group") ) {
gr = getgrgid(XAR(x)->sbcache.st_gid);
if( gr )
xar_prop_set(f, "group", gr->gr_name);
}
if( xar_check_prop(x, "atime") ) {
gmtime_r(&XAR(x)->sbcache.st_atime, &t);
memset(time, 0, sizeof(time));
strftime(time, sizeof(time), "%FT%T", &t);
strcat(time, "Z");
xar_prop_set(f, "atime", time);
}
if( xar_check_prop(x, "mtime") ) {
gmtime_r(&XAR(x)->sbcache.st_mtime, &t);
memset(time, 0, sizeof(time));
strftime(time, sizeof(time), "%FT%T", &t);
strcat(time, "Z");
xar_prop_set(f, "mtime", time);
}
if( xar_check_prop(x, "ctime") ) {
gmtime_r(&XAR(x)->sbcache.st_ctime, &t);
memset(time, 0, sizeof(time));
strftime(time, sizeof(time), "%FT%T", &t);
strcat(time, "Z");
xar_prop_set(f, "ctime", time);
}
flags_archive(x, f, &(XAR(x)->sbcache));
aacls(x, f, file);
return 0;
}
int32_t xar_set_perm(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) {
const char *opt;
int32_t m=0, mset=0;
uid_t u;
gid_t g;
const char *timestr;
struct tm t;
enum {ATIME=0, MTIME};
struct timeval tv[2];
char savesuid = 0;
if ( len )
return 0;
u = geteuid();
g = getegid();
opt = xar_opt_get(x, XAR_OPT_OWNERSHIP);
if( opt && (strcmp(opt, XAR_OPT_VAL_SYMBOLIC) == 0) ) {
struct passwd *pw;
struct group *gr;
xar_prop_get(f, "user", &opt);
if( opt ) {
pw = getpwnam(opt);
if( pw ) {
u = pw->pw_uid;
}
}
xar_prop_get(f, "group", &opt);
if( opt ) {
gr = getgrnam(opt);
if( gr ) {
g = gr->gr_gid;
}
}
savesuid = 1;
}
if( opt && (strcmp(opt, XAR_OPT_VAL_NUMERIC) == 0) ) {
xar_prop_get(f, "uid", &opt);
if( opt ) {
long long tmp;
tmp = strtol(opt, NULL, 10);
if( ( (tmp == LLONG_MIN) || (tmp == LLONG_MAX) ) && (errno == ERANGE) ) {
return -1;
}
u = (uid_t)tmp;
}
xar_prop_get(f, "gid", &opt);
if( opt ) {
long long tmp;
tmp = strtol(opt, NULL, 10);
if( ( (tmp == LLONG_MIN) || (tmp == LLONG_MAX) ) && (errno == ERANGE) ) {
return -1;
}
g = (gid_t)tmp;
}
savesuid = 1;
}
opt = xar_opt_get(x, XAR_OPT_SAVESUID);
if( opt && (strcmp(opt, XAR_OPT_VAL_TRUE) == 0) ) {
savesuid = 1;
}
xar_prop_get(f, "mode", &opt);
if( opt ) {
long long tmp;
tmp = strtoll(opt, NULL, 8);
if( ( (tmp == LLONG_MIN) || (tmp == LLONG_MAX) ) && (errno == ERANGE) ) {
return -1;
}
m = (mode_t)tmp;
if( !savesuid ) {
m &= ~S_ISUID;
m &= ~S_ISGID;
}
mset = 1;
}
xar_prop_get(f, "type", &opt);
if( opt && !mset ) {
mode_t u = umask(0);
umask(u);
if( strcmp(opt, "directory") == 0 ) {
m = (mode_t)(0777 & ~u);
} else {
m = (mode_t)(0666 & ~u);
}
mset = 1;
}
if( opt && (strcmp(opt, "symlink") == 0) ) {
#ifdef HAVE_LCHOWN
if( lchown(file, u, g) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "perm: could not lchown symlink");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
m &= ~S_ISUID;
m &= ~S_ISGID;
}
#ifdef HAVE_LCHMOD
if( mset )
if( lchmod(file, m) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "perm: could not lchmod symlink");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
}
#endif
#endif
} else {
if( chown(file, u, g) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "perm: could not chown file");
xar_err_set_errno(x, errno);
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
m &= ~S_ISUID;
m &= ~S_ISGID;
}
if( mset )
if( chmod(file, m) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "perm: could not chmod file");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
}
}
eacls(x, f, file);
memset(tv, 0, sizeof(struct timeval) * 2);
xar_prop_get(f, "atime", ×tr);
if( timestr ) {
memset(&t, 0, sizeof(t));
strptime(timestr, "%FT%T", &t);
tv[ATIME].tv_sec = timegm(&t);
} else {
tv[ATIME].tv_sec = time(NULL);
}
xar_prop_get(f, "mtime", ×tr);
if( timestr ) {
memset(&t, 0, sizeof(t));
strptime(timestr, "%FT%T", &t);
tv[MTIME].tv_sec = timegm(&t);
} else {
tv[MTIME].tv_sec = time(NULL);
}
utimes(file, tv);
return 0;
}
int32_t xar_stat_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) {
const char *opt;
int ret, fd;
mode_t modet = 0;
xar_prop_get(f, "type", &opt);
if(opt && (strcmp(opt, "character special") == 0))
modet = S_IFCHR;
if(opt && (strcmp(opt, "block special") == 0))
modet = S_IFBLK;
if( modet ) {
uint32_t major, minor;
long long tmpll;
dev_t devt;
xar_prop_get(f, "device/major", &opt);
tmpll = strtoll(opt, NULL, 10);
if( ( (tmpll == LLONG_MIN) || (tmpll == LLONG_MAX) ) && (errno == ERANGE) )
return -1;
if( (tmpll < 0) || (tmpll > 255) )
return -1;
major = tmpll;
xar_prop_get(f, "device/minor", &opt);
tmpll = strtoll(opt, NULL, 10);
if( ( (tmpll == LLONG_MIN) || (tmpll == LLONG_MAX) ) && (errno == ERANGE) )
return -1;
if( (tmpll < 0) || (tmpll > 255) )
return -1;
minor = tmpll;
devt = xar_makedev(major, minor);
unlink(file);
if( mknod(file, modet, devt) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "mknod: Could not create character device");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
return 0;
}
if(opt && (strcmp(opt, "directory") == 0)) {
ret = mkdir(file, 0700);
if( (ret != 0) && (errno != EEXIST) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "stat: Could not create directory");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return ret;
}
return 0;
}
if(opt && (strcmp(opt, "symlink") == 0)) {
xar_prop_get(f, "link", &opt);
if( opt ) {
unlink(file);
ret = symlink(opt, file);
if( ret != 0 ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "stat: Could not create symlink");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
}
return ret;
}
}
if(opt && (strcmp(opt, "hardlink") == 0)) {
xar_file_t tmpf;
opt = xar_attr_get(f, "type", "link");
if( !opt )
return 0;
if( strcmp(opt, "original") == 0 )
goto CREATEFILE;
tmpf = xmlHashLookup(XAR(x)->link_hash, BAD_CAST(opt));
if( !tmpf ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "stat: Encountered hardlink with no original");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
unlink(file);
if( link(XAR_FILE(tmpf)->fspath, file) != 0 ) {
if( errno == ENOENT ) {
xar_iter_t i;
const char *ptr;
i = xar_iter_new();
for(ptr = xar_prop_first(tmpf, i); ptr; ptr = xar_prop_next(i)) {
xar_iter_t a;
const char *val = NULL;
const char *akey, *aval;
if( strncmp("data", ptr, 4) != 0 )
continue;
if( xar_prop_get(tmpf, ptr, &val) )
continue;
xar_prop_set(f, ptr, val);
a = xar_iter_new();
for(akey = xar_attr_first(tmpf, ptr, a); akey; akey = xar_attr_next(a)) {
aval = xar_attr_get(tmpf, ptr, akey);
xar_attr_set(f, ptr, akey, aval);
}
xar_iter_free(a);
}
xar_iter_free(i);
xar_attr_set(f, "type", "link", "original");
return 0;
} else {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "stat: Could not link hardlink to original");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
}
return 0;
}
if(opt && (strcmp(opt, "fifo") == 0)) {
unlink(file);
if( mkfifo(file, 0) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "mkfifo: Could not create fifo");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
return 0;
}
if(opt && (strcmp(opt, "socket") == 0)) {
return 0;
}
CREATEFILE:
unlink(file);
fd = open(file, O_RDWR|O_CREAT|O_TRUNC, 0600);
if( fd > 0 )
close(fd);
return 0;
}