05 August 2017

Huawei Matebook X sound problems (distortions) at low volumes



I'm having problem with my Huawei Mateboox X. When playing music or Windows sounds at low volume I get distortions/cracks in the sound:


I've got confirmation that another Matebook X user also have this problem. This makes it very likely that it is not a specific problem with my notebook.


I’m very sure it is a driver issue. After a clean Windows install (directly from Microsoft homepage) without network and manually installing the Realtek driver directly from Realtek home page (saved on a USB stick) there is no sound problem.

After I enable the network and Windows update automatically starts installing drivers I get the problem back.

I hope that Huawei/Realtek/Dolby can fix this problem.

27 April 2016

List the scriptlets of an RPM file

On Windows 7-Zip is my favorite tool to view RPM files. Just open the file in 7-Zip to view its contents:

In the above screenshot I have opened the sudo RPM and I can see the files that would be copied into the file system if the RPM is installed.

Unfortunately you cannot see the RPM scriptlets (the %pre, %post, %preun, %postun etc) with 7-Zip. For that I have not found any GUI alternative, but the Linux rpm command can give the scriptlets:
[root@krusty temp]# rpm -qp --scripts sudo-1.8.6p7-17.el7_2.x86_64.rpm
postinstall scriptlet (using /bin/sh):
/bin/chmod 0440 /etc/sudoers || :


As seen in the above command only one scriptlet exists, the postinstall, that issues a chmod command.

11 December 2015

Close and kill TCP sockets on Linux (and Windows)

Sometimes it can be good to test how a program will behave if a TCP socket/connection that the program has created is closed.

For Windows it can easily be done by using Microsoft Windows Sysinternals program TCPView by right clicking on a TCP connection and choose "Close Connection". I'm not sure how it is implemented but by using Wireshark capture while closing a TCP connection you can see that a RST TCP segment is sent to the from your host to the remote side.

But with Linux it is a bit tricker. Here is a script I created that can do it:

#!/bin/bash

#Syntax: ./killtcp.sh 5328 10.10.14.41 14001
#                     PID  IP          PORT

pid=$1
ip=$2
port=$3

file_descriptors=`lsof -Pnp $pid`

echo "$file_descriptors" |grep TCP | grep $ip:$port | while read file_descriptor
do
    handle=`echo $file_descriptor | cut -f4 -d' '`
    handle=${handle/[a-z]/}
    echo "call close($handle)" > gdb_debugger.txt
    sudo gdb -p $pid -batch -x gdb_debugger.txt
done


It uses lsof to find out the internal file descriptor handle(s) of the application. Then it writes gdb close commands to a file (file was the only way I could get it into gdb). Then it uses gdb to connect to the PID of the program with the TCP connection and forces a close on the file handle(s).

This is not the cleanest way to do it. It might crash your application!? But I have used it successfully on ssh and some java programs I wrote and it worked okay.

29 October 2015

How to make a JTable a specific number of rows high

Java Swing is rather complex. You can do just about anything, but it can be hard to know how to do it. I have for a long time tried to adapt the visible (preferred) size of a JTable. I know how many rows I would like to display, but it is hard to know how to write the code for it.

I figured out this code today:
package se.lesc.blog;

import java.awt.Insets;

import javax.swing.GroupLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import static javax.swing.GroupLayout.DEFAULT_SIZE;

public class TableRowDemo extends JFrame {

    Object[][] data = { {"Kathy", "Smith", "Snowboarding", new Integer(5), new Boolean(false)},
        {"John", "Doe", "Rowing", new Integer(3), new Boolean(true)},
        {"Sue", "Black", "Knitting", new Integer(2), new Boolean(false)},
        {"Jane", "White", "Speed reading", new Integer(20), new Boolean(true)},
        {"Joe", "Brown", "Pool", new Integer(10), new Boolean(false)}
    };
  
    String[] columnNames = {"First Name", "Last Name", "Sport", "# of Years", "Vegetarian"};
  
    public static void main(String [] args) {
        new TableRowDemo().setVisible(true);
    }
  
    public TableRowDemo() {
        GroupLayout layout = new GroupLayout(getContentPane());
      
        JLabel label = new JLabel("My table:");
        JTable table = new JTable(data, columnNames);
      
        JScrollPane tableScrollPane = new JScrollPane(table);
      
        int numberOfRowsToDisplay = 3;
      
        //Fetch the border "padding"
        Insets insets = tableScrollPane.getBorder().getBorderInsets(table);
      
        //Compute the total height of the table
        int preferredTableHeight = insets.bottom + insets.top
                        + (int) table.getTableHeader().getPreferredSize().getHeight() +
                        numberOfRowsToDisplay * table.getRowHeight();
      
        layout.setVerticalGroup(layout.createSequentialGroup()
            .addComponent(label)
            .addComponent(tableScrollPane, DEFAULT_SIZE, preferredTableHeight, DEFAULT_SIZE)
        );
      
        layout.setHorizontalGroup(layout.createParallelGroup()
            .addComponent(label)
            .addComponent(tableScrollPane)
        );

        getContentPane().setLayout(layout);
        pack();
    }
}

15 September 2015

How Microsoft SmartScreen works and how it stores data in NTFS streams



Windows 10 (and 8) has a feature called Microsoft SmartScreen. It is split in two parts: one purely for the web and one for files downloaded for the web. I’ll try to explain how SmartScreen for downloaded files work. But first we need to know how streams works

ADS or just ”streams” is a feature in Microsoft NTFS file system feature that allows for ”hidden” data in a file. You can access the hidden data by using the colon separator.
Copy ftp.exe from C:\Windows\System32 to c:\temp\. I used ftp.exe because it is an unsigned executable that you probably can find on your hard drive. Use Windows PowerShell for these commands. Create an alternative stream by using notepad:
PS C:\temp> notepad ftp.exe:LennartStream
Answer yes in Notepad. Enter the content ”Hello World!”, save and close the file/stream. We can now open the file/stream by the same Notepad command again. No actual new file was created on the hard drive. It just created a new stream. You can list the streams by using Windows Sysinternals Streams program or just use PowerShell:
 PS C:\temp> Get-Item ftp.exe -Stream *


   FileName: C:\temp\ftp.exe

Stream                   Length
------                   ------
:$DATA                    55808
LennartStream.txt            12

As you can see my ”LennartStream” is there and it takes 12 bytes (the ”Hello World!” string). The main program for ftp takes 55808 bytes.

Microsoft SmartScreen
SmartScreen (https://en.wikipedia.org/wiki/Microsoft_SmartScreen) provides some protection for executing downloaded files from the internet. When a file is downloaded in the web browser (for example Firefox), a stream called “Zone.Identifier” is created. If the Zone is “dangerous” a warning dialog may be presented to the user when the file is run. In Windows 10 the settings for SmartScreen is in Control Panel\System and Security\Security and Maintenance.

Use notepad to edit the Zone.Identifier stream:
PS C:\temp> notepad ftp.exe:Zone.Identifier
Create a new stream and enter this content:
[ZoneTransfer]

ZoneId=3
Now double click on ftp.exe to run it. You will now get a dialog like this:
“Windows protected your PC. Windows SmartScreen prevented an unrecognized app from starting. Running this app might put your PC at risk”


Press “More info”:

Choose “Run anyway” and then just close the ftp program. View the Zone.Identifier stream again:
PS C:\temp> notepad ftp.exe:Zone.Identifier
The content has now changed to:
[ZoneTransfer]

AppZoneId=4
As you can see SmartScreen has updated the stream data with respect to your answer in the dialog.

Please note that if the file is signed with a certificate and Microsoft can verify it (with some magical “reputation” system I don’t know the details on) the dialog may not be shown and the stream will not be changed.

23 April 2014

What to do when you get "Comparison method violates its general contract!"

Java 7 switched to a new sort algorithm - called ComparableTimSort. The old algorithm would silently ignore when you violate the Comparator/Comparable contract. The new one throws an exception "Comparison method violates its general contract!"

The contract is in the interface Comparable. The most common is to break the transitive contract. That is: If A < B and B < C, than A should be less than C. Stackoverflow.com has several posts on the issue.

I have made a small program that detects what elements that causes this issue. It only works for small lists but has helped me to debug compareTo()/compare() methods.

package se.lesc.blog;

import java.util.Comparator;

public class TransitivityTester {

    public static void transitivityTester(Object list[]) {
        transitivityTester(list, null);
    }
    
    /** Check that a lists compareTo() method is correct with respect to transitivity */    
    public static void transitivityTester(Object list[], Comparator<Object> comparator) {

        //Cache all possible comparison (for speed)
        byte[][] compareTable = new byte[list.length][];
        for (int x = 0; x < list.length; x++) {
            byte[] column = new byte[list.length];
            compareTable[x] = column;
            for (int y = 0; y < list.length; y++) {
                int result;
                if (comparator != null) {
                    result = comparator.compare(list[x], list[y]);    
                } else {
                    @SuppressWarnings("unchecked")
                    Comparable<Object> comparableX = (Comparable<Object>)list[x];
                    result = comparableX.compareTo(list[y]);
                }
                
                byte normalizedResult = normalize(result);
                column[y] = normalizedResult; 
            }
        }
        
        //Expensive O(n^3) iteration
        for (int a = 0; a < list.length; a++) {
            for (int b = 0; b < list.length; b++) {
                for (int c = 0; c < list.length; c++) {

                    if (compareTable[a][b] < 0 && compareTable[b][c] < 0) {
                        if (! (compareTable[a][c] < 0)) {
                            transitiveError("A < B && B < C but not A < C", a, b, c);
                        }
                    } else if (compareTable[a][b] > 0 && compareTable[b][c] > 0) {
                        if (! (compareTable[a][c] > 0)) {
                            transitiveError("A > B && B > C but not A > C", a, b, c);
                        }
                    } else if (compareTable[a][b] == 0 && compareTable[b][c] == 0) {
                        if (! (compareTable[a][c] == 0)) {
                            transitiveError("A == B && B == C but not A == C", a, b, c);
                        }
                    }
                }
            }
        }
    }
    
    private static void transitiveError(String transitiveRule, int a, int b, int c) {
        String errorMessage =
                        transitiveRule +
                        " (A = " + a + ", B= " + b + ", C = " + c + ") " + 
                        "Comparison method violates its general contract!";
        throw new IllegalArgumentException(errorMessage);
    }

    private static byte normalize(int result) {
        byte normalizedResult;
        if (result > 0) {
            normalizedResult = 1;
        } else if (result < 0) {
            normalizedResult = -1;
        } else {
            normalizedResult = 0;
        }
        return normalizedResult;
    }
}

Here is some test code for the above class:
package se.lesc.blog;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

public class TransitivityTesterTest {

    private List<Integer> list;

    @Before
    public void setUp() {
        list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);
    }

    @Test
    public void testNormalIntegerListShouldWork() {
        TransitivityTester.transitivityTester(list.toArray(new Integer[0]));        
    }
    
    @Test
    public void testCrazyOneIsAlwaysMoreComparator() {
        TransitivityTester.transitivityTester(list.toArray(new Integer[0]), new CrazyOneIsAlwaysMoreComparator());        
    }
    
    @Test
    public void testCrazyAllIsOneComparator() {
        TransitivityTester.transitivityTester(list.toArray(new Integer[0]), new CrazyAllIsOneComparator());        
    }
    
    public static class CrazyOneIsAlwaysMoreComparator implements Comparator<Object> {
        @Override
        public int compare(Object o1, Object o2) {
            Integer i1 = (Integer) o1;
            Integer i2 = (Integer) o2;
            if (i1.intValue() == 1) {
                return 1; 
            } else {
                return i1.compareTo(i2);
            }
        }
    }
    
    public static class CrazyAllIsOneComparator implements Comparator<Object> {
        @Override
        public int compare(Object o1, Object o2) {
            Integer i1 = (Integer) o1;
            Integer i2 = (Integer) o2;
            if (i1.intValue() == 1 || i2.intValue() == 1) {
                return 0; 
            } else {
                return i1.compareTo(i2);
            }
        }
    }
}