Ticket #10134: 0001-Added-Disk-image-menu-register-unregister-disk-image.patch

File 0001-Added-Disk-image-menu-register-unregister-disk-image.patch, 62.9 KB (added by dsjonny, 10 years ago)
  • src/apps/drivesetup/DiskView.cpp

    From 2d83634b23804715d9250836e7f563800c622d61 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?Dancs=C3=B3=20R=C3=B3bert?= <dancso.robert@d-rendszer.hu>
    Date: Fri, 20 Dec 2013 15:59:22 +0100
    Subject: [PATCH] Added Disk image menu: register/unregister disk images, save
     partition to an image, write image to a partition.
    
    Added drop disk images to register images quickly.
    
    Added BitLocker/PGP/SafeBoot/LUKS encryption detection.
    
    If only one disk is in the list, DriveSetup automatically select it.
    
    Added icons for the boot/readonly/shared/encrypted/virtual drives/partitions.
    
    Show with a different color if the drive is boot/BFS/encrypted.
    
    Indicate the used space on the disk map.
    
    Added more partition info to the Parameters column.
    
    Added Open with DiskProbe menu item.
    
    Added free space and block size column.
    ---
     src/apps/drivesetup/DiskView.cpp      | 145 +++++++-
     src/apps/drivesetup/Jamfile           |   2 +-
     src/apps/drivesetup/MainWindow.cpp    | 622 +++++++++++++++++++++++++++++++++-
     src/apps/drivesetup/MainWindow.h      |  24 ++
     src/apps/drivesetup/PartitionList.cpp | 130 +++++--
     src/apps/drivesetup/icons.h           | 356 +++++++++++++++++++
     6 files changed, 1248 insertions(+), 31 deletions(-)
     create mode 100644 src/apps/drivesetup/icons.h
    
    diff --git a/src/apps/drivesetup/DiskView.cpp b/src/apps/drivesetup/DiskView.cpp
    index 8980cfe..96d7565 100644
    a b  
    77
    88#include <stdio.h>
    99
     10#include <Application.h>
     11#include <Bitmap.h>
    1012#include <DiskDeviceVisitor.h>
    1113#include <Catalog.h>
    1214#include <GroupLayout.h>
    1315#include <HashMap.h>
     16#include <IconUtils.h>
    1417#include <LayoutItem.h>
    1518#include <Locale.h>
    1619#include <PartitioningInfo.h>
     20#include <Path.h>
     21#include <Resources.h>
    1722#include <String.h>
     23#include <Volume.h>
     24#include <VolumeRoster.h>
    1825
     26#include "icons.h"
    1927#include "MainWindow.h"
    2028
    2129
    static const float kLayoutInset = 6;  
    3442class PartitionView : public BView {
    3543public:
    3644    PartitionView(const char* name, float weight, off_t offset,
    37             int32 level, partition_id id)
     45            int32 level, partition_id id, BPartition* partition)
    3846        :
    3947        BView(name, B_WILL_DRAW | B_SUPPORTS_LAYOUT | B_FULL_UPDATE_ON_RESIZE),
    4048        fID(id),
    public:  
    6371        fGroupLayout->SetInsets(kLayoutInset, kLayoutInset + font.Size(),
    6472            kLayoutInset, kLayoutInset);
    6573
    66         SetExplicitMinSize(BSize(font.Size() + 6, 30));
     74        SetExplicitMinSize(BSize(font.Size() + 20, 30));
     75
     76        fName = name;
     77
     78        BVolume volume;
     79        partition->GetVolume(&volume);
     80
     81        BVolume boot;
     82        BVolumeRoster().GetBootVolume(&boot);
     83        fBoot = volume == boot;
     84        fReadOnly = volume.IsReadOnly();
     85        fShared = volume.IsShared();
     86        fEncrypted = false;
     87
     88        BPath path;
     89        partition->GetPath(&path);
     90       
     91        if (partition->Device()->IsFile()) {
     92            fName = B_TRANSLATE("Virtual");
     93            fVirtual = true;
     94        } else
     95            fVirtual = false;
     96
     97        const char* encrypter = dynamic_cast<MainWindow*>(Window())->EncryptionType(path.Path());
     98        if (encrypter) {
     99            fName = encrypter;
     100            fEncrypted = true;
     101        }
     102       
     103        if (partition->Parent() != NULL) {
     104            partition->GetPath(&path);
     105
     106            encrypter = dynamic_cast<MainWindow*>(Window())->EncryptionType(path.Path());
     107            if (encrypter) {
     108                fName = encrypter;
     109                fEncrypted = true;
     110            }
     111        }
     112       
     113        fUsed = 100.0 / ((float)volume.Capacity() / (volume.Capacity() - volume.FreeBytes()));
     114        if (fUsed < 0)
     115            fUsed = 100.0;
     116
     117        fIcon = new BBitmap(BRect(0, 0, 15, 15), B_RGBA32);
     118
     119        fBFS = BString(partition->ContentType()) == "Be File System";
     120
     121        if (fBoot)
     122            BIconUtils::GetVectorIcon(kLeaf, sizeof(kLeaf), fIcon);
     123        else if (fEncrypted)
     124            BIconUtils::GetVectorIcon(kEncrypted, sizeof(kEncrypted), fIcon);
     125        else if (fReadOnly)
     126            BIconUtils::GetVectorIcon(kReadOnly, sizeof(kReadOnly), fIcon);
     127        else if (fShared)
     128            BIconUtils::GetVectorIcon(kShared, sizeof(kShared), fIcon);
     129        else if (fVirtual)
     130            BIconUtils::GetVectorIcon(kFile, sizeof(kFile), fIcon);
     131        else
     132            fIcon = NULL;
    67133    }
    68134
    69135    virtual void MouseDown(BPoint where)
    public:  
    94160
    95161        BRect b(Bounds());
    96162        if (fSelected) {
    97             SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
     163            if (fReadOnly)
     164                SetHighColor(make_color(255, 128, 128));
     165            else if (fBoot || fBFS)
     166                SetHighColor(make_color(128, 255, 128));
     167            else
     168                SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
    98169            StrokeRect(b, B_SOLID_HIGH);
    99170            b.InsetBy(1, 1);
    100171            StrokeRect(b, B_SOLID_HIGH);
    101172            b.InsetBy(1, 1);
    102         } else if (fLevel > 0) {
     173        } else if (fLevel >= 0) {
    103174            StrokeRect(b, B_SOLID_HIGH);
    104175            b.InsetBy(1, 1);
    105176        }
    106177
     178        if (CountChildren() == 0)
     179            SetLowColor(make_color(255, 255, 255));
    107180        FillRect(b, B_SOLID_LOW);
    108181
    109         // prevent the text from moving when border width changes
     182        if (fEncrypted && CountChildren() == 0) {
     183            SetHighColor(make_color(128, 128, 128));
     184            StrokeRect(b, B_SOLID_HIGH);
     185            b.InsetBy(1, 1);
     186            SetLowColor(make_color(224, 224, 0));
     187            BRect e(BPoint(15, b.top), b.RightBottom());
     188            e.InsetBy(1, 1);
     189            FillRect(e, kStripes);
     190        }
     191
    110192        if (!fSelected)
    111193            b.InsetBy(1, 1);
     194       
     195        BRect used(b.LeftTop(), BSize(b.Width() / (100.0 / fUsed), b.Height()));
     196
     197        SetLowColor(make_color(240, 248, 255));
     198
     199        if (fReadOnly)
     200            SetLowColor(make_color(255, 224, 224));
     201        if (fBoot || fBFS)
     202            SetLowColor(make_color(224, 255, 224));
     203        if (CountChildren() == 0)
     204            FillRect(used, B_SOLID_LOW);
     205
     206        if (fIcon && CountChildren() == 0) {
     207            BPoint where = b.RightBottom() - BPoint(fIcon->Bounds().Width(), fIcon->Bounds().Height());
     208            SetDrawingMode(B_OP_OVER);
     209            DrawBitmap(fIcon, where);
     210            SetDrawingMode(B_OP_COPY);
     211        }
    112212
    113213        float width;
    114214        BFont font;
    public:  
    134234        }
    135235
    136236        BString name(Name());
     237        if (fEncrypted && CountChildren() == 0)
     238            name.SetTo(fName);
     239        else if (fEncrypted)
     240            name << " (" << fName << ")";
     241        else if (fVirtual)
     242            name << " (" << fName << ")";
    137243        font.TruncateString(&name, B_TRUNCATE_END, width);
    138244
    139245        SetHighColor(tint_color(LowColor(), B_DARKEN_4_TINT));
    public:  
    168274        fSelected = selected;
    169275        Invalidate();
    170276    }
     277   
     278    bool IsEncrypted() {
     279        return fEncrypted;
     280    }
    171281
    172282private:
    173283    void _SetMouseOver(bool mouseOver)
    private:  
    186296    bool            fSelected;
    187297    bool            fMouseOver;
    188298    BGroupLayout*   fGroupLayout;
     299    bool            fBoot;
     300    bool            fReadOnly;
     301    bool            fShared;
     302    bool            fEncrypted;
     303    bool            fVirtual;
     304    float           fUsed;
     305    const char*     fName;
     306    bool            fBFS;
     307    BBitmap*        fIcon;
    189308};
    190309
    191310
    public:  
    208327        else
    209328            name = B_TRANSLATE("Device");
    210329
     330        if (BString(device->ContentName()).Length() > 0)
     331            name = device->ContentName();
     332
    211333        PartitionView* view = new PartitionView(name, 1.0,
    212             device->Offset(), 0, device->ID());
     334            device->Offset(), 0, device->ID(), device);
    213335        fViewMap.Put(device->ID(), view);
    214336        fView->GetLayout()->AddView(view);
    215337        _AddSpaces(device, view);
    public:  
    242364        }
    243365        partition_id id = partition->ID();
    244366        PartitionView* view = new PartitionView(name.String(), scale, offset,
    245             level, id);
     367            level, id, partition);
    246368        view->SetSelected(id == fSelectedPartition);
    247369        PartitionView* parent = fViewMap.Get(partition->Parent()->ID());
    248370        BGroupLayout* layout = parent->GroupLayout();
    public:  
    296418                double scale = (double)size / parentSize;
    297419                partition_id id
    298420                    = fSpaceIDMap.SpaceIDFor(partition->ID(), offset);
    299                 PartitionView* view = new PartitionView(B_TRANSLATE("<empty>"),
    300                     scale, offset, parentView->Level() + 1, id);
     421                PartitionView* view = new PartitionView(B_TRANSLATE("<empty or unknown>"),
     422                    scale, offset, parentView->Level() + 1, id, partition);
    301423
    302424                fViewMap.Put(id, view);
    303425                BGroupLayout* layout = parentView->GroupLayout();
    void  
    434556DiskView::SetDiskCount(int32 count)
    435557{
    436558    fDiskCount = count;
     559    if (count == 1) {
     560        BMessage message(MSG_SELECTED_PARTITION_ID);
     561        message.AddInt32("partition_id", 0);
     562        Window()->PostMessage(&message);
     563    }
    437564}
    438565
    439566
  • src/apps/drivesetup/Jamfile

    diff --git a/src/apps/drivesetup/Jamfile b/src/apps/drivesetup/Jamfile
    index cb003fa..086ac1f 100644
    a b Preference DriveSetup :  
    1515    PartitionList.cpp
    1616    Support.cpp
    1717
    18     : be localestub libcolumnlistview.a libshared.a
     18    : be localestub tracker libcolumnlistview.a libshared.a
    1919        $(TARGET_LIBSUPC++)
    2020    : DriveSetup.rdef
    2121;
  • src/apps/drivesetup/MainWindow.cpp

    diff --git a/src/apps/drivesetup/MainWindow.cpp b/src/apps/drivesetup/MainWindow.cpp
    index 94b6115..c56551b 100644
    a b  
    1313
    1414#include "MainWindow.h"
    1515
     16#include <errno.h>
    1617#include <stdio.h>
    1718#include <string.h>
    1819
    1920#include <Alert.h>
     21#include <AppFileInfo.h>
    2022#include <Application.h>
    2123#include <Catalog.h>
    2224#include <ColumnListView.h>
    2325#include <ColumnTypes.h>
     26#include <ControlLook.h>
    2427#include <Debug.h>
    2528#include <DiskDevice.h>
     29#include <DiskDeviceRoster.h>
    2630#include <DiskDeviceVisitor.h>
    2731#include <DiskDeviceTypes.h>
    2832#include <DiskSystem.h>
     33#include <IconUtils.h>
     34#include <LayoutBuilder.h>
    2935#include <Locale.h>
    3036#include <MenuItem.h>
    3137#include <MenuBar.h>
    enum {  
    6773    MSG_EJECT                   = 'ejct',
    6874    MSG_SURFACE_TEST            = 'sfct',
    6975    MSG_RESCAN                  = 'rscn',
     76    MSG_REGISTER                = 'regi',
     77    MSG_UNREGISTER              = 'unrg',
     78    MSG_SAVE                    = 'save',
     79    MSG_WRITE                   = 'writ',
     80    MSG_OPEN_DISKPROBE          = 'opdp',
     81    MSG_UPDATE_STATUS           = 'upst',
     82    MSG_COMPLETE                = 'comp',
    7083
    7184    MSG_PARTITION_ROW_SELECTED  = 'prsl',
    7285};
    MainWindow::MainWindow()  
    207220    fCurrentPartitionID(-1),
    208221    fSpaceIDMap()
    209222{
     223    SetSizeLimits(300, 8192, 270, 8192);
     224    UpdateSizeLimits();
     225
    210226    fMenuBar = new BMenuBar(Bounds(), "root menu");
    211227
    212228    // create all the menu items
    MainWindow::MainWindow()  
    235251    fMountAllMenuItem = new BMenuItem(B_TRANSLATE("Mount all"),
    236252        new BMessage(MSG_MOUNT_ALL), 'M', B_SHIFT_KEY);
    237253
     254    fOpenDiskProbeMenuItem = new BMenuItem(B_TRANSLATE("Open with DiskProbe"),
     255        new BMessage(MSG_OPEN_DISKPROBE));
     256
     257    fRegisterMenuItem = new BMenuItem(
     258        B_TRANSLATE("Register disk image" B_UTF8_ELLIPSIS),
     259        new BMessage(MSG_REGISTER));
     260    fUnRegisterMenuItem = new BMenuItem(
     261        B_TRANSLATE("Unregister disk image"),
     262        new BMessage(MSG_UNREGISTER));
     263    fSaveMenuItem = new BMenuItem(
     264        B_TRANSLATE("Save image" B_UTF8_ELLIPSIS),
     265        new BMessage(MSG_SAVE));
     266    fWriteMenuItem = new BMenuItem(
     267        B_TRANSLATE("Write image" B_UTF8_ELLIPSIS),
     268        new BMessage(MSG_WRITE));
     269
    238270    // Disk menu
    239271    fDiskMenu = new BMenu(B_TRANSLATE("Disk"));
    240272
    MainWindow::MainWindow()  
    268300    fPartitionMenu->AddSeparatorItem();
    269301
    270302    fPartitionMenu->AddItem(fMountAllMenuItem);
     303
     304    fPartitionMenu->AddSeparatorItem();
     305
     306    fPartitionMenu->AddItem(fOpenDiskProbeMenuItem);
    271307    fMenuBar->AddItem(fPartitionMenu);
    272308
     309    // Disk image menu
     310    fDiskImageMenu = new BMenu(B_TRANSLATE("Disk image"));
     311
     312    fDiskImageMenu->AddItem(fRegisterMenuItem);
     313    fDiskImageMenu->AddItem(fUnRegisterMenuItem);
     314
     315    fDiskImageMenu->AddSeparatorItem();
     316
     317    fDiskImageMenu->AddItem(fSaveMenuItem);
     318    fDiskImageMenu->AddItem(fWriteMenuItem);
     319
     320    fMenuBar->AddItem(fDiskImageMenu);
     321
    273322    AddChild(fMenuBar);
    274323
    275324    // Partition / Drives context menu
    MainWindow::MainWindow()  
    285334        new BMessage(MSG_MOUNT), 'M');
    286335    fUnmountContextMenuItem = new BMenuItem(B_TRANSLATE("Unmount"),
    287336        new BMessage(MSG_UNMOUNT), 'U');
     337    fOpenDiskProbeContextMenuItem = new BMenuItem(B_TRANSLATE("Open with DiskProbe"),
     338        new BMessage(MSG_OPEN_DISKPROBE));
    288339    fFormatContextMenuItem = new BMenu(B_TRANSLATE("Format"));
    289340
    290341    fContextMenu->AddItem(fCreateContextMenuItem);
    MainWindow::MainWindow()  
    294345    fContextMenu->AddSeparatorItem();
    295346    fContextMenu->AddItem(fMountContextMenuItem);
    296347    fContextMenu->AddItem(fUnmountContextMenuItem);
     348    fContextMenu->AddSeparatorItem();
     349    fContextMenu->AddItem(fOpenDiskProbeContextMenuItem);
    297350    fContextMenu->SetTargetForItems(this);
    298351
    299352    // add DiskView
    MainWindow::MainWindow()  
    317370    fListView->SetTarget(this);
    318371    fListView->MakeFocus(true);
    319372
     373    // add StatusView
     374    r.top = r.bottom + 2;
     375    r.bottom = Bounds().bottom + 40;
     376    fStatusView = new BView(r, "StatusView", B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM, 0);
     377    fStatusView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
     378    AddChild(fStatusView);
     379
     380    // add StatusBar
     381    r = fStatusView->Bounds();
     382    r.right = r.right - 15;
     383    r.InsetBy(2, -1);
     384    fStatusBar = new BStatusBar(r, "StatusBar");
     385    fStatusBar->SetResizingMode(B_FOLLOW_ALL);
     386    fStatusView->AddChild(fStatusBar);
     387
     388    fFileOpen = NULL;
     389
     390    fNotification = new BNotification(B_INFORMATION_NOTIFICATION);
     391    fNotification->SetGroup(BString(B_TRANSLATE_SYSTEM_NAME("DriveSetup")));
     392
     393    app_info info;
     394    be_roster->GetAppInfo("application/x-vnd.Haiku-DriveSetup", &info);
     395    BBitmap icon(BRect(0, 0, 32, 32), B_RGBA32);
     396    BNode node(&info.ref);
     397    BIconUtils::GetVectorIcon(&node, "BEOS:ICON", &icon);
     398    fNotification->SetIcon(&icon);
     399
    320400    status_t status = fDiskDeviceRoster.StartWatching(BMessenger(this));
    321401    if (status != B_OK) {
    322402        fprintf(stderr, "Failed to start watching for device changes: %s\n",
    MainWindow::~MainWindow()  
    339419}
    340420
    341421
     422const char*
     423MainWindow::EncryptionType(const char* path)
     424{
     425    char buffer[16];
     426    BString encrypter;
     427    BFile(path, B_READ_ONLY).ReadAt(0, &buffer, 11);
     428    encrypter.Append(buffer);
     429
     430    if (encrypter.FindFirst("-FVE-FS-") >= 0) {
     431        return B_TRANSLATE("BitLocker encrypted");
     432    } else if (encrypter.FindFirst("PGPGUARD") >= 0) {
     433        return B_TRANSLATE("PGP encrypted");
     434    } else if (encrypter.FindFirst("SafeBoot") >= 0) {
     435        return B_TRANSLATE("SafeBoot encrypted");
     436    } else if (encrypter.FindFirst("LUKS") >= 0) {
     437        return B_TRANSLATE("LUKS encrypted");
     438    }
     439
     440    return NULL;
     441}
     442
     443
     444status_t
     445MainWindow::RegisterFileDiskDevice(const char* fileName)
     446{
     447    BString message;
     448
     449    struct stat st;
     450    if (lstat(fileName, &st) != 0) {
     451        status_t error = errno;
     452
     453        message.SetTo(B_TRANSLATE("Failed to stat() %s"));
     454        message.ReplaceFirst("%s", fileName);
     455        BAlert* alert = new BAlert("error", message.String(), B_TRANSLATE("OK"), NULL, NULL,
     456            B_WIDTH_FROM_WIDEST, B_STOP_ALERT);
     457        alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
     458        alert->Go(NULL);
     459        return error;
     460    }
     461
     462    if (!S_ISREG(st.st_mode)) {
     463        message.SetTo(B_TRANSLATE("%s is not a regular file."));
     464        message.ReplaceFirst("%s", fileName);
     465        BAlert* alert = new BAlert("error", message.String(), B_TRANSLATE("OK"), NULL, NULL,
     466            B_WIDTH_FROM_WIDEST, B_STOP_ALERT);
     467        alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
     468        alert->Go(NULL);
     469        return B_BAD_VALUE;
     470    }
     471
     472    // register the file
     473    BDiskDeviceRoster roster;
     474    partition_id id = roster.RegisterFileDevice(fileName);
     475    if (id < 0) {
     476        message.SetTo(B_TRANSLATE("Failed to register file disk device: %s"));
     477        message.ReplaceFirst("%s", fileName);
     478        BAlert* alert = new BAlert("error", message.String(), B_TRANSLATE("OK"), NULL, NULL,
     479            B_WIDTH_FROM_WIDEST, B_STOP_ALERT);
     480        alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
     481        alert->Go(NULL);
     482        return id;
     483    }
     484
     485    fNotification->SetTitle(BString(B_TRANSLATE("Disk image")));
     486    fNotification->SetContent(BString(B_TRANSLATE("Disk image has been mounted.")));
     487    fNotification->Send();
     488
     489    return B_OK;
     490}
     491
     492
     493status_t
     494MainWindow::UnRegisterFileDiskDevice(const char* fileNameOrID)
     495{
     496    BString message;
     497
     498    // try to parse the parameter as ID
     499    char* numberEnd;
     500    partition_id id = strtol(fileNameOrID, &numberEnd, 0);
     501    BDiskDeviceRoster roster;
     502    if (id >= 0 && numberEnd != fileNameOrID && *numberEnd == '\0') {
     503        BDiskDevice device;
     504        if (roster.GetDeviceWithID(id, &device) == B_OK && device.IsFile()) {
     505            status_t error = roster.UnregisterFileDevice(id);
     506            if (error != B_OK) {
     507                message.SetTo(B_TRANSLATE("Failed to unregister file disk device."));
     508                BAlert* alert = new BAlert("error", message.String(), B_TRANSLATE("OK"), NULL, NULL,
     509                    B_WIDTH_FROM_WIDEST, B_STOP_ALERT);
     510                alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
     511                alert->Go(NULL);
     512                return error;
     513            }
     514
     515            fNotification->SetTitle(BString(B_TRANSLATE("Disk image")));
     516            fNotification->SetContent(BString(B_TRANSLATE("Disk image has been removed.")));
     517            fNotification->Send();
     518
     519            return B_OK;
     520        } else {
     521            message.SetTo(B_TRANSLATE("No file disk device found with the given ID, trying file %s"));
     522            message.ReplaceFirst("%s", fileNameOrID);
     523            BAlert* alert = new BAlert("error", message.String(), B_TRANSLATE("OK"), NULL, NULL,
     524                B_WIDTH_FROM_WIDEST, B_WARNING_ALERT);
     525            alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
     526            alert->Go(NULL);
     527        }
     528    }
     529
     530    // the parameter must be a file name -- stat() it
     531    struct stat st;
     532    if (lstat(fileNameOrID, &st) != 0) {
     533        status_t error = errno;
     534        message.SetTo(B_TRANSLATE("Failed to stat() \"%s\""));
     535        message.ReplaceFirst("%s", fileNameOrID);
     536        BAlert* alert = new BAlert("error", message.String(), B_TRANSLATE("OK"), NULL, NULL,
     537            B_WIDTH_FROM_WIDEST, B_STOP_ALERT);
     538        alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
     539        alert->Go(NULL);
     540        return error;
     541    }
     542
     543    // remember the volume and node ID, so we can identify the file
     544    // NOTE: There's a race condition -- we would need to open the file and
     545    // keep it open to avoid it.
     546    dev_t volumeID = st.st_dev;
     547    ino_t nodeID = st.st_ino;
     548
     549    // iterate through all file disk devices and try to find a match
     550    BDiskDevice device;
     551    while (roster.GetNextDevice(&device) == B_OK) {
     552        if (!device.IsFile())
     553            continue;
     554
     555        // get file path and stat it, same for the device path
     556        BPath path;
     557        bool isFilePath = true;
     558        if ((device.GetFilePath(&path) == B_OK && lstat(path.Path(), &st) == 0
     559                && volumeID == st.st_dev && nodeID == st.st_ino)
     560            || (isFilePath = false, false)
     561            || (device.GetPath(&path) == B_OK && lstat(path.Path(), &st) == 0
     562                && volumeID == st.st_dev && nodeID == st.st_ino)) {
     563            status_t error = roster.UnregisterFileDevice(device.ID());
     564            if (error != B_OK) {
     565                message.SetTo(B_TRANSLATE("Failed to unregister file disk device %s"));
     566                message.ReplaceFirst("%s", fileNameOrID);
     567                BAlert* alert = new BAlert("error", message.String(), B_TRANSLATE("OK"), NULL, NULL,
     568                    B_WIDTH_FROM_WIDEST, B_STOP_ALERT);
     569                alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
     570                alert->Go(NULL);
     571                return error;
     572            }
     573
     574            fNotification->SetTitle(BString(B_TRANSLATE("Disk image")));
     575            fNotification->SetContent(BString(B_TRANSLATE("Disk image has been removed.")));
     576            fNotification->Send();
     577
     578            return B_OK;
     579        }
     580    }
     581
     582    message.SetTo(B_TRANSLATE("%s does not refer to a file disk device."));
     583    message.ReplaceFirst("%s", fileNameOrID);
     584    BAlert* alert = new BAlert("error", message.String(), B_TRANSLATE("OK"), NULL, NULL,
     585        B_WIDTH_FROM_WIDEST, B_WARNING_ALERT);
     586    alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
     587    alert->Go(NULL);
     588    return B_BAD_VALUE;
     589}
     590
     591
     592int32
     593MainWindow::SaveDiskImage(void* data)
     594{
     595    BMessage* msg = (BMessage*)data;
     596    const char* sourcepath;
     597    const char* targetpath;
     598    const char* targetfolder;
     599    int32 partitionID;
     600    BMessenger messenger;
     601
     602    msg->FindString("source", &sourcepath);
     603    msg->FindString("target", &targetpath);
     604    msg->FindString("targetfolder", &targetfolder);
     605    msg->FindInt32("partitionID", &partitionID);
     606    msg->FindMessenger("messenger", &messenger);
     607
     608    BFile source(sourcepath, B_READ_ONLY);
     609    BFile target(targetpath, B_READ_WRITE | B_CREATE_FILE);
     610    BAlert* alert;
     611
     612    if (source.InitCheck() != B_OK) {
     613        alert = new BAlert("error", B_TRANSLATE("Cannot init source volume."),
     614            B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_FROM_WIDEST, B_STOP_ALERT);
     615        alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
     616        alert->Go(NULL);
     617        return -1;
     618    }
     619
     620    if (target.InitCheck() != B_OK) {
     621        alert = new BAlert("error", B_TRANSLATE("Cannot init target file."),
     622            B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_FROM_WIDEST, B_STOP_ALERT);
     623        alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
     624        alert->Go(NULL);
     625        return -1;
     626    }
     627   
     628    BDirectory* targetdir = new BDirectory(targetfolder);
     629    node_ref node;
     630    targetdir->GetNodeRef(&node);
     631    BVolume volume(node.device);
     632
     633    if (volume.InitCheck()) {
     634        alert = new BAlert("error", B_TRANSLATE("Cannot init target volume."),
     635            B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_FROM_WIDEST, B_STOP_ALERT);
     636        alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
     637        alert->Go(NULL);
     638        return -1;
     639    }
     640
     641    if (volume.IsReadOnly()) {
     642        alert = new BAlert("error", B_TRANSLATE("Target volume is read only."),
     643            B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_FROM_WIDEST, B_STOP_ALERT);
     644        alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
     645        alert->Go(NULL);
     646        return -1;
     647    }
     648
     649    BPartition *partition;
     650    BDiskDevice device;
     651
     652    BDiskDeviceRoster().GetPartitionWithID(partitionID, &device, &partition);
     653
     654    if (volume.FreeBytes() < partition->Size()) {
     655        alert = new BAlert("error", B_TRANSLATE("There is no enugth free space on target device."),
     656            B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_FROM_WIDEST, B_STOP_ALERT);
     657        alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
     658        alert->Go(NULL);
     659        return -1;
     660    }
     661
     662    size_t bufsize = partition->BlockSize();
     663    off_t sourcesize, targetsize;
     664    ssize_t targetbytes = 0;
     665
     666    source.GetSize(&sourcesize);
     667    BMessage* message = new BMessage(MSG_UPDATE_STATUS);
     668    message->AddFloat("maximumvalue", (float)sourcesize);
     669    message->AddFloat("currentvalue", 0);
     670    message->AddFloat("delta", 0);
     671    message->AddString("statustext", "");
     672
     673    BString statustext;
     674    statustext << B_TRANSLATE("Creating disk image") << ": " << targetpath;
     675
     676    char* buffer = new char[bufsize];
     677    while (true) {
     678        ssize_t bytes = source.Read(buffer, bufsize);
     679
     680        if (bytes > 0) {
     681            target.Write(buffer, (size_t)bytes);
     682            target.GetSize(&targetsize);
     683               
     684            targetbytes += bytes;
     685
     686            message->SetFloat("currentvalue", (float)targetbytes);
     687            message->SetFloat("delta", (float)bytes);
     688            message->SetString("statustext", statustext);
     689            messenger.SendMessage(message);
     690        } else
     691            break;
     692    }
     693
     694    message = new BMessage(MSG_COMPLETE);
     695    message->AddString("status", B_TRANSLATE("Disk image successfully created."));
     696    messenger.SendMessage(message);
     697   
     698    return 0;
     699}
     700
     701
     702int32
     703MainWindow::WriteDiskImage(void* data)
     704{
     705    BMessage* msg = (BMessage*)data;
     706    const char* sourcepath;
     707    const char* targetpath;
     708    BMessenger messenger;
     709
     710    msg->FindString("source", &sourcepath);
     711    msg->FindString("target", &targetpath);
     712    msg->FindMessenger("messenger", &messenger);
     713
     714    BFile source(sourcepath, B_READ_ONLY);
     715    BFile target(targetpath, B_READ_WRITE);
     716    BAlert* alert;
     717
     718    if (target.InitCheck() != B_OK) {
     719        alert = new BAlert("error", B_TRANSLATE("Cannot init target partition."),
     720            B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_FROM_WIDEST, B_STOP_ALERT);
     721        alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
     722        alert->Go(NULL);
     723        return -1;
     724    }
     725
     726    BPartition *partition;
     727    BDiskDevice device;
     728
     729    BDiskDeviceRoster().GetPartitionForPath(targetpath, &device, &partition);
     730
     731    if (partition->IsReadOnly()) {
     732        alert = new BAlert("error", B_TRANSLATE("Target partition is read only."),
     733            B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_FROM_WIDEST, B_STOP_ALERT);
     734        alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
     735        alert->Go(NULL);
     736        return -1;
     737    }
     738
     739    off_t size;
     740    source.GetSize(&size);
     741
     742    if (partition->Size() < size) {
     743        alert = new BAlert("error", B_TRANSLATE("The target partition is smaller than the image file."),
     744            B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_FROM_WIDEST, B_STOP_ALERT);
     745        alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
     746        alert->Go(NULL);
     747        return -1;
     748    }
     749
     750    size_t bufsize = partition->BlockSize();
     751    off_t sourcesize;
     752    ssize_t targetbytes = 0;
     753
     754    source.GetSize(&sourcesize);
     755    BMessage* message = new BMessage(MSG_UPDATE_STATUS);
     756    message->AddFloat("maximumvalue", (float)sourcesize);
     757    message->AddFloat("currentvalue", 0);
     758    message->AddFloat("delta", 0);
     759    message->AddString("statustext", "");
     760
     761    BString statustext;
     762    statustext << B_TRANSLATE("Writing image to disk") << ": " << targetpath;
     763
     764    char* buffer = new char[bufsize];
     765    while (true) {
     766        ssize_t bytes = source.Read(buffer, bufsize);
     767
     768        if (bytes > 0) {
     769            target.Write(buffer, (size_t)bytes);
     770           
     771            targetbytes += bytes;
     772
     773            message->SetFloat("currentvalue", (float)targetbytes);
     774            message->SetFloat("delta", (float)bytes);
     775            message->SetString("statustext", statustext);
     776            messenger.SendMessage(message);
     777        } else
     778            break;
     779    }
     780
     781    message = new BMessage(MSG_COMPLETE);
     782    message->AddString("status", B_TRANSLATE("Disk image successfully written to the target."));
     783    messenger.SendMessage(message);
     784   
     785    return 0;
     786}
     787
     788
    342789void
    343790MainWindow::MessageReceived(BMessage* message)
    344791{
    MainWindow::MessageReceived(BMessage* message)  
    429876                    true, false, true);
    430877            break;
    431878        }
     879        case MSG_REGISTER:
     880        {
     881            entry_ref entryRef;
     882            message->FindRef("refs", &entryRef);
     883            BEntry entry(&entryRef);
     884            BPath path;
     885            if (entry.GetPath(&path) == B_OK) {
     886                RegisterFileDiskDevice(path.Path());
     887                break;
     888            }
     889            fFileOpen = new BFilePanel(B_OPEN_PANEL, new BMessenger(this),
     890                NULL, B_FILE_NODE, false, new BMessage(MSG_REGISTER), NULL, true);
     891            fFileOpen->Show();
     892            break;
     893        }
     894        case MSG_UNREGISTER:
     895        {
     896            BPath path;
     897            fCurrentDisk->GetPath(&path);
     898            UnRegisterFileDiskDevice(path.Path());
     899            break;
     900        }
     901        case MSG_WRITE:
     902        {
     903            entry_ref entryRef;
     904            message->FindRef("refs", &entryRef);
     905            BEntry entry(&entryRef);
     906            BPath path;
     907            if (entry.GetPath(&path) == B_OK) {
     908                BMessage* msg = new BMessage();
     909
     910                PartitionListRow* row = dynamic_cast<PartitionListRow*>(fListView->CurrentSelection());
     911
     912                msg->AddString("source", path.Path());
     913                msg->AddString("target", row->DevicePath());
     914                msg->AddMessenger("messenger", BMessenger(this));
     915           
     916                fStatusView->MoveBy(0, -40);
     917                fListView->ResizeBy(0, -40);
     918
     919                thread_id write_thread = spawn_thread(WriteDiskImage, "WriteDiskImage",
     920                    B_LOW_PRIORITY, (void*)msg);
     921                resume_thread(write_thread);
     922            } else {
     923                fFileOpen = new BFilePanel(B_OPEN_PANEL, new BMessenger(this),
     924                    NULL, B_FILE_NODE, false, new BMessage(MSG_WRITE), NULL, true);
     925                fFileOpen->Show();
     926            }
     927            break;
     928        }
     929        case MSG_SAVE:
     930        {
     931            PartitionListRow* row = dynamic_cast<PartitionListRow*>(fListView->CurrentSelection());
     932
     933            fFileOpen = new BFilePanel(B_SAVE_PANEL, new BMessenger(this),
     934                NULL, B_FILE_NODE, false, NULL, NULL, true);
     935           
     936            const char* filename = "";
     937            BStringField* field = (BStringField*)row->GetField(2);
     938            filename = field->String();
     939            fFileOpen->SetSaveText(filename);
     940            fFileOpen->Show();
     941            break;
     942        }
     943        case B_SAVE_REQUESTED:
     944        {
     945            BMessage* msg = new BMessage();
     946
     947            entry_ref entryRef;
     948            message->FindRef("directory", &entryRef);
     949            BEntry entry(&entryRef);
     950            BPath path;
     951            entry.GetPath(&path);
     952            msg->AddString("targetfolder", path.Path());
     953            const char* name;
     954            message->FindString("name", &name);
     955            path.Append(name);
     956
     957            PartitionListRow* row = dynamic_cast<PartitionListRow*>(fListView->CurrentSelection());
     958           
     959            msg->AddString("source", row->DevicePath());
     960            msg->AddString("target", path.Path());
     961            msg->AddInt32("partitionID", row->ID());
     962            msg->AddMessenger("messenger", BMessenger(this));
     963           
     964            fStatusView->MoveBy(0, -40);
     965            fListView->ResizeBy(0, -40);
     966           
     967            thread_id save_thread = spawn_thread(SaveDiskImage, "SaveDiskImage", B_LOW_PRIORITY, (void*)msg);
     968            resume_thread(save_thread);
     969
     970            break;
     971        }
     972        case MSG_OPEN_DISKPROBE:
     973        {
     974            PartitionListRow* row = dynamic_cast<PartitionListRow*>(fListView->CurrentSelection());
     975            const char* args[] = { row->DevicePath(), NULL };
     976
     977            be_roster->Launch("application/x-vnd.Haiku-DiskProbe", 1, (char**)args);
     978
     979            break;
     980        }
     981        case MSG_UPDATE_STATUS:
     982        {
     983            float maximumvalue, currentvalue, delta;
     984            const char* statustext = "";
     985            BString statusprogress;
     986
     987            message->FindFloat("maximumvalue", &maximumvalue);
     988            message->FindFloat("currentvalue", &currentvalue);
     989            message->FindFloat("delta", &delta);
     990            message->FindString("statustext", &statustext);
     991
     992            statusprogress << (currentvalue / (1024 * 1024)) << " " << B_TRANSLATE("MiB") << " / ";
     993            statusprogress << (maximumvalue / (1024 * 1024)) << " " << B_TRANSLATE("MiB");
     994
     995            fStatusBar->SetMaxValue(maximumvalue);
     996            fStatusBar->Update(delta);
     997            fStatusBar->SetText(statustext);
     998            fStatusBar->SetTrailingText(statusprogress);
     999
     1000            break;
     1001        }
     1002        case MSG_COMPLETE:
     1003        {
     1004            fStatusBar->Reset();
     1005            fStatusView->MoveBy(0, 40);
     1006            fListView->ResizeBy(0, 40);
     1007
     1008            const char* status = "";
     1009
     1010            message->FindString("status", &status);
     1011
     1012            fNotification->SetTitle(BString(B_TRANSLATE("Disk image")));
     1013            fNotification->SetContent(BString(status));
     1014            fNotification->Send();
     1015
     1016            break;
     1017        }
    4321018
    4331019        case MSG_UPDATE_ZOOM_LIMITS:
    4341020            _UpdateWindowZoomLimits();
    4351021            break;
    4361022
    437         default:
     1023 
     1024        default:
     1025            entry_ref ref;
     1026            int32 i = 0;
     1027
     1028            while (message->FindRef("refs", i++, &ref) == B_OK) {
     1029                BEntry entry(&ref, true);
     1030                BPath path(&entry);
     1031                BNode node(&entry);
     1032
     1033                if (node.IsFile()) {
     1034                    if (entry.GetPath(&path) == B_OK) {
     1035                        RegisterFileDiskDevice(path.Path());
     1036                    }
     1037                }
     1038            }
    4381039            BWindow::MessageReceived(message);
    4391040            break;
    4401041    }
    MainWindow::_UpdateMenus(BDiskDevice* disk,  
    6421243        fWipeMenuItem->SetEnabled(false);
    6431244        fEjectMenuItem->SetEnabled(false);
    6441245        fSurfaceTestMenuItem->SetEnabled(false);
     1246        fUnRegisterMenuItem->SetEnabled(false);
     1247        fSaveMenuItem->SetEnabled(false);
     1248        fWriteMenuItem->SetEnabled(false);
     1249        fOpenDiskProbeMenuItem->SetEnabled(false);
     1250        fOpenDiskProbeContextMenuItem->SetEnabled(false);
    6451251    } else {
    6461252//      fWipeMenuItem->SetEnabled(true);
    6471253        fWipeMenuItem->SetEnabled(false);
    MainWindow::_UpdateMenus(BDiskDevice* disk,  
    6491255//      fSurfaceTestMenuItem->SetEnabled(true);
    6501256        fSurfaceTestMenuItem->SetEnabled(false);
    6511257
     1258        if (disk->IsFile())
     1259            fUnRegisterMenuItem->SetEnabled(true);
     1260        else
     1261            fUnRegisterMenuItem->SetEnabled(false);
     1262       
     1263        fSaveMenuItem->SetEnabled(true);
     1264        if (disk->IsReadOnly())
     1265            fWriteMenuItem->SetEnabled(false);
     1266        else
     1267            fWriteMenuItem->SetEnabled(true);
     1268
    6521269        // Create menu and items
    6531270        BPartition* parentPartition = NULL;
    6541271        if (selectedPartition <= -2) {
    MainWindow::_UpdateMenus(BDiskDevice* disk,  
    7631380            fFormatContextMenuItem->SetEnabled(false);
    7641381        }
    7651382
     1383        fOpenDiskProbeMenuItem->SetEnabled(true);
     1384        fOpenDiskProbeContextMenuItem->SetEnabled(true);
     1385
    7661386        if (prepared)
    7671387            disk->CancelModifications();
    7681388
  • src/apps/drivesetup/MainWindow.h

    diff --git a/src/apps/drivesetup/MainWindow.h b/src/apps/drivesetup/MainWindow.h
    index 6166d82..b48c94f 100644
    a b  
    1111
    1212
    1313#include <DiskDeviceRoster.h>
     14#include <FilePanel.h>
     15#include <Notification.h>
    1416#include <PopUpMenu.h>
     17#include <StatusBar.h>
     18#include <StringView.h>
    1519#include <Window.h>
    1620
    1721#include "Support.h"
    public:  
    4852            status_t            RestoreSettings(BMessage* archive);
    4953            void                ApplyDefaultSettings();
    5054
     55            status_t            RegisterFileDiskDevice(const char* fileName);
     56            status_t            UnRegisterFileDiskDevice(const char* fileName);
     57    static  int32               SaveDiskImage(void* data);
     58    static  int32               WriteDiskImage(void* data);
     59    const char*                 EncryptionType(const char* path);
     60
    5161private:
    5262            void                _ScanDrives();
    5363
    private:  
    8999
    90100            PartitionListView*  fListView;
    91101            DiskView*           fDiskView;
     102            BView*              fStatusView;
     103            BStatusBar*         fStatusBar;
    92104
    93105            SpaceIDMap          fSpaceIDMap;
    94106
    private:  
    97109
    98110            BMenu*              fPartitionMenu;
    99111            BMenu*              fFormatMenu;
     112            BMenu*              fDiskImageMenu;
    100113
    101114            BMenuBar*           fMenuBar;
    102115
    private:  
    111124            BMenuItem*          fMountMenuItem;
    112125            BMenuItem*          fUnmountMenuItem;
    113126            BMenuItem*          fMountAllMenuItem;
     127            BMenuItem*          fOpenDiskProbeMenuItem;
    114128
    115129            BMenu*              fFormatContextMenuItem;
    116130            BMenuItem*          fCreateContextMenuItem;
    private:  
    118132            BMenuItem*          fDeleteContextMenuItem;
    119133            BMenuItem*          fMountContextMenuItem;
    120134            BMenuItem*          fUnmountContextMenuItem;
     135            BMenuItem*          fOpenDiskProbeContextMenuItem;
    121136            BPopUpMenu*         fContextMenu;
     137
     138            BMenuItem*          fRegisterMenuItem;
     139            BMenuItem*          fUnRegisterMenuItem;
     140            BMenuItem*          fSaveMenuItem;
     141            BMenuItem*          fWriteMenuItem;
     142
     143            BFilePanel*         fFileOpen;
     144           
     145            BNotification*      fNotification;
    122146};
    123147
    124148
  • src/apps/drivesetup/PartitionList.cpp

    diff --git a/src/apps/drivesetup/PartitionList.cpp b/src/apps/drivesetup/PartitionList.cpp
    index 1fd2946..eb4057e 100644
    a b  
    1212
    1313#include "PartitionList.h"
    1414
     15#include <stdio.h>
    1516#include <Catalog.h>
    1617#include <ColumnTypes.h>
     18#include <DiskDevice.h>
     19#include <File.h>
     20#include <IconUtils.h>
    1721#include <Locale.h>
    1822#include <Path.h>
     23#include <Volume.h>
     24#include <VolumeRoster.h>
    1925
    2026#include <driver_settings.h>
    2127
    2228#include "Support.h"
    2329#include "MainWindow.h"
     30#include "icons.h"
    2431
    2532
    2633#undef B_TRANSLATION_CONTEXT
    enum {  
    3542    kVolumeNameColumn,
    3643    kMountedAtColumn,
    3744    kSizeColumn,
     45    kFreeSizeColumn,
     46    kBlockSizeColumn,
    3847    kParametersColumn,
    3948    kPartitionTypeColumn,
    4049};
    PartitionListRow::PartitionListRow(BPartition* partition)  
    208217
    209218    // Device icon
    210219
    211     BBitmap* icon = NULL;
    212     if (partition->IsDevice()) {
    213         icon_size size = B_MINI_ICON;
    214         icon = new BBitmap(BRect(0, 0, size - 1, size - 1), B_RGBA32);
    215         if (partition->GetIcon(icon, size) != B_OK) {
    216             delete icon;
    217             icon = NULL;
    218         }
     220    BVolume volume;
     221    partition->GetVolume(&volume);
     222
     223    BVolume boot;
     224    BVolumeRoster().GetBootVolume(&boot);
     225
     226    bool fBoot;
     227    bool fReadOnly;
     228    bool fShared;
     229    bool fEncrypted = false;
     230
     231    fBoot = volume == boot;
     232    fReadOnly = volume.IsReadOnly();
     233    fShared = volume.IsShared();
     234
     235    BString parameters;
     236    if (fBoot) {
     237        parameters += B_TRANSLATE("Boot");
     238        parameters += ", ";
     239    }
     240
     241    if (partition->Device()->IsFile()) {
     242        parameters += B_TRANSLATE("Virtual");
     243        parameters += ", ";
     244    }
     245
     246    if (fReadOnly) {
     247        parameters += B_TRANSLATE("Read only");
     248        parameters += ", ";
     249    }
     250    if (volume.IsRemovable()) {
     251        parameters += B_TRANSLATE("Removable");
     252        parameters += ", ";
     253    }
     254    if (fShared) {
     255        parameters += B_TRANSLATE("Shared");
     256        parameters += ", ";
     257    }
     258    if (volume.KnowsMime()) {
     259        parameters += B_TRANSLATE("Mimes");
     260        parameters += ", ";
     261    }
     262    if (volume.KnowsAttr()) {
     263        parameters += B_TRANSLATE("Attributes");
     264        parameters += ", ";
     265    }
     266    if (volume.KnowsQuery()) {
     267        parameters += B_TRANSLATE("Queries");
     268        parameters += ", ";
    219269    }
    220270
    221     SetField(new BBitmapStringField(icon, path.Path()), kDeviceColumn);
     271    const char* encrypter = dynamic_cast<MainWindow*>(be_app->WindowAt(0))->EncryptionType(path.Path());
     272    if (encrypter) {
     273        parameters.Append(encrypter);
     274        parameters += ", ";
     275        fEncrypted = true;
     276    }
    222277
    223     // File system & volume name
     278    BBitmap *fIcon = new BBitmap(BRect(0, 0, 15, 15), B_RGBA32);
     279 
     280    if (fBoot)
     281        BIconUtils::GetVectorIcon(kLeaf, sizeof(kLeaf), fIcon);
     282    else if (fEncrypted)
     283        BIconUtils::GetVectorIcon(kEncrypted, sizeof(kEncrypted), fIcon);
     284    else if (fReadOnly)
     285        BIconUtils::GetVectorIcon(kReadOnly, sizeof(kReadOnly), fIcon);
     286    else if (fShared)
     287        BIconUtils::GetVectorIcon(kShared, sizeof(kShared), fIcon);
     288    else if (partition->Device()->IsFile())
     289        BIconUtils::GetVectorIcon(kFile, sizeof(kFile), fIcon);
     290    else if (partition->IsDevice()) {
     291        icon_size size = B_MINI_ICON;
     292        fIcon = new BBitmap(BRect(0, 0, size - 1, size - 1), B_RGBA32);
     293        if (partition->GetIcon(fIcon, size) != B_OK) {
     294            delete fIcon;
     295            fIcon = NULL;
     296        }
     297    } else
     298        fIcon = NULL;
     299 
     300    SetField(new BBitmapStringField(fIcon, path.Path()), kDeviceColumn);
     301 
     302    // File system & volume name
    224303
    225304    BString partitionType(partition->Type());
    226305
    PartitionListRow::PartitionListRow(BPartition* partition)  
    260339        char size[1024];
    261340        SetField(new BStringField(string_for_size(partition->Size(), size,
    262341            sizeof(size))), kSizeColumn);
    263     } else {
     342    } else
    264343        SetField(new BStringField(kUnavailableString), kSizeColumn);
    265     }
     344
     345    if (volume.FreeBytes() > 0) {
     346        char size[1024];
     347        SetField(new BStringField(string_for_size(volume.FreeBytes(), size, sizeof(size))), kFreeSizeColumn);
     348    } else
     349        SetField(new BStringField(kUnavailableString), kFreeSizeColumn);
     350
     351    char blocksize;
     352    sprintf(&blocksize, "%" B_PRIu32, partition->BlockSize());
     353    SetField(new BStringField(const_cast<const char*>(&blocksize)), kBlockSizeColumn);
    266354
    267355    // Additional parameters
    268356
    269357    if (partition->Parameters() != NULL) {
    270         BString parameters;
    271 
    272358        // check parameters
    273359        void* handle = parse_driver_settings_string(partition->Parameters());
    274360        if (handle != NULL) {
    PartitionListRow::PartitionListRow(BPartition* partition)  
    278364
    279365            delete_driver_settings(handle);
    280366        }
    281 
    282         SetField(new BStringField(parameters), kParametersColumn);
    283     } else {
    284         SetField(new BStringField(kUnavailableString), kParametersColumn);
    285367    }
    286368
     369    if (parameters.EndsWith(", "))
     370        parameters.RemoveLast(", ");
     371    SetField(new BStringField(parameters), kParametersColumn);
     372
    287373    // Partition type
    288374
    289375    if (partitionType.IsEmpty())
    PartitionListRow::PartitionListRow(partition_id parentID, partition_id id,  
    304390    // TODO: design icon for spaces on partitions
    305391    SetField(new BBitmapStringField(NULL, "-"), kDeviceColumn);
    306392
    307     SetField(new BStringField(B_TRANSLATE("<empty>")), kFilesystemColumn);
     393    SetField(new BStringField(B_TRANSLATE("<empty or unknown>")), kFilesystemColumn);
    308394    SetField(new BStringField(kUnavailableString), kVolumeNameColumn);
    309395
    310396    SetField(new BStringField(kUnavailableString), kMountedAtColumn);
    PartitionListView::PartitionListView(const BRect& frame, uint32 resizeMode)  
    342428        B_TRUNCATE_MIDDLE), kVolumeNameColumn);
    343429    AddColumn(new PartitionColumn(B_TRANSLATE("Mounted at"), 100, 50, 500,
    344430        B_TRUNCATE_MIDDLE), kMountedAtColumn);
    345     AddColumn(new PartitionColumn(B_TRANSLATE("Size"), 100, 50, 500,
     431    AddColumn(new PartitionColumn(B_TRANSLATE("Size"), 80, 50, 500,
    346432        B_TRUNCATE_END, B_ALIGN_RIGHT), kSizeColumn);
     433    AddColumn(new PartitionColumn(B_TRANSLATE("Free space"), 80, 50, 500,
     434        B_TRUNCATE_END, B_ALIGN_RIGHT), kFreeSizeColumn);
     435    AddColumn(new PartitionColumn(B_TRANSLATE("Block size"), 50, 50, 500,
     436        B_TRUNCATE_END, B_ALIGN_RIGHT), kBlockSizeColumn);
    347437    AddColumn(new PartitionColumn(B_TRANSLATE("Parameters"), 100, 50, 500,
    348438        B_TRUNCATE_END), kParametersColumn);
    349439    AddColumn(new PartitionColumn(B_TRANSLATE("Partition type"), 200, 50, 500,
  • new file src/apps/drivesetup/icons.h

    diff --git a/src/apps/drivesetup/icons.h b/src/apps/drivesetup/icons.h
    new file mode 100644
    index 0000000..40fc94c
    - +  
     1const unsigned char kLeaf[] = {
     2    0x6e, 0x63, 0x69, 0x66, 0x02, 0x05, 0x00, 0x02, 0x01, 0x06, 0x02, 0x38,
     3    0xcc, 0x87, 0xbd, 0x08, 0x3d, 0x3d, 0xcc, 0x62, 0x39, 0x81, 0x95, 0x46,
     4    0x09, 0x92, 0x4a, 0x99, 0x6b, 0x00, 0xff, 0xb1, 0x1b, 0xff, 0xff, 0xf9,
     5    0xc7, 0x01, 0x06, 0x0d, 0xee, 0x1f, 0xbf, 0x03, 0x2f, 0x44, 0x2b, 0x4f,
     6    0x2b, 0x48, 0x29, 0x4b, 0x24, 0x4a, 0x29, 0x53, 0x23, 0x50, 0x29, 0x53,
     7    0x23, 0x54, 0x29, 0x54, 0x23, 0x54, 0x2e, 0x58, 0x26, 0x5a, 0x2e, 0x58,
     8    0x5c, 0x30, 0x30, 0x58, 0x30, 0x58, 0x38, 0x5a, 0x3b, 0x54, 0x3b, 0x54,
     9    0x35, 0x54, 0x35, 0x53, 0x35, 0x53, 0x3b, 0x50, 0x3a, 0x4a, 0x33, 0x4f,
     10    0x35, 0x4b, 0x33, 0x48, 0x03, 0x0a, 0x00, 0x01, 0x00, 0x1a, 0x41, 0xcc,
     11    0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xcc, 0x0a, 0x43, 0xa6,
     12    0x76, 0xcb, 0x99, 0xb5, 0x15, 0xff, 0x01, 0x17, 0x83, 0x00, 0x04, 0x0a,
     13    0x00, 0x01, 0x00, 0x1a, 0x41, 0xcc, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
     14    0x00, 0x41, 0xcc, 0x0a, 0x43, 0xa6, 0x76, 0xcb, 0x99, 0xb5, 0x00, 0x15,
     15    0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 0x01, 0x01, 0x00, 0x02, 0x41, 0xcc,
     16    0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xcc, 0x0a, 0x43, 0xa6,
     17    0x76, 0xcb, 0x99, 0xb5
     18};
     19
     20const unsigned char kEncrypted[] = {
     21    0x6e, 0x63, 0x69, 0x66, 0x02, 0x05, 0x00, 0x03, 0xff, 0x00, 0x00, 0x03,
     22    0x02, 0x04, 0x31, 0x22, 0xbd, 0x10, 0x22, 0xb6, 0x77, 0x22, 0x22, 0x31,
     23    0x22, 0xb6, 0x77, 0x22, 0xbd, 0x10, 0x31, 0x40, 0xb6, 0x77, 0x40, 0xbd,
     24    0x10, 0x40, 0x40, 0x31, 0x40, 0xbd, 0x10, 0x40, 0xb6, 0x77, 0x02, 0x03,
     25    0x28, 0x37, 0x28, 0x37, 0x25, 0x33, 0xb6, 0xaa, 0xb6, 0xaa, 0xb5, 0x50,
     26    0xb8, 0x07, 0xb8, 0x07, 0xb5, 0x50, 0x37, 0x28, 0xba, 0xe0, 0xb4, 0xe7,
     27    0x38, 0x29, 0x02, 0x03, 0x3a, 0x2b, 0x3a, 0x2b, 0x3e, 0x2f, 0xbc, 0xdd,
     28    0xbc, 0xdd, 0xbe, 0x34, 0xbb, 0x86, 0xbb, 0x84, 0xbe, 0x35, 0x2b, 0x3a,
     29    0x2f, 0x3d, 0x2b, 0x3a, 0x02, 0x0a, 0x00, 0x03, 0x00, 0x01, 0x02, 0x12,
     30    0x41, 0x95, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x95, 0x35,
     31    0x40, 0x17, 0x64, 0x40, 0x17, 0x64, 0x01, 0x17, 0x83, 0x02, 0x04, 0x0a,
     32    0x01, 0x03, 0x00, 0x01, 0x02, 0x02, 0x41, 0x95, 0x35, 0x00, 0x00, 0x00,
     33    0x00, 0x00, 0x00, 0x41, 0x95, 0x35, 0x40, 0x17, 0x64, 0x40, 0x17, 0x64
     34};
     35
     36const unsigned char kReadOnly[] = {
     37    0x6e, 0x63, 0x69, 0x66, 0x0f, 0x05, 0x01, 0x02, 0x00, 0x06, 0x03, 0x38,
     38    0xd2, 0xf7, 0x3c, 0xd1, 0x63, 0xbf, 0x82, 0xb2, 0x3b, 0x84, 0xa9, 0x4b,
     39    0x88, 0x50, 0x49, 0x10, 0xc9, 0x00, 0xff, 0xef, 0xa5, 0xbd, 0xff, 0xfc,
     40    0xc0, 0xff, 0xff, 0xf8, 0x90, 0x02, 0x01, 0x06, 0x02, 0x3e, 0x49, 0x24,
     41    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xaa, 0xaa, 0x49, 0x40, 0x00,
     42    0x4a, 0x80, 0x00, 0xff, 0xff, 0xfc, 0xc0, 0x7c, 0xf1, 0xb7, 0x06, 0x02,
     43    0x00, 0x16, 0x02, 0x3a, 0x55, 0xa6, 0xba, 0xc2, 0x29, 0x3f, 0x0d, 0xa3,
     44    0x3e, 0x95, 0x86, 0x46, 0xc2, 0xeb, 0x47, 0xa1, 0xd6, 0x00, 0x01, 0xff,
     45    0x9e, 0x02, 0x00, 0x06, 0x03, 0xb4, 0xa7, 0xac, 0x38, 0xfc, 0xa2, 0xbb,
     46    0xf7, 0x7b, 0xb7, 0x86, 0xa6, 0x49, 0x3b, 0x6c, 0x47, 0x11, 0x63, 0x00,
     47    0xff, 0xee, 0xd5, 0x8d, 0xdb, 0xab, 0x5f, 0xcf, 0xff, 0xee, 0xd5, 0x02,
     48    0x00, 0x06, 0x02, 0x3d, 0x4d, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     49    0x40, 0x00, 0x00, 0x4a, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xea,
     50    0xba, 0xff, 0xff, 0xf6, 0xe3, 0x02, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00,
     51    0x39, 0x0c, 0x30, 0xbb, 0xcf, 0x3c, 0x00, 0x00, 0x00, 0x4b, 0x60, 0x00,
     52    0x46, 0x00, 0x00, 0x00, 0xff, 0xea, 0xee, 0xc6, 0xd1, 0x7c, 0x8a, 0xff,
     53    0xda, 0x9f, 0xaa, 0x02, 0x00, 0x06, 0x02, 0xaa, 0xb1, 0xfb, 0x3a, 0x08,
     54    0x1f, 0xbe, 0x8a, 0x26, 0xaf, 0x5e, 0x79, 0x4c, 0x50, 0x14, 0x46, 0xc6,
     55    0xa1, 0x00, 0xff, 0xe3, 0xe8, 0xff, 0xf8, 0xa1, 0xb1, 0x02, 0x00, 0x06,
     56    0x02, 0x3c, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
     57    0x00, 0x4a, 0x40, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfb, 0xb5, 0x0d, 0x00,
     58    0xf0, 0xab, 0x06, 0x02, 0x00, 0x06, 0x02, 0xb6, 0x6e, 0x92, 0x3a, 0x77,
     59    0x41, 0xbf, 0xe2, 0x39, 0xbb, 0xd4, 0x8d, 0x4c, 0x06, 0x3f, 0x48, 0xc5,
     60    0xf5, 0x00, 0xa5, 0x2a, 0x04, 0xff, 0xfd, 0xb4, 0x4b, 0x02, 0x00, 0x06,
     61    0x02, 0x3b, 0x8e, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
     62    0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xb0, 0x3a, 0xff,
     63    0xe9, 0xda, 0x71, 0x03, 0xe2, 0xc2, 0x55, 0x04, 0x00, 0x66, 0x03, 0x80,
     64    0x00, 0x00, 0x02, 0x00, 0x06, 0x02, 0x00, 0x00, 0x00, 0x3c, 0x20, 0x00,
     65    0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x48, 0xe0, 0x00,
     66    0x00, 0xff, 0xab, 0xab, 0xff, 0xd9, 0x00, 0x00, 0x0c, 0x06, 0x0c, 0xae,
     67    0xaa, 0xba, 0xb4, 0x0b, 0xc1, 0x4b, 0x33, 0xc5, 0xad, 0xb7, 0x5d, 0xc3,
     68    0x71, 0xbd, 0xef, 0xc8, 0x05, 0xc1, 0x3e, 0xca, 0x02, 0xc4, 0xe0, 0x4f,
     69    0x41, 0xc5, 0x07, 0x37, 0x4b, 0x39, 0x4a, 0x45, 0xc3, 0x3c, 0xc6, 0xd1,
     70    0xc3, 0x6f, 0xca, 0x28, 0xbf, 0x80, 0xc1, 0x18, 0xbb, 0x1e, 0xc5, 0x1b,
     71    0xbd, 0x3e, 0xbf, 0x07, 0xba, 0x06, 0x3a, 0xb8, 0xba, 0x06, 0x09, 0xae,
     72    0xaa, 0x02, 0xb5, 0x7d, 0x43, 0xb9, 0xb9, 0xc5, 0xed, 0xb7, 0xbb, 0x49,
     73    0xbb, 0xb7, 0x56, 0xbd, 0x75, 0xcb, 0x34, 0xc6, 0xf0, 0xc5, 0xc2, 0x4e,
     74    0x4f, 0x51, 0x4b, 0xc9, 0xbb, 0xc4, 0x28, 0xca, 0x8e, 0xc3, 0xaf, 0x40,
     75    0x34, 0x06, 0x06, 0xb2, 0x08, 0x31, 0x24, 0x53, 0x56, 0x29, 0x56, 0x25,
     76    0x56, 0x2d, 0x53, 0x2e, 0x31, 0x26, 0x29, 0x0a, 0x06, 0x31, 0x24, 0xb8,
     77    0xba, 0xb5, 0xb2, 0xb8, 0xba, 0xb7, 0x79, 0x31, 0x2e, 0xb6, 0x77, 0xb6,
     78    0xec, 0xb6, 0x7c, 0xb6, 0x3c, 0x0a, 0x04, 0x33, 0x24, 0xb9, 0x69, 0xb5,
     79    0xba, 0x4a, 0x27, 0x4d, 0x24, 0x08, 0x04, 0xba, 0x28, 0xb4, 0xd3, 0x30,
     80    0x27, 0x30, 0x2b, 0xba, 0x28, 0xb8, 0x58, 0x06, 0x06, 0x2e, 0x0b, 0x53,
     81    0x24, 0x50, 0x29, 0x50, 0x25, 0x50, 0x2d, 0x53, 0x2e, 0x4f, 0x4c, 0x29,
     82    0x4c, 0x2d, 0x4c, 0x25, 0x4f, 0x24, 0x00, 0x03, 0xc4, 0xea, 0xb4, 0xd3,
     83    0xc4, 0xea, 0xb4, 0xd3, 0xc4, 0x92, 0xb5, 0x17, 0x4b, 0x29, 0x4b, 0xb5,
     84    0x9e, 0x4b, 0xb7, 0x8d, 0xc4, 0xea, 0xb8, 0x58, 0xc4, 0x92, 0xb8, 0x14,
     85    0xc4, 0xea, 0xb8, 0x58, 0x06, 0x04, 0xee, 0x53, 0x24, 0x56, 0x29, 0x56,
     86    0x25, 0x56, 0x2d, 0x53, 0x2e, 0x50, 0x29, 0x50, 0x2d, 0x50, 0x25, 0x0a,
     87    0x04, 0xb9, 0x69, 0xb5, 0xba, 0xb9, 0x69, 0xb7, 0x71, 0x4a, 0x2b, 0x4a,
     88    0x27, 0x0a, 0x04, 0xb9, 0x69, 0xb7, 0x71, 0x33, 0x2e, 0x4d, 0x2e, 0x4a,
     89    0x2b, 0x0a, 0x0c, 0x48, 0x2a, 0x40, 0x22, 0x35, 0x2d, 0x2a, 0x22, 0x22,
     90    0x2a, 0x2d, 0x35, 0x22, 0x40, 0x2a, 0x48, 0x35, 0x3d, 0x40, 0x48, 0x48,
     91    0x40, 0x3d, 0x35, 0x0a, 0x0a, 0x00, 0x03, 0x02, 0x05, 0x07, 0x12, 0x40,
     92    0x26, 0x8f, 0xbf, 0xa4, 0x83, 0x3f, 0xa4, 0x83, 0x40, 0x26, 0x8f, 0xc6,
     93    0x03, 0xab, 0x4b, 0x1c, 0x95, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 0x04,
     94    0x01, 0x03, 0x02, 0x40, 0x26, 0x8f, 0xbf, 0xa4, 0x83, 0x3f, 0xa4, 0x83,
     95    0x40, 0x26, 0x8f, 0xc6, 0x03, 0xab, 0x4b, 0x1c, 0x95, 0x0a, 0x05, 0x01,
     96    0x04, 0x02, 0x40, 0x26, 0x8f, 0xbf, 0xa4, 0x83, 0x3f, 0xa4, 0x83, 0x40,
     97    0x26, 0x8f, 0xc6, 0x03, 0xab, 0x4b, 0x1c, 0x95, 0x0a, 0x08, 0x01, 0x09,
     98    0x02, 0x40, 0x26, 0x8f, 0xbf, 0xa4, 0x83, 0x3f, 0xa4, 0x83, 0x40, 0x26,
     99    0x8f, 0xc6, 0x03, 0xab, 0x4b, 0x1c, 0x95, 0x0a, 0x09, 0x01, 0x0a, 0x02,
     100    0x40, 0x26, 0x8f, 0xbf, 0xa4, 0x83, 0x3f, 0xa4, 0x83, 0x40, 0x26, 0x8f,
     101    0xc6, 0x03, 0xab, 0x4b, 0x1c, 0x95, 0x0a, 0x06, 0x01, 0x06, 0x02, 0x40,
     102    0x26, 0x8f, 0xbf, 0xa4, 0x83, 0x3f, 0xa4, 0x83, 0x40, 0x26, 0x8f, 0xc6,
     103    0x03, 0xab, 0x4b, 0x1c, 0x95, 0x0a, 0x07, 0x01, 0x08, 0x02, 0x40, 0x26,
     104    0x8f, 0xbf, 0xa4, 0x83, 0x3f, 0xa4, 0x83, 0x40, 0x26, 0x8f, 0xc6, 0x03,
     105    0xab, 0x4b, 0x1c, 0x95, 0x0a, 0x0c, 0x01, 0x0b, 0x30, 0x36, 0x36, 0x01,
     106    0x17, 0x83, 0x22, 0x04, 0x0a, 0x0d, 0x01, 0x0b, 0x30, 0x34, 0x34, 0x01,
     107    0x17, 0x83, 0x22, 0x04, 0x0a, 0x0e, 0x01, 0x0b, 0x20, 0x34, 0x34
     108};
     109
     110const unsigned char kShared[] = {
     111    0x6e, 0x63, 0x69, 0x66, 0x13, 0x04, 0x00, 0x4c, 0x03, 0xff, 0xcb, 0x9a,
     112    0x01, 0xcd, 0x98, 0x66, 0xb2, 0x01, 0xcd, 0x99, 0x66, 0xb2, 0x01, 0xcd,
     113    0x99, 0x66, 0xb2, 0x01, 0xcd, 0x99, 0x66, 0xb2, 0x01, 0xcd, 0x99, 0x66,
     114    0xb2, 0x01, 0xcd, 0x99, 0x66, 0xb2, 0x01, 0xcd, 0x99, 0x66, 0xb2, 0x01,
     115    0xcd, 0x98, 0x66, 0xb2, 0x04, 0xff, 0xf2, 0x04, 0xff, 0xf2, 0x04, 0xff,
     116    0xf2, 0x04, 0xff, 0xf2, 0x05, 0x00, 0x04, 0xff, 0xb2, 0x01, 0xcd, 0x98,
     117    0x66, 0xb2, 0x04, 0x00, 0x2b, 0x05, 0x00, 0x12, 0x06, 0x17, 0xeb, 0xff,
     118    0xbe, 0xff, 0xbe, 0x3f, 0xc5, 0xdd, 0xb9, 0x18, 0xcb, 0xb1, 0xba, 0x52,
     119    0xc4, 0xc9, 0xb8, 0xdc, 0xc4, 0x28, 0xb9, 0x72, 0xc2, 0xdc, 0xba, 0x19,
     120    0xc1, 0xb3, 0xb9, 0xb6, 0xc2, 0x3c, 0xb9, 0xaf, 0xc1, 0xb3, 0xb9, 0xb6,
     121    0xb7, 0xbb, 0xb9, 0xb6, 0xb7, 0xbb, 0xb9, 0xb6, 0xb6, 0x4f, 0xb9, 0xb6,
     122    0xb7, 0x9b, 0xbc, 0x6c, 0xb5, 0xaa, 0xbc, 0x6c, 0xb7, 0x9b, 0xbc, 0x6c,
     123    0xbb, 0x19, 0xbc, 0x6c, 0xbb, 0x19, 0xbc, 0x6c, 0xbb, 0xa1, 0xbc, 0x77,
     124    0xbc, 0x21, 0xbd, 0x12, 0xbc, 0x21, 0xbc, 0x8e, 0xbc, 0x21, 0xbd, 0x12,
     125    0xbb, 0xbf, 0xbe, 0x1b, 0xb3, 0xb8, 0xc5, 0xdf, 0xb3, 0xb8, 0xc5, 0xdf,
     126    0xb2, 0x4b, 0xc7, 0x4d, 0xb5, 0x87, 0xc7, 0xb0, 0xb4, 0x90, 0xc8, 0xa7,
     127    0xb5, 0x87, 0xc7, 0xb0, 0xb5, 0x8d, 0xc7, 0xb1, 0xb5, 0x24, 0xc8, 0x13,
     128    0xb5, 0x24, 0xc8, 0x13, 0xb3, 0xb8, 0xc9, 0x80, 0xb8, 0x41, 0xc9, 0x52,
     129    0xb6, 0x4f, 0xcb, 0x01, 0xb8, 0x41, 0xc9, 0x52, 0xb8, 0x96, 0xc8, 0xfa,
     130    0xb8, 0x96, 0xc8, 0xfa, 0xb7, 0xaf, 0xca, 0x8b, 0xbc, 0x47, 0xc9, 0xcc,
     131    0xba, 0xed, 0xcb, 0x75, 0xbc, 0x47, 0xc9, 0xcc, 0xbc, 0x8f, 0xc9, 0x86,
     132    0xbc, 0x95, 0xc9, 0x88, 0xbc, 0x95, 0xc9, 0x88, 0xba, 0xef, 0xcb, 0x24,
     133    0xbf, 0x80, 0xca, 0x68, 0xbd, 0xb0, 0xcc, 0x58, 0xbf, 0x80, 0xca, 0x68,
     134    0x4d, 0xc5, 0x19, 0xc9, 0x55, 0xc0, 0x4f, 0xc8, 0xd0, 0xc1, 0x37, 0xc9,
     135    0xd9, 0xbf, 0x66, 0xc9, 0x77, 0xbd, 0xda, 0xc9, 0xb8, 0xbf, 0x25, 0xc9,
     136    0x77, 0xbd, 0xda, 0xca, 0x5f, 0xbd, 0x12, 0xca, 0x5f, 0xbd, 0x12, 0xca,
     137    0xa4, 0xbc, 0x2f, 0x06, 0x09, 0xdf, 0xfb, 0x03, 0xc2, 0xd1, 0xba, 0x5d,
     138    0xc2, 0xd1, 0xba, 0x5d, 0xc3, 0x09, 0xba, 0x68, 0xc4, 0x46, 0xbb, 0x84,
     139    0xc4, 0x46, 0xba, 0xf9, 0xc4, 0x46, 0xbb, 0x84, 0xbb, 0xd1, 0xc4, 0x92,
     140    0xbb, 0xc9, 0xc4, 0x92, 0xbb, 0xc9, 0xc6, 0x1a, 0xbb, 0xa0, 0x56, 0xbd,
     141    0x7f, 0x56, 0xbc, 0x25, 0x56, 0xbd, 0x7f, 0xc8, 0x59, 0xbc, 0x67, 0xc8,
     142    0xb7, 0xbc, 0x65, 0xc8, 0xb7, 0xbc, 0x65, 0xc8, 0x12, 0xbb, 0x65, 0xc4,
     143    0x9e, 0xbb, 0x70, 0xc6, 0x28, 0x35, 0xc4, 0x57, 0xba, 0x94, 0xc2, 0xe9,
     144    0xb9, 0xd4, 0xc3, 0x0d, 0xb9, 0xdc, 0xc2, 0xe9, 0xb9, 0xd4, 0x06, 0x08,
     145    0xbe, 0xbf, 0xb7, 0x35, 0xbb, 0xe0, 0xbc, 0x6b, 0xbb, 0x99, 0xbc, 0x6b,
     146    0xbb, 0x99, 0x3a, 0xbd, 0x11, 0xbf, 0xe8, 0xbc, 0xce, 0xbd, 0xe6, 0xbd,
     147    0x78, 0xc1, 0x90, 0xbc, 0x40, 0xc2, 0xb9, 0xbc, 0x21, 0xc0, 0x2c, 0xbd,
     148    0xdf, 0xc1, 0x61, 0xbd, 0x57, 0xbe, 0xf7, 0xbe, 0x68, 0xbb, 0x7b, 0xbe,
     149    0xae, 0xbd, 0x7f, 0xbe, 0x8c, 0xbb, 0x99, 0xbd, 0xbf, 0xbb, 0xe2, 0xbc,
     150    0x88, 0xbc, 0xac, 0xbc, 0xa4, 0xb9, 0x6e, 0xbc, 0x34, 0xb7, 0x9b, 0xbc,
     151    0x6c, 0x06, 0x09, 0xfe, 0xbf, 0x03, 0xbf, 0xc5, 0xc3, 0xc5, 0xc0, 0x4f,
     152    0xc4, 0xb6, 0xc0, 0x93, 0xc4, 0x4f, 0xc0, 0x0b, 0xc5, 0x1d, 0xbe, 0x07,
     153    0xc6, 0xb8, 0xbe, 0x29, 0xc6, 0x2f, 0xbd, 0x39, 0xc7, 0x41, 0xbc, 0x28,
     154    0xc8, 0xdc, 0xbc, 0x6b, 0xc8, 0x53, 0xbb, 0xe2, 0xc9, 0x67, 0xb9, 0xe0,
     155    0xc9, 0xab, 0xba, 0x6a, 0xc9, 0xab, 0xb9, 0x57, 0xc9, 0xab, 0xb9, 0xbd,
     156    0xca, 0x9b, 0xb9, 0x34, 0xca, 0x9b, 0xba, 0x46, 0xca, 0x9b, 0xbc, 0x47,
     157    0xc9, 0xcc, 0xbb, 0x9b, 0xca, 0x76, 0xbc, 0x47, 0xc9, 0xcc, 0xc0, 0xfa,
     158    0xc5, 0x1d, 0xc2, 0x0c, 0xc4, 0xb6, 0xc1, 0xa5, 0xc4, 0x70, 0xc1, 0x61,
     159    0xc4, 0x70, 0x06, 0x09, 0xfe, 0xbf, 0x03, 0xbb, 0xc1, 0xc2, 0xf7, 0xbc,
     160    0x4a, 0xc3, 0xe8, 0xbc, 0x8f, 0xc3, 0x81, 0xbc, 0x05, 0xc4, 0x4f, 0xba,
     161    0x03, 0xc5, 0xeb, 0xba, 0x24, 0xc5, 0x61, 0xb9, 0x34, 0xc6, 0x73, 0xb8,
     162    0x22, 0xc8, 0x0e, 0xb8, 0x67, 0xc7, 0x85, 0xb7, 0xdd, 0xc8, 0x99, 0xb5,
     163    0xda, 0xc8, 0xdc, 0xb6, 0x64, 0xc8, 0xdc, 0xb5, 0x51, 0xc8, 0xdc, 0xb5,
     164    0xb9, 0xc9, 0xcd, 0xb5, 0x3a, 0xc9, 0x97, 0xb6, 0x85, 0xca, 0x26, 0xb8,
     165    0x42, 0xc8, 0xfe, 0xb7, 0x95, 0xc9, 0xa7, 0xb8, 0x42, 0xc8, 0xfe, 0x39,
     166    0xc4, 0x4f, 0xbe, 0x07, 0xc3, 0xe8, 0xbd, 0xa0, 0xc3, 0xa2, 0x3a, 0xc3,
     167    0xa2, 0x06, 0x09, 0xfe, 0xbf, 0x03, 0xba, 0x03, 0xc0, 0xf4, 0xba, 0x8c,
     168    0xc1, 0xe5, 0xba, 0xd1, 0xc1, 0x7d, 0xba, 0x47, 0xc2, 0x4c, 0xb8, 0x45,
     169    0xc3, 0xe8, 0xb8, 0x67, 0xc3, 0x5e, 0xb7, 0x76, 0xc4, 0x70, 0xb6, 0x64,
     170    0xc6, 0x0c, 0xb6, 0xa9, 0xc5, 0x84, 0xb6, 0x20, 0xc6, 0x96, 0xb4, 0x1d,
     171    0xc6, 0xda, 0xb5, 0x17, 0xc7, 0x53, 0xb3, 0xa1, 0xc6, 0x9f, 0xb3, 0xfa,
     172    0xc7, 0xcb, 0xb3, 0x71, 0xc7, 0xcb, 0xb4, 0x83, 0xc7, 0xcb, 0xb6, 0x84,
     173    0xc6, 0xfc, 0xb5, 0xd6, 0xc7, 0xa5, 0xb6, 0x84, 0xc6, 0xfc, 0xbb, 0x37,
     174    0xc2, 0x4c, 0xbc, 0x4a, 0xc1, 0xe5, 0xbb, 0xe2, 0xc1, 0xa1, 0xbb, 0x9e,
     175    0xc1, 0xa1, 0x02, 0x05, 0xbc, 0xb1, 0xbf, 0x15, 0xbc, 0xb1, 0xbf, 0x15,
     176    0xbd, 0xa0, 0xbf, 0x36, 0xc0, 0x2c, 0xc0, 0x6c, 0xbf, 0xa4, 0xc0, 0x05,
     177    0xc0, 0xb6, 0xc0, 0xd3, 0xc3, 0x20, 0xc1, 0xa1, 0xc2, 0xda, 0xc0, 0xd3,
     178    0xc2, 0x52, 0xc1, 0x17, 0xc0, 0x72, 0xc1, 0x17, 0xc1, 0x66, 0xc1, 0x72,
     179    0xbf, 0x5e, 0xc0, 0xb0, 0xbd, 0xe6, 0x41, 0xbe, 0x6f, 0xc0, 0x6c, 0x3a,
     180    0xbf, 0xe2, 0x02, 0x02, 0xbd, 0x7f, 0xbe, 0x8c, 0xbe, 0xf7, 0xbf, 0x7c,
     181    0xbe, 0xb4, 0xbe, 0x8c, 0xc3, 0x20, 0xbd, 0x9b, 0xc2, 0x52, 0xbe, 0x46,
     182    0xc1, 0xeb, 0xbe, 0xcf, 0x02, 0x03, 0xc0, 0x2c, 0xc1, 0xc2, 0xc0, 0x93,
     183    0xc1, 0xe5, 0xc1, 0x61, 0xc2, 0x08, 0xc2, 0xb9, 0xc2, 0x29, 0xc2, 0x52,
     184    0xc1, 0xe5, 0xc3, 0x20, 0xc2, 0x6f, 0xc3, 0x41, 0xc3, 0x1a, 0xc3, 0x41,
     185    0xc3, 0x1a, 0xc2, 0x73, 0xc2, 0xb3, 0x06, 0x08, 0xff, 0xaa, 0xb3, 0xfd,
     186    0xc6, 0xa8, 0xb3, 0xc5, 0xc6, 0x54, 0xb4, 0x6c, 0xc6, 0x70, 0xb5, 0x83,
     187    0xc5, 0x43, 0xb5, 0x4a, 0xc5, 0xb3, 0xb5, 0xba, 0xc4, 0xd4, 0xb6, 0x7e,
     188    0xc4, 0x2b, 0xb5, 0xf3, 0xc4, 0x80, 0xb7, 0x09, 0xc3, 0xd8, 0xb8, 0xad,
     189    0xc2, 0x51, 0xb8, 0x75, 0xc2, 0xc0, 0xb8, 0xe5, 0xc1, 0xe1, 0xb9, 0xa9,
     190    0xc1, 0x1e, 0xba, 0x4e, 0xc0, 0xcc, 0xbb, 0x0e, 0xbf, 0x19, 0xb4, 0x18,
     191    0xc5, 0xb4, 0x06, 0x08, 0xff, 0xaa, 0xb5, 0xb3, 0xc8, 0xa0, 0xb5, 0x7a,
     192    0xc8, 0x4d, 0xb6, 0x22, 0xc8, 0x69, 0xb7, 0x37, 0xc7, 0x3a, 0xb7, 0x00,
     193    0xc7, 0xaa, 0xb7, 0x6f, 0xc6, 0xcc, 0xb8, 0x34, 0xc6, 0x23, 0xb7, 0xa8,
     194    0xc6, 0x77, 0xb8, 0xc0, 0xc5, 0xd0, 0xba, 0x62, 0xc4, 0x49, 0xba, 0x2b,
     195    0xc4, 0xb9, 0xba, 0x9b, 0xc3, 0xd8, 0x35, 0xc3, 0x14, 0xbc, 0x5b, 0xc2,
     196    0xe6, 0xbb, 0x95, 0xc2, 0x1a, 0xb5, 0xcd, 0xc7, 0xaa, 0x06, 0x08, 0xff,
     197    0xe8, 0xb9, 0x19, 0xc9, 0x94, 0xb8, 0x9e, 0xc9, 0x22, 0xb9, 0x89, 0xc9,
     198    0x5b, 0xba, 0x9f, 0xc8, 0x2f, 0xba, 0x68, 0xc8, 0x9d, 0xba, 0xd6, 0xc7,
     199    0xbe, 0xbb, 0x9b, 0xc7, 0x17, 0xbb, 0x0f, 0xc7, 0x6b, 0xbc, 0x03, 0xc6,
     200    0xd7, 0xbd, 0x6e, 0xc5, 0xa9, 0xbc, 0xe9, 0xc6, 0x2b, 0xbd, 0x9b, 0xc5,
     201    0x7f, 0xbd, 0x29, 0xbb, 0x93, 0xc6, 0xdb, 0xbb, 0x05, 0xc6, 0xd7, 0xb9,
     202    0x33, 0xc8, 0x9e, 0xb9, 0x33, 0xc8, 0x9e, 0xb9, 0x33, 0xc8, 0x9d, 0x06,
     203    0x06, 0xff, 0x0e, 0xbc, 0xce, 0xca, 0x7b, 0xbb, 0xdb, 0xca, 0x48, 0xbd,
     204    0x3e, 0xca, 0x43, 0xbe, 0x53, 0xc9, 0x15, 0xbe, 0x1b, 0xc9, 0x84, 0xbe,
     205    0x8c, 0xc8, 0xa5, 0xbf, 0x4e, 0xc7, 0xfe, 0xbe, 0xc3, 0xc8, 0x51, 0xbf,
     206    0xab, 0xc7, 0xc6, 0xc0, 0xf1, 0xc6, 0xbe, 0xc0, 0x6b, 0xc7, 0x38, 0xc1,
     207    0x35, 0xc6, 0x81, 0xbf, 0xe0, 0xc6, 0x9f, 0xbc, 0xe8, 0xc9, 0x84, 0xbc,
     208    0xe8, 0xc9, 0x84, 0xbc, 0xe9, 0xc9, 0x84, 0x02, 0x1e, 0xca, 0xe4, 0xbb,
     209    0xfe, 0xca, 0xe4, 0xbc, 0x5f, 0xca, 0xe4, 0xbb, 0xb6, 0xca, 0xa6, 0xbb,
     210    0x1a, 0xca, 0xd3, 0xbb, 0x6a, 0xca, 0x19, 0xba, 0x20, 0xc5, 0xec, 0xb8,
     211    0xd4, 0xc8, 0x8c, 0xb9, 0x62, 0xc4, 0xd1, 0xb8, 0x99, 0xc4, 0x04, 0xb9,
     212    0x39, 0xc4, 0x24, 0xb9, 0x1c, 0xc3, 0xfa, 0xb9, 0x3e, 0xc2, 0xdf, 0xb9,
     213    0xca, 0xc3, 0x14, 0xb9, 0xb0, 0xc2, 0xa3, 0xb9, 0xaa, 0xc1, 0xaf, 0xb9,
     214    0x70, 0xc2, 0x25, 0xb9, 0x6c, 0xc1, 0xaf, 0xb9, 0x70, 0xb7, 0xbb, 0xb9,
     215    0x70, 0xb7, 0xbb, 0xb9, 0x70, 0xb6, 0xc9, 0xb9, 0x70, 0xb6, 0x1f, 0xbb,
     216    0x4c, 0xb6, 0x1f, 0xba, 0x6b, 0xb6, 0x1f, 0xbb, 0xae, 0xb6, 0x7b, 0xbc,
     217    0x44, 0xb6, 0x3e, 0xbc, 0x04, 0xb6, 0xa9, 0xbc, 0x76, 0xb7, 0x9b, 0xbc,
     218    0xb2, 0xb7, 0x01, 0xbc, 0xb2, 0xb7, 0x9b, 0xbc, 0xb2, 0xbb, 0x19, 0xbc,
     219    0xb2, 0xbb, 0x19, 0xbc, 0xb2, 0xbb, 0xb5, 0xbc, 0xbe, 0xbb, 0xdc, 0xbd,
     220    0x0b, 0xbb, 0xd8, 0xbc, 0xda, 0xbb, 0xd1, 0xbd, 0x26, 0xbb, 0x84, 0xbd,
     221    0xf5, 0xbb, 0x8d, 0xbd, 0xdc, 0xbb, 0x6d, 0xbe, 0x0b, 0xb3, 0x89, 0xc5,
     222    0xaf, 0xb3, 0x89, 0xc5, 0xaf, 0xb3, 0x25, 0xc6, 0x11, 0x20, 0xc6, 0xcf,
     223    0x20, 0xc6, 0x75, 0x20, 0xc7, 0x30, 0xb3, 0x68, 0xc7, 0xbf, 0xb3, 0x2c,
     224    0xc7, 0x85, 0xb3, 0xb8, 0xc8, 0x10, 0xb4, 0xa8, 0xc8, 0x46, 0x23, 0xc8,
     225    0x42, 0xb4, 0x5e, 0xc8, 0xc6, 0xb4, 0xce, 0xc9, 0xbb, 0xb4, 0x69, 0x58,
     226    0xb5, 0x7d, 0xca, 0x78, 0x2d, 0xc9, 0xb5, 0xb6, 0xf5, 0xca, 0x98, 0xb8,
     227    0x32, 0xc9, 0xc1, 0xb8, 0x38, 0xc9, 0xd9, 0xb8, 0x34, 0xc9, 0xcf, 0xb8,
     228    0x65, 0xca, 0x5e, 0xb9, 0xb6, 0xca, 0xe6, 0xb8, 0xf3, 0xca, 0xc2, 0xba,
     229    0x4f, 0xcb, 0x01, 0xbb, 0xd0, 0xca, 0x8a, 0xbb, 0x1f, 0xca, 0xf2, 0xbb,
     230    0xd0, 0xca, 0x9f, 0xbb, 0xd9, 0xca, 0xc2, 0xbb, 0xd4, 0xca, 0xb3, 0xbb,
     231    0xf5, 0xcb, 0x2c, 0xbc, 0xd8, 0xcb, 0x9c, 0xbc, 0x52, 0xcb, 0x7b, 0xbd,
     232    0x8e, 0xcb, 0xca, 0xbf, 0xb2, 0xca, 0x97, 0xbe, 0xb9, 0xcb, 0x9f, 0xbf,
     233    0xb0, 0xca, 0x99, 0xc5, 0x1f, 0xc5, 0x4a, 0xc5, 0x1f, 0xc5, 0x4a, 0xc5,
     234    0x48, 0xc5, 0x21, 0xc9, 0x91, 0xc0, 0x71, 0xc9, 0x09, 0xc1, 0x5e, 0xc9,
     235    0xda, 0xbf, 0xf1, 0xc9, 0xf4, 0xbf, 0x38, 0xc9, 0xf4, 0xbf, 0x99, 0xc9,
     236    0xf4, 0xbe, 0xeb, 0xc9, 0xcc, 0xbe, 0x25, 0xc9, 0xe4, 0xbe, 0x98, 0xc9,
     237    0xcc, 0xbe, 0x25, 0xca, 0x9a, 0xbd, 0x3a, 0xca, 0x9a, 0xbd, 0x3a, 0xca,
     238    0x9a, 0xbd, 0x3a, 0x06, 0x35, 0xfb, 0xff, 0xbf, 0xfa, 0xbf, 0xaf, 0xfe,
     239    0xbf, 0xea, 0xef, 0xff, 0xbf, 0xfe, 0x03, 0xca, 0x2d, 0xbc, 0xcf, 0xca,
     240    0x41, 0xbc, 0x91, 0xca, 0x2d, 0xbc, 0xcf, 0xc9, 0x2c, 0xbd, 0xc0, 0xc9,
     241    0x46, 0xbe, 0x41, 0xc9, 0x46, 0xbe, 0x41, 0xc9, 0x5d, 0xbe, 0xb2, 0xc9,
     242    0x6c, 0xbf, 0x39, 0xc9, 0x6c, 0xbe, 0xfb, 0xc9, 0x6c, 0xbf, 0x88, 0xc9,
     243    0x1a, 0xc0, 0x2c, 0xc9, 0x54, 0xbf, 0xc5, 0xc8, 0xb1, 0xc0, 0xe4, 0xc4,
     244    0xbe, 0xc4, 0xe9, 0xc5, 0xd1, 0xc3, 0xd5, 0xc4, 0xbe, 0xc4, 0xe9, 0xbf,
     245    0x4f, 0xca, 0x36, 0xbf, 0x4f, 0xca, 0x36, 0xbe, 0x7e, 0xcb, 0x17, 0xbc,
     246    0xf9, 0xcb, 0x18, 0xbd, 0x8b, 0xcb, 0x3b, 0xbc, 0xa6, 0xcb, 0x02, 0xbc,
     247    0x5d, 0xca, 0x9d, 0xbc, 0x6b, 0xca, 0xd5, 0xbc, 0x4b, 0xca, 0x5e, 0xbc,
     248    0xc5, 0xc9, 0xb9, 0xbc, 0x71, 0xca, 0x0c, 0xbc, 0xc5, 0xc9, 0xb9, 0xbc,
     249    0xc1, 0xc9, 0xb5, 0xbc, 0xc1, 0xc9, 0xb5, 0xbd, 0xce, 0xc8, 0xb0, 0xc1,
     250    0xa6, 0xc4, 0xef, 0xc0, 0xa8, 0xc4, 0xc0, 0xc0, 0xdd, 0xc4, 0xf4, 0xbc,
     251    0x18, 0xc9, 0x9b, 0xbc, 0x18, 0xc9, 0x9b, 0xbb, 0x77, 0xca, 0x5f, 0xb9,
     252    0xcf, 0xca, 0x5f, 0xba, 0x79, 0xca, 0x7e, 0xb9, 0x41, 0xca, 0x45, 0xb8,
     253    0xba, 0xc9, 0xae, 0xb8, 0xd5, 0xca, 0x00, 0xb8, 0xb5, 0xc9, 0x9f, 0xb8,
     254    0xb3, 0xc9, 0x82, 0xb8, 0xb3, 0xc9, 0x91, 0xb8, 0xb3, 0xc9, 0x61, 0xb8,
     255    0xce, 0xc9, 0x22, 0xb8, 0xbf, 0xc9, 0x40, 0xb9, 0x18, 0xc8, 0xd4, 0xb9,
     256    0x70, 0xc8, 0x78, 0xb9, 0x6c, 0xc8, 0x71, 0xb9, 0x6c, 0xc8, 0x71, 0xba,
     257    0x5c, 0xc7, 0x87, 0xbd, 0x6a, 0xc4, 0x8f, 0xbc, 0xcc, 0xc5, 0x2a, 0xbd,
     258    0x82, 0xc4, 0x78, 0xbe, 0x01, 0xc4, 0x3f, 0xbc, 0xf5, 0xc3, 0xcd, 0xbd,
     259    0x0a, 0xc4, 0x2f, 0xb8, 0xa8, 0xc8, 0x70, 0xb8, 0xa8, 0xc8, 0x70, 0xb8,
     260    0x8b, 0xc8, 0x91, 0xb8, 0x62, 0xc8, 0xcd, 0xb8, 0x74, 0xc8, 0xaf, 0xb8,
     261    0x62, 0xc8, 0xcd, 0xb8, 0x0f, 0xc9, 0x23, 0xb8, 0x0f, 0xc9, 0x23, 0xb6,
     262    0xf9, 0xca, 0x16, 0xb5, 0x33, 0xc9, 0x5f, 0xb5, 0xac, 0xc9, 0xe1, 0xb5,
     263    0x11, 0xc9, 0x3a, 0xb5, 0x01, 0x57, 0xb5, 0x01, 0xc9, 0x13, 0xb5, 0x01,
     264    0xc8, 0xb5, 0xb5, 0x56, 0xc8, 0x43, 0xb5, 0x1d, 0xc8, 0x7c, 0xb5, 0x56,
     265    0xc8, 0x43, 0xbb, 0x89, 0xc2, 0x71, 0xbb, 0x01, 0xc1, 0xb3, 0xba, 0xdb,
     266    0xc2, 0x72, 0xb5, 0x5b, 0xc7, 0x84, 0xb5, 0x57, 0xc7, 0x80, 0xb5, 0x57,
     267    0xc7, 0x80, 0xb4, 0xee, 0xc7, 0xe8, 0xb3, 0xc8, 0xc7, 0x60, 0xb4, 0x2e,
     268    0xc7, 0xc5, 0xb3, 0x69, 0xc6, 0xff, 0xb3, 0xe8, 0xc6, 0x10, 0xb3, 0x75,
     269    0xc6, 0x85, 0xb3, 0xe8, 0xc6, 0x10, 0xbb, 0xf9, 0xbe, 0x42, 0xbc, 0x67,
     270    0xbd, 0x12, 0xbc, 0x67, 0xbd, 0x12, 0xbc, 0x67, 0xbc, 0x42, 0xbb, 0x1e,
     271    0xbc, 0x29, 0xbb, 0x88, 0xbc, 0x31, 0xbb, 0x1e, 0xbc, 0x29, 0xb7, 0x9b,
     272    0xbc, 0x29, 0xb7, 0x9b, 0xbc, 0x29, 0xb7, 0x47, 0xbc, 0x29, 0xb6, 0xde,
     273    0xbb, 0xe7, 0xb7, 0x08, 0xbc, 0x12, 0xb6, 0xb1, 0xbb, 0xb7, 0xb6, 0xa9,
     274    0xbb, 0x4c, 0xb6, 0xa9, 0xbb, 0x77, 0xb6, 0xa9, 0xba, 0xab, 0xb7, 0xbb,
     275    0xb9, 0xf9, 0xb7, 0x1d, 0xb9, 0xf9, 0xb7, 0xbb, 0xb9, 0xf9, 0xc1, 0xb3,
     276    0xb9, 0xf9, 0xc1, 0xb3, 0xb9, 0xf9, 0xc2, 0x13, 0xb9, 0xf6, 0xc2, 0xb8,
     277    0xba, 0x52, 0xc2, 0x8f, 0xba, 0x38, 0xc2, 0xb8, 0xba, 0x52, 0xc2, 0xd8,
     278    0xba, 0x68, 0xc4, 0x50, 0xb9, 0xac, 0xc4, 0x56, 0xb9, 0xa5, 0xc4, 0x56,
     279    0xb9, 0xa5, 0xc4, 0x5c, 0xb9, 0xa0, 0xc5, 0xd0, 0xb9, 0x5a, 0xc4, 0xe4,
     280    0xb9, 0x28, 0xc8, 0x3e, 0xb9, 0xde, 0xca, 0x30, 0x35, 0xc9, 0xb7, 0xba,
     281    0x8c, 0xca, 0x4f, 0xbb, 0x94, 0xca, 0x59, 0xbb, 0xfe, 0xca, 0x59, 0xbb,
     282    0xcb, 0xca, 0x59, 0xbc, 0x4b, 0x02, 0x07, 0xc3, 0x13, 0xbd, 0x34, 0xc3,
     283    0xb9, 0xbc, 0x51, 0xc3, 0x8b, 0xbc, 0xca, 0xc4, 0x6e, 0xbb, 0xf7, 0xc3,
     284    0xba, 0xbc, 0x15, 0xc5, 0x22, 0xbb, 0xd9, 0xc7, 0xe7, 0xbc, 0x7f, 0xc7,
     285    0x14, 0xbb, 0xab, 0xc7, 0x40, 0xbc, 0x7f, 0xc5, 0xf5, 0xbd, 0xd9, 0xc6,
     286    0x05, 0xbd, 0x51, 0xc5, 0xe7, 0xbe, 0x60, 0xc5, 0x5e, 0xbe, 0x16, 0xc5,
     287    0x9b, 0xbe, 0x42, 0xc5, 0x22, 0xbd, 0xe8, 0xc4, 0xf5, 0xbd, 0x16, 0xc4,
     288    0xf5, 0xbd, 0x60, 0xc4, 0xf5, 0xbc, 0xca, 0xc5, 0xc9, 0xbc, 0x51, 0xc5,
     289    0x5e, 0xbc, 0x60, 0xc4, 0xb9, 0xbc, 0x6f, 0x06, 0x0b, 0xff, 0xee, 0x3f,
     290    0xc9, 0x77, 0xbd, 0xda, 0xc9, 0x77, 0xbd, 0xda, 0xca, 0x5f, 0xbd, 0x12,
     291    0xc9, 0x4a, 0xba, 0x63, 0xcb, 0x6e, 0xbb, 0x32, 0xc9, 0xb1, 0xbb, 0x32,
     292    0xc8, 0x59, 0xbc, 0x67, 0xc8, 0xe3, 0xbc, 0x67, 0xc8, 0x59, 0xbc, 0xf0,
     293    0xc7, 0x6a, 0xc0, 0x05, 0xc8, 0xe3, 0xbe, 0x46, 0xc7, 0x1a, 0xc0, 0x63,
     294    0xc3, 0x2a, 0xc4, 0x32, 0xc1, 0xba, 0xc6, 0xb8, 0xc1, 0xba, 0xc6, 0xb8,
     295    0xc0, 0xde, 0xc7, 0xa1, 0xbf, 0xe9, 0xc8, 0x99, 0xbd, 0xa0, 0xca, 0x9b,
     296    0xbe, 0x2a, 0xca, 0x9b, 0xbd, 0x18, 0xca, 0x9b, 0xbd, 0x18, 0xcb, 0x47,
     297    0xbc, 0x6c, 0xcb, 0x47, 0xbd, 0xc3, 0xcb, 0x47, 0xc1, 0x3f, 0xc8, 0x99,
     298    0xbe, 0xf7, 0xca, 0xe0, 0xc3, 0x87, 0xc6, 0x51, 0xc9, 0xb1, 0xbf, 0x36,
     299    0xc9, 0x8e, 0xc0, 0xd3, 0xc9, 0xd2, 0xbd, 0x9b, 0x02, 0x1c, 0xca, 0xd7,
     300    0xbd, 0xfc, 0xca, 0xec, 0xbd, 0xbd, 0xca, 0xd7, 0xbd, 0xfc, 0xca, 0x53,
     301    0xbe, 0xe5, 0xca, 0x53, 0xbe, 0xe5, 0xca, 0x53, 0xbe, 0xe5, 0xca, 0x24,
     302    0xbf, 0x73, 0xca, 0x24, 0xbf, 0x73, 0xca, 0x3b, 0xbf, 0xe3, 0xca, 0x18,
     303    0xc0, 0x64, 0xca, 0x18, 0x41, 0xca, 0x18, 0xc0, 0xb3, 0xc9, 0xc5, 0x44,
     304    0xca, 0x00, 0x43, 0xc9, 0x5b, 0xc2, 0x10, 0xc5, 0x6a, 0xc6, 0x15, 0xc6,
     305    0x7c, 0xc5, 0x02, 0xc5, 0x6a, 0xc6, 0x15, 0xbf, 0xfa, 0xcb, 0x62, 0xbf,
     306    0xfa, 0xcb, 0x62, 0xbf, 0x28, 0xcc, 0x43, 0xbd, 0xa5, 0xcc, 0x43, 0xbe,
     307    0x35, 0xcc, 0x67, 0xbd, 0x51, 0xcc, 0x2f, 0xbd, 0x07, 0xcb, 0xca, 0xbd,
     308    0x17, 0xcc, 0x01, 0x39, 0xcb, 0x89, 0xbc, 0xc3, 0xca, 0xc7, 0xbc, 0x6d,
     309    0xcb, 0x1a, 0xbc, 0x22, 0xcb, 0x8a, 0xba, 0x79, 0xcb, 0x8a, 0xbb, 0x25,
     310    0xcb, 0xaa, 0xb9, 0xec, 0xcb, 0x70, 0xb8, 0xc4, 0x5b, 0xb8, 0xdf, 0xca,
     311    0xd3, 0xb8, 0xbf, 0xca, 0x73, 0xb8, 0xba, 0xca, 0x4f, 0xb8, 0xba, 0xca,
     312    0x4f, 0xb7, 0xa3, 0xcb, 0x40, 0xb5, 0xdd, 0xca, 0x89, 0xb6, 0x56, 0xcb,
     313    0x0c, 0xb5, 0xbc, 0xca, 0x66, 0xb5, 0x2a, 0xc9, 0xe9, 0xb5, 0x2a, 0xca,
     314    0x13, 0xb5, 0x2a, 0xc9, 0xb4, 0xb6, 0x03, 0xc8, 0xab, 0xb6, 0x03, 0xc8,
     315    0xab, 0xb5, 0x9a, 0xc9, 0x14, 0xbc, 0xa5, 0xbf, 0x6e, 0xbc, 0xa5, 0xbf,
     316    0x6e, 0xbc, 0xa5, 0xbf, 0x6e, 0xbd, 0x11, 0xbe, 0x3f, 0xbd, 0x11, 0xbe,
     317    0x3f, 0xbd, 0x11, 0xbd, 0x6d, 0xbb, 0xc8, 0xbd, 0x54, 0xbc, 0x34, 0x3a,
     318    0xbb, 0xc8, 0xbd, 0x54, 0xb8, 0x13, 0xbe, 0x34, 0xb8, 0x13, 0xbe, 0x34,
     319    0xb7, 0xbf, 0xbe, 0x34, 0xb7, 0x56, 0xbd, 0xf2, 0xb7, 0x80, 0xbe, 0x1d,
     320    0xb7, 0x29, 0x3b, 0xb7, 0x21, 0xbd, 0x57, 0xb7, 0x21, 0xbd, 0x82, 0xb7,
     321    0x21, 0xbc, 0xb6, 0xb8, 0x34, 0xbc, 0x04, 0xb7, 0x95, 0xbc, 0x04, 0xb8,
     322    0x34, 0xbc, 0x04, 0xc4, 0xfb, 0xba, 0xd7, 0xc4, 0xfb, 0xba, 0xd7, 0xc4,
     323    0xfb, 0xba, 0xd7, 0xc5, 0x02, 0xba, 0xd1, 0xc5, 0x02, 0xba, 0xd1, 0xc5,
     324    0x07, 0xba, 0xcc, 0xc6, 0x7b, 0xba, 0x86, 0xc5, 0x8e, 0xba, 0x54, 0x57,
     325    0xbb, 0x09, 0xca, 0xda, 0xbc, 0x8a, 0xca, 0x63, 0xbb, 0xb7, 0xca, 0xfa,
     326    0xbc, 0xc1, 0xcb, 0x04, 0xbd, 0x29, 0xcb, 0x04, 0x39, 0xcb, 0x04, 0xbd,
     327    0x75, 0x11, 0x0a, 0x00, 0x01, 0x11, 0x00, 0x0a, 0x01, 0x01, 0x00, 0x00,
     328    0x0a, 0x02, 0x01, 0x01, 0x00, 0x0a, 0x03, 0x01, 0x02, 0x00, 0x0a, 0x04,
     329    0x01, 0x03, 0x00, 0x0a, 0x05, 0x01, 0x04, 0x00, 0x0a, 0x06, 0x01, 0x05,
     330    0x00, 0x0a, 0x07, 0x01, 0x06, 0x00, 0x0a, 0x08, 0x01, 0x07, 0x00, 0x0a,
     331    0x09, 0x01, 0x08, 0x00, 0x0a, 0x0a, 0x01, 0x09, 0x00, 0x0a, 0x0b, 0x01,
     332    0x0a, 0x00, 0x0a, 0x0c, 0x01, 0x0b, 0x00, 0x0a, 0x0d, 0x01, 0x0c, 0x00,
     333    0x0a, 0x0e, 0x02, 0x0d, 0x0e, 0x00, 0x0a, 0x0f, 0x01, 0x0f, 0x00, 0x0a,
     334    0x10, 0x01, 0x10, 0x00
     335};
     336
     337const unsigned char kFile[] = {
     338    0x6e, 0x63, 0x69, 0x66, 0x04, 0x02, 0x00, 0x06, 0x03, 0x39, 0x9e, 0x0f,
     339    0x3d, 0x9c, 0x0a, 0xbf, 0x82, 0xb2, 0x3b, 0x84, 0xa9, 0x4b, 0x88, 0x50,
     340    0x48, 0x70, 0xc9, 0x00, 0xa5, 0xb1, 0xff, 0xbc, 0xea, 0xf1, 0xff, 0xff,
     341    0xb3, 0xb8, 0xff, 0x05, 0x01, 0x02, 0x01, 0x06, 0x02, 0x3e, 0x49, 0x24,
     342    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xaa, 0xaa, 0x49, 0x40, 0x00,
     343    0x4a, 0x30, 0x00, 0xff, 0xc0, 0xd5, 0xff, 0x7c, 0x89, 0x6e, 0xff, 0x04,
     344    0x01, 0x92, 0x04, 0x06, 0x06, 0xae, 0x0b, 0xb4, 0x0b, 0xbf, 0x4d, 0x33,
     345    0xc3, 0xaf, 0xb7, 0x5d, 0xc1, 0x73, 0xbd, 0xef, 0xc6, 0x07, 0xc1, 0x3e,
     346    0xc8, 0x04, 0xca, 0x28, 0xbd, 0x82, 0xc1, 0x18, 0xb9, 0x20, 0xc5, 0x1b,
     347    0xbb, 0x40, 0xbf, 0x07, 0xb8, 0x08, 0x3a, 0xb6, 0xbc, 0x06, 0x05, 0xae,
     348    0x02, 0xb5, 0x7d, 0x3e, 0xb9, 0xb9, 0xc3, 0xef, 0xb7, 0xbb, 0x44, 0xbb,
     349    0xb7, 0x51, 0xbd, 0x75, 0xc9, 0x36, 0xca, 0x8e, 0xc1, 0xb1, 0x40, 0x2f,
     350    0x0a, 0x09, 0x3b, 0x59, 0x3d, 0x5b, 0xbf, 0xcd, 0xc9, 0x3e, 0x45, 0x5b,
     351    0xc5, 0x16, 0xc5, 0xf1, 0x60, 0x46, 0x5b, 0x43, 0x5d, 0x45, 0x44, 0x51,
     352    0x0a, 0x04, 0x5a, 0x42, 0x5e, 0x3f, 0x5a, 0x3d, 0x57, 0x40, 0x05, 0x0a,
     353    0x03, 0x02, 0x02, 0x03, 0x00, 0x0a, 0x01, 0x01, 0x01, 0x10, 0x01, 0x17,
     354    0x84, 0x00, 0x04, 0x0a, 0x02, 0x01, 0x01, 0x00, 0x0a, 0x01, 0x01, 0x00,
     355    0x10, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 0x00, 0x01, 0x00, 0x00
     356};