'Execute the ``READ`` command of the ``SYNC`` API.
Arguments:
path(str): Path to the file to read
filesize(int): Size of the file, in bytes.  Optional.
callback(callable): Callback function invoked as data
becomes available.  Arguments provided are:
- File path
- All data
- Expected size of all data
- Current chunk
- Expected size of chunk
Return:
The data received as a string.'

@_with_transport
@_sync
def read(self, path, filesize=0, callback=(lambda *a: True)):

    self.c.send((('RECV' + p32(len(path))) + path))
    all_data = ''
    while True:
        magic = self.c.recvn(4)
        if (magic == 'DONE'):
            break
        if (magic == 'FAIL'):
            self.error(('Could    not    read    file    %r:    Got    FAIL.' % path))
        if (magic != 'DATA'):
            self.error(('Error    after    file    read:    %r    (expected    DATA)' % magic))
        chunk_size = self.c.u32()
        chunk_data = ''
        while (len(chunk_data) != chunk_size):
            chunk_data += self.c.recv((chunk_size - len(chunk_data)))
            if callback:
                callback(path, all_data, filesize, chunk_data, chunk_size)
        all_data += chunk_data
    zero = self.c.u32()
    if (zero != 0):
        self.error(('Error    after    file    read:    %r    (expected    ZERO)' % zero))
    return all_data
