Одна из основных функций десктопного клиента Облака Mail.Ru — синхронизация данных. Ее целью является приведение папки на ПК и ее представления в Облаке к одинаковому состоянию. При разработке этого механизма мы встретились с некоторыми, с первого взгляда, достаточно очевидными особенностями различных файловых и операционных систем. Однако если о них не знать, можно столкнуться с довольно неприятными последствиями (не получится загрузить или удалить файл). В этой статье мы собрали особенности, знание которых позволит вам правильно работать с данными на дисках и, возможно, убережет от необходимости срочного хотфикса.

1. События от файловой системы не гарантируют полную картину произошедшего


Любой механизм синхронизации директорий требует мониторинг изменений состояния файлов и папок. Благо API каждой операционной системы предоставляет нам такую возможность. Мы используем ReadDirectoryChangesW для Windows, FSEventStream для macOS и inotify для Linux. И уже тут подстерегают неприятные моменты. Дело в том, что под macOS нельзя с уверенностью сказать, какое именно событие пришло от файловой системы. Вы запросто можете получить CREATED, DELETED, RENAMED, MODIFIED на файл в одном событии. И, вроде бы, все логично: если есть удаление, значит файла уже нет, однако:

$ rm 1.txt && echo "hello" > 1.txt

придет одним событием:

1.txt: CREATED | REMOVED | MODIFIED

Поэтому приходится использовать дополнительные механизмы проверки событий для понимания, что именно произошло с файлом или директорией.

В inotify очередь событий может переполниться, и можно начать терять их до того момента, пока вы не заберете некоторые эвенты из очереди. При этом потерянные события вам никак не компенсируются, и нужно будет выполнять дорогостоящие операции вроде обхода по диску.

2. С символическими ссылками не получится работать как с обычными файлами


Символические ссылки могут быть зацикленными: A -> B -> C -> B. Решить эту проблему можно, например, с помощью номера inode (уникальный номер файла или папки в текущем разделе диска, но о них чуть ниже). В нашем случае мы храним список inode символических ссылок, по которым прошли до текущей директории. Если inode текущей символической ссылки совпадает с тем, что уже есть в списке, то считаем ее зацикленной и пропускаем.

Символическая ссылка может оказаться битой. Если в какой-то момент контент, на который указывала символическая ссылка будет, перемещен или удален, то ссылка станет недоступной. Важно правильно обработать этот момент.

Если вы подписаны на событие от директории, в которой у вас есть символические ссылки на другие директории, то события об изменении контента по символической ссылки приходить не будут.

3. Имена файлов и папок могут быть в неправильной UTF-16


Был один интересный баг. В локальном дереве пользователя, который зарепортил нам проблему, был файл. Однако при попытке его чтения мы понимали, что файла нет. Вроде бы логичная ситуация, когда в момент нашей работы файл удаляется. Но при следующем листинге директории файл опять был на месте. Дело в том, что под Windows можно создать невалидную кодировку UTF-16. Точнее, название может содержать невалидную суррогатную пару. Конвертировать такое название в UTF-8, а затем обратно в UTF-16 стандартными средствами (WideCharToMultiByte, MultiByteToWideChar) не получится. Возьмем пример:

wchar_t name[] =  { 0xDCA9, 0x2E, 0x74, 0x78, 0x74, 0x00 };



Суррогатные пары состоят из High и Low значения и нужны для того, чтобы расширить диапазон кодируемых символов. High Surrogates лежат в диапазоне xD800 — xDB7F. Low Surrogates в диапазоне DC00 — DFFF. В нашем названии мы взяли High, но не взяли Low. Таким образом, мы получили невалидный UTF-16.

Конвертируем такое название в UTF-8, затем обратно:

wchar_t name2[] =  { 0xFFFD, 0x2E, 0x74, 0x78, 0x74, 0x00 }; // "?.txt"

Символ, представляющий начало суррогатной пары, ломается. Обратиться по такому названию уже не получится.

Код примера
#include <assert.h>
#include <string>
#include <Windows.h>

std::string utf16ToUtf8(const std::wstring& utf16) {
    int size = WideCharToMultiByte(CP_UTF8, 0, utf16.data(), static_cast<int>(utf16.size()), NULL, 0, NULL, NULL);
    std::string utf8(size, 0x00);
    WideCharToMultiByte(CP_UTF8, 0, utf16.data(), static_cast<int>(utf16.size()), &utf8[0], size, NULL, NULL);
    return utf8;
}

std::wstring utf8ToUtf16(const std::string& utf8) {
    int size = MultiByteToWideChar(CP_UTF8, 0, utf8.data(), static_cast<int>(utf8.size()), NULL, 0);
    std::wstring utf16(size, 0x00);
    MultiByteToWideChar(CP_UTF8, 0, utf8.data(), static_cast<int>(utf8.size()), &utf16[0], size);
    return utf16;
}

int main() {
    std::wstring original_utf16 = { 0xDCA9, 0x2E, 0x74, 0x78, 0x74, 0x00 };

    // Создаем файл с невалидной суррогатной парой
    HANDLE handle = CreateFileW(original_utf16.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
    if (handle == INVALID_HANDLE_VALUE) {
        return 1;
    }

    CloseHandle(handle);

    // Преобразуем название в UTF-8 и обратно
    std::string utf8 = utf16ToUtf8(original_utf16);
    std::wstring utf16 = utf8ToUtf16(utf8);

    // Снова пытаемся открыть файл с преобразованным названием
    handle = CreateFileW(utf16.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
    if (handle == INVALID_HANDLE_VALUE) {
        // Не имеем доступа до файла
        assert(original_utf16 == utf16);
        return 1;
    }

    // Сюда никогда не придем
    CloseHandle(handle);
    return 0;
}

Мы в модуле синхронизации всегда работаем с UTF-8. Получаем от файловой системы события или листинг и преобразуем названия в UTF-8. Сервер также работает с UTF-8. При обращении к файловой системе, мы преобразуем UTF-8 обратно в UTF-16. Проблема была решена запретом синхронизации невалидных UTF-16.

4. Подводные камни при работе с inodes


Долгое время десктопный клиент не поддерживал переименование файлов и папок. Вместо этого событие переименования обрабатывалось удалением файлов в одном месте и созданием в другом. Этот механизм работал довольно долго и стабильно. Дело в том, что удаление файла из облака — это лишь удаление ссылки на этот файл из пользовательского дерева. Сам файл при этом остается еще на какое-то время жить на сервере, чтобы вы потом, например, могли его восстановить из корзины. Таким образом, удаление и создание файла в другом месте обходились лишь отправкой мета-информации на сервер, который просто удалял ссылку на файл из одного места и создавал ее в другом, даже не открывая при этом локальную копию. Однако с появлением общих папок мы стали понимать, что должны обрабатывать именно перемещение (чтобы не потерять признак общей папки и не отключить присоединенную папку).

Одно дело, когда от файловой системы приходит событие переименования. Тут проблем никаких. Тыц-тыц и переименовали. А если приложение выключено? Нужна какая-то информация, по которой мы будем детектировать событие переименования. Было несколько вариантов детектирования перемещения:

  • Сравнивать иерархию файлов и папок. Весьма тяжелый процесс, даже исходя из того, что деревья хранятся в оперативной памяти.
  • Создавать скрытые файлы со служебной информацией в каждой папке, по которым мы будем понимать, куда папка переместилась или во что переименовалась. Однако это вызывает некоторые сложности, включая то, что пользователь может менять и редактировать эти служебные файлы, что может привести к неприятным последствиям. Да и «следить» в каждой директории не хотелось.
  • Inodes. На этом варианте мы и остановились.

Inode — индексный дескриптор. Обозначается целым числом и представляет собой идентификатор файла или папки в конкретной файловой системе.



Чуток более человечное описание «как это работает» рекомендую почитать в этой статье. В POSIX получаем inode из stat (st_ino), в Windows — GetFileInformation (nFileIndex). И все, вроде бы, просто:

  1. Клиент перезапускается, подгружаем закэшированное представление файловой иерархии.
  2. Сравниваем с тем, что сейчас лежит на диске по факту.
  3. Находим узлы, номера inode которых отсутствуют в месте, где мы полагаем, но есть в каком-то другом месте.
  4. Перемещаем эти узлы.

Однако с inodes нужно быть очень и очень осторожными. Вот некоторые подводные камни, с которыми мы столкнулись.

4.1. Хардлинки


Каждая ссылка данного типа на один файл имеет одинаковый номер inode. Мы не детектим переименование, если в дереве есть хардлинки. Хардлинк нельзя создать на папку (ну или почти нельзя), потому особенных проблем тут нет.

4.2. Inodes могут работать иначе, чем вы ожидаете


На некоторых файловых системах номера inode присваиваются не так, как должны (ну или как нам кажется, что должны). Мы полагаем, что их номера при переименовании файла не изменяются. Также мы предполагаем, что если последний файл на ФС с inode 9 удалить, то следующий файл будет иметь inode номер 10. К сожалению, некоторые файловые системы с этим не согласны.

Под macOS на FAT создаются новые файлы (не папки) с inode номер 9999… При переименовании этих файлов номер inode не меняется. При редактировании этих файлов номера меняются на порядковые значения, которые мы и ожидаем увидеть:

$ touch 1.txt
$ ls -i
999999999 1.txt
$ echo "hello" > 1.txt
$ ls -i
223 1.txt

Ext4. Дело в том, что если на этой файловой системе (которая является стандартной в большинстве дистрибутивов Linux), удалить файл с inode номер 9 в одном месте и создать новый файл в другом месте, он будет иметь inode с номером не 10 или выше, а 9.

$ touch 1.txt
$ ls -i
270 1.txt
$ rm 1.txt && touch 2.txt
$ ls -i
270 2.txt

Т.е. на данной файловой системе номером inode становится первый свободный номер. Это немного сломало нам логику. Решение пришло само собой: если задетектили переименование папки, сравниваем для ее контента номера inode для папок и хэш + размер для файлов. Если директории совпадают на 70% и выше — переименовываем. Для файлов — если хэш + размер совпали.

С учетом того, что нумерация inodes в разных файловых системах работает по-разному, у нас есть проверка, работают ли inode так, как мы ожидаем: при запуске модуля синхронизации воспроизводится тестовое поведение для проверки. Если оно такое, как мы ожидаем, значит с номерами inode можно работать. Иначе — продолжаем без поддержки переименования.

5. Программы хранят много служебных файлов на диске


Операционные системы и разной популярности программы используют служебные файлы на диске, синхронизировать которые нет особого смысла. Ниже приведен список файлов и масок, которые, как мы посчитали, нужно игнорировать:

Windows:
  • desktop.ini — хранит пользовательские настройки для текущей директории;
  • Thumbs.db — кэши эскизов для изображений;
  • файлы, начинающиеся с "~$", или ".~", или начинающиеся с "~" и заканчивающиеся ".tmp" — довольно распространенный шаблон временных файлов. Файлы такого шаблона также создает Microsoft Office при редактировании документов.

macOS:
  • .DS_Store — аналог desktop.ini под Windows;
  • Icon\r — достаточно интересный файл, при листинге файл отображается как «Icon?», хранит информацию о изображении на директории, в которой находится;
  • файлы, начинающиеся с "._" — достаточно много было шаблонов вместо этого, однако, разнообразным ПО больше нравится использовать свой формат временных файлов, после чего и было решено игнорировать файлы по данной маске.

Linux:
  • .directory — аналог desktop.ini под Windows и .DS_Store под macOS, актуально для некоторых оконных менеджеров.

6. Особенности путей в Windows до файлов и папок


Пути под Windows, безусловно, заслуживают отдельного внимания. Для путей, превышающих значение MAX_PATH (260 символов), нужно использовать перефикс "\\?\". Данный префикс, кстати, нужно использовать для CreateFile, если вы собираетесь открыть COM-порт.

Windows для каждого файла или папки, название которых длиннее 8 символов, создает короткие альясы (еще называются «8.3»). Альясы всегда в высоком регистре, содержат знак "~", за которым идет цифра, увеличивающаяся, если такой альяс уже занят (Например: «C:\PROGRA~1\»). Содержание этих признаков необходимо, но не достаточно, чтобы понять — перед вами обычное название или короткий альяс. WinApi умеет превращать короткие пути обратно в длинные (GetFullPathName). Однако нужно помнить, что он не превратит путь в длинное представление, если такой файл уже не существует.

Если кто-то откроет файл с помощью CreateFile, используя короткий путь и модифицирует его, то в событии от файловой системы (с помощью ReadDirectoryChangesW) вам придет такой же короткий путь. В связи с этим мы стараемся превратить их в длинные как можно скорее. Кстати, вы можете увидеть альясы, если введете «dir /x» из нужной директории в командной строке Windows.


Еще одной неприятной особенностью, которую нельзя пропустить: файлы и папки с точкой в конце нельзя открыть с помощью проводника (справедливо для Windows 7):


7. Заключение


Для каждой файловой системы алгоритм синхронизации пришлось адаптировать соответствующим образом. Лучшим решением в нашем случае было воссоздание тестового окружения при старте для проверки той папки, которую выбирает пользователь. И если тесты не проходят, то мы узнаем новую особенность, а пользователю либо запрещаем работать с данной папкой, либо отключаем какой-то функционал. Надеюсь, особенности, с которыми мы столкнулись, помогут вам избежать трудностей при работе с файловой системой.

Если у вас есть вопросы или замечания, смело задавайте их в комментариях или пишите лично мне на a.skogorev@corp.mail.ru.
Поделиться с друзьями
-->

Комментарии (78)


  1. azsx
    10.08.2016 11:46
    +1

    Проблема была решена запретом синхронизации невалидных UTF-16.

    А есть ли какое-то еще решение кроме исключения невалидных суррогатных пар? Я сталкиваюсь с такой проблемой при парсинге сайтов и также ничего лучше кроме исключения таких пар не придумал.


    1. askogorev
      10.08.2016 12:10
      +1

      Все зависит от того, реально ли вам нужно преобразование в кодировку, отличную от UTF-16. Я бы советовал работать именно с ней и оставить данное название «как есть». В другом случае, опишите ваш кейс более подробно, подумаем все вместе =)


      1. dartraiden
        10.08.2016 16:06

        Интересно, существуют ли какие-то утилиты, которые могли бы прошерстить содержимое диска и вывести список файлов, чьи имена содержат невалидный UTF-16?


      1. Eklykti
        16.08.2016 15:22
        -1

        Одна и та же директория синхронизируется с вендой, у которой UTF-16, и с линуксом, у которого UTF-8. Оставлять как есть и пусть в одной из систем будут крякозяблы вместо имён файлов?


  1. turbanoff
    10.08.2016 12:00
    +1

    Учитывается ли случаи, когда в папку синхронизации подмонтирована подпапка в какой-нибудь другой файловой системе? Ведь в таком случае ваш тест может не соответствовать действительности


    1. askogorev
      10.08.2016 12:01

      Если в дереве появится какой-то номер inode, совпадающий с уже существующим, то пытаться обработать перемещение для этих файлов или папок мы не будем.
      Также при обнаружения inode в другом месте проверяется контрольная сумма объекта (или какой-то процент соответствия вложенного контента, если это папка), которая отметает возможность ложного срабатывания.


  1. termsl
    10.08.2016 12:03
    +1

    Сорри, как создать папку с точкой на конце?


    1. saboteur_kiev
      10.08.2016 12:13

      mkdir a.
      в FAR или DN


      1. termsl
        10.08.2016 12:39

        Сейчас попробую.


      1. termsl
        10.08.2016 12:43

        Нет, и через FAR просто создает папку без точки.


        1. punkkk
          10.08.2016 13:32

          Попробуйте в ковычки взять имя.


          1. termsl
            10.08.2016 13:37

            нет, не работает, ниже написали как


            1. saboteur_kiev
              10.08.2016 15:44

              C:\test>mkdir a.
              C:\test>dir
               Volume in drive C has no label.
               Directory of C:\test
              10.08.2016  15:41    <DIR>          .
              10.08.2016  15:41    <DIR>          ..
              10.08.2016  15:41    <DIR>          a.
                             0 File(s)              0 bytes
                             3 Dir(s)      39 964 672 bytes free
              
              C:\test>cd a.
              C:\test\a.>
              


              Хм… Я не припоминаю, чтобы я что-либо патчил. Попробую проверить на других системах.


              1. MacIn
                10.08.2016 15:51

                На XP тоже создает без точки в CMD.


                1. saboteur_kiev
                  10.08.2016 15:59

                  что значит тоже — я ж привел пример, что у меня на win7 64бит все отлично сработало и в cmd и в FAR.


                  1. MacIn
                    10.08.2016 16:21

                    Дополнение к

                    Попробую проверить на других системах.

                    «тоже» = «так же, как и у остальных, а не как в вашей системе». В FAR все работает нормально.


        1. saboteur_kiev
          10.08.2016 15:02

          Ну я же как-то создал
          F7
          a.
          успех


    1. Cr3w
      10.08.2016 13:25
      +2

      mkdir \\?\C:\a.


      1. termsl
        10.08.2016 13:38

        Супер, оно, спасибо)
        Windows 10 кстати тоже не может открыть такую папку.


      1. dr_begemot
        10.08.2016 13:58

        А можно ли потом в этой папке создать файл и писать/читать в него?


        1. Cr3w
          10.08.2016 14:20
          +2

          mkdir \\?\C:\a.
          echo test > \\?\C:\a.\1.txt
          type \\?\C:\a.\1.txt

          Посмотреть листинг директории не получится. Удалить отдельный файл тоже, только папку целиком: rmdir /S \\?\C:\a.\


          1. termsl
            10.08.2016 15:12
            +1

            FAR спокойно заходит в такие папки и позволяет работать с ними, как с обычными.


    1. vlreshet
      10.08.2016 15:07

      Можно создать из под виртуальной машины, в общей папке. Допустим, у меня ubuntu крутится на virtual box в windows 10. Из под убунты — папка отлично создаётся и работается с ней как ни в чём не бывало. Из под windows — эту папку видно, но никаких действий предпринять не получается, даже удалить не даёт.


  1. saboteur_kiev
    10.08.2016 12:13
    +1

    «Мы полагаем, что их номера при переименовании файла не изменяются.»
    При переименовывании inode и не будет меняться. А при редактировании — может. Если данные не меняются — inode не меняется. Все зависит от того, с чем вы работаете — с directory entry или содержимым файла. У вас проблемы были только при изменении содержимого файла.

    в Windows можно отключить создание короткого алиаса через реестр

    В имени могут быть точки, но расширение — это отдельная структура, и с ней связаны ассоциации.
    Следовательно если в конце точка есть а расширения нет, нельзя понять с чем оно ассоциируется. Поэтому файл и открыть нельзя.
    А с каталогами да, забавно, но это баг именно проводника. Все остальное работает ОК.


    1. bzzz00
      10.08.2016 13:35

      в простых случаях номер иноды не меняется, но на самом деле это зависит от файловой системы. в некоторых случаях инода может поменяться. например — Lustre с clustered metadata.


    1. MacIn
      10.08.2016 15:15

      , но это баг именно проводника

      И cmd.exe тоже.


  1. lemproix
    10.08.2016 12:28
    +7

    Стоит ли ждать webdav?


    1. askogorev
      10.08.2016 12:28
      -2

      К сожалению, разглашать планы не могу. Следите за новостями ;)


      1. saege5b
        10.08.2016 13:26
        +7

        «Следите за новостями» — это становится фирменым ответом на вопрос о вебдав.
        Прошу инсайда: хотя бы в этом столетии ждать? или завещать детям/внукам?


        1. merlin-vrn
          10.08.2016 13:36
          -1

          Предлагаю организовать петицию на Change.org


    1. roller
      11.08.2016 18:38
      -1

      Уверен, что как только выкатят webdav — сразу же отберут халявный террабайт


      1. merlin-vrn
        12.08.2016 08:28

        приставка "тера" (вообще-то 1012, а иногда терабайтом называют 240) — одна "р"


        "терра" (от латинского "terra") — "Земля", две "р"


  1. Zenitchik
    10.08.2016 12:41

    Я вот как-то раз создал файл с пробелом в конце. Удалять nodejs-ом пришлось.


    1. saboteur_kiev
      10.08.2016 15:20

      пробел экранируется бэкслешом. Плюс автодополнение отлично это делает за вас


  1. silvansky
    10.08.2016 12:47

    А как разруливается ситуация, когда валидное имя в одной fs синхронизируется на другую? К примеру, если на OS X юзер создал папку или файл con, то как этот файл/папка будет синхронизироваться на Windows?


    1. askogorev
      10.08.2016 15:12
      +2

      Сейчас в разработке на находится инструмент, который позволит синхронизировать любые символы и названия. Неразрешенные для платформы символы будут экранироваться.


  1. Antikiller
    10.08.2016 12:47
    +1

    Буквально на днях разбирал интесный баг: оказалось, что у некоторых файлов в Облаке дата съехала далеко в будущее, вылетев за пределы int32. Скриншот того, как это выглядит в браузере есть по ссылке; что стало причиной глюка установить уже не получится — это могла быть как ошибка сохранения файла, ошибка в клиенте под Android, ну или ещё что-то.


    1. askogorev
      10.08.2016 15:20

      Напишите мне на почту a.skogorev@corp.mail.ru, пожалуйста, подробную информацию о вашей проблеме, будем разбираться.


      1. Antikiller
        10.08.2016 16:31

        Отписал.


  1. heleo
    10.08.2016 13:26

    Скажите, а под Windows не было проблем с файлами начинающимися с пробела?


  1. 42dmitriy
    10.08.2016 13:26

    А когда уберете ограничение на максимальную длину пути/имени файла/имени папки?


  1. bzzz00
    10.08.2016 13:35
    +1

    очень странная идея ориентироваться на номера инодов. очевидное решение — строить свой namespace, а fs использовать как object storage. не?


    1. askogorev
      10.08.2016 15:13

      Могли бы вы более подробно рассказать про технологию, поделиться какими-то ссылками?


      1. bzzz00
        10.08.2016 15:20
        +1

        кхм… ну вот так сразу ссылок нет. идея-то простая. представим, что каждый раз, когда Вы создаете новый объект (файл/каталог), вы генерируется уникальный ID — это будет эквивалент номера иноды. теперь этот уникальный ID используем как имя файла на локальной FS (ext4, например). таким образом получается «объектное хранилище» — плоское пространство объектов с ID, который генерируете Вы. дальше поверх этих объектов можно построить свое пространство имен: одни объекты хранят списки других объектов — каталоги.
        предполагаемая засада — отстутствие атомарности: создание файла в Вашем пространстве имен будет распадаться на 2+ разные транзакции в локальной fs: создание объекта и запись о нем в Вашем каталоге. но в принципе и с этим можно справиться.


  1. merlin-vrn
    10.08.2016 13:36
    +4

    Вот я слегка не доверяю облакам и дополнительно шифрую всё, что туда кладу.


    Существует замечательная схема: я внутри синхронизируемого дерева разместил том encfs. Это директория, которая содержит файл .encfs6.xml и файлы/директории с зашифрованными именами и данными. Имена получаются вида "QDtj2N,ncNwY2DeP38Ug-oR4", запятые и минусы могут быть где угодно (например, минус в начале имени или две запятых в конце — легко), это просто "модифицированный base64", в котором запятая и минус используется вместо слеша и плюса. Преимущество такой схемы в том, что я меняю один файл, он один и синхронизируется, а не весь том, как это было бы в случае с TrueCrypt.
    А дальше я просто монтирую это в какую-то директорию вне синхонизируемого дерева, и получаю прозрачно доступ к зашифрованным файлам.


    Схема идеально работает в Dropbox, но вызвала проблемы в Cloud@Mail.ru. В какой-то момент ломается синхронизация, причём какой именно файл это вызывает — выяснить не удалось. В общем, это привело к тому, что mail.ru я теперь используют как вне-домовой бекап и работаю с ним только через веб-интерфейс.


    Однако, хотелось бы работать по-нормальному!


    1. askogorev
      10.08.2016 15:24

      Что значит «ломается синхронизация»? Могли вы написать мне на почту a.skogorev@corp.mail.ru дату проблемы, название проблемного файла, попробуем разобраться с вашей ситуацией.


      1. merlin-vrn
        10.08.2016 15:47
        +2

        Ну, прочитали вы не внимательно. Я же написал, что имя проблемного файла выяснить не удалось.


        Я должен отметить, что это не единственная причина моего недовольства десктопным приложением. Другая, не менее важная — оно не работает без X. Мне это неудобно. Более того, оно теперь требует Qt5, что само по себе не плохо, но вот нет его на этом компьютере, так что даже просто запустить приложение не смог, а соберу потом, после отпуска. Дома собрано, попробую вечером, если не забуду.


        Да, и ещё тонкость. Вот я использую Gentoo, я вполне допускаю, что вы не слышали, что кроме Debian (Ubuntu, Mint), Fedora и openSUSE конкретных версий существуют другие дистрибутивы, но у вас нет и элементарно "отвязанного от дистрибутива" файла .tar.gz (.bz2, .xz на выбор). Стыдно, даже богомерзкий Oracle выкладывает JRE и JVM в таком виде! (Ubuntu у вас тоже только древний)


        1. kalterfive
          11.08.2016 16:32

          нет и элементарно "отвязанного от дистрибутива" файла .tar.gz (.bz2, .xz на выбор).

          Да ладно, мейнтейнеры других дистрибутивов могут использовать «привязанные к дистрибутиву» пакеты ровно как и .tar.gz: распаковка, применение специфичных для дистрибутива изменений, и, собственно, упаковка в целевой пакет. Если нет нужды во втором этапе, то есть конвертеры вроде debtap.


          1. merlin-vrn
            11.08.2016 16:58

            Если что, deb вообще руками распаковать можно. Ну, не совсем руками, это архив ar, внутри которого несколько сжатых архивов tar.gz и контроль-файлик. Но всё равно выглядит некрасиво.


    1. ArtRoman
      10.08.2016 16:32

      Аналогично, пробовал использовать шифрованный sparse bundle (растущий пакет-образ диска) в OS X (пакет из файлов по несколько Мб, при изменении контента в образе меняются лишь соответствующие файлы). Всё ок, если работать с закрытым приложением облака, но на живую обязательно полезут коллизии синхронизации и конфликты файлов частей образа, что ломает весь образ в дальнейшем. В своё время писал достаточно детальный репорт, ответа не получил.


  1. teecat
    10.08.2016 13:53
    +1

    > И, вроде бы, все логично: если есть удаление, значит файла уже нет
    Почему это? Это логично только для Windows. Для Линукс файл после удаления не виден, но удаляется только после того, как его закроет последняя открывшая/создавшая его программа. Использовал активно для работы с временными файлами. Очень удобно. Даже если крешится программа, то все временные файлы уже при создании удалены и не засоряют систему


    1. saboteur_kiev
      11.08.2016 17:05

      Да, это POSIX фича.

      Файл жив, пока на него есть хотя бы одна ссылка, а в Linux имя файла — это именно ссылка на конкретный inode.

      При открытии файла, на него создается очередная ссылка среди прочих открытых дескрипторов где-то в /proc/PID/fd — она и держит файл от удаления.

      Поэтому в Linux могут быть полноправные несколько имен на тот же файл, и открытый в каком-то процессе файл — такая же ссылка, включая то, что у нее есть обычный файловый путь.

      Эта философия, например, позволяет сделать автоапдейт программы, не создавая отдельный «апдейтер», а заменяя файл прямо там где он есть, да и вообще много забавных вещей.


  1. punkkk
    10.08.2016 13:56

    Хотел проверить это приложение и поковырять с разными файлами, в итоге не запускается, а в консоли ошибка сегментации.


    1. askogorev
      10.08.2016 15:14

      Пожалуйста, отправьте мне на почту a.skogorev@corp.mail.ru вашу версию ОС и дамп файл, если есть, будем разбираться.


      1. 13_beta2
        11.08.2016 03:58

        Да ну о чём вы? Если элементарные мета-данные вроде времени создания файла не хранятся, какие тут потоки…


      1. punkkk
        11.08.2016 17:21

        Отправил.


  1. teecat
    10.08.2016 13:59

    И чисто для интереса — а вы такие вещи, как стримы, существующие для файлов и директорий в NTFS — синхронизируете?


    1. askogorev
      10.08.2016 15:07

      Нет, альтернативные стримы мы не синхронизируем.


  1. DrZlodberg
    10.08.2016 14:13

    Альясы всегда в высоком регистре, содержат знак "~", за которым идет цифра, увеличивающаяся, если такой альяс уже занят (Например: «C:\PROGRA~1\»)
    Не совсем верно. Не знаю, как сейчас в 8-ках и прочих, но в 95, 98, ХР тильду можно отключить через реестр, что я и делал. Из эстетических соображений и из практических. Иногда проще искать файл, если имя чуть длиннее (в куче файлов с похожими именами). Сейчас уже не актуально, но тем не менее.


    1. askogorev
      10.08.2016 15:17

      По путям в Windows совсем недавно была интересная статья.


    1. dartraiden
      10.08.2016 16:00

      Можно вообще отключить эти короткие имена в современных операционных системах.

      Windows Registry Editor Version 5.00

      [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem]
      "NtfsDisable8dot3NameCreation"=dword:00000001


      Либо через групповые политики (Конфигурация компьютера > Административные шаблоны > Система > Файловая система > NTFS > Параметры создания коротких имён).

      Всегда первым делом отключаю короткие имена. За 10 лет встретилась лишь одна программа, установщик которой из-за этого вываливался с ошибкой — какая-то древняя версия CSE HTML Validator.


    1. askogorev
      10.08.2016 16:53
      +2

      Решение отключить что-то в реестре должен принимать пользователь, а не мы =)
      Мы учимся работать с тем, что есть.


      1. DrZlodberg
        11.08.2016 08:42

        Так и речь о том, что это может быть потому, что пользователь такое решение принял.


  1. Godless
    10.08.2016 17:25

    del.


  1. rkfg
    10.08.2016 17:56

    Как решаете кроссплатформенные ограничения? Например, на линуксе создали файл с двоеточиями и звёзодчками в имени, что получится, если такой файл синхронизировать на Windows? И наоборот, если в Windows создать файл с именем в 250 русских символов, что получится на линуксе (у Ext4 ограничение в 255 байт, русские буквы занимают в UTF-8 по два байта, так что не влезет)?


    1. askogorev
      11.08.2016 09:34

      Ответ на данный вопрос тут.


      1. rkfg
        11.08.2016 09:41

        По запрещённым символам да, это я проглядел. Но что делать со слишком длинными именами, тем более, если префикс допустимой длины будет совпадать? Как в DOS будете сокращать и дописывать ~1, ~2 и.т.д.? Тогда надо будет вести какой-то реестр соответствия имён, наверно.


  1. svr_91
    10.08.2016 17:56

    А что сейчас с длительностью индексирования всех файлов? Я как-то пытался подключить к облаку свои каталоги, но индексирование занимает ну очень много времени, причем из-за высокой нагрузки на диск практически невозможно пользоваться никакими программами. К тому же, в какой-то момент, у меня просто перестали индексироваться файлы (приложение ходит по кругу и пытается проиндексировать одни и те же каталоги, видимо, в какой-то момент ломается и начинает это делать заново)


    1. askogorev
      11.08.2016 09:36

      Мы прямо сейчас работаем в направлении ускорения индексации.
      Можете написать мне на почту a.skogorev@corp.mail.ru, посмотрим, чем вызвана конкретно ваша проблема.


  1. zapimir
    10.08.2016 18:59
    +2

    Спасибо за интересную статью. Несколько вопросов.
    Используете ли при блочную синхронизацию или синхронизация на уровне файлов? Какие хэши для файлов используете, попадались ли коллизии?


  1. ANDRE888
    11.08.2016 00:51
    +1

    В вашем облаке очень не хватает поддержки журнала версий файлов как в DropBox. Планируется ли введение данного функционала в ваше облако?


  1. KVL01
    11.08.2016 11:24

    Забавная штука, в проводнике (семёрка) создать папку с точкой просто не получается, а если попробовать создать с двумя точками, то она вообще исчезает из перечня. Появляется, если нажать F5, ессно, уже без точек


  1. daihatsu
    11.08.2016 11:28

    Под macOS на FAT создаются новые файлы (не папки) с inode номер 9999…


    inode и FAT????


    1. saboteur_kiev
      11.08.2016 12:47

      Наверное просто stat команда на FAT и других не-POSIX файловых системах выводит 9999 для всех, вот и подумали…
      например на NTFS портированный stat из git работает, в смысле пытается выдавать информацию, и номер inode и даже количество линков, правда на всех каталогах там только один линк, то есть что оно выдает — неясно. Владельца, размеры и timestamps выдает верно


  1. arxont
    11.08.2016 12:48

    А можно узнать, как вы работаете с файлами к примеру Microsoft Word? Он при сохранении файла, идёт в три шага —
    1) Создает временный файл, куда сохраняет новую версию
    2) Удаляет предыдущий файл (до редактирования)
    3) Переименовывает темповый
    При синхронизации на это либо надо ставить специальный хак именно на doc&docx (и ещё некоторые), либо синхронизировать полностью, даже если поменялся один символ. Сам сталкивался с этой проблемой, хотелось бы узнать как у вас её решили.


    1. askogorev
      11.08.2016 12:55

      Есть ряд правил:
      1) Мы не синхронизируем временные файлы офиса, информация об этом есть в статье
      2) Мы начинаем синхронизацию через 4 секунды после изменения

      Таким образом, файл будет изменен правильно.


      1. arxont
        11.08.2016 13:05

        А можно где-нибудь посмотреть список темповых файлов-путей которые вы не синхронизируете? :)


        1. askogorev
          11.08.2016 14:10

          В статье, например =) (пункт 5)