/* $Id: swpackagefile.cxx,v 1.8 2000/04/06 22:39:41 jhl Exp jhl $
 * swpackagefile.cxx -
 *
 */ 

/*
 * Copyright (C) 1998  James H. Lowe, Jr.  <jhlowe@acm.org>
 *
 * COPYING TERMS AND CONDITIONS
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
 */

#include "swuser_config.h"
#include "swuser_assert_config.h"
#include "swpackagefile.h"

mode_t swPackageFile::default_tar_mode_dir = (00|S_IRWXU|(S_IRWXG&(S_IXGRP|S_IRGRP))|(S_IRWXO&(S_IXOTH|S_IROTH)));
mode_t swPackageFile::default_tar_mode_regfile = (00|(S_IRWXU&(~S_IXUSR))|(S_IRWXG&(S_IRGRP))|(S_IRWXO&(S_IROTH)));

int swPackageFile::Initor::use_count_=0;
int swPackageFile::Initor::did_create_=0;
uxFormat * swPackageFile::uxformatM = NULL;
STROB * swPackageFile::tmpM = NULL;


static
void
apply_umask(mode_t * mode, char * cumask)
{
	mode_t umask;
	unsigned long ul_umask;
	SWPACKAGEFILE_DEBUG("");
	taru_otoul(cumask, &ul_umask);
	umask = (mode_t)(ul_umask);
	(*mode) &= (~umask);
	return;
}

static
void
add_if_vremoval(swDefinition * swdef, swMetaData * swmd, char * name)
{
	swMetaData * existing_swmd;	
	
	SWPACKAGEFILE_DEBUG("");
	existing_swmd = swdef->findAttribute(name);
	if (existing_swmd && existing_swmd->get_status() > 0) {
		//
		// Dont add
		//
	} else if (existing_swmd  && !existing_swmd->get_status()) {
		swdef->list_replace(swmd);
	} else if (!existing_swmd) {
		swdef->list_add(swmd);
	}
	return;
}

int swPackageFile::initialize_file_stats_array(swDefinition * swdef,
				char fileArray[][file_permsLength],
					int fileArrayWasSet[]) 
{
	int i;
	swMetaData * swmd;	
	char * value;
	
	SWPACKAGEFILE_DEBUG("");
	for (i=0; i<=lastE; i++) {
		*fileArray[i]='\0';
		fileArrayWasSet[i] = 0;
	}

	for (i=0; i<lastE; i++) {
		switch(i) {
			case modeE: 	// 1
			case ownerE: 	// 4
			case uidE: 	// 5
			case groupE:	// 6
			case gidE:	// 7
			case majorE:	// 16
			case minorE:	// 15
				//
				//  Preserve these attributes that are
				//  already set from the PSF file.
				//
				swmd = swdef->findAttribute(namesM[i]);
				if (swmd) {
					value = swmd->get_value((int*)(NULL));
					SWPACKAGEFILE_DEBUG3("setting attribute [%s] == [%s]", namesM[i], value);
					::swlib_strncpy(fileArray[i], value, file_permsLength);
					fileArrayWasSet[i] = 1;
				} else {
					SWPACKAGEFILE_DEBUG3("NOT setting attribute [%s] == [%s]", namesM[i], value);
					;
				}
				break;
			case volaE:
			case compE:
			case linksourceE:
			case cksumE:
			case md5sumE:
			case typeE:
			case ctimeE:
			case mtimeE:
			case nlinkE:
			case inoE:
			case swbiE:
			case umaskE:
			case sizeE:
			default:
				break;	
		}
	}
	return 0;
}

int swPackageFile::apply_file_stats(swDefinition * swdef, SWVARFS * swvarfs, char *source, int cksumflags ) {
	int ret;
	struct stat st;
	char fileArray			[lastE+1][file_permsLength];
	int  fileArrayWasSet		[lastE+1];
	swMetaData * swmd;	
	SWVARFS * swvarfs1 = (SWVARFS*)xFormat_get_swvarfs();
	int level = swdef->get_level();
	char * umask_value;
	int i;

	SWPACKAGEFILE_DEBUG("");
	if (source == NULL) {
		//
		// Determine what to use as the effective source from the contents
		// of the definition.
		//
		fprintf(stderr, "swPackageFile::apply_file_stats: missing source attribute, fatal.\n");
		return -1;
	}

	swdef->set_path_attribute(source);

	SWLIB_ASSERT(swvarfs == swvarfs1);

	//if (*source == SWBIS_NO_STAT_INDICATOR_C) return 0;
	if (swdef->get_no_stat()) return 0;

	//for (i=0; i<=lastE; i++) {
	//	*fileArray[i]='\0';
	//	fileArrayWasSet[i] = 0;
	//}
	initialize_file_stats_array(swdef, fileArray, fileArrayWasSet);

	swmd = swdef->findAttribute("umask");
	if (swmd) {
		/*
		* This umask value came from a file_permissions extended
		* defintiion and was applied to subsequent file (object keyword)
		* definitions in the PSF.
		* It is applies elsewhere in the case of subsequent file 
		* (explicit extended) definitions.
		*/
		SWPACKAGEFILE_DEBUG("");
		umask_value = swmd->get_value((int*)(NULL));
	} else {
		SWPACKAGEFILE_DEBUG("");
		umask_value = (char*)NULL;
	}
	
	cksumflags = swdef->apply_cksum_policy_specialization(cksumflags);  // cksum are on for control_files.

	if (xFormat_u_lstat(source, &st) != 0) {
		// fprintf(stderr, "_u_lstat error : %s\n", source);
		return -9991;
	}

	if (umask_value) {
		SWPACKAGEFILE_DEBUG("");
		apply_umask(&(st.st_mode), umask_value);
	}
	
	ret = swMetaData::swmetadata_decode_file_stats(swvarfs1, source, source,
				&st, fileArray, fileArrayWasSet, cksumflags);
	if (ret) {
		SWPACKAGEFILE_DEBUG("");
		return ret;
	}

	for (i=0; i<lastE; i++) {
		if (fileArrayWasSet[i]) {
			swmd = new swAttribute(const_cast<char*>(namesM[i]), fileArray[i]);
			swmd->set_level(level + 1);
			switch(i) {
				case ctimeE:
				case mtimeE:
				case sizeE:
				case typeE:
				case linksourceE:
				case volaE:
				case compE:
				case cksumE:
				case md5sumE:
					SWPACKAGEFILE_DEBUG("");
					swdef->list_replace(swmd);
					break;
				case ownerE:
				case groupE:
					SWPACKAGEFILE_DEBUG("");
					add_if_vremoval(swdef, swmd, namesM[i]);
					break;
				case majorE:
				case minorE:
					SWPACKAGEFILE_DEBUG("");
					if (
						*fileArray[typeE] == 'c' ||
						*fileArray[typeE] == 'b'
					) {
						SWPACKAGEFILE_DEBUG("");
						swdef->list_add_if_new(swmd);
					} else {
						SWPACKAGEFILE_DEBUG("");
						swmd->vremove();
					}
					break;
				case uidE:
				case gidE:
					SWPACKAGEFILE_DEBUG("");
					swdef->list_add_if_new(swmd);
					break;
				case modeE:
					SWPACKAGEFILE_DEBUG("");
					swdef->list_add_if_new(swmd);
					break;
				case nlinkE:
				case inoE:
				case swbiE:
				case umaskE:
					SWPACKAGEFILE_DEBUG("");
					swdef->list_replace(swmd);
					swmd->vremove();
					break;
			}
		}
	}
	swdef->set_no_stat(1);
	swdef->apply_file_stat_specialization(fileArray, fileArrayWasSet);  // some stats are turned off in control_files.
	SWPACKAGEFILE_DEBUG("");
	return 0;
}
