Example #1
0
static uint8_t
ntfs_dent_copy(NTFS_INFO * ntfs, ntfs_idxentry * idxe,
    TSK_FS_NAME * fs_name)
{
    ntfs_attr_fname *fname = (ntfs_attr_fname *) & idxe->stream;
    TSK_FS_INFO *fs = (TSK_FS_INFO *) & ntfs->fs_info;
    UTF16 *name16;
    UTF8 *name8;
    int retVal;
    int i;

    fs_name->meta_addr = tsk_getu48(fs->endian, idxe->file_ref);
    fs_name->meta_seq = tsk_getu16(fs->endian, idxe->seq_num);

    name16 = (UTF16 *) & fname->name;
    name8 = (UTF8 *) fs_name->name;

    retVal = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &name16,
        (UTF16 *) ((uintptr_t) name16 +
            fname->nlen * 2), &name8,
        (UTF8 *) ((uintptr_t) name8 +
            fs_name->name_size), TSKlenientConversion);

    if (retVal != TSKconversionOK) {
        *name8 = '\0';
        if (tsk_verbose)
            tsk_fprintf(stderr,
                "Error converting NTFS name to UTF8: %d %" PRIuINUM,
                retVal, fs_name->meta_addr);
    }

    /* Make sure it is NULL Terminated */
    if ((uintptr_t) name8 > (uintptr_t) fs_name->name + fs_name->name_size)
        fs_name->name[fs_name->name_size] = '\0';
    else
        *name8 = '\0';

    /* Clean up name */
    i = 0;
    while (fs_name->name[i] != '\0') {
        if (TSK_IS_CNTRL(fs_name->name[i]))
            fs_name->name[i] = '^';
        i++;
    }

    if (tsk_getu64(fs->endian, fname->flags) & NTFS_FNAME_FLAGS_DIR)
        fs_name->type = TSK_FS_NAME_TYPE_DIR;
    else
        fs_name->type = TSK_FS_NAME_TYPE_REG;

    fs_name->flags = 0;

    return 0;
}
Example #2
0
/* 
 *
 * NoTe that this does not set the flag value.
 *
 * return 1 on error and 0 on success */
static uint8_t
ext2fs_dent_copy(EXT2FS_INFO * ext2fs, EXT2FS_DINFO * dinfo,
    char *ext2_dent, TSK_FS_DENT * fs_dent)
{
    TSK_FS_INFO *fs = &(ext2fs->fs_info);
    int i;

    if (ext2fs->deentry_type == EXT2_DE_V1) {
        ext2fs_dentry1 *dir = (ext2fs_dentry1 *) ext2_dent;

        fs_dent->inode = tsk_getu32(fs->endian, dir->inode);

        /* ext2 does not null terminate */
        if (tsk_getu16(fs->endian, dir->name_len) >= fs_dent->name_max) {
            tsk_error_reset();
            tsk_errno = TSK_ERR_FS_ARG;
            snprintf(tsk_errstr, TSK_ERRSTR_L,
                "ext2fs_dent_copy: Name Space too Small %d %lu",
                tsk_getu16(fs->endian, dir->name_len), fs_dent->name_max);
            return 1;
        }

        /* Copy and Null Terminate */
        strncpy(fs_dent->name, dir->name, tsk_getu16(fs->endian,
                dir->name_len));
        fs_dent->name[tsk_getu16(fs->endian, dir->name_len)] = '\0';

        fs_dent->ent_type = TSK_FS_DENT_TYPE_UNDEF;
    }
    else {
        ext2fs_dentry2 *dir = (ext2fs_dentry2 *) ext2_dent;

        fs_dent->inode = tsk_getu32(fs->endian, dir->inode);

        /* ext2 does not null terminate */
        if (dir->name_len >= fs_dent->name_max) {
            tsk_error_reset();
            tsk_errno = TSK_ERR_FS_ARG;
            snprintf(tsk_errstr, TSK_ERRSTR_L,
                "ext2_dent_copy: Name Space too Small %d %lu",
                dir->name_len, fs_dent->name_max);
            return 1;
        }

        /* Copy and Null Terminate */
        strncpy(fs_dent->name, dir->name, dir->name_len);
        fs_dent->name[dir->name_len] = '\0';

        switch (dir->type) {
        case EXT2_DE_REG_FILE:
            fs_dent->ent_type = TSK_FS_DENT_TYPE_REG;
            break;
        case EXT2_DE_DIR:
            fs_dent->ent_type = TSK_FS_DENT_TYPE_DIR;
            break;
        case EXT2_DE_CHRDEV:
            fs_dent->ent_type = TSK_FS_DENT_TYPE_CHR;
            break;
        case EXT2_DE_BLKDEV:
            fs_dent->ent_type = TSK_FS_DENT_TYPE_BLK;
            break;
        case EXT2_DE_FIFO:
            fs_dent->ent_type = TSK_FS_DENT_TYPE_FIFO;
            break;
        case EXT2_DE_SOCK:
            fs_dent->ent_type = TSK_FS_DENT_TYPE_SOCK;
            break;
        case EXT2_DE_SYMLINK:
            fs_dent->ent_type = TSK_FS_DENT_TYPE_LNK;
            break;
        case EXT2_DE_UNKNOWN:
        default:
            fs_dent->ent_type = TSK_FS_DENT_TYPE_UNDEF;
            break;
        }
    }

    /* Clean up name */
    i = 0;
    while (fs_dent->name[i] != '\0') {
        if (TSK_IS_CNTRL(fs_dent->name[i]))
            fs_dent->name[i] = '^';
        i++;
    }

    fs_dent->path = dinfo->dirs;
    fs_dent->pathdepth = dinfo->depth;

    if ((fs != NULL) && (fs_dent->inode)
        && (fs_dent->inode <= fs->last_inum)) {
        /* Get inode */
        if (fs_dent->fsi)
            tsk_fs_inode_free(fs_dent->fsi);

        if ((fs_dent->fsi = fs->inode_lookup(fs, fs_dent->inode)) == NULL) {
            strncat(tsk_errstr2, " - ext2fs_dent_copy",
                TSK_ERRSTR_L - strlen(tsk_errstr2));
            return 1;
        }
    }
    else {
        if (fs_dent->fsi)
            tsk_fs_inode_free(fs_dent->fsi);
        fs_dent->fsi = NULL;
    }
    fs_dent->flags = 0;

    return 0;
}
Example #3
0
/* 
 * Process the contents of a directory and add them to FS_DIR. 
 * 
 * @param fatfs File system information structure
 * @param a_fs_dir Structure to store the files in. 
 * @param list_seen List of directory inodes that have been seen thus far in
 * directory walking (can be a pointer to a NULL pointer on first call). 
 * @param buf Buffer that contains the directory contents. 
 * @param len Length of buffer in bytes (must be a multiple of sector size)
 * @param addrs Array where each element is the original address of the 
 * corresponding block in buf (size of array is number of blocks in directory).
 *
 * @return -1 on error, 0 on success, and 1 to stop
 */
static TSK_RETVAL_ENUM
fatfs_dent_parse_buf(FATFS_INFO * fatfs, TSK_FS_DIR * a_fs_dir, char *buf,
    TSK_OFF_T len, TSK_DADDR_T * addrs)
{
    unsigned int idx, sidx;
    int a, b;
    TSK_INUM_T inode, ibase;
    fatfs_dentry *dep;
    TSK_FS_INFO *fs = (TSK_FS_INFO *) & fatfs->fs_info;
    int sectalloc;
    TSK_FS_NAME *fs_name;
    FATFS_LFN lfninfo;

    if (buf == NULL) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_FS_ARG;
        snprintf(tsk_errstr, TSK_ERRSTR_L,
            "fatfs_dent_parse_buf: buffer is NULL");
        return TSK_ERR;
    }

    dep = (fatfs_dentry *) buf;

    if ((fs_name = tsk_fs_name_alloc(FATFS_MAXNAMLEN_UTF8, 32)) == NULL) {
        return TSK_ERR;
    }

    memset(&lfninfo, 0, sizeof(FATFS_LFN));
    lfninfo.start = FATFS_MAXNAMLEN_UTF8 - 1;

    for (sidx = 0; sidx < (unsigned int) (len / fatfs->ssize); sidx++) {

        /* Get the base inode for this sector */
        ibase = FATFS_SECT_2_INODE(fatfs, addrs[sidx]);

        if (ibase > fs->last_inum) {
            tsk_error_reset();
            tsk_errno = TSK_ERR_FS_ARG;
            snprintf(tsk_errstr, TSK_ERRSTR_L,
                "fatfs_parse: inode address is too large");
            tsk_fs_name_free(fs_name);
            return TSK_COR;
        }

        if (tsk_verbose)
            tsk_fprintf(stderr,
                "fatfs_dent_parse_buf: Parsing sector %" PRIuDADDR
                "\n", addrs[sidx]);

        if ((sectalloc = fatfs_is_sectalloc(fatfs, addrs[sidx])) == -1) {
            if (tsk_verbose) {
                tsk_fprintf(stderr,
                    "fatfs_dent_parse_buf: Error looking up sector allocation: %"
                    PRIuDADDR "\n", addrs[sidx]);
                tsk_error_print(stderr);
            }
            tsk_error_reset();
            continue;
        }

        /* cycle through the directory entries */
        for (idx = 0; idx < fatfs->dentry_cnt_se; idx++, dep++) {
            fatfs_dentry *dir;
            int i;

            /* is it a valid dentry? */
            if (0 == fatfs_isdentry(fatfs, dep)) {
                if (tsk_verbose)
                    tsk_fprintf(stderr,
                        "fatfs_dent_parse_buf: Entry %u is invalid\n",
                        idx);
                continue;
            }

            /* Copy the directory entry into the TSK_FS_NAME structure */
            dir = (fatfs_dentry *) dep;

            inode = ibase + idx;

            /* Take care of the name 
             * Copy a long name to a buffer and take action if it
             * is a small name */
            if ((dir->attrib & FATFS_ATTR_LFN) == FATFS_ATTR_LFN) {
                fatfs_dentry_lfn *dirl = (fatfs_dentry_lfn *) dir;

                /* Store the name in dinfo until we get the 8.3 name 
                 * Use the checksum to identify a new sequence 
                 * */
                if (((dirl->seq & FATFS_LFN_SEQ_FIRST)
                        && (dirl->seq != FATFS_SLOT_DELETED))
                    || (dirl->chksum != lfninfo.chk)) {
                    // @@@ Do a partial output here


                    /* Reset the values */
                    lfninfo.seq = dirl->seq & FATFS_LFN_SEQ_MASK;
                    lfninfo.chk = dirl->chksum;
                    lfninfo.start = FATFS_MAXNAMLEN_UTF8 - 1;

                }
                else if (dirl->seq != lfninfo.seq - 1) {
                    // @@@ Check the sequence number - the checksum is correct though...

                }

                /* Copy the UTF16 values starting at end of buffer */
                for (a = 3; a >= 0; a--) {
                    if ((lfninfo.start > 0))
                        lfninfo.name[lfninfo.start--] = dirl->part3[a];
                }
                for (a = 11; a >= 0; a--) {
                    if ((lfninfo.start > 0))
                        lfninfo.name[lfninfo.start--] = dirl->part2[a];
                }
                for (a = 9; a >= 0; a--) {
                    if ((lfninfo.start > 0))
                        lfninfo.name[lfninfo.start--] = dirl->part1[a];
                }

                // Skip ahead until we get a new sequence num or the 8.3 name
                continue;
            }
            /* Special case for volume label: name does not have an
             * extension and we add a note at the end that it is a label */
            else if ((dir->attrib & FATFS_ATTR_VOLUME) ==
                FATFS_ATTR_VOLUME) {
                a = 0;

                for (b = 0; b < 8; b++) {
                    if ((dir->name[b] >= 0x20) && (dir->name[b] != 0xff)) {
                        fs_name->name[a++] = dir->name[b];
                    }
                    else {
                        fs_name->name[a++] = '^';
                    }
                }
                for (b = 0; b < 3; b++) {
                    if ((dir->ext[b] >= 0x20) && (dir->ext[b] != 0xff)) {
                        fs_name->name[a++] = dir->ext[b];
                    }
                    else {
                        fs_name->name[a++] = '^';
                    }
                }

                fs_name->name[a] = '\0';
                /* Append a string to show it is a label */
                if (a + 22 < FATFS_MAXNAMLEN_UTF8) {
                    char *volstr = " (Volume Label Entry)";
                    strncat(fs_name->name, volstr,
                        FATFS_MAXNAMLEN_UTF8 - a);
                }
            }

            /* A short (8.3) entry */
            else {
                char *name_ptr; // The dest location for the short name

                /* if we have a lfn, copy it into fs_name->name
                 * and put the short name in fs_name->shrt_name */
                if (lfninfo.start != FATFS_MAXNAMLEN_UTF8 - 1) {
                    int retVal;

                    /* @@@ Check the checksum */

                    /* Convert the UTF16 to UTF8 */
                    UTF16 *name16 =
                        (UTF16 *) ((uintptr_t) & lfninfo.name[lfninfo.
                            start + 1]);
                    UTF8 *name8 = (UTF8 *) fs_name->name;

                    retVal =
                        tsk_UTF16toUTF8(fs->endian,
                        (const UTF16 **) &name16,
                        (UTF16 *) & lfninfo.name[FATFS_MAXNAMLEN_UTF8],
                        &name8,
                        (UTF8 *) ((uintptr_t) name8 +
                            FATFS_MAXNAMLEN_UTF8), TSKlenientConversion);

                    if (retVal != TSKconversionOK) {
                        tsk_error_reset();
                        tsk_errno = TSK_ERR_FS_UNICODE;
                        snprintf(tsk_errstr, TSK_ERRSTR_L,
                            "fatfs_parse: Error converting FAT LFN to UTF8: %d",
                            retVal);
                        continue;
                    }

                    /* Make sure it is NULL Terminated */
                    if ((uintptr_t) name8 >
                        (uintptr_t) fs_name->name + FATFS_MAXNAMLEN_UTF8)
                        fs_name->name[FATFS_MAXNAMLEN_UTF8 - 1] = '\0';
                    else
                        *name8 = '\0';

                    /* Clean up name */
                    i = 0;
                    while (fs_name->name[i] != '\0') {
                        if (TSK_IS_CNTRL(fs_name->name[i]))
                            fs_name->name[i] = '^';
                        i++;
                    }

                    lfninfo.start = FATFS_MAXNAMLEN_UTF8 - 1;
                    name_ptr = fs_name->shrt_name;      // put 8.3 into shrt_name
                }
                /* We don't have a LFN, so put the short name in 
                 * fs_name->name */
                else {
                    fs_name->shrt_name[0] = '\0';
                    name_ptr = fs_name->name;   // put 8.3 into normal location
                }


                /* copy in the short name into the place specified above. 
                 * Skip spaces and put in the . */
                a = 0;
                for (b = 0; b < 8; b++) {
                    if ((dir->name[b] != 0) && (dir->name[b] != 0xff) &&
                        (dir->name[b] != 0x20)) {

                        if ((b == 0)
                            && (dir->name[0] == FATFS_SLOT_DELETED)) {
                            name_ptr[a++] = '_';
                        }
                        else if ((dir->lowercase & FATFS_CASE_LOWER_BASE)
                            && (dir->name[b] >= 'A')
                            && (dir->name[b] <= 'Z')) {
                            name_ptr[a++] = dir->name[b] + 32;
                        }
                        else {
                            name_ptr[a++] = dir->name[b];
                        }
                    }
                }

                for (b = 0; b < 3; b++) {
                    if ((dir->ext[b] != 0) && (dir->ext[b] != 0xff) &&
                        (dir->ext[b] != 0x20)) {
                        if (b == 0)
                            name_ptr[a++] = '.';
                        if ((dir->lowercase & FATFS_CASE_LOWER_EXT) &&
                            (dir->ext[b] >= 'A') && (dir->ext[b] <= 'Z'))
                            name_ptr[a++] = dir->ext[b] + 32;
                        else
                            name_ptr[a++] = dir->ext[b];
                    }
                }
                name_ptr[a] = '\0';
            }

            /* Clean up name to remove control chars */
            i = 0;
            while (fs_name->name[i] != '\0') {
                if (TSK_IS_CNTRL(fs_name->name[i]))
                    fs_name->name[i] = '^';
                i++;
            }

            /* file type: FAT only knows DIR and FILE */
            if ((dir->attrib & FATFS_ATTR_DIRECTORY) ==
                FATFS_ATTR_DIRECTORY)
                fs_name->type = TSK_FS_NAME_TYPE_DIR;
            else
                fs_name->type = TSK_FS_NAME_TYPE_REG;

            /* Get inode */
            fs_name->meta_addr = inode;

            /* Handle the . and .. entries specially
             * The current inode 'address' they have is for the current
             * slot in the cluster, but it needs to refer to the original
             * slot 
             */
            if (TSK_FS_ISDOT(fs_name->name)) {
                if (fs_name->name[1] == '\0') {
                    inode = fs_name->meta_addr =
                        a_fs_dir->fs_file->meta->addr;
                }
                /* for the parent directory, look up in the list that 
                 * is maintained in fafs_info */
                else if (fs_name->name[1] == '.') {
                    size_t q;
                    uint8_t dir_found = 0;
                    for (q = 0; q < fatfs->dir_buf_next; q++) {
                        if (fatfs->dir_buf[q] ==
                            a_fs_dir->fs_file->meta->addr) {
                            inode = fs_name->meta_addr = fatfs->par_buf[q];
                            dir_found = 1;
                            break;
                        }
                    }

                    if ((dir_found == 0) && (fs->isOrphanHunting)) {
                        /* if we are currently scanning the fs to determine the orphan files,
                         * then we do not care about the value of '..' and this can only cause
                         * infinite loop problems */
                        inode = fs_name->meta_addr = 0;
                        dir_found = 1;
                    }
                    if ((dir_found == 0)
                        && (addrs[0] == fatfs->firstdatasect)) {
                        /* if we are currently in the root directory, we aren't going to find
                         * a parent.  This shouldn't happen, but could result in an infinite loop. */
                        inode = fs_name->meta_addr = 0;
                        dir_found = 1;
                    }
                    if (dir_found == 0) {
                        /* The parent directory is not in the list.  We are going to walk
                         * the directory until we hit this directory. This process will
                         * populate the buffer table and we will then rescan it */
                        if (tsk_fs_dir_walk(fs, fs->root_inum,
                                TSK_FS_DIR_WALK_FLAG_ALLOC | TSK_FS_DIR_WALK_FLAG_UNALLOC | 
                                TSK_FS_DIR_WALK_FLAG_RECURSE,
                                find_parent_act,
                                (void *) &a_fs_dir->fs_file->meta->addr)) {
                            return 0;
                        }

                        for (q = 0; q < fatfs->dir_buf_next; q++) {
                            if (fatfs->dir_buf[q] ==
                                a_fs_dir->fs_file->meta->addr) {
                                inode = fs_name->meta_addr =
                                    fatfs->par_buf[q];
                                dir_found = 1;
                                break;
                            }
                        }
                        // if we did not find it, then it was probably 
                        // from the orphan directory...
                        if (dir_found == 0)
                            inode = fs_name->meta_addr =
                                TSK_FS_ORPHANDIR_INUM(fs);
                    }
                }
            }
            else {
                /* Save the (non-. or ..) directory to parent directory info to local
                 * structures so that we can later fill into the inode
                 * info for '..' entries */
                if (fs_name->type == TSK_FS_NAME_TYPE_DIR) {
                    if (fatfs_dir_buf_add(fatfs,
                            a_fs_dir->fs_file->meta->addr, inode))
                        return TSK_ERR;
                }
            }


            /* The allocation status of an entry is based on the allocation
             * status of the sector it is in and the flag.  Deleted directories
             * do not always clear the flags of each entry
             */
            if (sectalloc == 1) {
                fs_name->flags = (dep->name[0] == FATFS_SLOT_DELETED) ?
                    TSK_FS_NAME_FLAG_UNALLOC : TSK_FS_NAME_FLAG_ALLOC;
            }
            else {
                fs_name->flags = TSK_FS_NAME_FLAG_UNALLOC;
            }

            tsk_fs_dir_add(a_fs_dir, fs_name);
        }
    }
    tsk_fs_name_free(fs_name);

    return TSK_OK;
}
Example #4
0
/*
 * copy the index (directory) entry into the generic structure
 *
 * uses the global variables 'dirs' and 'depth'
 *
 * Returns 1 on eror and 0 on success
 */
static uint8_t
ntfs_dent_copy(NTFS_INFO * ntfs, NTFS_DINFO * dinfo, ntfs_idxentry * idxe,
               TSK_FS_DENT * fs_dent)
{
    ntfs_attr_fname *fname = (ntfs_attr_fname *) & idxe->stream;
    TSK_FS_INFO *fs = (TSK_FS_INFO *) & ntfs->fs_info;
    UTF16 *name16;
    UTF8 *name8;
    int retVal;
    int i;

    fs_dent->inode = tsk_getu48(fs->endian, idxe->file_ref);

    name16 = (UTF16 *) & fname->name;
    name8 = (UTF8 *) fs_dent->name;

    retVal = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &name16,
                             (UTF16 *) ((uintptr_t) name16 +
                                        fname->nlen * 2), &name8,
                             (UTF8 *) ((uintptr_t) name8 +
                                       fs_dent->name_max), TSKlenientConversion);

    if (retVal != TSKconversionOK) {
        *name8 = '\0';
        if (tsk_verbose)
            tsk_fprintf(stderr,
                        "Error converting NTFS name to UTF8: %d %" PRIuINUM,
                        retVal, fs_dent->inode);
    }

    /* Make sure it is NULL Terminated */
    if ((uintptr_t) name8 > (uintptr_t) fs_dent->name + fs_dent->name_max)
        fs_dent->name[fs_dent->name_max] = '\0';
    else
        *name8 = '\0';

    /* Clean up name */
    i = 0;
    while (fs_dent->name[i] != '\0') {
        if (TSK_IS_CNTRL(fs_dent->name[i]))
            fs_dent->name[i] = '^';
        i++;
    }

    /* copy the path data */
    fs_dent->path = dinfo->dirs;
    fs_dent->pathdepth = dinfo->depth;

    /* Get the actual inode */
    if (fs_dent->fsi != NULL)
        tsk_fs_inode_free(fs_dent->fsi);

    if (NULL == (fs_dent->fsi = fs->inode_lookup(fs, fs_dent->inode))) {
        if (tsk_verbose) {
            tsk_fprintf(stderr,
                        "ntfs_dent_copy: error looking up inode: %" PRIuINUM "\n",
                        fs_dent->inode);
            tsk_error_print(stderr);
            tsk_error_reset();
        }
    }

    if (tsk_getu64(fs->endian, fname->flags) & NTFS_FNAME_FLAGS_DIR)
        fs_dent->ent_type = TSK_FS_DENT_TYPE_DIR;
    else
        fs_dent->ent_type = TSK_FS_DENT_TYPE_REG;

    fs_dent->flags = 0;

    return 0;
}
Example #5
0
/**
 * \internal
 *
** Print output in the format that mactime reads.
**
** If the flags in the fs_file->meta structure are set to FS_FLAG_ALLOC
** then it is assumed that the inode has been reallocated and the
** contents are not displayed
**
** fs is not required (only used for block size).
 * @param hFile handle to print results to
 * @param fs_file File to print details about
 * @param a_path Parent directory of file (needs to end with "/")
 * @param fs_attr Attribute in file that is being called for (NULL for non-NTFS)
 * @param prefix Path of mounting point for image
 * @param time_skew number of seconds skew to adjust time
*/
void
tsk_fs_name_print_mac(FILE * hFile, const TSK_FS_FILE * fs_file,
    const char *a_path, const TSK_FS_ATTR * fs_attr,
    const char *prefix, int32_t time_skew)
{
    char ls[12];
    size_t i;
    uint8_t isADS = 0;

    if ((!hFile) || (!fs_file))
        return;

    /* see if we are going to be printing the name of the attribute
     * We don't do it for FNAME attributes, which we handle specially below.
     */
    if ((fs_attr) && (fs_attr->name)
        && (fs_attr->type != TSK_FS_ATTR_TYPE_NTFS_FNAME)
        && ((fs_attr->type != TSK_FS_ATTR_TYPE_NTFS_IDXROOT)
            || (strcmp(fs_attr->name, "$I30") != 0))) {
        isADS = 1;
    }

    /* md5 */
    tsk_fprintf(hFile, "0|");

    /* file name */
    tsk_fprintf(hFile, "%s", prefix);

    // remove any control chars as we print the names
    if (a_path != NULL) {
        for (i = 0; i < strlen(a_path); i++) {
            if (TSK_IS_CNTRL(a_path[i]))
                tsk_fprintf(hFile, "^");
            else
                tsk_fprintf(hFile, "%c", a_path[i]);
        }
    }

    for (i = 0; i < strlen(fs_file->name->name); i++) {
        if (TSK_IS_CNTRL(fs_file->name->name[i]))
            tsk_fprintf(hFile, "^");
        else
            tsk_fprintf(hFile, "%c", fs_file->name->name[i]);
    }

    /* print the data stream name if it exists and is not the default NTFS */
    if (isADS) {
        tsk_fprintf(hFile, ":");
        for (i = 0; i < strlen(fs_attr->name); i++) {
            if (TSK_IS_CNTRL(fs_attr->name[i]))
                tsk_fprintf(hFile, "^");
            else
                tsk_fprintf(hFile, "%c", fs_attr->name[i]);
        }
    }

    // special label if FNAME
    if ((fs_attr) && (fs_attr->type == TSK_FS_ATTR_TYPE_NTFS_FNAME)) {
        tsk_fprintf(hFile, " ($FILE_NAME)");
    }

    if ((fs_file->meta)
        && (fs_file->meta->type == TSK_FS_META_TYPE_LNK)
        && (fs_file->meta->link)) {
        tsk_fprintf(hFile, " -> %s", fs_file->meta->link);
    }

    /* if filename is deleted add a comment and if the inode is now
     * allocated, then add realloc comment */
    if (fs_file->name->flags & TSK_FS_NAME_FLAG_UNALLOC)
        tsk_fprintf(hFile, " (deleted%s)", ((fs_file->meta)
                && (fs_file->
                    meta->flags & TSK_FS_META_FLAG_ALLOC)) ? "-realloc" :
            "");

    /* inode */
    tsk_fprintf(hFile, "|%" PRIuINUM, fs_file->name->meta_addr);
    if (fs_attr)
        tsk_fprintf(hFile, "-%" PRIu32 "-%" PRIu16 "", fs_attr->type,
            fs_attr->id);

    tsk_fprintf(hFile, "|");

    /* TYPE as specified in the directory entry
     */
    if (fs_file->name->type < TSK_FS_NAME_TYPE_STR_MAX)
        tsk_fprintf(hFile, "%s/",
            tsk_fs_name_type_str[fs_file->name->type]);
    else
        tsk_fprintf(hFile, "-/");

    if (!fs_file->meta) {
        tsk_fprintf(hFile, "----------|0|0|0|");
    }
    else {
        /* mode as string */
        tsk_fs_meta_make_ls(fs_file->meta, ls, sizeof(ls));
        tsk_fprintf(hFile, "%s|", ls);

        /* uid, gid */
        tsk_fprintf(hFile, "%" PRIuUID "|%" PRIuGID "|",
            fs_file->meta->uid, fs_file->meta->gid);

        /* size - use data stream if we have it */
        if (fs_attr)
            tsk_fprintf(hFile, "%" PRIuOFF "|", fs_attr->size);
        else
            tsk_fprintf(hFile, "%" PRIuOFF "|", fs_file->meta->size);
    }

    if (!fs_file->meta) {
        tsk_fprintf(hFile, "0|0|0|0\n");
    }
    else {
        // special case for NTFS FILE_NAME attribute
        if ((fs_attr) && (fs_attr->type == TSK_FS_ATTR_TYPE_NTFS_FNAME)) {
            /* atime, mtime, ctime, crtime */
            if (fs_file->meta->time2.ntfs.fn_atime)
                tsk_fprintf(hFile, "%" PRIu32 "|",
                    fs_file->meta->time2.ntfs.fn_atime - time_skew);
            else
                tsk_fprintf(hFile, "%" PRIu32 "|",
                    fs_file->meta->time2.ntfs.fn_atime);

            if (fs_file->meta->time2.ntfs.fn_mtime)
                tsk_fprintf(hFile, "%" PRIu32 "|",
                    fs_file->meta->time2.ntfs.fn_mtime - time_skew);
            else
                tsk_fprintf(hFile, "%" PRIu32 "|",
                    fs_file->meta->time2.ntfs.fn_mtime);

            if (fs_file->meta->time2.ntfs.fn_ctime)
                tsk_fprintf(hFile, "%" PRIu32 "|",
                    fs_file->meta->time2.ntfs.fn_ctime - time_skew);
            else
                tsk_fprintf(hFile, "%" PRIu32 "|",
                    fs_file->meta->time2.ntfs.fn_ctime);

            if (fs_file->meta->time2.ntfs.fn_crtime)
                tsk_fprintf(hFile, "%" PRIu32 "\n",
                    fs_file->meta->time2.ntfs.fn_crtime - time_skew);
            else
                tsk_fprintf(hFile, "%" PRIu32 "\n",
                    fs_file->meta->time2.ntfs.fn_crtime);
        }
        else {
            /* atime, mtime, ctime, crtime */
            if (fs_file->meta->atime)
                tsk_fprintf(hFile, "%" PRIu32 "|",
                    fs_file->meta->atime - time_skew);
            else
                tsk_fprintf(hFile, "%" PRIu32 "|", fs_file->meta->atime);

            if (fs_file->meta->mtime)
                tsk_fprintf(hFile, "%" PRIu32 "|",
                    fs_file->meta->mtime - time_skew);
            else
                tsk_fprintf(hFile, "%" PRIu32 "|", fs_file->meta->mtime);

            if (fs_file->meta->ctime)
                tsk_fprintf(hFile, "%" PRIu32 "|",
                    fs_file->meta->ctime - time_skew);
            else
                tsk_fprintf(hFile, "%" PRIu32 "|", fs_file->meta->ctime);

            if (fs_file->meta->crtime)
                tsk_fprintf(hFile, "%" PRIu32 "\n",
                    fs_file->meta->crtime - time_skew);
            else
                tsk_fprintf(hFile, "%" PRIu32 "\n", fs_file->meta->crtime);
        }
    }
}
Example #6
0
/**
* \internal
 * Simple print of dentry type / inode type, deleted, inode, and
 * name
 *
 * fs_attr is used for alternate data streams in NTFS, set to NULL
 * for all other file systems
 *
 * A newline is not printed at the end
 *
 * If path is NULL, then skip else use. it has the full directory name
 *  It needs to end with "/"
 */
void
tsk_fs_name_print(FILE * hFile, const TSK_FS_FILE * fs_file,
    const char *a_path, TSK_FS_INFO * fs, const TSK_FS_ATTR * fs_attr,
    uint8_t print_path)
{
    size_t i;

    /* type of file - based on dentry type */
    if (fs_file->name->type < TSK_FS_NAME_TYPE_STR_MAX)
        tsk_fprintf(hFile, "%s/",
            tsk_fs_name_type_str[fs_file->name->type]);
    else
        tsk_fprintf(hFile, "-/");

    /* type of file - based on inode type: we want letters though for
     * regular files so we use the dent_str though */
    if (fs_file->meta) {
        /* 
         * An NTFS directory can have a Data stream, in which
         * case it would be printed with modes of a
         * directory, although it is really a file
         * So, to avoid confusion we will set the modes
         * to a file so it is printed that way.  The
         * entry for the directory itself will still be
         * printed as a directory
         */
        if ((fs_attr) && (fs_attr->type == TSK_FS_ATTR_TYPE_NTFS_DATA) &&
            (fs_file->meta->type == TSK_FS_META_TYPE_DIR)) {
            tsk_fprintf(hFile, "r ");
        }
        else {
            if (fs_file->meta->type < TSK_FS_META_TYPE_STR_MAX)
                tsk_fprintf(hFile, "%s ",
                    tsk_fs_meta_type_str[fs_file->meta->type]);
            else
                tsk_fprintf(hFile, "- ");
        }
    }
    else {
        tsk_fprintf(hFile, "- ");
    }


    /* print a * if it is deleted */
    if (fs_file->name->flags & TSK_FS_NAME_FLAG_UNALLOC)
        tsk_fprintf(hFile, "* ");

    tsk_fprintf(hFile, "%" PRIuINUM "", fs_file->name->meta_addr);

    /* print the id and type if we have fs_attr (NTFS) */
    if (fs_attr)
        tsk_fprintf(hFile, "-%" PRIu32 "-%" PRIu16 "", fs_attr->type,
            fs_attr->id);

    tsk_fprintf(hFile, "%s:\t",
        ((fs_file->meta) && (fs_file->meta->flags & TSK_FS_META_FLAG_ALLOC)
            && (fs_file->
                name->flags & TSK_FS_NAME_FLAG_UNALLOC)) ? "(realloc)" :
        "");

    if ((print_path) && (a_path != NULL)) {
        for (i = 0; i < strlen(a_path); i++) {
            if (TSK_IS_CNTRL(a_path[i]))
                tsk_fprintf(hFile, "^");
            else
                tsk_fprintf(hFile, "%c", a_path[i]);
        }
    }

    for (i = 0; i < strlen(fs_file->name->name); i++) {
        if (TSK_IS_CNTRL(fs_file->name->name[i]))
            tsk_fprintf(hFile, "^");
        else
            tsk_fprintf(hFile, "%c", fs_file->name->name[i]);
    }

/*  This will add the short name in parentheses
    if (fs_file->name->shrt_name != NULL && fs_file->name->shrt_name[0] != '\0')
	tsk_fprintf(hFile, " (%s)", fs_file->name->shrt_name);
*/

    /* print the data stream name if we the non-data NTFS stream */
    if ((fs_attr) && (fs_attr->name)) {
        if ((fs_attr->type != TSK_FS_ATTR_TYPE_NTFS_IDXROOT) ||
            (strcmp(fs_attr->name, "$I30") != 0)) {
            tsk_fprintf(hFile, ":");
            for (i = 0; i < strlen(fs_attr->name); i++) {
                if (TSK_IS_CNTRL(fs_attr->name[i]))
                    tsk_fprintf(hFile, "^");
                else
                    tsk_fprintf(hFile, "%c", fs_attr->name[i]);
            }
        }
    }

    return;
}