<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:

def set_crypttab(
        name,
        device,
        password='none',
        options='',
        config='/etc/crypttab',
        test=False,
        match_on='name'):
    '''
    Verify that this device is represented in the crypttab, change the device to
    match the name passed, or add the name if it is not present.

    CLI Example:

    .. code-block:: bash

        salt '*' cryptdev.set_crypttab foo /dev/sdz1 mypassword swap,size=256
    '''

    # Fix the options type if it is not a string
    if options is None:
        options = ''
    elif isinstance(options, six.string_types):
        pass
    elif isinstance(options, list):
        options = ','.join(options)
    else:
        msg = 'options must be a string or list of strings'
        raise CommandExecutionError(msg)

    # preserve arguments for updating
    entry_args = {
        'name': name,
        'device': device,
        'password': password if password is not None else 'none',
        'options': options,
    }

    lines = []
    ret = None

    # Transform match_on into list--items will be checked later
    if isinstance(match_on, list):
        pass
    elif not isinstance(match_on, six.string_types):
        msg = 'match_on must be a string or list of strings'
        raise CommandExecutionError(msg)
    else:
        match_on = [match_on]

    # generate entry and criteria objects, handle invalid keys in match_on
    entry = _crypttab_entry(**entry_args)
    try:
        criteria = entry.pick(match_on)

    except KeyError:
        filterFn = lambda key: key not in _crypttab_entry.crypttab_keys
        invalid_keys = six.moves.filter(filterFn, match_on)

        msg = 'Unrecognized keys in match_on: "{0}"'.format(invalid_keys)
        raise CommandExecutionError(msg)

    # parse file, use ret to cache status
    if not os.path.isfile(config):
        raise CommandExecutionError('Bad config file "{0}"'.format(config))

    try:
        with salt.utils.files.fopen(config, 'r') as ifile:
            for line in ifile:
                line = salt.utils.stringutils.to_unicode(line)
                try:
                    if criteria.match(line):
                        # Note: If ret isn't None here,
                        # we've matched multiple lines
                        ret = 'present'
                        if entry.match(line):
                            lines.append(line)
                        else:
                            ret = 'change'
                            lines.append(six.text_type(entry))
                    else:
                        lines.append(line)

                except _crypttab_entry.ParseError:
                    lines.append(line)

    except (IOError, OSError) as exc:
        msg = 'Couldn\'t read from {0}: {1}'
        raise CommandExecutionError(msg.format(config, exc))

    # add line if not present or changed
    if ret is None:
        lines.append(six.text_type(entry))
        ret = 'new'

    if ret != 'present':  # ret in ['new', 'change']:
        if not test:
            try:
                with salt.utils.files.fopen(config, 'w+') as ofile:
                    # The line was changed, commit it!
                    ofile.writelines((salt.utils.stringutils.to_str(line) for line in lines))
            except (IOError, OSError):
                msg = 'File not writable {0}'
                raise CommandExecutionError(msg.format(config))

    return ret