Esempio n. 1
0
/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  MFS_Write_back_directory_sector_buffer
* Returned Value   :  MFS error code
* Comments  :
*   Write the sector buffer back to the disk.
*   Assumes the semaphore is already obtained.
*END*---------------------------------------------------------------------*/
_mfs_error MFS_Write_back_directory_sector_buffer
    (
    MFS_DRIVE_STRUCT_PTR  drive_ptr
    )
{
#if MFSCFG_READ_ONLY
    return MFS_NO_ERROR;
#else
    _mfs_error   error_code = MFS_NO_ERROR;

#if MFSCFG_READ_ONLY_CHECK
    if (MFS_is_read_only (NULL, drive_ptr))
    {
        return error_code;
    }
#endif

    MFS_LOG(printf("MFS_Write_back_directory_sector_buffer"));
    drive_ptr->DIR_SECTOR_DIRTY = TRUE;
    if ( drive_ptr->WRITE_CACHE_POLICY==MFS_WRITE_THROUGH_CACHE )
    {
        error_code = MFS_Flush_directory_sector_buffer(drive_ptr);
    }

    return(error_code);
#endif

}  
Esempio n. 2
0
_mfs_error MFS_Read_fat
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,
    uint_32                 offset      /*[IN] the offset byte in the FAT that we are looking for */
    )
{
    uint_32     needed_sector,needed_end_sector,i;
    _mfs_error  error_code;

    error_code = MFS_NO_ERROR;
    needed_sector = offset / drive_ptr->BPB.SECTOR_SIZE;

    MFS_LOG(printf("\nRead fat: Offset = %d\n", offset));

    if ( drive_ptr->FAT_TYPE == MFS_FAT12 ) 
    {
       needed_end_sector = (offset+1)/ drive_ptr->BPB.SECTOR_SIZE;
    } 
    else 
    {
       needed_end_sector = needed_sector;
    }


    /*
    ** If the FAT fragment that we already have in memory is requested, do
    ** not update or re-read it.
    */
    if ( (needed_sector < drive_ptr->FAT_CACHE_START) || (needed_end_sector  > drive_ptr->FAT_CACHE_START + drive_ptr->FAT_CACHE_SIZE - 1) )
    {
        error_code = MFS_Flush_fat_cache(drive_ptr);
        if ( error_code )
        {
            return(error_code);
        }

        if ( drive_ptr->FAT_TYPE == MFS_FAT32 )
        {
            if ( needed_sector > (drive_ptr->BPB32.FAT_SIZE - drive_ptr->FAT_CACHE_SIZE) )
            {
                needed_sector = drive_ptr->BPB32.FAT_SIZE - drive_ptr->FAT_CACHE_SIZE;
            }
        }
        else
        {
            if ( needed_sector > (drive_ptr->BPB.SECTORS_PER_FAT - drive_ptr->FAT_CACHE_SIZE) )
            {
                needed_sector = drive_ptr->BPB.SECTORS_PER_FAT -  drive_ptr->FAT_CACHE_SIZE;
            }
        }

        for ( i=0;i<(drive_ptr->FAT_CACHE_SIZE) && (error_code==MFS_NO_ERROR);i++ )
        {
            error_code = MFS_Read_device_sector (drive_ptr, drive_ptr->FAT_START_SECTOR + needed_sector + i,
                (pointer) &drive_ptr->FAT_CACHE_PTR[drive_ptr->BPB.SECTOR_SIZE*i]);
        }

        if ( error_code == MFS_NO_ERROR )
        {
            drive_ptr->FAT_CACHE_START = needed_sector;
            drive_ptr->FAT_CACHE_DIRTY = FALSE;
        }
    }

    return(error_code);
}  
Esempio n. 3
0
/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  MFS_Write_device_sector
* Returned Value   :  error_code
* Comments  :
*     Reads or writes consecutive clusters.
*END*---------------------------------------------------------------------*/
_mfs_error MFS_Write_device_sector
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,
    uint_32                 sector_number,  /*[IN] sector number to read/write from/to file system medium */
    char_ptr                buffer_ptr      /*[IN/OUT] address of where data is to be stored/written */
    )
{
    uint_32    new_cluster_number, next_cluster, bad_cluster_number;
    uint_32    i;
    uint_32    retries, attempts;
    uint_32    new_sector_number, no_of_sectors;
    char_ptr   temp_buffer_ptr;
    int_32     num, expect_num, shifter, seek_loc, tmp;
    _mfs_error error;

#if MFSCFG_READ_ONLY_CHECK
    if (MFS_is_read_only (NULL, drive_ptr))
    {
        return MFS_DISK_IS_WRITE_PROTECTED;
    }
#endif

    error = MFS_NO_ERROR;

    MFS_LOG(printf("MFS_Write_device_sector %d\n", sector_number));

    if ( sector_number > drive_ptr->BPB.MEGA_SECTORS )
    {
        return(MFS_SECTOR_NOT_FOUND);
    }

    attempts = 0;
    /* Lock device */
    ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_LOCK, &drive_ptr->DRV_NUM);

    if ( drive_ptr->BLOCK_MODE )
    {
        shifter    = 0;
        seek_loc   = sector_number;
        expect_num = 1;
    }
    else
    {
        shifter    = drive_ptr->SECTOR_POWER;
        seek_loc   = sector_number << shifter;
        expect_num = 1 << shifter;
    }  

    MFS_device_write_internal(drive_ptr, seek_loc, buffer_ptr, &expect_num,  &buffer_ptr, shifter);

    if ( expect_num > 0 )
    {
        error = drive_ptr->DEV_FILE_PTR->ERROR;
#if MFSCFG_MAX_CLUSTER_REMAP_ATTEMPTS
        /*
        ** Check to see if the write failed due to a bad sector. If so, 
        ** rewrite cluster by cluster until we find bad cluster, then move 
        ** it.
        */
        temp_buffer_ptr = buffer_ptr;
        if ( drive_ptr->BLOCK_MODE )
        {
            expect_num = drive_ptr->BPB.SECTORS_PER_CLUSTER;
        }
        else
        {
            expect_num = drive_ptr->CLUSTER_SIZE_BYTES;
        }  
        tmp = expect_num;

        for ( i = 0; i < no_of_clusters; i++ )
        {
            MFS_device_write_internal(drive_ptr, seek_loc, temp_buffer_ptr, &expect_num, &buffer_ptr, shifter);

            if ( expect_num > 0 )
            {
                error_code = drive_ptr->DEV_FILE_PTR->ERROR;
                ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_UNLOCK, &drive_ptr->DRV_NUM);
                bad_cluster_number = cluster_number + i;
                error_code = MFS_get_cluster_from_fat(drive_ptr, bad_cluster_number, &next_cluster);
                if ( error_code != MFS_NO_ERROR )
                {
                    /* 
                    ** This is done so that the unlock at end of function
                    ** works properly
                    */
                    ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_LOCK, &drive_ptr->DRV_NUM);
                    break;
                }

                retries = MFSCFG_MAX_CLUSTER_REMAP_ATTEMPTS;

                while ( (error_code != MFS_NO_ERROR) && retries-- )
                {
                    /*
                    ** Mark old cluster BAD 
                    */
                    error_code = MFS_Put_fat(drive_ptr, bad_cluster_number, CLUSTER_BAD);
                    if ( error_code )
                    {
                        break;
                    }

                    /*
                    ** Find available fat, update old FAT as invalid, 
                    ** update new fat, and write new cluster.
                    */
                    new_cluster_number = MFS_Find_unused_cluster_from(drive_ptr, bad_cluster_number);
                    if ( new_cluster_number ==  CLUSTER_INVALID )
                    {
                        /*
                        ** No more clusters
                        */
                        return MFS_DISK_FULL;
                    }

                    new_sector_number = drive_ptr->DATA_START_SECTOR + ((uint_32)(new_cluster_number - CLUSTER_MIN_GOOD)) * drive_ptr->BPB.SECTORS_PER_CLUSTER;

                    ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_LOCK, &drive_ptr->DRV_NUM);

                    expect_num = tmp;

                    MFS_device_write_internal(drive_ptr, new_sector_number << shifter, temp_buffer_ptr, &expect_num, &buffer_ptr, shifter);

                    if ( expect_num > 0 )
                    {
                        error_code = drive_ptr->DEV_FILE_PTR->ERROR;
                    }

                    ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_UNLOCK, &(drive_ptr->DRV_NUM));
                    bad_cluster_number = new_cluster_number;
                }  

                if ( error_code != MFS_NO_ERROR )
                {
                    return MFS_WRITE_FAULT;
                }

                /*
                ** update chain, 
                */
                error_code = MFS_Put_fat(drive_ptr, new_cluster_number, next_cluster);
                if ( error_code )
                {
                    return(error_code);
                }

                if ( handle->PREVIOUS_CLUSTER )
                {
                    error_code = MFS_Put_fat(drive_ptr,handle->PREVIOUS_CLUSTER, new_cluster_number );
                    if ( error_code )
                    {
                        return(error_code);
                    }
                }
                else
                {
                    clustod(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER, new_cluster_number);
                }  
                handle->PREVIOUS_CLUSTER = new_cluster_number;
                ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_LOCK, &drive_ptr->DRV_NUM);
            }
            else
            {
                handle->PREVIOUS_CLUSTER = cluster_number+i;
            }  
            temp_buffer_ptr += drive_ptr->CLUSTER_SIZE_BYTES;
            sector_number   += drive_ptr->BPB.SECTORS_PER_CLUSTER;
        }  
#endif
    }

    /* Unlock device under MFS */
    ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_UNLOCK, &drive_ptr->DRV_NUM);

    switch ( error )
    {
        case IO_ERROR_WRITE_PROTECTED:
            error = MFS_DISK_IS_WRITE_PROTECTED;
            break;

        case IO_ERROR_WRITE:
            error = MFS_WRITE_FAULT;
            break;

        case IO_ERROR_WRITE_ACCESS:
            error = MFS_SECTOR_NOT_FOUND;
            break;

        case IO_ERROR_READ:
            error = MFS_READ_FAULT;
            break;

        case IO_ERROR_READ_ACCESS:
            error = MFS_SECTOR_NOT_FOUND;
            break;

        default:
            break;
    }  

    return(error);
}  
Esempio n. 4
0
/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  MFS_Read_device_sector
* Returned Value   :  error_code
* Comments  :
*     Readsone sector into the DATA_SECTOR buffer
*END*---------------------------------------------------------------------*/
_mfs_error MFS_Read_device_sector
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,
    uint_32                 sector_number,  /*[IN] sector number to read/write from/to file system medium */
    char_ptr               sector_ptr
    )
{
    uint_32    new_cluster_number, next_cluster, bad_cluster_number;
    uint_32    i;
    uint_32    retries, attempts;
    uint_32    new_sector_number, error_code, no_of_sectors;
    char_ptr   temp_buffer_ptr;
    int_32     num, expect_num, shifter, seek_loc, tmp;
    _mfs_error error;

    error = MFS_NO_ERROR;

    if ( sector_number > drive_ptr->BPB.MEGA_SECTORS )
    {
        return(MFS_SECTOR_NOT_FOUND);
    }

    MFS_LOG(printf("MFS_Read_device_sector %d", sector_number));

    attempts = 0;
    /* Lock device */
    ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_LOCK, &drive_ptr->DRV_NUM);

    if ( drive_ptr->BLOCK_MODE )
    {
        shifter    = 0;
        seek_loc   = sector_number;
        expect_num = 1;
    }
    else
    {
        shifter    = drive_ptr->SECTOR_POWER;
        seek_loc   = sector_number << shifter;
        expect_num = 1 << shifter;
    }  

    fseek(drive_ptr->DEV_FILE_PTR, seek_loc, IO_SEEK_SET);

    while ( expect_num > 0 && attempts++ < MFSCFG_MAX_READ_RETRIES )
    {
        num = read(drive_ptr->DEV_FILE_PTR, sector_ptr, expect_num);
        if ( num == IO_ERROR )
        {
            break;
        }
        expect_num -= num;
        sector_ptr += num << shifter;
    }  

    if ( expect_num > 0 )
    {
        error = drive_ptr->DEV_FILE_PTR->ERROR;
    }

    /* Unlock device under MFS */
    ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_UNLOCK, &drive_ptr->DRV_NUM);

    if ( error == IO_ERROR_READ )
    {
        error = MFS_READ_FAULT;
    }
    else if ( error == IO_ERROR_READ_ACCESS )
    {
        error = MFS_SECTOR_NOT_FOUND;
    }

    return error;
}  
Esempio n. 5
0
uint32_t MFS_Move_file_pointer
    (
    MFS_HANDLE_PTR          handle,
    MFS_DRIVE_STRUCT_PTR    drive_ptr,
    _mfs_error_ptr          error_ptr /*[IN/OUT] resulting error code is written to this address*/
    )
{
    uint32_t                 position_after_seek, position_before_seek;
    uint32_t                 current_cluster,
                            previous_cluster,
                            first_cluster,
                            skip_clusters,
                            k;
    _mfs_error              error_code;


    error_code = MFS_lock_dos_disk( drive_ptr );
    if ( error_code != MFS_NO_ERROR )
    {
        if ( error_ptr != NULL )
        {
            *error_ptr = error_code;
        }
        return 0;
    }

    position_after_seek = handle->LOCATION;

    MFS_LOG(printf("seek to %d\n",position_after_seek));

    /*
    ** Cannot move ahead of the beginning of the file; force beginning.
    */
    if ( error_code == MFS_NO_ERROR )
    {

        /*
        ** There are four cases
        **
        ** 1) Seeking to beginning of file (position_after_seek=0, cluster=0)
        ** 2) No change in position (position_after_seek==position_before_seek)
        ** 2) Seeking ahead of current file pointer
        ** 3) Seeking behind current file pointer
        */
        /*
        ** Cannot move beyond the end of file !
        */
        if ( position_after_seek> mqx_dtohl(handle->DIR_ENTRY.FILE_SIZE) )     // + 1
        {
            position_after_seek = mqx_dtohl(handle->DIR_ENTRY.FILE_SIZE);  //  - 1
            error_code = MFS_EOF;
        }

        current_cluster = 0;
        previous_cluster = 0;
        first_cluster = clustoh(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER);
        MFS_LOG(printf("first_cluster =  %d\n",first_cluster));

        /*
        ** Set the current_cluster correctly.
        ** If we're moving ahead, don't start from the beginning.
        */
        position_before_seek = CLUSTER_BOUNDARY(handle->SAVED_POSITION);

        if ( handle->CURRENT_CLUSTER==0 )
        {
            handle->CURRENT_CLUSTER = first_cluster;
            handle->PREVIOUS_CLUSTER = 0;
            position_before_seek = 0;
        }

        if ( position_after_seek == 0 )
        {
            current_cluster = first_cluster;
            previous_cluster = 0;
        }
        else if ( position_after_seek == position_before_seek )
        {
            current_cluster  = handle->CURRENT_CLUSTER;
            previous_cluster = handle->PREVIOUS_CLUSTER;
        }
        else
        {
            if ( position_after_seek < position_before_seek )
            {
                position_before_seek = 0;
                current_cluster = first_cluster;
                previous_cluster = 0;
            }
            else
            {
                current_cluster  = handle->CURRENT_CLUSTER;
                previous_cluster = handle->PREVIOUS_CLUSTER;
            }  

            MFS_LOG(printf("current cluster =  %d\n",current_cluster));

            if ( current_cluster && (current_cluster!=CLUSTER_EOF) )
            {
                /*
                ** How many clusters do we need to skip?
                */
                skip_clusters = (position_after_seek - position_before_seek) >> drive_ptr->CLUSTER_POWER_BYTES;
                for ( k = 0; k < skip_clusters; k++ )
                {
                    previous_cluster = current_cluster;

                    error_code = MFS_get_cluster_from_fat(drive_ptr, previous_cluster, &current_cluster);
                    if ( error_code != MFS_NO_ERROR )
                    {
                        break;
                    }
                    if ( current_cluster==CLUSTER_EOF )
                    {
                        error_code = MFS_EOF;
                        break;
                    }
                    else if ( (current_cluster < CLUSTER_MIN_GOOD) || (current_cluster > drive_ptr->LAST_CLUSTER) )
                    {
                        error_code = MFS_BAD_DISK_UNIT;
                        break;
                    }
                    MFS_LOG(printf("skip, current cluster =  %d\n",current_cluster));
                }  
            }
            else
            {
                error_code = MFS_EOF;
            }
        }  
Esempio n. 6
0
/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  MFS_Write_device_sectors
* Returned Value   :  error_code
* Comments  :
*     Reads or writes consecutive sectors.
*END*---------------------------------------------------------------------*/
_mfs_error MFS_Write_device_sectors
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,
    uint_32                 sector_number,  /*[IN] first sector to read/write from/to file system medium */
    uint_32                 sector_count,   /*[IN] number of sectors to read/write from/to file system medium */
    uint_32                 max_retries,    /*[IN] number of retries of the same low level operation if it fails */ 
    char_ptr                buffer_ptr,     /*[IN/OUT] address of where data is to be stored/written */
    uint_32_ptr             processed       /*[OUT] number of sector successfully processed */
    )
{
    uint_32    attempts;
    int_32     num, expect_num, seek_loc, shifter;
    char_ptr   data_ptr;
    _mfs_error error;

#if MFSCFG_READ_ONLY_CHECK
    if (MFS_is_read_only (NULL, drive_ptr))
    {
        return MFS_DISK_IS_WRITE_PROTECTED;
    }
#endif

    error = MFS_NO_ERROR;

    MFS_LOG(printf("MFS_Write_device_sector %d\n", sector_number));

    if ( sector_number > drive_ptr->BPB.MEGA_SECTORS )
    {
        return(MFS_SECTOR_NOT_FOUND);
    }

    if ( drive_ptr->BLOCK_MODE )
    {
        shifter    = 0;
        seek_loc   = sector_number;
        expect_num = sector_count;
    }
    else
    {
        shifter    = drive_ptr->SECTOR_POWER;
        seek_loc   = sector_number << shifter;
        expect_num = sector_count << shifter;
    }  

    fseek(drive_ptr->DEV_FILE_PTR, seek_loc, IO_SEEK_SET);

    data_ptr = buffer_ptr;
    attempts = 0;
    while ( expect_num > 0 && attempts <= max_retries)
    {
        num = write(drive_ptr->DEV_FILE_PTR, data_ptr, expect_num);
        if ( num == IO_ERROR )
        {
            error = IO_ERROR_WRITE;
            break;
        }
        if ( num > 0 )
        {
            expect_num -= num;
            data_ptr += num << (drive_ptr->SECTOR_POWER - shifter);
            attempts = 0; /* there is a progress, reset attempts counter */
        }
        attempts++;
    }  

    if ( expect_num > 0 )
    {
        error = drive_ptr->DEV_FILE_PTR->ERROR;
    }
    else if (drive_ptr->READBACK_SECTOR_PTR) 
    {
        fseek(drive_ptr->DEV_FILE_PTR, seek_loc, IO_SEEK_SET);
        
        data_ptr = buffer_ptr;        
        expect_num = sector_count << shifter;
        while ( expect_num > 0 )
        {
            num = read(drive_ptr->DEV_FILE_PTR, drive_ptr->READBACK_SECTOR_PTR, 1<<shifter);
            if ( num != (1<<shifter) )
            {
                error = drive_ptr->DEV_FILE_PTR->ERROR;
                break;
            } 
            if ( memcmp(data_ptr, drive_ptr->READBACK_SECTOR_PTR, drive_ptr->BPB.SECTOR_SIZE) != 0 ) 
            {
                error = IO_ERROR_WRITE;
                break;
            }
            expect_num -= num;
            data_ptr += num << (drive_ptr->SECTOR_POWER - shifter);
        }
    }    
    
    switch ( error )
    {
        case IO_ERROR_WRITE_PROTECTED:
            error = MFS_DISK_IS_WRITE_PROTECTED;
            break;

        case IO_ERROR_WRITE:
            error = MFS_WRITE_FAULT;
            break;

        case IO_ERROR_WRITE_ACCESS:
            error = MFS_SECTOR_NOT_FOUND;
            break;

        case IO_ERROR_READ:
            error = MFS_READ_FAULT;
            break;

        case IO_ERROR_READ_ACCESS:
            error = MFS_SECTOR_NOT_FOUND;
            break;

        case MFS_NO_ERROR:
            /* Ensure that error code is always set if less than requested data was written */
            if ( expect_num > 0 ) error = MFS_WRITE_FAULT;
            break;

        default:
            break;
    }  

    if (processed)
        *processed = ((sector_count<<shifter) - expect_num) >> shifter;  
        
    return error;
}  
Esempio n. 7
0
/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  MFS_Read_device_sectors
* Returned Value   :  error_code
* Comments  :
*     Reads consecutive sectors into given buffer
*END*---------------------------------------------------------------------*/
_mfs_error MFS_Read_device_sectors
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,
    uint_32                 sector_number,  /*[IN] first sector to read/write from/to file system medium */
    uint_32                 sector_count,   /*[IN] number of sectors to read/write from/to file system medium */
    uint_32                 max_retries,    /*[IN] number of retries of the same low level operation if it fails */ 
    char_ptr                buffer_ptr,     /*[IN/OUT] address of where data is to be stored/written */          
    uint_32_ptr             processed       /*[OUT] number of sector successfully processed */
    )
{
    uint_32    attempts;
    int_32     num, expect_num, shifter, seek_loc;
    _mfs_error error;

    error = MFS_NO_ERROR;

    if ( sector_number+sector_count-1 > drive_ptr->BPB.MEGA_SECTORS )
    {
        return(MFS_SECTOR_NOT_FOUND);
    }

    MFS_LOG(printf("MFS_Read_device_sectors %d %d", sector_number, sector_count));

    if ( drive_ptr->BLOCK_MODE )
    {
        shifter    = 0;
        seek_loc   = sector_number;
        expect_num = sector_count;
    }
    else
    {
        shifter    = drive_ptr->SECTOR_POWER;
        seek_loc   = sector_number << shifter;
        expect_num = sector_count << shifter;
    }  

    fseek(drive_ptr->DEV_FILE_PTR, seek_loc, IO_SEEK_SET);

    attempts = 0;
    while ( expect_num > 0 && attempts <= max_retries )
    {
        num = read(drive_ptr->DEV_FILE_PTR, buffer_ptr, expect_num);
        if ( num == IO_ERROR )
        {
            error = IO_ERROR_READ;
            break;
        }
        if ( num > 0 )
        {
            expect_num -= num;
            buffer_ptr += num << (drive_ptr->SECTOR_POWER - shifter);
            attempts = 0; /* there is a progress, reset attempts counter */
        }
        attempts++;
    }  

    if ( expect_num > 0 )
    {
        error = drive_ptr->DEV_FILE_PTR->ERROR;
    }

    if ( error == IO_ERROR_READ )
    {
        error = MFS_READ_FAULT;
    }
    else if ( error == IO_ERROR_READ_ACCESS )
    {
        error = MFS_SECTOR_NOT_FOUND;
    }
    else if ( (error == MFS_NO_ERROR) && (expect_num > 0) )
    {
        /* Ensure that error code is always set if less than requested data was read */
        error = MFS_READ_FAULT;
    }

    if (processed)
        *processed = ((sector_count<<shifter) - expect_num) >> shifter;  

    return error;
}