Logo Search packages:      
Sourcecode: udftools version File versions  Download package

wrudf-desc.c

/*    wrudf-desc.c  
 *
 * PURPOSE
 *    Routines to create/find/insert/delete FileIdentDesc's and FileEntries.
 *  
 * CONTACTS
 *    E-mail regarding this program to
 *          e.fennema@dataweb.nl
 *
 * COPYRIGHT
 *    This file is distributed under the terms of the GNU General Public
 *    License (GPL). Copies of the GPL can be obtained from:
 *          ftp://prep.ai.mit.edu/pub/gnu/GPL
 *
 *    (C) 2001 Enno Fennema
 *
 * HISTORY
 *    16 Aug 01  ef  Created.
 */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#include "wrudf.h"

/*    removeFID()
 *
 *    Physically remove a FileIdentDesc from the directory
 */
int
removeFID(Directory *dir, struct fileIdentDesc *fid) 
{
    uint32_t lenFID = (sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3;
    uint32_t lenMove;

    dir->fe.informationLength -= lenFID;
    lenMove = dir->fe.informationLength - ((uint8_t*)fid - dir->data);
    memcpy(fid, (uint8_t*)fid + lenFID, lenMove);
    dir->dirDirty = 1;
    return 0;
}

/*    deleteFID()
 *
 *    Remove an FID from the directory
 *    If fileLinkCount now zero, deallocate FileEntry and any data extents
 */
int 
deleteFID(Directory * dir, struct fileIdentDesc * fid)
{
    int           rv;
    struct fileEntry *fe;

    rv = CMND_OK;

//    if( fid->icb.extLocation.partitionReferenceNum != pd->partitionNumber )
//    return NOT_IN_RW_PARTITION;

    fe = readTaggedBlock(fid->icb.extLocation.logicalBlockNum, fid->icb.extLocation.partitionReferenceNum);

    /* check permission */

    freeBlock(fid->icb.extLocation.logicalBlockNum, fid->icb.extLocation.partitionReferenceNum);

    if( fe->fileLinkCount > 1 ) {
      fe->fileLinkCount--;
      setChecksum(fe);
      if( medium == CDRW ) 
          dirtyBlock(fid->icb.extLocation.logicalBlockNum, fid->icb.extLocation.partitionReferenceNum);
      else
          vat[fid->icb.extLocation.logicalBlockNum] = writeCDR(fe);
    } else {
      if( medium == CDR ) {
          if( fe->icbTag.fileType == ICBTAG_FILE_TYPE_DIRECTORY )
            dir->fe.fileLinkCount--;
          vat[fid->icb.extLocation.logicalBlockNum] = 0xFFFFFFFF; 
      } else {
          if( fe->icbTag.fileType == ICBTAG_FILE_TYPE_DIRECTORY ) {
            dir->fe.fileLinkCount--;
            ((struct logicalVolIntegrityDescImpUse*)
                (lvid->impUse + 2 * sizeof(uint32_t) * lvid->numOfPartitions))->numDirs--;
          } else {
            ((struct logicalVolIntegrityDescImpUse*)
                (lvid->impUse + 2 * sizeof(uint32_t) * lvid->numOfPartitions))->numFiles--;
          }

          /* free file data */
          switch( fe->icbTag.flags & ICBTAG_FLAG_AD_MASK ) {
          case ICBTAG_FLAG_AD_IN_ICB:
            break;
          case ICBTAG_FLAG_AD_SHORT:
            freeShortExtents((short_ad*)(fe->allocDescs + fe->lengthExtendedAttr));
            break;
          case ICBTAG_FLAG_AD_LONG:
            freeLongExtents((long_ad*)(fe->allocDescs + fe->lengthExtendedAttr));
            break;
          default:
            printf("UDF does not use Extended Alloc Descs\n");
            rv = CMND_FAILED;
          }
      /* free the File Entry itself */
      markBlock(FREE, fid->icb.extLocation.logicalBlockNum);
      }
    }

    removeFID(dir, fid);
    dir->dirDirty = 1;

    return rv;
}

struct fileIdentDesc* 
findFileIdentDesc(Directory *dir, char* name) 
{
    int                 i;
    uint8_t       *data;
    struct fileIdentDesc *fid;
    char                uName[256];
    int                 uLen;

    uLen = encode_utf8(uName, "", name, 256);

    data = dir->data;

    for( i = 0; i < dir->fe.informationLength; 
       i += (sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3 ) {

      fid = (struct fileIdentDesc*)(data + i);

      if( fid->descTag.tagIdent == TAG_IDENT_TE )
          return NULL;

      if( fid->descTag.tagIdent == TAG_IDENT_IE ) {
          printf("Indirect Entry not yet implemented\n");
          continue;
      }
      if( fid->descTag.tagIdent != TAG_IDENT_FID )
          fail("Unknown tag id %08X in directory\n", fid->descTag.tagIdent);

      // check CRC

      if( fid->fileCharacteristics == FID_FILE_CHAR_PARENT)
          continue;

      if( fid->lengthFileIdent == uLen
          && memcmp( fid->fileIdent, uName, fid->lengthFileIdent) == 0 )
          return fid;
    }
    return NULL;
}


/*
 *    Return pointer to new FileEntry in a 2k allocated block to be free'd when no longer required.
 *    Only basic data is filled in. 
 */
struct fileEntry* 
makeFileEntry() 
{
    struct fileEntry *fe = (struct fileEntry*) calloc(2048, 1);

    updateTimestamp(0,0);
    fe->descTag.tagIdent = TAG_IDENT_FE;
    fe->descTag.descVersion = 2;
    fe->descTag.tagSerialNum = lvd->descTag.tagSerialNum;
    fe->icbTag.strategyType = 4;
    fe->icbTag.numEntries = 1;
    fe->icbTag.fileType = ICBTAG_FILE_TYPE_REGULAR;
    /* User has all permission; Group/Others Read/Exec */
    fe->permissions = FE_PERM_U_READ | FE_PERM_U_WRITE | FE_PERM_U_DELETE | FE_PERM_U_CHATTR | FE_PERM_U_EXEC |
      FE_PERM_G_READ | FE_PERM_G_EXEC | FE_PERM_O_READ | FE_PERM_O_EXEC;
    fe->fileLinkCount = 1;
    fe->accessTime = timeStamp;
    fe->modificationTime = timeStamp;
    fe->attrTime = timeStamp;
    fe->impIdent = entityWRUDF;
    fe->uniqueID = ((struct logicalVolHeaderDesc*)lvid->logicalVolContentsUse)->uniqueID++;
    return fe;
}


/*
 *    Return pointer to new FileIdentDesc in an allocated block to be free'd when no longer required.
 *    Does NOT fill: descTag.checksum, descTag.tagLocation, icbTag.characteristics, icb
 */
struct fileIdentDesc*
makeFileIdentDesc(char* name) 
{
    char uName[256];
    int uLen;
    struct fileIdentDesc *fid;

    fid = (struct fileIdentDesc*) calloc(512,1);
    fid->descTag.tagIdent = TAG_IDENT_FID;
    fid->descTag.descVersion = 2;
    fid->descTag.tagSerialNum = lvd->descTag.tagSerialNum;
    fid->fileVersionNum = 1;
    fid->icb.extLength = 2048;

    if( name[0] != 0 ) {                        /* FID to parent directory has no name */
      memset(&uName, 0, 256);
        uLen = encode_utf8(uName, "", name, 256);
      fid->lengthFileIdent = uLen;
      memcpy(fid->fileIdent + fid->lengthOfImpUse, uName, fid->lengthFileIdent);
    }
    return fid;
} 


int 
insertFileIdentDesc(Directory *dir, struct fileIdentDesc* fid) 
{
    uint32_t            lenFid;
    
    lenFid = (sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3;
    fid->descTag.descCRCLength = lenFid - sizeof(tag);
    setChecksum(fid);

    if( dir->fe.informationLength + lenFid > dir->dataSize ) {
      if( !(dir->data = realloc(dir->data, dir->dataSize + 2048)) ) {
          fail("Realloc directory data failed\n");
      }
      dir->dataSize += 2048;
    }
    
    memcpy(dir->data + dir->fe.informationLength, fid, lenFid);
    dir->fe.informationLength += lenFid;
    dir->dirDirty = 1;
    return CMND_OK;
}

Generated by  Doxygen 1.6.0   Back to index