Ian C. Wong

22 papers B 5Misc 2Journal 8Unranked 6
YearRankTypeTitle / Venue / Authors
2024 conf
CAMAD
Ali Saeizadeh, Miead Tehrani Moayyed, Davide Villa, J. Gordon Beattie, Ian C. Wong, Pedram Johari, Eric W. Anderson, Stefano Basagni, Tommaso Melodia
2017 J jnl
IEEE Access
Steffen Malkowsky, Joao Vieira, Liang Liu, Paul Harris, Karl Nieman, Nikhil Kundargi, Ian C. Wong, Fredrik Tufvesson, Viktor Öwall, Ove Edfors
2017 J jnl
CoRR
Steffen Malkowsky, Joao Vieira, Liang Liu, Paul Harris, Karl Nieman, Nikhil Kundargi, Ian C. Wong, Fredrik Tufvesson, Viktor Öwall, Ove Edfors
2016 J jnl
CoRR
Xi Yang, Wen-Jun Lu, Ning Wang, Karl Nieman, Shi Jin, Hongbo Zhu, Xiaomin Mu, Ian C. Wong, Yongming Huang, Xiaohu You
2016 conf
SiPS
Steffen Malkowsky, Joao Vieira, Karl Nieman, Nikhil Kundargi, Ian C. Wong, Viktor Öwall, Ove Edfors, Fredrik Tufvesson, Liang Liu
2014 conf
GLOBECOM Workshops
Joao Vieira, Steffen Malkowsky, Karl Nieman, Zachary Miers, Nikhil Kundargi, Liang Liu, Ian C. Wong, Viktor Öwall, Ove Edfors, Fredrik Tufvesson
2014 ch.
Embedded Systems Development, From Functional Models to Implementations
Kaushik Ravindran, Arkadeb Ghosal, Rhishikesh Limaye, Douglas Kim, Hugo A. Andrade, Jeff Correll, Jacob Kornerup, Ian C. Wong, Gerald Wang, Guang Yang, Amal Ekbal, Mike Trimborn, Ankita Prasad, Trung N. Tran
2012 J jnl
J. Signal Process. Syst.
Hojin Kee, Chung-Ching Shen, Shuvra S. Bhattacharyya, Ian C. Wong, Yong Rao, Jacob Kornerup
2011 Misc conf
CODES+ISSS
Stavros Tripakis, Hugo A. Andrade, Arkadeb Ghosal, Rhishikesh Limaye, Kaushik Ravindran, Guoqiang Wang, Guang Yang, Jacob Kornerup, Ian C. Wong
2010 Misc conf
ICASSP
Hojin Kee, Shuvra S. Bhattacharyya, Ian C. Wong, Yong Rao
2009 J jnl
IEEE Trans. Commun.
Ian C. Wong, Brian L. Evans
2009 J jnl
IEEE Trans. Wirel. Commun.
Oghenekome Oteri, Ian C. Wong, Wes McCoy
2008 conf
ACSCC
Ian C. Wong, Brian L. Evans
2008 J jnl
IEEE Trans. Wirel. Commun.
Ian C. Wong, Brian L. Evans
2008 J jnl
IEEE Trans. Signal Process.
Ian C. Wong, Brian L. Evans
2007 B conf
GLOBECOM
Ian C. Wong, Brian L. Evans
2007 B conf
GLOBECOM
Ian C. Wong, Brian L. Evans
2007 conf
ICASSP (3)
Ian C. Wong, Brian L. Evans
2007 conf
ICASSP (3)
Ian C. Wong, Brian L. Evans
2006 B conf
GLOBECOM
Ian C. Wong, Brian L. Evans
2006 B conf
GLOBECOM
Ian C. Wong, Brian L. Evans
2005 B conf
GLOBECOM
Ian C. Wong, Brian L. Evans
redb/s3_utils.py
← Index redb/s3_utils.py python
"""
S3 and file utility functions for REDB.

Contains MinIO/S3 client creation, S3 key generation,
file download, and archive extraction helpers.
"""
import os
import tempfile
from typing import Optional, List

from minio import Minio
from minio.error import S3Error


def get_minio_client():
    """Create and return a Minio client using credentials from .env file"""
    return Minio(
        endpoint=os.getenv("S3_ENDPOINT"),
        access_key=os.getenv("S3_ACCESS_KEY"),
        secret_key=os.getenv("S3_SECRET_KEY"),
        secure=os.getenv("S3_SECURE", "false").lower() == "true"
    )


def generate_s3_key_from_hash(sample_hash: str) -> str:
    """
    Generate S3 key from hash using sharding structure.
    Example: 09f7d02a3c2382199458c98a62b045145ee54ab6aba86166aecf3d10c3c1444c
    becomes: 09/f7/09f7d02a3c2382199458c98a62b045145ee54ab6aba86166aecf3d10c3c1444c.zip
    """
    if len(sample_hash) < 4:
        raise ValueError(f"Hash too short for sharding: {sample_hash}")

    # Create sharded path: first 2 chars / next 2 chars / full_hash.zip
    return f"{sample_hash[:2]}/{sample_hash[2:4]}/{sample_hash}.zip"


def download_s3_object(s3_bucket: str, s3_key: str, temp_dir: str, logger=None) -> Optional[str]:
    """
    Download an object from S3 to a local temporary directory and return the local path.
    If the .zip file is not found, automatically tries .7z as a fallback for legacy uploads.
    """
    try:
        minio_client = get_minio_client()
        local_path = os.path.join(temp_dir, os.path.basename(s3_key))

        # Download the file
        minio_client.fget_object(s3_bucket, s3_key, local_path)

        return local_path
    except S3Error as e:
        # If .zip not found and error is NoSuchKey, try .7z fallback
        if e.code == 'NoSuchKey' and s3_key.endswith('.zip'):
            s3_key_7z = s3_key[:-4] + '.7z'  # Replace .zip with .7z
            if logger:
                logger.info(f".zip not found, trying .7z fallback: {s3_key_7z}")
            try:
                local_path_7z = os.path.join(temp_dir, os.path.basename(s3_key_7z))
                minio_client.fget_object(s3_bucket, s3_key_7z, local_path_7z)
                if logger:
                    logger.info(f"Successfully downloaded .7z fallback: {s3_key_7z}")
                return local_path_7z
            except S3Error as e2:
                if logger:
                    logger.error(f"Failed to download S3 object {s3_key} (tried both .zip and .7z): {e2}")
                else:
                    print(f"[ERROR] Failed to download S3 object {s3_key} (tried both .zip and .7z): {e2}")
                return None
        else:
            if logger:
                logger.error(f"Failed to download S3 object {s3_key}: {e}")
            else:
                print(f"[ERROR] Failed to download S3 object {s3_key}: {e}")
            return None


def extract_fat_slices(macho, output_dir: str, logger) -> List[tuple]:
    """
    Extract slices from FAT Mach-O binary using machofile's dump_slices() API.

    Args:
        macho: Parsed machofile.UniversalMachO object
        output_dir: Directory to write slice files
        logger: Logger instance

    Returns:
        List of (arch_name, slice_path, slice_sha256, slice_md5, slice_sha1) tuples
    """
    result = []
    try:
        # Use machofile's dump_slices API (v2026.2.5+)
        slices = macho.dump_slices(output_dir=output_dir)
        logger.debug(f"Extracted {len(slices)} slices from FAT binary")

        for arch_name, slice_path in slices:
            # Get hash info for this slice from machofile
            general_info = macho.get_general_info(arch=arch_name)
            slice_sha256 = general_info.get('SHA256')
            slice_md5 = general_info.get('MD5')
            slice_sha1 = general_info.get('SHA1')
            result.append((arch_name, slice_path, slice_sha256, slice_md5, slice_sha1))
            logger.debug(f"Slice {arch_name}: {slice_sha256}")

    except Exception as e:
        logger.error(f"Error extracting FAT slices: {e}")

    return result