/* GETPUTEA.C Routines to read and write extended attributes. Compatible with OS/2 version 1.2. Microsoft or IBM PTK header files not required. Will need modification for OS/2 2.0. Copyright (C) 1989 Ziff Davis Communications PC Magazine * Ray Duncan, December 1989 */ #include #include #include #include // EA predefined value types #define EAT_BINARY 0x0fffe // Length-preceeded binary #define EAT_ASCII 0x0fffd // Length-preceeded ASCII #define EAT_BITMAP 0x0fffb // Length-preceeded bitmap #define EAT_METAFILE 0x0fffa // Metafile #define EAT_ICON 0x0fff9 // Length-preceeded icon #define EAT_EA 0x0ffee // ASCIIZ name of associated EA #define EAT_MVMT 0x0ffdf // Multi-value multi-type #define EAT_MVST 0x0ffde // Multi-value single-type #define EAT_ASN1 0x0ffdd // ASN.1 field #define MAXPATHNAME 260 // max length of pathname #define MAXFILENAME 255 // max length of filename #define FEALISTSIZE 1024 // arbitrary buffer size #define GEALISTSIZE 260 // arbitrary buffer size #define API unsigned extern far pascal // OS/2 API function prototypes API DosQFileInfo(unsigned, unsigned, void far *, unsigned); API DosSetFileInfo(unsigned, unsigned, void far *, unsigned); struct _EA { // extended attribute header unsigned char flags; // critical flag etc. unsigned char nsize; // length of EA name (without null) unsigned vsize; // total size of EA value char name[1]; } ; // EA name and value begin here struct _EAval { // extended attribute value unsigned type; // EA value type unsigned size; // length of EA variable data char data[1]; } ; // actual data begins here struct _FEAList { // receives extended attributes unsigned long size; // total size of structure char data[1]; } ; // extended attributes begin here struct _GEA { // extended attribute target name unsigned char size; // length of name char name[1]; } ; // actual name begins here struct _GEAList { // holds names of EAs to get unsigned long size; // total size of structure struct _GEA GEA; } ; // name length and name text struct _EAOP { // used by all EA functions void far *pGEAList; // pointer to GEAList structure void far *pFEAList; // pointer to FEAList structure unsigned long oError; } ; // offset of error, if any /* putEA: constructs and writes an extended attribute for a previously opened file. Called with the handle of the file, the extended attribute name, the EA value type, and the address and length of the EA value field data. Returns FALSE if extended attribute was written successfully. Returns -1 or OS/2 errcode if function failed. */ int putEA(int handle, char * eaname, void * eavalue, unsigned eavalsize, unsigned eatype) { struct _FEAList *pFEAList; // misc scratch variables struct _EA *pEA; // and pointers struct _EAval *pEAval; struct _EAOP EAOP; int errcode; pFEAList = malloc(FEALISTSIZE); // allocate buffer for FEAList if(pFEAList == NULL) return(-1); // bail out if no heap available EAOP.pFEAList = pFEAList; // initialize contents of EAOP.pGEAList = NULL; // EAOP pointer structure EAOP.oError = NULL; (char *) pEA = pFEAList->data; // point to EA header field pEA->flags = 0; // construct header portion pEA->nsize = strlen(eaname); // of extended attribute pEA->vsize = eavalsize + 4; strcpy(pEA->name, eaname); (char *) pEAval = // calculate address of pEA->name + pEA->nsize + 1; // EA's value field pEAval->type = eatype; // construct value portion pEAval->size = eavalsize; // of extended attribute memcpy(pEAval->data, eavalue, eavalsize); pFEAList->size = // calculate size of entire pEA->nsize + pEA->vsize + 9; // FEAList structure errcode = // set extended attributes DosSetFileInfo(handle, // file handle 2, // info level 2 = set EAs &EAOP, // EAOP structure holds pointer sizeof(EAOP)); // to FEAList containing EAs free(pFEAList); // release working buffer return(errcode); // return DosSetFileInfo status } /* getEA: fetches an extended attribute for a previously opened file. Returns FALSE if the extended attribute does not exist; otherwise, returns a pointer to the extended attribute value in a chunk of heap memory. The EA value is in the form of the EA type indicator, followed by the length of variable data, followed by the data itself. The exact format of the EA value is given by the structure _EAval. The caller must be sure to free the memory holding the extended attribute value after the value has been used or copied elsewhere. */ struct _EAval * getEA(int handle, char * eaname) { struct _FEAList *pFEAList = NULL; // misc scratch variables struct _GEAList *pGEAList = NULL; // and pointers struct _EA *pEA = NULL; struct _EAval *pEAval = NULL; struct _EAOP EAOP; pFEAList = malloc(FEALISTSIZE); // allocate buffers pGEAList = malloc(GEALISTSIZE); if((pFEAList == NULL) || (pGEAList == NULL)) goto errexit; // bail out if no heap EAOP.pFEAList = pFEAList; // initialize contents of EAOP.pGEAList = pGEAList; // EAOP pointer structure EAOP.oError = NULL; strcpy(pGEAList->GEA.name, eaname); // fill in EA name & length pGEAList->GEA.size = strlen(eaname); pFEAList->size = FEALISTSIZE; // fill in structure sizes pGEAList->size = pGEAList->GEA.size + 6; if(DosQFileInfo(handle, // get extended attribute 3, // info level 3 = get EA &EAOP, // EAOP struct holds pointers sizeof(EAOP))) // to GEAList and FEAList goto errexit; // exit if API function failed (char *) pEA = pFEAList->data; // point to EA header field if(pEA->vsize == 0) goto errexit; // exit if no EA value present if((pEAval = malloc(pEA->vsize)) // allocate space for EA value == NULL) goto errexit; // exit if heap is full // copy EA value to heap memcpy(pEAval, pEA->name + pEA->nsize + 1, pEA->vsize); free(pFEAList); // release working buffers free(pGEAList); return(pEAval); // return pointer to EA value errexit: // common exit point for errors if(pFEAList != NULL) free(pFEAList); if(pGEAList != NULL) free(pGEAList); return(NULL); // NULL pointer indicates error }