LINUX.ORG.RU

Сообщения gentoo_root

 

Быстрый протокол для удалённого доступа к файлам

Разыскивается протокол для доступа к NAS со следующими требованиями:

  1. Должен вывозить гигабит в любую сторону.
  2. Шифрование. Безопасность такая, чтоб не страшно было через интернет этим пользоваться.
  3. Отсутствие тупорылых ограничений в стиле «имена файлов не могут содержать запрещённые в венде символы», «каталоги не имеют reliable mtime».
  4. Метаданные (такие как mtime) не теряются при копировании и перемещении между локальной и удалённой ФС.

Что я рассматривал/пробовал:

  • SSH (SFTP). По непонятным причинам медленный. scp просто упирается примерно в 30 МБ/с. gvfs и rsync выжимают 80 МБ/с между машинами на x86, но когда сервер — плата на ARM (helios4 NAS), оно тоже останавливается примерно на 30 МБ/с. Я ожидаю числа, более близкие к 125 МБ/с. Узкое место не в дисках. На ARM идёт жор процессора на 100%, на x86 нет. Есть некий патчсет HPN-SSH, который должен что-то ускорить, но патчить SSH не очень хочется из соображений секурности.
  • FTP. Не годится из-за отсутствия шифрования, ещё эта наркомания с двумя соединениями, пассивным режимом, conntrack и т.д.
  • SMB. Не годится из-за наркоманских ограничений на имена файлов, стрёмно использовать через интернет из-за критических уязвимостей в прошлом.
  • NFS. Вроде не работает через интернет?
  • WebDAV. Умеет ли он сохранять mtime при выгрузке файлов на сервер? Как минимум реализация в gvfs это не делает, насколько я вижу из кода. Если сам протокол это поддерживает, gvfs можно починить (gvfs-sftp я уже чинил).

Какие вообще остаются варианты нормального доступа к файлам по сети в 2021?

 , , ,

gentoo_root
()

GNOME, X11, переключать по caps lock две раскладки из трёх

У меня было две раскладки, которые переключались по caps lock. Я хочу добавить третью, но так, чтобы она не мешала двум основным. Один из двух вариантов подойдёт, лучше первый:

  1. Caps lock переключает только между первыми двумя. Третью можно включить каким-нибудь способом (из меню мышкой или проклацать по super+space — удобство вообще не важно).
  2. Caps lock переключает между двумя последними в использовании. По super+space можно выбрать любую.

Вообще говоря, super+space работает как раз по второму варианту — он переключает между двумя последними использованными, а если удержать super, появляется меню для выбора любой. Но caps lock почему-то тупо крутит их по кругу, а не повторяет это поведение. Может, есть способ исправить?

Я видел интересный способ здесь, который бы решил вопрос по первому сценарию, но к моему удивлению, ISO_Prev_Group и ISO_First_Group просто игнорируются! Я пытался даже отредактировать системные раскладки в /usr/share/X11/xkb/ и опытным путём понял, что эти два кода не имеют эффекта в гноме. Кто-то знает, с чем это может быть связано, куда копать, как исправить?

 , , , ,

gentoo_root
()

KVM switch на два монитора

Разыскивается KVM-переключатель со странными требованиями:

  1. Два монитора, два компьютера, одна клавиатура, одна мышь.
  2. DisplayPort или HDMI (вероятно, в любом случае придётся лепить переходники; возможно, с DisplayPort не придётся).
  3. Возможность частичного переключения (это важно, подробнее ниже).
  4. Очень желательно моментальное переключение устройств ввода и вывода. Чтобы я мог не ждать пару секунд, пока мониторы отдуплятся, и мышь начнёт ездить.
  5. Желательно возможность управлять с компьютера.

Что я понимаю под частичным переключением. Обычные KVM-свичи отдают все мониторы и устройства ввода одному из компьютеров. Мне нужны также конфигурации, когда один монитор показывает с одного компьютера, другой с другого, а устройства ввода подключены к одному из них (либо первому, либо второму). Иными словами, нужно следующие 4 конфигурации (первые две стандартные, вторые нестандартные):

  1. Левый монитор показывает дисплей 1 компьютера 1, правый монитор показывает дисплей 2 компьютера 1, устройства ввода на компьютере 1.
  2. Левый монитор показывает дисплей 1 компьютера 2, правый монитор показывает дисплей 2 компьютера 2, устройства ввода на компьютере 2.
  3. Левый монитор показывает дисплей 1 компьютера 1, правый монитор показывает дисплей 2 компьютера 2, устройства ввода на компьютере 1.
  4. Левый монитор показывает дисплей 1 компьютера 1, правый монитор показывает дисплей 2 компьютера 2, устройства ввода на компьютере 2.

Существует ли в дикой природе такое устройство?

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

(Возможность управлять с компьютера опциональна, но если будет, можно будет поиграться и заскриптовать переброс устройств ввода, когда мышь проходит через границу экранов в конфигурациях 3 и 4.)

 , ,

gentoo_root
()

NDP proxy не работает на VPS

Есть VPS, дают блок /64 (провайдер veesp). На сервере крутится openvpn, соответственно, я хочу, чтобы клиенты получали глобальные ipv6-адреса.

Что я для этого сделал:

  • Разделил блок адресов на два по /65.
  • В нижней половине выделил один адрес, назначил его на wan-интерфейс сервера (с маской /65).
  • В верхней половине выделил /112 под openvpn: один адрес стоит на tun-интерфейсе, другие openvpn раздаёт клиентам.
  • Когда клиент подключается, выполняется ip neigh add proxy "$CLIENT_IPV6" dev eth0 (eth0 — это wan).
  • Стоят опции sysctl:
    • net.ipv6.conf.all.forwarding = 1
    • net.ipv6.conf.eth0.proxy_ndp = 1

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

Если назначать любые адреса из моего блока /64 на eth0, то снаружи пинг проходит: ко мне от шлюза приходит neighbor solicitation, мой сервер отвечает neighbor advertisement, потом идут echo request и echo reply. Если этот же адрес не стоит на eth0, а используется для vpn (либо в качестве адреса одного из клиентов, либо адреса на tun-интерфейсе), и ndp proxy для него включён, то приходит neighbor solicitation, мой сервер отвечает neighbor advertisement — и тишина, echo request не доходят до моего сервера. Единственная разница — во втором случае neighbor advertisement уходит с link-local адреса на eth0, а в первом случае с того адреса, который запрашивается (потому что он назначен на eth0).

Как можно решить эту проблему, чтобы мои хосты за vpn нормально маршрутизировались?

Спасибо.

 , ndp,

gentoo_root
()

Android 9 с записью разговоров

Имел ли кто-то опыт записи разговоров на Android 9?

Насколько я понимаю, status quo следующий (поправьте, если я где-то не прав):

  • Палки в колёса, которые вставляет гугл — чистой воды идиотизм. Можно поставить громкую связь и включить диктофон на том же телефоне, и всё отлично пишется (так ли это на Android 9?). Если бы вдруг не писалось, берём второй девайс и пишем им. То есть записать всё равно можно, но гугл упорно закручивает гайки и усложняет нормальную запись разговоров с самого аппарата без костылей с диктофоном и громкой связью.
  • Испокон веков есть MediaRecorder.AudioSource.VOICE_CALL, предназначенный для записи с линии, однако, начиная с Android 6, им могут воспользоваться только системные приложения (установленные в /system и подписанные ключом, которым подписана прошивка). Это нововведение сломало все сторонние приложения для записи, но некоторые умельцы нашли способ обхода (мне он неизвестен) и интегрировали в свои проприетарные и платные приложения (boldbeast, skvalex). Этот способ перестал работать в Android 9.
  • Понятное дело, есть способы записать звук из-под рута. Так как все приложения, которые это умеют делать, проприетарны, этот способ не подходит из соображений безопасности.
  • OnePlus 5T на стоковом Android 8 писал с VOICE_CALL без рута свободной программой без каких-либо workaround. На стоковом Android 9 на этом телефоне это перестало работать.
  • Я собираю себе прошивку сам, поэтому мне открыты способы, недоступные авторам сторонних приложений. А именно, я могу использовать VOICE_CALL и подписать приложение ключом прошивки. Более того, мне даже не надо писать приложение для записи разговоров и даже не надо брать свободное из F-Droid: в LineageOS стандартный Dialer имеет эту функциональность, и она включается для некоторых девайсов.
  • VOICE_CALL из системного приложения работает не на всех девайсах. На Nexus 5X раньше он писал тишину, в последних экспериментах на собранном мной Android 8 пишет мой голос чётко, а вместо собеседника каша.

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

  • Будет ли работать на Android 9 запись с VOICE_CALL из системного приложения, если это поддерживается устройством? Или они огородили настолько, что даже так нельзя записать?
  • Будет ли работать на Android 9 обходной способ с громкой связью и диктофоном на том же устройстве?
  • Поддерживается ли запись с VOICE_CALL на Pixel 3, OnePlus 6, OnePlus 6T? Или там, как на Nexus 5X, будет тишина/неразборчиво?
  • Что за телефон такой LeEco S2? Стоит $100, при этом в LineageOS для него включена запись разговоров стандартным Dialer (есть основания предполагать, что там поддерживается запись с VOICE_CALL), и железо выглядит норм. В чём подвох, почему такая цена? Что я не заметил?
  • Есть ли способы записать разговор, задействующие рут-доступ, который предоставляется только открытому коду?

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

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

 , ,

gentoo_root
()

2D-ускорение видео на Skylake

Всем привет, речь идёт не об аппаратном ускорении декодирования видео, а о фиче, которая в плеере VLC называется "Accelerated video output (overlay)".

Насколько я знаю, эта фича была ещё в Windows XP в предустановленном проигрывателе. Суть заключается в том, что прямоугольник с видео отрисовывается напрямую в нужное место экрана, в обход оконной системы. Это даёт ускорение отрисовки. Из-за этого ещё на скриншотах в Windows XP получался чёрный прямоугольник вместо видео.

У меня встроенное видео на Skylake, Linux и два медиаплеера: Parole (в котором эта фича не отключается) и VLC (в котором отключается). Проблема проявляется независимо от оконного менеджера (попробовал xfwm с включённым и выключенным композитингом, а также compiz; также попробовал Ubuntu 15.10 с флешки, там тоже есть эта проблема).

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

Я попробовал на другом компьютере (там Nvidia GeForce 6600GT с nouveau) посмотреть видео в Parole, там такой проблемы не было. Если отключить фичу ускоренного видеовывода в VLC, то проблемы тоже не будет.

Вопроса два:

  • Как починить?
  • Как вообще организована работа этой фичи в случае, когда окно проигрывателя перекрывается другим окном? В смысле, что сделано для того, чтобы прямоугольник видео не перекрывал всё, как это происходит у меня?

К сожалению, ничего не удаётся найти в гугле, там все говорят про ускорение декодирования видео.

 ,

gentoo_root
()

А как вы кросс-компилируете util-linux?

Всем привет, возникло такое чувство, что только у меня возникают какие-то проблемы с кросс-компиляцией util-linux, потому что в интернетах на этот счёт пусто, но мне кажется, что моя проблема должна возникать просто у всех.

Итак, я собрал тулчейн (gcc, glibc, sysroot). Беру util-linux-2.27.1, распаковываю его, собираю:

$ ./configure --build=x86_64-pc-linux-gnu --host=arm-rpi-linux-gnueabihf
$ make V=1

Отлично, это всё прошло без ошибок. Смотрим, что там натворил libtool:

$ arm-rpi-linux-gnueabihf-objdump -x .libs/libblkid.so | grep RPATH
  RPATH                /tmp/util-linux-2.27.1/.libs

Собиралось это добро такой командой: http://pastebin.com/fsaCgF5n

Выхлоп от команды был следующий: http://pastebin.com/6geAwkKk

Было бы нехорошо такой бинарник ставить в таргет. Но ничего, на этот счёт у libtool есть свой костыль — relink. При make install перелинкуются заново все библиотеки без добавления каталога сборки в rpath.

Пробуем:

make install V=1 DESTDIR=/tmp/dest

Терпим фиаско при попытке релинка libblkid. Выхлоп по делу: http://pastebin.com/6ej6KNaw

Теперь сравниваем, как libtool вызывал gcc при первой линковке и при второй, пробуем также запускать обе команды с -Wl,--verbose и делаем следующие выводы:

Команды отличаются только тем, что в первую приходит -Wl,-rpath -Wl,/tmp/util-linux-2.27.1/.libs ./.libs/libuuid.so, а во вторую -L/tmp/dest/usr/lib -L/usr/lib -luuid.

Не линкуется во второй раз, потому что когда линкер ищет libc.so, то из-за флагов -L у второй команды он сначала пойдёт по этим директориям, в первой ничего не найдёт, а вот во второй найдёт /usr/lib/libc.so, представляющий собой ld-script, и дело закончится попыткой слинковаться с libc.so с хоста.

Осталось понять, откуда такие флаги у второй команды. Не вопрос, libtool'у аргументом приехал libuuid.la (libuuid тоже входит в состав util-linux), смотрим в него, а там:

# Directory that this library needs to be installed in:
libdir='/usr/lib'

Потом смотрим в код libtool, который поставляется с util-linux-2.27.1, строка 7342:

              # We cannot seem to hardcode it, guess we'll fake it.
              add_dir="-L$libdir"
              # Try looking first in the location we're being installed to.
              if test -n "$inst_prefix_dir"; then
                case $libdir in
                  [\\/]*)
                    add_dir+=" -L$inst_prefix_dir$libdir"
                    ;;
                esac
              fi
              add="-l$name"

Весь скрипт здесь: http://pastebin.com/fds2eKCA

Не копал, куда дальше уезжает эта переменная add_dir, но её изменение в этом месте приводит к изменению тех самых флагов -L, которые приезжают линкеру.

Простое решение, казалось бы, приходит сразу. Убираем add_dir="-L$libdir", потому что нам не нужно, чтобы линкеру передавался /usr/lib с хоста. Однако это вызывает массу вопросов:

  • Для чего-то же это сделано. Для чего-то при установке в DESTDIR линкеру передаётся и путь без DESTDIR тоже. Почему-то ведь нет проверки на то, кросс-компиляция это или нет. Почему-то никак не учитывается sysroot, хотя в libtool есть некая переменная lt_sysroot. Поэтому первый вопрос: почему сделано именно так?
  • Что сломается, если это изменить? Здесь я имею в виду не только util-linux, но и другие пакеты на libtool.
  • Почему я не нахожу других людей, сталкивающихся с этой проблемой? Очевидно, не я один кросс-компилирую util-linux. Может, я что-то делаю не так? Максимум, что я находил, это письмо разработчика buildroot с аналогичным вопросом. Ответы на него были полезными, но они не отвечают на мои вопросы.

Я также пробовал смотреть, как кросс-компилируют util-linux в других проектах:

  • CLFS безнадёжно протух, там очень древние версии всего, и там непохоже, чтобы они как-то пытались решить эту проблему. Возможно, там она и не возникает, но я пойти по их руководству и проверить пока не пробовал.
  • Buildroot не решает эту проблему. Он маскирует её другой, незаметной проблемой. Он накладывает патчи на libtool, после чего relink не выполняется в принципе, и в таргет отправляются бинарники с rpath, указывающим на каталог сборки на хосте.
  • В Gentoo при сборке util-linux на libtool тоже накладываются патчи, но они, как мне показалось, не касаются этой проблемы. Попытка кросс-компилировать util-linux с помощью portage успехом не увенчалась, до сборки дело просто не дошло. Я собрал тулчейн crossdev'ом, потом начал делать emerge, указав --root и --config-root, но portage не смог распарсить профиль. Возможно, дело в моей специфической конфигурации, но с этой проблемой мне предстоит справляться самому.

Основной и наиболее общий вопрос из всего этого: как всё-таки собрать util-linux правильно?

 ,

gentoo_root
()

Куда делась кнопка «Показать различия»?

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

P.S. Почему нельзя запостить без тегов? Ну не к любой же теме можно придумать подходящие теги. К этой у меня не получилось, например.

 

gentoo_root
()

Кнопки включения на lenovo ideapad

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

Можно настроить grub, чтобы он загружал одну из двух ОС в зависимости от кнопки, которой был включён ноутбук. Но не у всех есть grub, да и такой юз-кейс — не единственный, который можно придумать для двух кнопок включения.

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

Поэтому я подумал, что было бы полезно иметь простой способ из загруженного линукса узнать, какой кнопкой был включён ноутбук. Например, можно чуток допилить драйвер ideapad-laptop, чтобы он показывал в файлике /sys/bus/platform/drivers/ideapad_acpi/VPC2004:00/power_button единичку или двоечку. Но мне нужно быть уверенным, что на всех ideapad'ах действует один и тот же способ определения кнопки. Поэтому к владельцам ideapad'ов просьба выполнить следующие действия:

  • Загрузиться с помощью обычной кнопки и выполнить cat /dev/nvram | hexdump -C > nvram.1
  • Загрузиться с помощью маленькой кнопки и выполнить cat /dev/nvram | hexdump -C > nvram.2
  • Найти десять отличий: diff -u nvram.1 nvram.2. В моём случае отличался байт по адресу 0x6c и принимал значения 0x00 или 0xaa. Если у вас будет точно так же, это очень хорошо. Если по-другому, тогда это очень нехорошо, но всё равно напишите отличающиеся значения.
  • Также сообщите мне модель ноутбука, на котором проводилось тестирование.

Заранее спасибо за инфу!

 

gentoo_root
()

Stack Smashing Protector без libssp

Глянув в выхлоп objdump -d, обнаружил, что SSP у меня в системе работает и без libssp (её просто нет у меня). Глянул в libc.so.6 и увидел там __stack_chk_fail. Выходит, glibc предоставляет функцию, которая обычно лежит в libssp, поэтому ssp будет работать и без libssp? Есть ли тогда смысл использовать libssp?

 , ssp

gentoo_root
()

evdev, X11 и магия

Давно не пользовался нетбуком MSI Wind U100 (видеокарта intel 945GSE), накатил на него генту. Т.к. это может быть важно, у меня systemd. Конфиг ядра. dmesg (с кучей багов с видеокартой). Ещё systemd-logind где-то писал ошибку kernel does not support evdev-revocation, но я уже не могу найти её ни в каком логе.

Суть заключается в том, что я обнаружил, что при нажатии кнопочек яркости она меняется на две ступени сразу. sudo showkey из-под иксов (там KDE 4) действительно показывал двойные нажатия клавиш. Потыкался по /dev/input/event* и оказалось, что события идут из event4 (Video Bus) и из event5 (AT Translated Set 2 keyboard). Проблема знакомая — на моём другом ноуте та же фигня. Поэтому первым делом я решил применить решение с другого ноута — сказать иксам игнорировать Video Bus:

/etc/udev/rules.d/90-intel-quirks.rules:

ACTION=="add", KERNEL=="event*", ENV{ID_PATH}=="acpi-LNXVIDEO:00", ENV{ID_INPUT.tags}="intel-video-bus"

/etc/X11/xorg.conf.d/90-intel-quirks.conf:

Section "InputClass"
        Identifier "Ignore Intel brightness keys"
        MatchTag "intel-video-bus"
        Option "Ignore" "on"
EndSection

После перезагрузки или перезапуска иксов (не имеет значения) результат оказался неожиданным. Из /dev/input/event5 события клавиш яркости больше не сыпались! При этом event5 — это клавиатура, обычные клавиши работали и сыпались из файла. А event4 игнорировался моим конфигом, поэтому яркость вообще не регулировалась. Номера evdev'ов не менялись, это я проверяю каждый раз. Если убрать /etc/X11/xorg.conf.d/90-intel-quirks.conf, то события снова начинают сыпаться и из /dev/input/event4, и из /dev/input/event5. Это мне показалось очень и очень странным.

Но ещё более странным оказалось то, что как только я переключаюсь на виртуальный терминал, события клавиш яркости из event5 сразу же перестают сыпаться!

Из этого я делаю вывод: если Xorg не игнорирует Video Bus, то он что-то делает, что в иксах кнопочки яркости начинают сыпаться и из event5. Это какая-то магия, и я прошу кого-нибудь объяснить, как же это работает.

Вдобавок стоит сказать, что в hwdb для моего ноута настроены следующие маппинги клавиш:

KEYBOARD_KEY_f7=brightnessdown # Fn+F4
KEYBOARD_KEY_f8=brightnessup   # Fn+F5

Если их убрать из hwdb, то события из event5 продолжают сыпяться по тому же правилу, но т.к. коды клавиш другие, яркость переключается по одной ступеньке. Это можно считать workaround'ом моей проблемы, но мой вопрос в том, как же работает вышеописанная магия?

 , ,

gentoo_root
()

Я познаю strict aliasing

Всем привет, недавно у меня стало возникать слишком много мыслей о том, насколько легитимно приводить типы указателей в некоторых случаях и не нарушает ли это правил strict aliasing.

Компилируется код такой командой (gcc 4.9.2):

gcc test.c -o /dev/null -O3 -Wall -Wextra

Случай №1. Есть какой-то буфер в виде массива чаров, полученный откуда-то (по сети, например). Хочется его распарсить, для этого привести char * к какому-нибудь struct payload * и работать со структурой; выравнивание и порядок байтов к вопросу отношения не имеют, считаем, что там всё правильно. Для примера можно для упрощения вместо struct payload взять обычный int — с ним происходит то же самое:

int main()
{
        char buf[5] = "TEST";
        int *p = (int *)&buf; // По стандарту char может алиасить любой тип, но не наоборот
        *p = 0x48414559; // Но здесь предупреждения о нарушении strict aliasing почему-то нет
        *(int *)buf = 0x48414559; // А вот здесь есть
//        *(int *)(buf+1) = 0x48414559; // Вот так уже не будет, кстати
        return 0;
}
test.c: In function 'main':
test.c:6:2: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
  *(int *)buf = 0x48414559;
  ^

Вопрос: чем отличается доступ через указатель p и через buf, приведенный к int *? Почему в одном случае нет варнинга, в другом есть? Действительно ли в одном случае нарушается правило strict aliasing, а в другом нет? Или это потерянный варнинг? Или особенность реализации gcc?

Случай №2. Приведение struct sockaddr_in * к struct sockaddr *, использующееся повсеместно. Для чистоты эксперимента структуры объявнены вручную, а не взяты из хедеров. Да, их наполнение отличается от того, что там должно быть. Итак, я решил продолжить эксперимент с приведением типа указателя без промежуточной переменной.

#include <stdint.h>

struct sockaddr {
        uint16_t sa_family;
        char sa_data[14];
};

struct sockaddr_in
{
        uint16_t sin_family;
        uint16_t sin_port;
        uint32_t sin_addr;
        char sin_zero[8];
};

int main()
{
        {
                struct sockaddr_in addr;
                ((struct sockaddr *)&addr)->sa_family = 2; // Тут варнинга почему-то нет
        }
        {
                char addr[16];
                ((struct sockaddr *)&addr)->sa_family = 2; // А тут есть, как и в предыдущем примере
        }
        {
                uint32_t addr[4];
                ((struct sockaddr *)&addr)->sa_family = 2; // А здесь почему-то снова нет
        }
        return 0;
}

Господа, я в замешательстве. Вот моё мнение по этому поводу:

В первом примере нарушения правила strict aliasing есть в обоих случаях (char может алиасить любой тип, но не наоборот), однако варнинг есть почему-то в одном из случаев, в связи с этим вопрос: это недостающий варнинг или особенность поведения gcc?

Во втором примере нарушений правила strict aliasing нет, поскольку я обращаюсь только к объекту struct sockaddr. Однако в случае, когда addr — это массив чаров (как в первом примере), варнинг возникает. Здесь аналогичный вопрос: это лишний варнинг, или же смысл различен?

Ну и один глобальный вопрос: если я где-то в своих рассуждениях ошибаюсь (или чего-то не понимаю), то где?

 

gentoo_root
()

Запустить юнит при условии, что вспомогательная программа вернула 0

В юнитах systemd есть возможность задать условия, при невыполнении которых юнит не будет запускаться (например, ConditionFileExists). Мне же нужно, чтобы выполнилась вспомогательная программа и юнит стартовал, только если вспомогательная программа завершилась успешно (с кодом 0). Судя по man systemd.unit, для этого готового Condition'а не существует.

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

Есть ли какой-то минимально костыльный способ добиться того, что мне нужно?

 

gentoo_root
()

Найти границы XML-документа

Есть файл, в котором идут подряд несколько XML-документов. Какая существующая библиотека позволит из программы на C++ найти границы этих документов (для дальнейшего парсинга их)?

Пробовал скормить это QXmlStreamReader'у, но тот ругается ошибкой:

XML declaration not at start of document.

до того, как readNext() вернёт EndDocument.

 ,

gentoo_root
()

Доступ к Context в State pattern

Пытаюсь применить State pattern, но мне также нужно, чтобы из ConcreteStateA и ConcreteStateB я мог вызывать методы объекта Context, причём нужно сделать так, чтобы эти методы можно было вызывать только из наследников State, т.е. просто сделать эти методы public нельзя.

Получается, если я сделаю нужные методы класса Context приватными, то придётся всех наследников класса State записать во friend'ы класса Context. Это неподходящее решение, поскольку я не смогу создавать новые состояния без модификации класса Context.

Для обхода этой проблемы я создал класс Accessor. Класс Accessor — это friend класса Context, по сути класс Accessor предоставляет интерфейс к нужным приватным методам класса Context, при этом объекты состояний имеют ссылку на Accessor, таким образом, могут вызывать нужные приватные методы класса Context. Конструктор класса Accessor приватный, чтобы кто угодно не мог создать его и получить доступ к приватным методам класса Context.

Вот набросал примерный код этого всего:

#include <iostream>

class Accessor;

class State
{
public:
        State(Accessor *accessor) : m_accessor(accessor) {}
        virtual ~State() {}

        virtual void event1() = 0;
        virtual void event2() = 0;

protected:
        Accessor *accessor() const { return m_accessor; }

private:
        Accessor *m_accessor;
};

class ConcreteStateA : public State
{
public:
        ConcreteStateA(Accessor *accessor) : State(accessor) {}

        virtual void event1() override;
        virtual void event2() override;
};

class ConcreteStateB : public State
{
public:
        ConcreteStateB(Accessor *accessor) : State(accessor) {}

        virtual void event1() override;
        virtual void event2() override;
};

class Context
{
public:
        Context();
        ~Context();

        void event1() { m_state->event1(); }
        void event2() { m_state->event2(); }

private:
        Accessor *m_accessor;
        State *m_state;

        void setState(State *state) { delete m_state; m_state = state; }
        void action1();
        void action2();

        friend class Accessor;
};

class Accessor
{
private:
        Accessor(Context *context) : m_context(context) {}

public:
        void setState(State *state) { m_context->setState(state); }
        void action1() { m_context->action1(); }
        void action2() { m_context->action2(); }

private:
        Context *m_context;

        friend class Context;
};

Context::Context() :
        m_accessor(new Accessor(this)),
        m_state(new ConcreteStateA(m_accessor))
{}

Context::~Context()
{
        delete m_state;
        delete m_accessor;
}

void Context::action1()
{
        std::cout << "Context::action1()" << std::endl;
}

void Context::action2()
{
        std::cout << "Context::action2()" << std::endl;
}

void ConcreteStateA::event1()
{
        std::cout << "ConcreteStateA::event1()" << std::endl;
        accessor()->action1();
}

void ConcreteStateA::event2()
{
        std::cout << "ConcreteStateA::event2()" << std::endl;
        accessor()->action2();
        accessor()->setState(new ConcreteStateB(accessor()));
}

void ConcreteStateB::event1()
{
        std::cout << "ConcreteStateB::event1()" << std::endl;
        accessor()->action1();
        accessor()->setState(new ConcreteStateA(accessor()));
}

void ConcreteStateB::event2()
{
        std::cout << "ConcreteStateB::event2()" << std::endl;
        accessor()->action2();
}

int main()
{
        Context context;
        context.event1();
        context.event2();
        context.event2();
        context.event1();
        context.event1();
        return 0;
}

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

 

gentoo_root
()

Помогите найти песню

Помню точно, что слушал когда-то какую-то случайно найденную песню, она была тяжёлая (возможно, Death Metal), там было слово betroyal (именно через o оно там пелось), причём слово betroyal там было с некоторыми паузами перед и после слова. Больше ничего про песню не помню. Помогите найти её, может, кто-то слышал %)

 

gentoo_root
()

Гентушники, как вы управляете своим оверлеем?

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

Естественно, почти все действия я выполняю из-под пользователя, который не root. Там и ssh-ключи лежат, и оверлей я создал в хомяке пользователя, и git настроен на моё имя и email. Если бы можно было просто в оверлее добавлять файлики, всё было бы замечательно, но ведь нужно ещё генерировать Manifest при каждом изменении файликов, а команда ebuild digest отказывается работать, мотивируя это тем, что пользователь portage не имеет доступа в мой хомяк.

Можно было бы вносить изменения из-под рута напрямую в каталоге, куда положил мой оверлей layman. Но тут неприятностей ещё больше: layman настраивает git так, что user.name=layman, user.email=layman@localhost; ssh-ключей моих нет.

Вопрос к тем, кто имеет собственные оверлеи: как вы справляетесь со всеми этими неудобствами? Есть какой-то некостыльный способ разруливания проблем?

 , ,

gentoo_root
()

Удобная звонилка для использования с гарнитурой

С самого начала пользования своим самсунгом с андроидом я заметил, что принимать звонки через него невозможно, ибо этот процесс разработчики телефона (или андроида) сделали максимально неудобным.

Итак, чего я ожидаю:

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

А теперь что я вижу на своём самсунге:

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

Я также попробовал принять звонок на нексусе 5. И что я увидел:

Телефон в кармане, гарнитура, музыка, все дела. Поступает звонок, всё также я не знаю, от кого, отвечаю кнопкой на гарнитуре, телефон разблокированный лежит в кармане точно так же, в конце разговора я нажимаю на кнопку на гарнитуре, но трубка не вешается, нет! Выключается микрофон! Я не знаю, какой гений до этого додумался, но для вешания трубки нужно достать телефон из кармана и нажать на нарисованную на экране красную кнопку. Естественно, он после этого остаётся разблокированным. При этом также во время звучания рингтона он звучал и в наушники, и в динамик.

Итак, в увиденных мной вариантах меня не устраивает следующее:

  • Если я в наушниках, то рингтон должен звучать только в наушники. Меня не устраивает, если он звучит ещё и в динамики.
  • Если я в наушниках, то я должен узнать, кто звонит, не вынимая телефон из кармана. Меня не устраивает, что телефон не озвучивает имя звонящего.
  • Если телефон в кармане, то он не должен разблокироваться в начале и в конце звонка. Для этого у телефона есть датчик присутствия. Также возможен следующий вариант: если я ответил на звонок кнопкой на гарнитуре, то после звонка экран должен заблокироваться.
  • Естественно, я должен иметь возможность повесить трубку с помощью гарнитуры, иначе это нелогично, что снять её я могу, но не могу повесить.

Вопрос такой: существуют ли телефоны, прошивки, ОС, костыли и т.п., в которых процесс звонка реализован адекватно, т.е. так, как я описал в начале поста? Интересует также, как сделан этот процесс в MeeGo (и его форках), CyanogenMod и iOS, а также в дефолтной прошивке Nexus 4.

Для решения первых двух пунктов из списка у меня есть написанная мной программа-костыль, но она ещё не очень хорошо работает и не готова для публичного выпуска. Она работает на моём самсунге с андроидом 4.2.2. Для решения третьего пункта тоже возможно написать костыль, существует даже программа After Call Lock, но она не очень хорошо работает. О существовании четвёртого пункта я не подозревал, пока не потестил нексус. Так что я знаю, что хотя бы для первых трёх пунктов костыли возможно реализовать, но меня интересует именно то, как это сделано из коробки в других прошивках и ОС, а также интересует, существуют ли другие костыли.

 , ,

gentoo_root
()

Подарить 0.1 биткоин

Тут недавно товарищ Dron был готов подарить 0.013 BTC, а мне сейчас понадобилось чуть больше, а именно 0.1 BTC. Так вот, не готов ли кто-нибудь мне подарить 0.1 BTC прямо сейчас? Буду очень признателен и благодарен.

Мой адрес: 1EmDFJaAmDAsu1FyAa8EBFfE51ZnEKuZr8.

 

gentoo_root
()

C++, std::function, шаблоны, что я делаю не так?

#include <functional>
#include <algorithm>
#include <vector>

template<typename Iterator>
void test(Iterator begin, Iterator end, std::function<void (Iterator, Iterator)> func)
{
}

template<typename Iterator>
void mysort(Iterator begin, Iterator end)
{
}

int main()
{
        std::vector<int> data;
        test(data.begin(), data.end(), std::sort<std::vector<int>::iterator>);
        test(data.begin(), data.end(), mysort<std::vector<int>::iterator>);
        return 0;
}

Первый вызов функции test компилируется, второй — нет, сообщение об ошибке:

test.cpp: В функции «int main()»:
test.cpp:19:67: ошибка: нет соответствующей функции для вызова «test(std::vector<int>::iterator, std::vector<int>::iterator, <unresolved overloaded function type>)»
  test(data.begin(), data.end(), mysort<std::vector<int>::iterator>);
                                                                   ^
test.cpp:19:67: замечание: candidate is:
test.cpp:6:6: замечание: template<class Iterator> void test(Iterator, Iterator, std::function<void(Iterator, Iterator)>)
 void test(Iterator begin, Iterator end, std::function<void (Iterator, Iterator)> func)
      ^
test.cpp:6:6: замечание:   template argument deduction/substitution failed:
test.cpp:19:67: замечание:   mismatched types «std::function<void(Iterator, Iterator)>» and «void (*)(__gnu_cxx::__normal_iterator<int*, std::vector<int> >, __gnu_cxx::__normal_iterator<int*, std::vector<int> >)»
  test(data.begin(), data.end(), mysort<std::vector<int>::iterator>);
                                                                   ^
test.cpp:19:67: замечание:   could not resolve address from overloaded function «mysort<std::vector<int>::iterator>»
test.cpp: In instantiation of «void test(Iterator, Iterator, std::function<void(Iterator, Iterator)>) [with Iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >]»:
test.cpp:18:70:   required from here
test.cpp:6:6: предупреждение: параметр «begin» не используется [-Wunused-parameter]
 void test(Iterator begin, Iterator end, std::function<void (Iterator, Iterator)> func)
      ^
std::sort объявлен так:
  template<typename _RandomAccessIterator>
    inline void
    sort(_RandomAccessIterator __first, _RandomAccessIterator __last)
Кроме inline, нет никаких отличий от mysort, но дело не в inline (пробовал и его добавлять к mysort).

Заставить код компилироваться можно, например, так:

test<std::vector<int>::iterator>(data.begin(), data.end(), mysort<std::vector<int>::iterator>);

Но почему в случае std::sort происходит разворачивание шаблона нормально, а в случае mysort нет?

gcc 4.8.2

 

gentoo_root
()

RSS подписка на новые темы