home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: WPS_PM
/
WPS_PM.zip
/
xfld085s.zip
/
helpers
/
eas.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-02-23
|
16KB
|
502 lines
/*
*@@sourcefile eas.c:
* contains helper functions for handling Extended Attributes.
* See explanations below.
*
* Function prefixes (new with V0.81):
* -- ea* EA helper functions
*
* This file is new with V0.81 and contains all the EA functions
* that were in helpers.c previously.
*
*@@include #include <os2.h>
*@@include #include "eas.h"
*/
/*
* Most of the code in this file dealing with Extended Attributes is based
* on code (w) by Chris Hanson (cph@zurich.ai.mit.edu).
* Copyright (c) 1995 Massachusetts Institute of Technology.
*
* The original code is available as EALIB.ZIP at Hobbes.
*
* This material was developed by the Scheme project at the Massachusetts
* Institute of Technology, Department of Electrical Engineering and
* Computer Science. Permission to copy this software, to redistribute
* it, and to use it for any purpose is granted, subject to the following
* restrictions and understandings.
*
* 1. Any copy made of this software must include this copyright notice
* in full.
*
* 2. Users of this software agree to make their best efforts (a) to
* return to the MIT Scheme project any improvements or extensions that
* they make, so that these may be included in future releases; and (b)
* to inform MIT of noteworthy uses of this software.
*
* 3. All materials developed as a consequence of the use of this
* software shall duly acknowledge such use, in accordance with the usual
* standards of acknowledging credit in academic research.
*
* 4. MIT has made no warrantee or representation that the operation of
* this software will be error-free, and MIT is under no obligation to
* provide any services, by way of maintenance, update, or otherwise.
*
* 5. In conjunction with products arising from the use of this material,
* there shall be no use of the name of the Massachusetts Institute of
* Technology nor of any adaptation thereof in any advertising,
* promotional, or sales literature without prior written consent from
* MIT in each case.
*
* This file Copyright (C) 1997-99 Ulrich Möller,
* Massachusetts Institute of Technology.
* This file is part of the XFolder source package.
* XFolder 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, in version 2 as it comes in the
* "COPYING" file of the XFolder main distribution.
* 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.
*/
#define INCL_DOS
#define INCL_DOSERRORS
#include <os2.h>
#include <stdlib.h>
#include <string.h>
#include "eas.h"
// #define _PMPRINTF_
#include "pmprintf.h"
/********************************************************************
* *
* Extended Attribute handling *
* *
********************************************************************/
#define EA_BINDING_FLAGS(binding) ((binding)->bFlags)
#define EA_BINDING_NAME_LENGTH(binding) ((binding)->bNameLength)
#define EA_BINDING_VALUE_LENGTH(binding) ((binding)->usValueLength)
#define EA_BINDING_NAME(binding) ((binding)->pszName)
#define EA_BINDING_VALUE(binding) ((binding)->pszValue)
#define EA_LIST_BINDING(list) ((list)->binding)
#define EA_LIST_NEXT(list) ((list)->next)
// forward declarations to helper funcs at bottom
static PEALIST ReadEAList(ULONG, PVOID);
static EABINDING * ReadEAByIndex(ULONG, PVOID, ULONG);
static EABINDING * ReadEAByName(ULONG, PVOID, PSZ);
static PDENA2 ReadDenaByIndex(ULONG, PVOID, ULONG);
static PEABINDING GetEAValue(ULONG, PVOID, PDENA2);
static void SetupQueryEAInfo(PDENA2, PEAOP2);
static PEABINDING ConvertFeal2Binding(PFEA2LIST);
static void WriteEAList(ULONG, PVOID, PEALIST);
static void WriteEA(ULONG, PVOID, PEABINDING);
static PFEA2LIST ConvertBinding2Feal(PEABINDING);
/*
*@@ eaFreeBinding:
* deallocate EA binding memory that was generated
* by the ea...Read... procedures below. These procs
* assume that "malloc" was used for allocation and
* that the "name" and "value" fields of each binding
* were also allocated using "malloc". "value" may also
* be NULL.
*/
void eaFreeBinding(PEABINDING binding)
{
free(EA_BINDING_NAME(binding));
if ((EA_BINDING_VALUE(binding)) != 0)
free(EA_BINDING_VALUE(binding));
free(binding);
}
/*
*@@ eaFreeList:
* like eaFreeBinding, but for an EA binding list.
*/
void eaFreeList(PEALIST list)
{
while (list != 0)
{
PEALIST next = (EA_LIST_NEXT (list));
eaFreeBinding(EA_LIST_BINDING (list));
free(list);
list = next;
}
}
/*
* All of the following functions come in two flavors:
*
* eaHFile* operate on an open file handle.
*
* eaPath* operate on any file specified by its
* filename, which may be fully qualified.
*/
/*
* ------ READ EXTENDED ATTRIBUTES
*/
/*
*@@ eaPathQueryTotalSize::
* returns the total size of all EAs for a given file.
* (W) Ulrich Möller.
*/
ULONG eaPathQueryTotalSize(PSZ pszPath)
{
APIRET arc;
ULONG ulTotalEASize = 0;
CHAR pchPath;
// HDIR hdir;
// ULONG ulCount = 1;
FILEFINDBUF4 ffb4;
_Pmpf(("eaPathQueryTotalSize %s", pszPath));
arc = DosQueryPathInfo(pszPath,
// &hdir,
// FILE_ARCHIVED | FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY | FILE_DIRECTORY,
FIL_QUERYEASIZE,
&ffb4,
sizeof(FILEFINDBUF4));
if (arc == NO_ERROR)
{
// CHAR szFile[CCHMAXPATH];
// PBYTE pbBuffer = malloc(ffb4.cbList);
BYTE abBuf[2000];
LONG lCount = 0;
PDENA2 pdena2;
lCount = -1;
arc = DosEnumAttribute(ENUMEA_REFTYPE_PATH,
pszPath,
1,
abBuf,
sizeof(abBuf),
(PULONG)&lCount,
ENUMEA_LEVEL_NO_VALUE);
// ulCount now contains the EA count
pdena2 = (PDENA2)abBuf;
_Pmpf((" %s: arc = %d, count = %d", pszPath, arc, lCount));
if (lCount > 0) {
ulTotalEASize = pdena2->cbName + 8;
while (lCount > 0) {
ulTotalEASize += (pdena2->cbValue + sizeof(DENA2));
lCount--;
pdena2 = (PDENA2) (((PBYTE) pdena2) +
pdena2->oNextEntryOffset);
}
}
}
_Pmpf((" %s: total %d", pszPath, ulTotalEASize));
return (ulTotalEASize);
}
/*
*@@ eaPathReadAll:
* reads all of the extended attributes into an EALIST.
* Returns NULL if no EAs were found.
* The returned list should be freed using eaFreeList.
*/
PEALIST eaPathReadAll(PSZ path)
{
return (ReadEAList(ENUMEA_REFTYPE_PATH, path));
}
/*
*@@ eaHFileReadAll:
* like eaPathReadAll, but for an open file handle.
*/
PEALIST eaHFileReadAll(HFILE hfile)
{
return (ReadEAList(ENUMEA_REFTYPE_FHANDLE, (&hfile)));
}
/*
*@@ eaPathReadOneByIndex:
* returns one EA specified by a given index, counting
* from 1. Returns NULL if the specified index was not
* found, either because the file has no EAs at all or
* the index is too large.
* The returned binding should be freed using eaFreeBinding.
*/
PEABINDING eaPathReadOneByIndex(PSZ path, ULONG index)
{
return (ReadEAByIndex(ENUMEA_REFTYPE_PATH, path, index));
}
/*
*@@ eaHFileReadOneByIndex:
* like eaPathReadOneByIndex, but for an open file handle.
*/
PEABINDING eaHFileReadOneByIndex(HFILE hfile, ULONG index)
{
return (ReadEAByIndex(ENUMEA_REFTYPE_FHANDLE, (&hfile), index));
}
/*
*@@ eaPathReadOneByName:
* returns one EA specified by the given EA name (e.g.
* ".LONGNAME"). Returns NULL if not found.
* The returned binding should be freed using eaFreeBinding.
*/
PEABINDING eaPathReadOneByName(PSZ path, PSZ name)
{
return (ReadEAByName(ENUMEA_REFTYPE_PATH, path, name));
}
/*
*@@ eaHFileReadOneByName:
* like eaPathReadOneByName, but for an open file handle.
*/
PEABINDING eaHFileReadOneByName(HFILE hfile, PSZ name)
{
return (ReadEAByName(ENUMEA_REFTYPE_FHANDLE, (&hfile), name));
}
/*
* ------ WRITE EXTENDED ATTRIBUTES
*/
/*
*@@ eaPathWriteAll:
* writes a list of EAs to a given file. These EAs
* are added to possibly existing EAs on the file.
* A given EA is deleted if its usValueLength field
* is 0; in that case, the value field may also be NULL.
*/
void eaPathWriteAll(PSZ path, PEALIST list)
{
WriteEAList(ENUMEA_REFTYPE_PATH, path, list);
}
/*
*@@ eaHFileWriteAll:
* like eaPathWriteAll, but for an open file handle.
*/
void eaHFileWriteAll(HFILE hfile, PEALIST list)
{
WriteEAList(ENUMEA_REFTYPE_FHANDLE, (&hfile), list);
}
/*
*@@ eaPathWriteOne:
* adds one EA to a given file.
* A given EA is deleted if its usValueLength field
* is 0; in that case, the value field may also be NULL.
*/
void eaPathWriteOne(PSZ path, PEABINDING binding)
{
WriteEA(ENUMEA_REFTYPE_PATH, path, binding);
}
/*
*@@ eaHFileWriteOne:
* like eaPathWriteOne, but for an open file handle.
*/
void eaHFileWriteOne(HFILE hfile, PEABINDING binding)
{
WriteEA(ENUMEA_REFTYPE_FHANDLE, (&hfile), binding);
}
/********************************************************************
* *
* EA helper funcs *
* *
********************************************************************/
static PEALIST ReadEAList(ULONG type, PVOID pfile)
{
ULONG index = 1;
PEALIST head = 0;
PEALIST tail = 0;
while (1)
{
PEABINDING binding = (ReadEAByIndex(type, pfile, index));
if (binding == 0)
break;
{
PEALIST list = (malloc(sizeof (EALIST)));
(EA_LIST_BINDING (list)) = binding;
(EA_LIST_NEXT (list)) = 0;
if (head == 0)
head = list;
else
(EA_LIST_NEXT (tail)) = list;
tail = list;
}
index += 1;
}
return (head);
}
static PEABINDING ReadEAByIndex(ULONG type, PVOID pfile, ULONG index)
{
PDENA2 dena = (ReadDenaByIndex(type, pfile, index));
return ((dena == 0)
? 0
: (GetEAValue(type, pfile, dena)));
}
static PEABINDING ReadEAByName(ULONG type, PVOID pfile, PSZ name)
{
ULONG index = 1;
while (1)
{
PDENA2 dena = ReadDenaByIndex(type, pfile, index);
if (dena == 0)
return (NULL);
if ((strcmp(name, (dena->szName))) == 0)
return (GetEAValue(type, pfile, dena));
free(dena);
index += 1;
}
}
static PDENA2 ReadDenaByIndex(ULONG type, PVOID pfile, ULONG index)
{
ULONG count = 1;
PDENA2 dena = (malloc(500)); // 500 is magic -- IBM doesn't explain.
APIRET arc = DosEnumAttribute(type, pfile, index, dena, 500, (&count),
ENUMEA_LEVEL_NO_VALUE);
if (count == 0)
{
free(dena);
return (0);
}
else
return (dena);
}
static PEABINDING GetEAValue(ULONG type, PVOID pfile, PDENA2 dena)
{
ULONG level = FIL_QUERYEASFROMLIST;
EAOP2 eaop;
ULONG size = (sizeof(eaop));
APIRET arc = NO_ERROR;
SetupQueryEAInfo(dena, (&eaop));
if (type == ENUMEA_REFTYPE_FHANDLE)
arc = DosQueryFileInfo((* ((PHFILE) pfile)), level, (&eaop), size);
else
arc = DosQueryPathInfo(pfile, level, (&eaop), size);
free(eaop.fpGEA2List);
return (ConvertFeal2Binding(eaop.fpFEA2List));
}
static void SetupQueryEAInfo(PDENA2 dena, PEAOP2 eaop)
{
unsigned int geal_size = ((sizeof (GEA2LIST)) + (dena->cbName));
unsigned int feal_size
= ((sizeof (FEA2LIST)) + (dena->cbName) + (dena->cbValue));
(eaop->fpGEA2List) = (malloc(geal_size));
((eaop->fpGEA2List)->cbList) = geal_size;
(eaop->fpFEA2List) = (malloc(feal_size));
((eaop->fpFEA2List)->cbList) = feal_size;
(eaop->oError) = 0;
{
PGEA2 gea = (&(((eaop->fpGEA2List)->list) [0]));
(gea->oNextEntryOffset) = 0;
(gea->cbName) = (dena->cbName);
strcpy ((gea->szName), (dena->szName));
}
free(dena);
}
static PEABINDING ConvertFeal2Binding(PFEA2LIST feal)
{
PFEA2 fea = (&((feal->list) [0]));
PEABINDING binding = (malloc(sizeof (EABINDING)));
(EA_BINDING_FLAGS (binding)) = (fea->fEA);
(EA_BINDING_NAME_LENGTH (binding)) = (fea->cbName);
(EA_BINDING_VALUE_LENGTH (binding)) = (fea->cbValue);
(EA_BINDING_NAME (binding)) = (malloc((fea->cbName) + 1));
strcpy ((EA_BINDING_NAME (binding)), (fea->szName));
(EA_BINDING_VALUE (binding)) = (malloc(fea->cbValue));
memcpy ((EA_BINDING_VALUE (binding)),
(&((fea->szName) [(fea->cbName) + 1])),
(fea->cbValue));
free(feal);
return (binding);
}
static void WriteEAList(ULONG type, PVOID pfile, PEALIST list)
{
while (list != 0)
{
WriteEA(type, pfile, (EA_LIST_BINDING (list)));
list = (EA_LIST_NEXT (list));
}
}
static void WriteEA(ULONG type, PVOID pfile, PEABINDING binding)
{
ULONG level = FIL_QUERYEASIZE;
EAOP2 eaop;
ULONG size = (sizeof (eaop));
APIRET arc = NO_ERROR;
(eaop.fpGEA2List) = 0;
(eaop.fpFEA2List) = (ConvertBinding2Feal(binding));
(eaop.oError) = 0;
if (type == ENUMEA_REFTYPE_FHANDLE)
arc = DosSetFileInfo((* ((PHFILE) pfile)), level, (&eaop), size);
else
arc = DosSetPathInfo(pfile, level, (&eaop), size, DSPI_WRTTHRU);
free(eaop.fpFEA2List);
}
static PFEA2LIST ConvertBinding2Feal(PEABINDING binding)
{
unsigned int feal_size
= ((sizeof (FEA2LIST))
+ (EA_BINDING_NAME_LENGTH (binding))
+ (EA_BINDING_VALUE_LENGTH (binding)));
PFEA2LIST feal = (malloc(feal_size));
PFEA2 fea = (&((feal->list) [0]));
(feal->cbList) = feal_size;
(fea->oNextEntryOffset) = 0;
(fea->fEA) = (EA_BINDING_FLAGS (binding));
(fea->cbName) = (EA_BINDING_NAME_LENGTH (binding));
(fea->cbValue) = (EA_BINDING_VALUE_LENGTH (binding));
strcpy ((fea->szName), (EA_BINDING_NAME (binding)));
if ((EA_BINDING_VALUE (binding)) != 0)
memcpy ((&((fea->szName) [(fea->cbName) + 1])),
(EA_BINDING_VALUE (binding)),
(fea->cbValue));
return (feal);
}