Exemple #1
0
 def execute_command(self, diag_input, args : Namespace):
 
     # First, emit a stat() (EFS2_DIAG_STAT) call in order to understand whether
     # the remote path input by the user is a directory or not
     
     is_directory : bool = False
     
     opcode, payload = diag_input.send_recv(DIAG_SUBSYS_CMD_F, pack('<BH',
         DIAG_SUBSYS_FS, # Command subsystem number
         EFS2_DIAG_STAT,
     ) + args.path.encode('latin1').decode('unicode_escape').encode('latin1') + b'\x00', accept_error = True)
     
     if opcode != DIAG_SUBSYS_CMD_F:
 
         print('Error executing STAT: %s received with payload "%s"' % (message_id_to_name.get(opcode, opcode),
             repr(payload)))
         return
 
     (cmd_subsystem_id, subcommand_code,
         errno, file_mode, file_size, num_links,
         atime, mtime, ctime) = unpack('<BH7i', payload)
     
     if errno:
         print('Error executing STAT: %s' % (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
         return
     
     if file_mode & 0o170000 == 0o040000: # S_IFDIR
         
         is_directory = True
 
     # Then, actually open the file for write and/or creation
     
     opcode, payload = diag_input.send_recv(DIAG_SUBSYS_CMD_F, pack('<BH',
         DIAG_SUBSYS_FS, # Command subsystem number
         EFS2_DIAG_RMDIR if is_directory else EFS2_DIAG_UNLINK,
     ) + args.path.encode('latin1').decode('unicode_escape').encode('latin1') + b'\x00', accept_error = True)
     
     if opcode != DIAG_SUBSYS_CMD_F:
         print('Error executing %s: %s received with payload "%s"' % ('RMDIR' if is_directory else 'UNLINK',
             message_id_to_name.get(opcode, opcode),
             repr(payload)))
         return
     
     (cmd_subsystem_id, subcommand_code, errno) = unpack('<BHi', payload)
     
     if errno:
         print('Error executing %s: %s' % ('RMDIR' if is_directory else 'UNLINK',
             EFS2_ERROR_CODES.get(errno) or strerror(errno)))
         return
Exemple #2
0
    def execute_command(self, diag_input, args: Namespace):

        # Rename the target path

        opcode, payload = diag_input.send_recv(
            DIAG_SUBSYS_CMD_F,
            pack(
                '<BH',
                DIAG_SUBSYS_FS,  # Command subsystem number
                EFS2_DIAG_RENAME,
            ) + args.remote_src.encode('latin1').decode(
                'unicode_escape').encode('latin1') + b'\x00' +
            args.remote_dst.encode('latin1').decode('unicode_escape').encode(
                'latin1') + b'\x00',
            accept_error=True)

        if opcode != DIAG_SUBSYS_CMD_F:
            print('Error executing RENAME: %s received with payload "%s"' %
                  (message_id_to_name.get(opcode, opcode), repr(payload)))
            return

        (cmd_subsystem_id, subcommand_code, errno) = unpack('<BHi', payload)

        if errno:
            print('Error executing RENAME: %s' %
                  (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
            return
Exemple #3
0
    def execute_command(self, diag_input, args: Namespace):

        # Create the directory

        opcode, payload = diag_input.send_recv(
            DIAG_SUBSYS_CMD_F,
            pack(
                '<BHh',
                DIAG_SUBSYS_FS,  # Command subsystem number
                EFS2_DIAG_MKDIR,
                0o777 | 0o040000  # S_IFDIR (directory) + all permissions
            ) + args.path.encode('latin1').decode('unicode_escape').encode(
                'latin1') + b'\x00',
            accept_error=True)

        if opcode != DIAG_SUBSYS_CMD_F:
            print('Error executing MKDIR: %s received with payload "%s"' %
                  (message_id_to_name.get(opcode, opcode), repr(payload)))
            return

        (cmd_subsystem_id, subcommand_code, errno) = unpack('<BHi', payload)

        if errno:
            print('Error executing MKDIR: %s' %
                  (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
            return
Exemple #4
0
    def execute_command(self, diag_input, args: Namespace):

        # Obtain the file checksum

        sequence_number = randint(0, 0xffff)

        opcode, payload = diag_input.send_recv(
            DIAG_SUBSYS_CMD_F,
            pack(
                '<BHH',
                DIAG_SUBSYS_FS,  # Command subsystem number
                EFS2_DIAG_MKDIR,
                sequence_number) + args.path.encode('latin1').decode(
                    'unicode_escape').encode('latin1') + b'\x00',
            accept_error=True)

        if opcode != DIAG_SUBSYS_CMD_F:
            print('Error executing MD5SUM: %s received with payload "%s"' %
                  (message_id_to_name.get(opcode, opcode), repr(payload)))
            return

        md5sum_spec = '<BHHi'

        (cmd_subsystem_id, subcommand_code, sequence_number,
         errno) = unpack(md5sum_spec, payload[:calcsize(md5sum_spec)])

        text_hash: str = payload[calcsize(md5sum_spec):].hex()

        if errno:
            print('Error executing MD5SUM: %s' %
                  (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
            return

        print(text_hash)
Exemple #5
0
    def execute_command(self, diag_input, args: Namespace):

        # Obtain the EFS underlying flash device information

        sequence_number = randint(0, 0xffff)

        opcode, payload = diag_input.send_recv(
            DIAG_SUBSYS_CMD_F,
            pack(
                '<BH',
                DIAG_SUBSYS_FS,  # Command subsystem number
                EFS2_DIAG_DEV_INFO),
            accept_error=True)

        if opcode != DIAG_SUBSYS_CMD_F:
            print('Error executing DEV_INFO: %s received with payload "%s"' %
                  (message_id_to_name.get(opcode, opcode), repr(payload)))
            return

        device_info_spec = '<BH7iB'

        (cmd_subsystem_id, subcommand_code, errno, num_blocks, pages_per_block,
         page_size, total_page_size, maker_id, device_id,
         device_type) = unpack(device_info_spec,
                               payload[:calcsize(device_info_spec)])

        device_name: str = payload[calcsize(device_info_spec):].rstrip(
            b'\x00').decode('utf8')

        if errno:
            print('Error executing DEV_INFO: %s' %
                  (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
            return

        print()
        print('Device information:')
        print('- Number of blocks: %d' % num_blocks)
        print('- Number of pages per block: %d' % pages_per_block)
        print('- Page size in bytes: %d' % page_size)
        print('- Total page size: %d' % total_page_size)
        print('- Device marker ID: %d' % maker_id)
        print('- Device ID: %d' % device_id)
        print('- Device type: ' + ('NAND' if device_type else 'NOR'))
        print('- Device name: %s' % device_name)
        print()
Exemple #6
0
    def execute_command(self, diag_input, args: Namespace):

        opcode, payload = diag_input.send_recv(
            DIAG_SUBSYS_CMD_F,
            pack(
                '<BHii',
                DIAG_SUBSYS_FS,  # Command subsystem number
                EFS2_DIAG_OPEN,
                0x0,  # oflag - "O_RDONLY"
                0,  # mode (ignored)
            ) + args.path.encode('latin1').decode('unicode_escape').encode(
                'latin1') + b'\x00',
            accept_error=True)

        if opcode != DIAG_SUBSYS_CMD_F:
            print('Error executing OPEN: %s received with payload "%s"' %
                  (message_id_to_name.get(opcode, opcode), repr(payload)))
            return

        (cmd_subsystem_id, subcommand_code, file_fd,
         errno) = unpack('<BHIi', payload)

        if errno:
            print('Error executing OPEN: %s' %
                  (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
            return

        try:  # try/finally block for remotely closing the file opened with the "EFS2_DIAG_OPEN" command in all cases:

            bytes_read: bytes = b''

            BYTES_TO_READ = 1024

            while True:

                opcode, payload = diag_input.send_recv(
                    DIAG_SUBSYS_CMD_F,
                    pack(
                        '<BHiII',
                        DIAG_SUBSYS_FS,  # Command subsystem number
                        EFS2_DIAG_READ,
                        file_fd,  # File descriptor to read from
                        BYTES_TO_READ,  # Bytes to read at once
                        len(bytes_read)  # Offset where to read
                    ))

                read_struct = '<BHiIii'

                (cmd_subsystem_id, subcommand_code, file_fd, offset,
                 num_bytes_read,
                 errno) = unpack(read_struct, payload[:calcsize(read_struct)])

                read_data: bytes = payload[calcsize(read_struct):]

                if errno:
                    print('Error executing READ: %s' %
                          (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
                    return

                bytes_read += read_data
                if len(read_data) < BYTES_TO_READ:
                    break  # EOF was reached

            is_printable: bool = False

            try:
                if bytes_read.decode('utf8').replace('\n', '').replace(
                        '\t', '').isprintable():
                    is_printable = True
            except Exception:
                pass

            if is_printable:  # Print raw text if printable
                print(bytes_read.decode('utf8'))

            else:  # Print an hexadecimal/ascii dump if non-ascii printable
                BYTES_PER_LINE = 32

                print()

                for position in range(0, len(bytes_read), BYTES_PER_LINE):
                    hexdump_line: str = '  '

                    for byte_index in range(
                            BYTES_PER_LINE):  # Display hex bytes

                        if position + byte_index < len(bytes_read):
                            hexdump_line += '%02x ' % bytes_read[position +
                                                                 byte_index]
                        else:  # Apply padding if needed
                            hexdump_line += '   '

                        if byte_index & 3 == 3:
                            hexdump_line += ' '

                    hexdump_line += '  '

                    for byte in bytes_read[
                            position:position +
                            BYTES_PER_LINE]:  # Display ascii bytes at the end of the printed line

                        hexdump_line += chr(
                            byte) if 0x20 <= byte <= 0x7f else '.'

                    hexdump_line += ' '

                    print(hexdump_line)

                print()

        finally:

            opcode, payload = diag_input.send_recv(
                DIAG_SUBSYS_CMD_F,
                pack(
                    '<BHi',
                    DIAG_SUBSYS_FS,  # Command subsystem number
                    EFS2_DIAG_CLOSE,
                    file_fd))

            (cmd_subsystem_id, subcommand_code,
             errno) = unpack('<BHi', payload)

            if errno:
                print('Error executing CLOSE: %s' %
                      (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
                return
Exemple #7
0
    def execute_command(self, diag_input, args: Namespace):

        opcode, payload = diag_input.send_recv(
            DIAG_SUBSYS_CMD_F,
            pack(
                '<BH',
                DIAG_SUBSYS_FS,  # Command subsystem number
                EFS2_DIAG_OPENDIR) + args.path.encode('latin1').decode(
                    'unicode_escape').encode('latin1') + b'\x00',
            accept_error=True)

        if opcode != DIAG_SUBSYS_CMD_F:
            print('Error executing OPENDIR: %s received with payload "%s"' %
                  (message_id_to_name.get(opcode, opcode), repr(payload)))
            return

        (cmd_subsystem_id, subcommand_code, dir_fd,
         errno) = unpack('<BHIi', payload)

        if errno:
            print('Error executing OPENDIR: %s' %
                  (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
            return

        try:  # Close the directory identifier in all cases using the "finally" block below

            sequence_number = 1  # For the protocol

            table_rows_to_print: List[Dict[str, str]] = [
            ]  # For the standard output

            while True:  # Iterate over directory files

                opcode, payload = diag_input.send_recv(
                    DIAG_SUBSYS_CMD_F,
                    pack(
                        '<BHIi',
                        DIAG_SUBSYS_FS,  # Command subsystem number,
                        EFS2_DIAG_READDIR,
                        dir_fd,
                        sequence_number),
                    accept_error=False)

                readdir_struct = '<BHI8i'

                (cmd_subsystem_id, subcommand_code, dir_fd, sequence_number,
                 errno, entry_type, mode, size, atime, mtime,
                 ctime) = unpack(readdir_struct,
                                 payload[:calcsize(readdir_struct)])

                entry_path = payload[calcsize(readdir_struct):]

                if errno:
                    print('Error executing READDIR: %s' %
                          (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
                    return

                if not entry_path.strip(b'\x00'):  # End of directory reached
                    break

                special_flags: List[str] = []
                if mode & 0o4000:
                    special_flags.append(
                        '(setuid)')  # S_ISUID - Set UID on execution.
                if mode & 0o2000:
                    special_flags.append(
                        '(setgid)')  # S_ISGID - Set GID on execution.
                if mode & 0o1000:
                    special_flags.append(
                        '(sticky)'
                    )  # S_ISVTX - Sticky (HIDDEN attribute in HFAT)

                file_rights = ''
                for shift in range(8, -1, -1):  # (1<<8) == 0o400, ...
                    file_rights += 'rwx'[(8 - shift) %
                                         3] if (mode & (1 << shift)) else '-'

                # Resolve the symbolic file of the concerned file if needed

                real_path: Optional[str] = None

                if mode & 0o170000 == 0o120000:  # S_IFLNK

                    opcode, payload = diag_input.send_recv(
                        DIAG_SUBSYS_CMD_F,
                        pack(
                            '<BH',
                            DIAG_SUBSYS_FS,  # Command subsystem number,
                            EFS2_DIAG_READLINK) + entry_path.rstrip(b'\x00') +
                        b'\x00',
                        accept_error=False)

                    readlink_struct = '<BHI'

                    (cmd_subsystem_id, subcommand_code,
                     errno) = unpack(readlink_struct,
                                     payload[:calcsize(readlink_struct)])

                    real_path = payload[calcsize(readlink_struct):].rstrip(
                        b'\x00').decode('latin1')

                    if errno:
                        print('Error executing READLINK: %s' %
                              (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
                        return

                table_rows_to_print.append({
                    'File type':
                    EFS2_FILE_TYPES[mode & 0o170000],
                    'Special flags':
                    ' '.join(special_flags),
                    'File rights':
                    file_rights,
                    'File name':
                    repr(entry_path.rstrip(b'\x00').decode('latin1')) +
                    ((' -> ' + repr(real_path)) if real_path else ''),
                    'File size':
                    str(size) if entry_type != 0x01 else
                    '',  # 0x01: "FS_DIAG_FTYPE_DIR - Directory file"
                    'Modification':
                    datetime.fromtimestamp(mtime).strftime(
                        '%Y-%m-%d %H:%M:%S'),
                    # 'Access': datetime.fromtimestamp(atime).strftime('%Y-%m-%d %H:%M:%S'), # Was taking too much horizontal space
                    'Creation':
                    datetime.fromtimestamp(ctime).strftime(
                        '%Y-%m-%d %H:%M:%S'),
                })

                sequence_number += 1

            if table_rows_to_print:
                column_names: List[str] = list(table_rows_to_print[0].keys())

                column_index_to_max_value_char_width: List[int] = [
                    max(
                        len(column_name),
                        max(
                            len(row[column_name])
                            for row in table_rows_to_print))
                    for column_name in column_names
                ]

                separator_row_text: str = ('+' + '-' * (sum(
                    char_width + 3
                    for char_width in column_index_to_max_value_char_width) -
                                                        1) + '+')

                print(separator_row_text)

                print('+ ' + ' | '.join(
                    column_name.ljust(
                        column_index_to_max_value_char_width[column_index],
                        ' ')
                    for column_index, column_name in enumerate(column_names)) +
                      ' +')

                print(separator_row_text)

                for row in table_rows_to_print:
                    print('+ ' + ' | '.join(row[column_name].ljust(
                        column_index_to_max_value_char_width[column_index],
                        ' ') for column_index, column_name in enumerate(
                            column_names)) + ' +')

                print(separator_row_text)

        finally:

            opcode, payload = diag_input.send_recv(
                DIAG_SUBSYS_CMD_F,
                pack(
                    '<BHi',
                    DIAG_SUBSYS_FS,  # Command subsystem number
                    EFS2_DIAG_CLOSEDIR,
                    dir_fd))

            (cmd_subsystem_id, subcommand_code,
             errno) = unpack('<BHi', payload)

            if errno:
                print('Error executing CLOSEDIR: %s' %
                      (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
                return
Exemple #8
0
    def execute_command(self, diag_input, args: Namespace):

        encoded_path: bytes = args.path.encode('latin1').decode(
            'unicode_escape').encode('latin1') + b'\x00'

        opcode, payload = diag_input.send_recv(
            DIAG_SUBSYS_CMD_F,
            pack(
                '<BH',
                DIAG_SUBSYS_FS,  # Command subsystem number,
                EFS2_DIAG_STAT) + encoded_path,
            accept_error=True)

        readdir_struct = '<BHI8i'

        (cmd_subsystem_id, subcommand_code, errno, mode, size, num_links,
         atime, mtime, ctime) = unpack('<BH7i', payload)

        if errno:
            print('Error executing STAT: %s' %
                  (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
            return

        if opcode != DIAG_SUBSYS_CMD_F:

            print('Error executing STAT: %s received with payload "%s"' %
                  (message_id_to_name.get(opcode, opcode), repr(payload)))
            return

        special_flags: List[str] = []
        if mode & 0o4000:
            special_flags.append('(setuid)')  # S_ISUID - Set UID on execution.
        if mode & 0o2000:
            special_flags.append('(setgid)')  # S_ISGID - Set GID on execution.
        if mode & 0o1000:
            special_flags.append(
                '(sticky)')  # S_ISVTX - Sticky (HIDDEN attribute in HFAT)

        file_rights = ''
        for shift in range(8, -1, -1):  # (1<<8) == 0o400, ...
            file_rights += 'rwx'[(8 - shift) % 3] if (mode &
                                                      (1 << shift)) else '-'

        # Resolve the symbolic file of the concerned file if needed

        real_path: Optional[str] = None

        if mode & 0o170000 == 0o120000:  # S_IFLNK

            opcode, payload = diag_input.send_recv(
                DIAG_SUBSYS_CMD_F,
                pack(
                    '<BH',
                    DIAG_SUBSYS_FS,  # Command subsystem number,
                    EFS2_DIAG_READLINK) + encoded_path,
                accept_error=False)

            readlink_struct = '<BHI'

            (cmd_subsystem_id, subcommand_code,
             errno) = unpack(readlink_struct,
                             payload[:calcsize(readlink_struct)])

            real_path = payload[calcsize(readlink_struct):].rstrip(
                b'\x00').decode('latin1')

            if errno:
                print('Error executing READLINK: %s' %
                      (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
                return

        print()

        for row, value in {
                'File type':
                EFS2_FILE_TYPES[mode & 0o170000],
                'Special flags':
                ' '.join(special_flags),
                'File rights':
                file_rights,
                'File name':
                repr(args.path) +
            ((' -> ' + repr(real_path)) if real_path else ''),
                'Number of entries' if mode & 0o170000 == 0o040000 else 'File size':
                str(size),  # Directory (S_IFDIR)
                'Number of links on the filesystem':
                str(num_links),
                'Modification time':
                datetime.fromtimestamp(mtime).strftime('%Y-%m-%d %H:%M:%S'),
                'Access time':
                datetime.fromtimestamp(
                    atime).strftime('%Y-%m-%d %H:%M:%S'
                                    ),  # Was taking too much horizontal space
                'Creation time':
                datetime.fromtimestamp(ctime).strftime('%Y-%m-%d %H:%M:%S'),
        }.items():
            if value:
                print(' - %s: %s' % (row, value))

        print()
Exemple #9
0
 def execute_command(self, diag_input, args : Namespace):
     
     remote_src : str = args.remote_src
     local_dst : str = expanduser(args.local_dst or (getcwd() + '/' + basename(remote_src)))
     
     if exists(local_dst) and isdir(local_dst):
         local_dst += '/' + basename(remote_src)
     
     if not exists(realpath(dirname(local_dst))):
         print('Error: "%s": No such file or directory' % local_dst)
         return
     
     opcode, payload = diag_input.send_recv(DIAG_SUBSYS_CMD_F, pack('<BHii',
         DIAG_SUBSYS_FS, # Command subsystem number
         EFS2_DIAG_OPEN,
         0x0, # oflag - "O_RDONLY"
         0, # mode (ignored)
     ) + remote_src.encode('latin1').decode('unicode_escape').encode('latin1') + b'\x00', accept_error = True)
     
     if opcode != DIAG_SUBSYS_CMD_F:
         print('Error executing OPEN: %s received with payload "%s"' % (message_id_to_name.get(opcode, opcode),
             repr(payload)))
         return
     
     (cmd_subsystem_id, subcommand_code,
         file_fd, errno) = unpack('<BHIi', payload)
     
     if errno:
         print('Error executing OPEN: %s' % (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
         return
     
     try: # try/finally block for remotely closing the file opened with the "EFS2_DIAG_OPEN" command in all cases:
         
         BYTES_TO_READ = 1024
         
         with open(local_dst, 'wb') as output_file:
             
             while True:
                 
                 opcode, payload = diag_input.send_recv(DIAG_SUBSYS_CMD_F, pack('<BHiII',
                     DIAG_SUBSYS_FS, # Command subsystem number
                     EFS2_DIAG_READ,
                     file_fd, # File descriptor to read from
                     BYTES_TO_READ, # Bytes to read at once
                     output_file.tell() # Offset where to read
                 ))
                 
                 read_struct = '<BHiIii'
                 
                 (cmd_subsystem_id, subcommand_code,
                         file_fd, offset, num_bytes_read,
                         errno) = unpack(read_struct, payload[:calcsize(read_struct)])
                 
                 read_data : bytes = payload[calcsize(read_struct):]
                 
                 output_file.write(read_data)
                 
                 if errno:
                     print('Error executing READ: %s' % (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
                     return
                 
                 if len(read_data) < BYTES_TO_READ:
                     break # EOF was reached
         
     
     finally:
         
         opcode, payload = diag_input.send_recv(DIAG_SUBSYS_CMD_F, pack('<BHi',
             DIAG_SUBSYS_FS, # Command subsystem number
             EFS2_DIAG_CLOSE,
             file_fd
         ))
         
         (cmd_subsystem_id, subcommand_code, errno) = unpack('<BHi', payload)
         
         if errno:
             print('Error executing CLOSE: %s' % (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
             return
Exemple #10
0
    def execute_command(self, diag_input, args: Namespace):

        local_src: str = expanduser(args.local_src)
        remote_dst: str = args.remote_dst

        if not exists(local_src):

            print('Error: "%s" does not exist on your local disk' % local_src)
            return

        with open(local_src, 'rb') as input_file:

            # First, emit a stat() (EFS2_DIAG_STAT) call in order to understand whether
            # the remote target path input by the user is a directory or not, and to
            # know the UNIX mode of the original file in the case where it already
            # exists, so that we don't have to overwrite it when uploading our
            # new file with open() (EFS2_DIAG_OPEN)

            file_mode_int: int = 0o100777  # By default, our remotely created file will have all rights, and be a regular file (S_IFREG)
            is_directory: bool = False

            opcode, payload = diag_input.send_recv(
                DIAG_SUBSYS_CMD_F,
                pack(
                    '<BH',
                    DIAG_SUBSYS_FS,  # Command subsystem number
                    EFS2_DIAG_STAT,
                ) + remote_dst.encode('latin1').decode(
                    'unicode_escape').encode('latin1') + b'\x00',
                accept_error=True)

            if opcode == DIAG_SUBSYS_CMD_F:  # No error, file or directory exists?

                (cmd_subsystem_id, subcommand_code, errno, file_mode,
                 file_size, num_links, atime, mtime,
                 ctime) = unpack('<BH7i', payload)

                if not errno:

                    if file_mode & 0o170000 == 0o040000:  # S_IFDIR
                        is_directory = True

                    else:
                        file_mode_int = file_mode

            if is_directory:

                remote_dst += '/' + basename(local_src)

            # Then, actually open the file for write and/or creation

            opcode, payload = diag_input.send_recv(
                DIAG_SUBSYS_CMD_F,
                pack(
                    '<BHii',
                    DIAG_SUBSYS_FS,  # Command subsystem number
                    EFS2_DIAG_OPEN,
                    0o1101,  # oflag - "O_WRONLY | O_TRUNC | O_CREAT "
                    file_mode_int,  # mode
                ) + remote_dst.encode('latin1').decode(
                    'unicode_escape').encode('latin1') + b'\x00',
                accept_error=True)

            if opcode != DIAG_SUBSYS_CMD_F:
                print('Error executing OPEN: %s received with payload "%s"' %
                      (message_id_to_name.get(opcode, opcode), repr(payload)))
                return

            (cmd_subsystem_id, subcommand_code, file_fd,
             errno) = unpack('<BHIi', payload)

            if errno:
                print('Error executing OPEN: %s' %
                      (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
                return

            try:  # try/finally block for remotely closing the file opened with the "EFS2_DIAG_OPEN" command in all cases:

                BYTES_TO_WRITE = 1024

                while True:

                    read_position: int = input_file.tell()
                    read_data: bytes = input_file.read(BYTES_TO_WRITE)

                    if not read_data:  # EOF was reached
                        break

                    opcode, payload = diag_input.send_recv(
                        DIAG_SUBSYS_CMD_F,
                        pack(
                            '<BHiI',
                            DIAG_SUBSYS_FS,  # Command subsystem number
                            EFS2_DIAG_WRITE,
                            file_fd,  # File descriptor to write to
                            read_position  # File position to write at
                        ) + read_data)

                    (cmd_subsystem_id, subcommand_code, file_fd, offset,
                     num_bytes_written, errno) = unpack('<BHiIii', payload)

                    if errno:
                        print('Error executing WRITE: %s' %
                              (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
                        return

            finally:

                opcode, payload = diag_input.send_recv(
                    DIAG_SUBSYS_CMD_F,
                    pack(
                        '<BHi',
                        DIAG_SUBSYS_FS,  # Command subsystem number
                        EFS2_DIAG_CLOSE,
                        file_fd))

                (cmd_subsystem_id, subcommand_code,
                 errno) = unpack('<BHi', payload)

                if errno:
                    print('Error executing CLOSE: %s' %
                          (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
                    return
Exemple #11
0
    def execute_command(self, diag_input, args: Namespace):

        try:
            assert int(args.octal_perms, 8) & ~0o777 == 0
        except Exception:
            print('Error: "octal_perms" should be a three-digit octal number')
            return

        # First, emit a stat() (EFS2_DIAG_STAT) call in order to understand whether
        # the remote path input by the user is a directory or not

        is_directory: bool = False

        opcode, payload = diag_input.send_recv(
            DIAG_SUBSYS_CMD_F,
            pack(
                '<BH',
                DIAG_SUBSYS_FS,  # Command subsystem number
                EFS2_DIAG_STAT,
            ) + args.file_path.encode('latin1').decode(
                'unicode_escape').encode('latin1') + b'\x00',
            accept_error=True)

        if opcode != DIAG_SUBSYS_CMD_F:

            print('Error executing STAT: %s received with payload "%s"' %
                  (message_id_to_name.get(opcode, opcode), repr(payload)))
            return

        (cmd_subsystem_id, subcommand_code, errno, file_mode, file_size,
         num_links, atime, mtime, ctime) = unpack('<BH7i', payload)

        if errno:
            print('Error executing STAT: %s' %
                  (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
            return

        file_mode = (file_mode & ~0o777) | (int(args.octal_perms, 8) & 0o777)
        file_mode &= ~0o170000  # S_IFMT (don't try to change the file type bits by default)

        if args.set_file_type:
            S_IFMT = 0o170000  # Mask of all values

            file_type_value = {
                'S_IFIFO': 0o010000,
                'S_IFCHR': 0o020000,
                'S_IFDIR': 0o040000,
                'S_IFBLK': 0o060000,
                'S_IFREG': 0o100000,
                'S_IFLNK': 0o120000,
                'S_IFSOCK': 0o140000,
                'S_IFITM': 0o160000
            }.get(args.set_file_type.upper())

            if not file_type_value:
                print(('Error: "%s" is not a valid file type, please see ' +
                       'the command help for details') % args.set_file_type)
                return

            file_mode = (file_mode & ~S_IFMT) | file_type_value

        if args.set_suid:
            file_mode |= 0o4000  # S_ISUID
        if args.unset_suid:
            file_mode &= ~0o4000  # S_ISUID
        if args.set_sgid:
            file_mode |= 0o2000  # S_ISGID
        if args.unset_sgid:
            file_mode &= ~0o2000  # S_ISGID
        if args.set_sticky:
            file_mode |= 0o1000  # S_ISVTX
        if args.unset_sticky:
            file_mode &= ~0o1000  # S_ISVTX

        # Then, actually open the file for write and/or creation

        opcode, payload = diag_input.send_recv(
            DIAG_SUBSYS_CMD_F,
            pack(
                '<BHH',
                DIAG_SUBSYS_FS,  # Command subsystem number
                EFS2_DIAG_CHMOD,
                file_mode) + args.file_path.encode('latin1').decode(
                    'unicode_escape').encode('latin1') + b'\x00',
            accept_error=True)

        if opcode != DIAG_SUBSYS_CMD_F:
            print('Error executing CHMOD: %s received with payload "%s"' %
                  (message_id_to_name.get(opcode, opcode), repr(payload)))
            return

        (cmd_subsystem_id, subcommand_code, errno) = unpack('<BHi', payload)

        if errno:
            print('Error executing CHMOD: %s' %
                  (EFS2_ERROR_CODES.get(errno) or strerror(errno)))
            return