LINUX.ORG.RU

Сообщения Bass

 

OpenBSD более не разрешает недопустимые NUL-символы в сценариях оболочки

Форум — Talks
  • OpenBSD изменяет оболочку ksh для исключения недопустимых NUL-символов.
  • Изменения направлены на улучшение поведения программного обеспечения.
  • Для использования нового функционала необходимо установить OpenBSD-current.
  • Обновление произошло после выпуска OpenBSD 7.6.

Подробности.

 , ,

Bass
()

Кто пользуется Nala?

Форум — Admin

Всем здравствуйте.

Буквально только что YT подкинул мне видеоролик под заголовком Stop using APT, где адекватный на первый взгляд мужик без тени иронии говорит, что консольный apt-get — это фу, а вот есть к нему frontend под названием Nala. Правда, в стандартном Дебиане нет, но вот внешний репозиторий.

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

Кто-нибудь пробовал это чудо?

Оно действительно лучше, чем aptitude?

Просто у меня ощущение, что мне пытаются продать BolgenOS и Антивирус Попова впридачу.

 , , , , nala

Bass
()

Debian 12 Bookworm, сломали Doomsday

Форум — Games

Всем здравствуйте.

На самом деле – Devuan 5 Daedalus, но разницы нет.

Обновился на stable, и теперь doomsday на старте выдаёт:

[NotFoundError] (in Record::operator []) Variable ‘audio.soundPlugin’ not found

Быстрый поиск выдаёт похожую проблему.

Последняя рабочая версия была 1.15.8-5+b1 в Debian 10. Версии 2.2.2+ds1-1 и 2.3.1+ds1-1+b2 (Debian 11 и 12, соответственно) одинаково сломаны.

Вопрос: кто-нибудь с похожим сталкивался?

 , , , heretic,

Bass
()

Apt Pinning: комбинирование предикатов (origin + release)

Форум — Admin

Всем здравствуйте.

Есть, например, репозиторий PaleMoon, который, помимо собственно пакета palemoon, тащит некоторое количество пересобранных пакетов из Debian 11 (oldstable), которые у меня при одинаковом приоритете репозиториев (500) выглядят как upgradeable. Например, у меня пакет python2.7-minimal версии 2.7.18-8+deb11u1 из локального кэша с приоритетом 100, а из репозитория PaleMoon прилетает версия 2.7.18-13ubuntu2, которая как бы «новее» (u > d).

Соответственно, хочется правильно настроить apt pinning. Настроить у меня получилось двумя путями, либо через release:

Package: palemoon
Pin: release o=obs://build.opensuse.org/home:stevenpusser/*,l=home:stevenpusser
Pin-Priority: 400

Package: *
Pin: release o=obs://build.opensuse.org/home:stevenpusser/*,l=home:stevenpusser
Pin-Priority: -1

либо вот так через origin:

Package: palemoon
Pin: origin download.opensuse.org
Pin-Priority: 400

Package: *
Pin: origin download.opensuse.org
Pin-Priority: -1

Вопрос: как в поле Pin: скомбинировать сразу два предиката – относительно release и относительно origin?

 , ,

Bass
()

Выбор протокола для агента системы мониторинга

Форум — Development

Всем здравствуйте.

Есть задача периодически снимать значение некой целочисленной метрики (в общем случае – по сети) у ряда машин с дальнейшим представлением исторических данных на графике (как это делает MRTG – за день, за неделю, за месяц, за год). Предполагаю связать своего колхозного агента с какой-л. системой мониторинга (с какой именно – выбор свободен).

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

  • SNMP. Казалось бы, любая собака умеет взаимодействовать по SNMP, и с аутентификацией там (в третьей версии протокола) всё хорошо, но вот почитал я, как внедрить своего суб-агента в snmpd через AgentX – и вижу, что это ни разу не просто.
  • Произвольный текстовый или бинарный протокол и интеграция с inetd/xinetd. Очевидный плюс в простоте решения. Минусы:
    • невозможно навесить аутентификацию;
    • не только лишь всякая система мониторинга сумеет снять данные, используя произвольный протокол. Кажется, здесь получится использовать лишь MRTG, т. е. это «восход солнца вручную».
  • NRPE. Хорош своей популярностью (едва ли не второе место после SNMP; поддерживают, как минимум, Nagios, Icinga и OpenNMS), но позволяет передавать лишь данные вида «всё хорошо»/«почти хорошо»/«плохо»/«совсем плохо». Т. е. не годится.
  • HTTP. Прекрасен всем, но не хотелось бы на каждой машине поднимать httpd с CGI. Хотя есть вариант embedded-сервера, как это сделано, напр., в API агентов для Prometheus (там text/plain поверх HTTP). Данные в формате Prometheus могут «читать» и другие инструменты, напр., OpenNMS и Zabbix.
  • SSH. SSH есть везде, и это хорошо. Но снять данные, используя вывод команды ssh remote-host agent-command, кажется, возможно лишь в MRTG. А при наличии M машин с N метрик вручную описывать M x N графиков в mrtg.cfg не хотелось бы (т. е. хотелось бы ещё какой-л. аналог service/MIB discovery, как в SNMP).

Что посоветуете?

 , , , ,

Bass
()

Вызов native-кода из Java посредством CNI

Форум — Development

Всем здравствуйте.

Развлекаюсь со стюардессой.

GNU Compiler for Java предоставляет два способа вызвать native-код из Java.

  1. Во-первых, есть спецификация JNI, разработанная Sun Microsystems, и GCJ вполне следует этой спецификации.
  2. Во-вторых, есть стандарт CNI, или Compiled Native Interface, реализованный одним лишь GCJ, к которому почти нет документации, но который позволяет писать native-код сразу на C++, предоставляя более высокоуровневый API для взаимодействия между native-кодом и JVM.

Поскольку GCJ также умеет выполнять AOT-компиляцию JVM-байткода, у нас появляются следующие возможные подходы к вызову native-кода из Java:

  1. Запустить обычную JVM с помощью интерпретатора байткода gij, загрузить в неё Java-класс, в нём загрузить native-библиотеку посредством System.loadLibrary(), и вызвать native-метод. Это традиционный путь, привычный нам по Sun/Oracle JVM.
  2. То же, что и в предыдущем пункте, но предварительно выполнить AOT-компиляцию байткода JVM посредством gcj и выполнить динамическое связывание получившегося исполняемого файла с native-библиотекой, используя стандартный ключ -l. Вызов System.loadLibrary() можно оставить как есть из соображений совместимости, но, фактически, необходимость в нём отпадает, поскольку к моменту запуска JVM native-библиотека уже загружена динамическим интерпретатором (ld.so). Здесь есть варианты:
    • Загрузить библиотеку средствами JVM, через System.loadLibrary() — это прямая аналогия с вызовом dlopen().
    • Выполнить динамическое связывание с библиотекой средствами ld, который вызывается процессом gcj -l во время AOT-компиляции. Это значительно удобнее, чем loadLibrary(), поскольку gcj «понимает» многие стандартные ключи gcc, и ему можно «скормить», в частности, -rpath, что в дальнейшем избавит нас от необходимости вручную выставлять LD_LIBRARY_PATH перед запуском программы.
    • Неочевидно, но можно вообще не выполнять никакого связывания с библиотекой и просто положить её в LD_PRELOAD. Да, нормальные люди так не делают, но тоже вариант.
  3. Наконец, можно статически связать объектный файл, получившийся в результате AOT-компиляции байткода, с объектным файлом, являющимся результатом компиляции native-кода. Это полностью избавляет нас от необходимости вызывать System.loadLibrary(), поскольку уже нет никакой внешней библиотеки, a код native-метода является частью кода исполняемого файла.

Поскольку у нас есть два «протокола» вызова native-кода (JNI и CNI), в теории это удваивает количество возможных вариантов (с 3 до 6).

По результатам экспериментов, CNI прекрасно работает со статическим связыванием, но вот в случае с динамическим (и AOT-компиляцией) я получаю ошибку.

Java-класс:

public final class Main {
        static {
                System.loadLibrary("foo");
        }

        private Main() {
                assert false;
        }

        public static native void foo();

        public static void main(final String args[]) {
                foo();
        }
}

Сгенерированный header-файл в формате CNI (Main.h):

#ifndef __Main__
#define __Main__

#pragma interface

#include <java/lang/Object.h>
#include <gcj/array.h>

extern "Java"
{
    class Main;
}

class Main : public ::java::lang::Object
{

  Main();
public:
  static void foo();
  static void main(JArray< ::java::lang::String * > *);
public: // actually package-private
  static jboolean $assertionsDisabled;
public:
  static ::java::lang::Class class$;
};

#endif // __Main__

… и реализация C++-класса, который попадёт в нашу внешнюю библиотеку:

#include <iostream>

#include <gcj/cni.h>

#include "Main.h"

void Main::foo() {
        std::cout << "Hello, World!" << std::endl;
}

При связывании объектного файла со внешней библиотекой:

gcj -pie -fPIE -save-temps --main=Main -o cni-dynamic-native -L/opt/gcc64/6.5/lib64 -Wl,-rpath=/opt/gcc64/6.5/lib64 -L. -Wl,-rpath='$ORIGIN' -lstdc++ -lgcj -lfoo Main.class

… имеем:

/usr/bin/ld: Main.o: in function `void Main::main(JArray<java::lang::String*>*)':
Main.java:13: undefined reference to `hidden alias for void Main::foo()'
/usr/bin/ld: Main.o:(.data.rel+0xc0): undefined reference to `hidden alias for void Main::foo()'
collect2: error: ld returned 1 exit status

Действительно, если посмотреть на символы внутри Main.o с помощью nm, есть один неопределённый:

                 U hidden alias for void Main::foo()

Этот символ определён во внешней библиотеке (libfoo.so), с которой выполняется связывание. Но в объектном файле, из которого собирается внешняя библиотека, этот символ глобальный (T), а в самой библиотеке уже статический (t), так что показанная выше ошибка ld вполне закономерна.

0000000000001180 t hidden alias for void Main::foo()

Ровно та же самая проблема описана вот в этом багрепорте, но, увы, никакого решения там не предложено. Как уже было сказано, всё прекрасно работает при статическом связывании в режиме CNI или динамическом в режиме JNI (пример кода).

Как динамически связать внешнюю native-библиотеку с результатом AOT-компиляции байткода, используя CNI? Предназначен ли механизм CNI для динамического связывания?

 cni, , , ,

Bass
()

Бинарная совместимость, серия 3

Форум — Development

Всем здравствуйте.

Разобрался, почему Java 1.3 несовместима с современными Glibc (серия 1, серия 2).

С целью выяснения канонического пути до rt.jar процесс JVM вызывает функцию canonicalize(), определённую в файле canonicalize_md.c и находящуюся в libjava.so. Ниже фрагмент исходников Java 1.4.1 (ещё даже не GPL). Более ранних у меня нет, но между 1.3 и 1.4 конкретно этот код вряд ли менялся:

/*
 * @(#)canonicalize_md.c	1.35 01/12/03
 *
 * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

/*
 * Pathname canonicalization for Unix file systems
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <errno.h>
#include <limits.h>
#include <alloca.h>


/* Note: The comments in this file use the terminology
         defined in the java.io.File class */


/* Check the given name sequence to see if it can be further collapsed.
   Return zero if not, otherwise return the number of names in the sequence. */

static int
collapsible(char *names)
{
    char *p = names;
    int dots = 0, n = 0;

    while (*p) {
	if ((p[0] == '.') && ((p[1] == '\0')
			      || (p[1] == '/')
			      || ((p[1] == '.') && ((p[2] == '\0')
						    || (p[2] == '/'))))) {
	    dots = 1;
	}
	n++;
	while (*p) {
	    if (*p == '/') {
		p++;
		break;
	    }
	    p++;
	}
    }
    return (dots ? n : 0);
}


/* Split the names in the given name sequence,
   replacing slashes with nulls and filling in the given index array */

static void
splitNames(char *names, char **ix)
{
    char *p = names;
    int i = 0;

    while (*p) {
	ix[i++] = p++;
	while (*p) {
	    if (*p == '/') {
		*p++ = '\0';
		break;
	    }
	    p++;
	}
    }
}


/* Join the names in the given name sequence, ignoring names whose index
   entries have been cleared and replacing nulls with slashes as needed */

static void
joinNames(char *names, int nc, char **ix)
{
    int i;
    char *p;

    for (i = 0, p = names; i < nc; i++) {
	if (!ix[i]) continue;
	if (i > 0) {
	    p[-1] = '/';
	}
	if (p == ix[i]) {
	    p += strlen(p) + 1;
	} else {
	    char *q = ix[i];
	    while ((*p++ = *q++));
	}
    }
    *p = '\0';
}


/* Collapse "." and ".." names in the given path wherever possible.
   A "." name may always be eliminated; a ".." name may be eliminated if it
   follows a name that is neither "." nor "..".  This is a syntactic operation
   that performs no filesystem queries, so it should only be used to cleanup
   after invoking the realpath() procedure. */

static void
collapse(char *path)
{
    char *names = (path[0] == '/') ? path + 1 : path; /* Preserve first '/' */
    int nc;
    char **ix;
    int i, j;
    char *p, *q;

    nc = collapsible(names);
    if (nc < 2) return;		/* Nothing to do */
    ix = (char **)alloca(nc * sizeof(char *));
    splitNames(names, ix);

    for (i = 0; i < nc; i++) {
	int dots = 0;

	/* Find next occurrence of "." or ".." */
	do {
	    char *p = ix[i];
	    if (p[0] == '.') {
		if (p[1] == '\0') {
		    dots = 1;
		    break;
		}
		if ((p[1] == '.') && (p[2] == '\0')) {
		    dots = 2;
		    break;
		}
	    }
	    i++;
	} while (i < nc);
	if (i >= nc) break;

	/* At this point i is the index of either a "." or a "..", so take the
	   appropriate action and then continue the outer loop */
	if (dots == 1) {
	    /* Remove this instance of "." */
	    ix[i] = 0;
	}
	else {
	    /* If there is a preceding name, remove both that name and this
	       instance of ".."; otherwise, leave the ".." as is */
	    for (j = i - 1; j >= 0; j--) {
		if (ix[j]) break;
	    }
	    if (j < 0) continue;
	    ix[j] = 0;
	    ix[i] = 0;
	}
	/* i will be incremented at the top of the loop */
    }

    joinNames(names, nc, ix);
}


/* Convert a pathname to canonical form.  The input path is assumed to contain
   no duplicate slashes.  On Solaris we can use realpath() to do most of the
   work, though once that's done we still must collapse any remaining "." and
   ".." names by hand. */

int
canonicalize(char *original, char *resolved, int len)
{
    if (len < PATH_MAX) {
	errno = EINVAL;
	return -1;
    }

    if (strlen(original) > PATH_MAX) {
	errno = ENAMETOOLONG;
	return -1;
    }

    /* First try realpath() on the entire path */
    if (realpath(original, resolved)) {
	/* That worked, so return it */
	collapse(resolved);
	return 0;
    }
    else {
	/* Something's bogus in the original path, so remove names from the end
	   until either some subpath works or we run out of names */
	char *p, *end, *r = NULL;
	char path[PATH_MAX + 1];

	strncpy(path, original, sizeof(path));
	if (path[PATH_MAX] != '\0') {
	    errno = ENAMETOOLONG;
	    return -1;
	}
	end = path + strlen(path);

	for (p = end; p > path;) {

	    /* Skip last element */
	    while ((--p > path) && (*p != '/'));
	    if (p == path) break;

	    /* Try realpath() on this subpath */
	    *p = '\0';
	    r = realpath(path, resolved);
	    *p = (p == end) ? '\0' : '/';

	    if (r != NULL) {
		/* The subpath has a canonical path */
		break;
	    }
	    else if (errno == ENOENT || errno == ENOTDIR || errno == EACCES) {
		/* If the lookup of a particular subpath fails because the file
		   does not exist, because it is of the wrong type, or because
		   access is denied, then remove its last name and try again.
		   Other I/O problems cause an error return. */
		continue;
	    }
	    else {
		return -1;
	    }
	}

	if (r != NULL) {
	    /* Append unresolved subpath to resolved subpath */
	    int rn = strlen(r);
	    if (rn + strlen(p) >= len) {
		/* Buffer overflow */
		errno = ENAMETOOLONG;
		return -1;
	    }
	    if ((rn > 0) && (r[rn - 1] == '/') && (*p == '/')) {
		/* Avoid duplicate slashes */
		p++;
	    }
	    strcpy(r + rn, p);
	    collapse(r);
	    return 0;
	}
	else {
	    /* Nothing resolved, so just return the original path */
	    strcpy(resolved, path);
	    collapse(resolved);
	    return 0;
	}
    }

}

И код прекрасен всем, кроме одного: в 2017-м году в Glibc 2.25 появилась стандартная функция с тем же именем, хоть и другой сигнатурой (eaf5ad0bc4a67bf40999e22db6f583ebc3a806ba):

TS 18661-1 defines canonicalize functions to produce a canonical version of a floating-point representation. This patch implements these functions for glibc.

As with the iscanonical macro, these functions are oriented to the decimal floating-point case, where some values have both canonical and noncanonical representations. However, the functions have a return value that says whether they succeeded in storing a canonical result; thus, they can fail for the case of an invalid representation (while still not making any particular choice from among multiple equally canonical valid representations of the same value). Since no floating-point formats in glibc actually have noncanonical valid representations, a type-generic implementation of these functions can be used that expects iscanonical to return 0 only for invalid representations. Now that iscanonical is used within libm.so, libm_hidden_proto / libm_hidden_def are added for __iscanonicall.

The definition of these functions is intended to correspond to a convertFormat operation to the same floating-point format. Thus, they convert signaling NaNs to quiet NaNs, raising the «invalid» exception. Such a conversion «should» produce «the canonical version of that signaling NaN made quiet».

Удивительным образом JVM не валится с segfault, хотя количество аргументов и различается, но, так или иначе, canonicalize(char*, char*, int) из libjava.so не вызывается уж боле.

Вот стектрейс здорового человека (Glibc 2.24, смотрим на фрейм 0):

#0  0xf79c304a in canonicalize () from /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/i386/libjava.so
#1  0xf79bec50 in Canonicalize () from /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/i386/libjava.so
#2  0xf7d05c4b in ClassLoader::get_canonical_path(char *, char *, int) () from /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/x86_64/client/libjvm.so
#3  0xf7d0506f in ClassLoader::setup_bootstrap_search_path(void) () from /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/x86_64/client/libjvm.so
#4  0xf7d05cad in classLoader_init(void) () from /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/x86_64/client/libjvm.so
#5  0xf7d1bad3 in init_globals(void) () from /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/x86_64/client/libjvm.so
#6  0xf7de14ea in Threads::create_vm(JavaVMInitArgs *) () from /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/x86_64/client/libjvm.so
#7  0xf7d4b620 in JNI_CreateJavaVM () from /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/x86_64/client/libjvm.so
#8  0x08049bca in InitializeJVM ()
#9  0x08048fd0 in main ()

А вот стектрейс курильщика (фрейм 1 и далее общие, фрейм 0 другой):

#0  __canonicalize (cx=0x8050d50, x=0xffff948c) at ./s_canonicalize_template.c:24
#1  0xf7fa9c50 in Canonicalize () from /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/i386/libjava.so
#2  0xf7c8dc4b in ClassLoader::get_canonical_path(char *, char *, int) () from /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/x86_64/client/libjvm.so
#3  0xf7c8d06f in ClassLoader::setup_bootstrap_search_path(void) () from /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/x86_64/client/libjvm.so
#4  0xf7c8dcad in classLoader_init(void) () from /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/x86_64/client/libjvm.so
#5  0xf7ca3ad3 in init_globals(void) () from /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/x86_64/client/libjvm.so
#6  0xf7d694ea in Threads::create_vm(JavaVMInitArgs *) () from /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/x86_64/client/libjvm.so
#7  0xf7cd3620 in JNI_CreateJavaVM () from /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/x86_64/client/libjvm.so
#8  0x08049bca in InitializeJVM ()
#9  0x08048fd0 in main ()

Здесь значения cx и x – видимо, исходные значения указателей на строки путей (char *), интерпретированные как double *.

Собственно, вопрос.

Я решил, что я, типа, умный, и сейчас я возьму, соберу пресловутый сановский исходник в 32-разрядную библиотеку (gcc -m32 ...) и положу её в LD_PRELOAD.

Ага, щаз.

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

ERROR: ld.so: object '.../libcanonicalize.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32): ignored.

за которыми следует радостный Segmentation fault. Причём, если я явно запускаю 32-разрядный динамический интерпретатор:

LD_PRELOAD='...' /lib/i386-linux-gnu/ld-linux.so.2 java -version

— то результат ровно тот же.

ЧЯДНТ?

 , , , ,

Bass
()

Emacs в качестве GUI для GDB, или небинарная совместимость

Галерея — Скриншоты

Всем здравствуйте.

На снимке – эксперименты, являющиеся продолжением вот этой темы.

Как уже не в первый раз убеждаюсь, утилита strace с ключом -k (печатать stack trace каждого вызова) – прекрасный инструмент для первичного (грубого) поиска проблемы. Собственно, именно таким способом было выяснено, что на Debian 9 и Debian 10+ поведение java начинает различаться, начиная с инструкции <open64_w+22> из libhpi.so. В результате последовательность

b main
r
b open64_w
cont

позволяет вплотную подобраться к проблеме, но уже пер-ректально «изнутри».

На снимке – сравнение консольного интерфейса GDB (слева) и Emacs (справа). Если честно, Emacs’ом для отладки пользовался в первый раз в жизни – и он мне понравился. Понравился даже больше, чем старик DDD, который умные люди используют для полноценной визуализации данных в памяти, но вот мне самому как-то не доводилось.

В чём ценность cgdb как обёртки над gdb, особенно в отсутствие исходного кода, – я так и не понял. Если у вас есть успешный успех опыт использования cgdb – поделитесь, пожалуйста. Аналогично, xxgdb, наверное, хорош – но для того, чтобы он завёлся в 2023 году, мне надо выкинуть из ~/.gdbinit буквально всё.

За каким рожном нужен убогий и деревянный как Буратино Nemiver, по недосмотру появившийся в пакетах Debian и заявляющий в качестве ключевых особенностей совместимость с GNOME 3 и умение скопировать значение переменной в буфер обмена (я не шучу: «Ability to copy the content of a variable into the GTK clipboard») – я тоже не понял. Зачем, если есть прекрасный Emacs?

В сухом остатке: насколько я понял, ebp + 0x8, ebp + 0xc и ebp + 0x10 – это адреса параметров функции. По первому адресу лежит строка, и строка эта на Debian 9 и Debian 10 разная:

  • /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/rt.jar (нормальное поведение, слева) и
  • /usr/lib/jvm/java-1.3.1_20-sun-i386/jre (аномальное, справа).

Стало быть, ерунда начинается ещё до системного вызова open()/openat() и происходит в одном из пяти вызовов:

  1. sysOpen(...)
  2. JVM_Open(...)
  3. ZIP_Open_Generic(...)
  4. ZIP_Open(...)
  5. ClassLoader::setup_bootstrap_search_path(void)

Будем копать дальше.

>>> Просмотр (3840x2160, 853 Kb)

 cgdb, , , ,

Bass
()

Бинарная совместимость и старые версии JDK

Форум — Development

Всем здравствуйте.

С целью опытов над умершими пытаюсь завести старую версию JDK (1.3) на умеренно современной операционке (Debian 10). И да, я не оговорился – это именно JDK 1.3, выпущенный в мае 2000 года н. э., а не JDK 13, выпущенный в 2019.

И всё бы хорошо с бинарной совместимостью в том смысле, что, на первый взгляд, достаточно установить 32-разрядные зависимости, которые до сих пор есть в Debian:

  • libbsd0
  • libc6
  • libgcc1
  • libice6
  • libnspr4
  • libodbc1
  • libsm6
  • libuuid1
  • libx11-6
  • libxau6
  • libxcb1
  • libxdmcp6
  • libxext6
  • libxi6
  • libxt6
  • libxtst6
  • unixodbc-dev

Из нестандартного нужно доустановить лишь libxp6, которая без проблем достаётся из почти свежего Debian 8, да libstdc++ от gcc 2.96 (пакет compat-libstdc++-296 из ранних версий CentOS).

И вот такой набор (вплоть до моста JDBC-ODBC) прекрасно работал у меня вплоть до Debian 9 включительно.

В Debian 10 что-то случилось, и команда java -version вместо привычного

java version "1.3.1_20"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_20-b03)
Java HotSpot(TM) Client VM (build 1.3.1_20-b03, mixed mode)

выдаёт

Error occurred during initialization of VM
java/lang/NoClassDefFoundError: java/lang/Object

И, если присмотреться, она таки действительно не может распаковать rt.jar и достать оттуда java/lang/Object.class. При запуске strace -f видно, что на Debian 9 процесс открывает rt.jar и отображает (mmap) его содержимое в виртуальную память. Это java здорового некрофила:

stat64("/usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/rt.jar", {st_mode=S_IFREG|0644, st_size=13904932, ...}) = 0
lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/usr/lib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/usr/lib/jvm", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/usr/lib/jvm/java-1.3.1_20-sun-i386", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
lstat64("/usr/lib/jvm/java-1.3.1_20-sun-i386/jre", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
lstat64("/usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
lstat64("/usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/rt.jar", {st_mode=S_IFREG|0664, st_size=13904932, ...}) = 0
open("/usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/rt.jar", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0664, st_size=13904932, ...}) = 0
_llseek(3, 0, [13904932], SEEK_END)     = 0
mmap2(NULL, 13904932, PROT_READ, MAP_SHARED, 3, 0) = 0xf6b9c000
close(3)                                = 0

А вот ровно то же самое, но на Debian 10. Так сказать, java некрофила-курильщика:

stat64("/usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/rt.jar", {st_mode=S_IFREG|0644, st_size=13904932, ...}) = 0
openat(AT_FDCWD, "/usr/lib/jvm/java-1.3.1_20-sun-i386/jre", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
close(3)                                = 0

Как видно, мы вместо того, чтобы выполнить open()/openat() для файла /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/rt.jar, выполняем то же самое действие для каталога /usr/lib/jvm/java-1.3.1_20-sun-i386/jre – с предсказуемым исходом.

Проблема совершенно точно не в ядре – её можно воспроизвести на чистом Docker-контейнере i386/debian:10, а на i386/debian:9 всё работает. Ну, т. е., на худой конец, можно гонять старый софт в Docker’е и этим удовлетвориться.

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

 , , бинарная совместимость, ,

Bass
()

Дельта альфа альфа штрих

Форум — Talks

Извините, если баян.

https://youtube.com/watch?v=0Ji4kJ3-0E4

 ,

Bass
()

KDE2 в современном разрешении

Галерея — Скриншоты

Всем здравствуйте.

На снимке – промежуточный результат эксперимента, описанного несколькими днями ранее.

В виртуальной машине работает Red Hat Linux 7.1 с KDE2, используя для отрисовки современный X-сервер на настоящем железе. Кстати, чёрное окно VirtualBox в левом верхнем углу – это настоящая консоль.

В центре экрана – то, ради чего всё затевалось. Эмулятор QPE версии 1.3, июнь 2001 года. В целом, я бы сказал, что лишь немногим хуже первых версий Android или iOS. И уж точно на голову выше того, что спустя 7 лет могла исполнить ОС Symbian, хоть в варианте S40 (Nokia), хоть в варианте UIQ (Motorola и Sony-Ericsson).

>>> Просмотр (3840x2160, 379 Kb)

 , qpe, , ,

Bass
()

Ищу демонстрационные дискеты Qtopia

Форум — Desktop

Всем здравствуйте.

В ноябре или декабре 1999 года, успешно собрав вручную Qt/X11 версии 1.45, и начав от нечего делать лазить по FTP-сайту Trolltech, обнаружил там образы дискет с Qtopia.

Qtopia – это был такой продукт на основе Qt Embedded, предназначенный для смартфонов и КПК. Одним из первых устройств был вышедший в 2001 Sharp Zaurus SL-5000D.

Так вот, на демонстрационных дискетах был какой-то ужатый Linux (наверное, в то время 2.4) и графическая оболочка, работающая через фреймбуфер. По ощущениям – всё летало, т. е. было очень похоже на QNX Demo Diskette, только у меня был не QNX. У меня была созданная сумрачным норвежским гением Qtopia.

Сейчас в сети возможно найти лишь исходники (начиная примерно с версии 1.5, выпущенной в марте 2002), да несколько пресс-релизов в архиве:

Вопрос: не сохранилось ли у кого демонстрационных дискет?

Update: таки это была не Qtopia, а Qt Embedded. Файлы назывались qpe-1.0.0-x86-vesa.tar.gz и qpe-1.0.0-x86-vesa.zip.

 , , , ,

Bass
()

А поясните за синтаксис BSD sed, пожалуйста

Форум — Development
echo 'libastral-1.2.3.so' | sed '/^libastral-\(.\+\)\.so$/s//\1/'

При использовании GNU sed получаю, как и ожидалось, 1.2.3.

При использовании Mac OS X (Darwin, использующий юзерспейс FreeBSD), внезапно, никакой замены не происходит.

Тестировать разные варианты долго, потому что никакого BSD-юзерспейса под рукой нет, а происходит всё при исполнении процесса GitHub Actions. Т. е. проверка каждой новой гипотезы выливается в git push и ожидание готовности агента.

Поясните, пожалуйста.

 , , ,

Bass
()

Выбор внешнего (USB) WiFi-адаптера для FreeBSD

Форум — Linux-hardware

Всем здравствуйте.

Хочу выяснить, возможно ли во FreeBSD «завести» внешний (подключаемый по USB, не PCI-e) WiFi-адаптер.

Хочется более-менее современное железо из того, что сейчас есть в продаже, т. е. не б/у и не new old stock. И ещё душа просит поддержки 5 ГГц.

Руководствовался следующими источниками:

– но ни к какому заключению не пришёл.

Насколько я понял, я могу выбирать из следующих драйверов/производителей:

  • Broadcom BCM 43xxx (драйвер bwn, но, кажется, заявлена поддержка только PCI и CardBus)
  • Intel (драйвер iwn, официально – только MiniPCI)
  • Ralink (умер)
    • RT2500USB (ural)
    • RT2501USB, RT2601USB (rum)
    • RT2700U/ RT2800U/ RT3000U / RT3900E (run)
  • Atheros AR5005UG/ AR5005UX (uath)
  • Conexant/Intersil PrismGT SoftMAC GW3887 (upgt)
  • Realtek RTL8187B и RTL8187L (urtw), только 802.11b/g
  • ZyDAS ZD1211/ZD1211B (zyd)

Выходит, что ответа на вопрос как бы и нет.

У кого какие истории успеха? Поделитесь, пожалуйста.

 , ,

Bass
()

Вопрос о выборе программатора

Форум — Linux-hardware

Всем здравствуйте.

Хочу установить Linux на старое железо (есть несколько материнок на Intel i440BX и VIA KT133A и россыпь Coppemine’ов и Tualation’ов к ним). Материнки исправны, но наиболее «топовые» процессоры не держат (всё виснет посреди POST), хотя по спецификациям должны. Есть подозрение, что BIOS тупо не знает некоторых cpuid, что можно исправить с помощью последних версий BIOS с Ultimate Retro и BIOS Patcher.

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

Вопрос: у кого есть положительный опыт с EZP 2019 или MiniPro TL866ii+?

Можно ли прошить старые 32-х и 34-пиновые микросхемы AWARD BIOS с помощью более дешёвого CH341A, который так хвалит современная молодёжь?

Ну и, наконец, работает ли какое-л. из устройств напрямую из Linux, дабы не городить виртуалку сами знаетсе с чем?

 , ,

Bass
()

Включить текстовый (80x25) или VGA16-режим (640x480-4) при загрузке с UEFI

Форум — Linux-hardware

Всем здравствуйте.

Итак, задача.

Задача

Заела ностальгия, хочу увидеть старую добрую фреймбуферную консоль с пингвином (CONFIG_LOGO_LINUX_VGA16 или CONFIG_LOGO_LINUX_CLUT224).

Всё это безобразие я пытаюсь выполнить на не самом старом ноутбуке с Core i7-7700HQ и i915 в качестве основной видеоплаты (есть ещё дискретная видеоплата AMD, но речь сейчас не о ней). Причём грузится Linux посредством UEFI (не BIOS).

«Родное» разрешение экрана – 1920x1080, поэтому в обычных условиях (без извращений, т. е. без efifb либо inteldrmfb) GRUB как-то автоматически цепляет именно это разрешение, а дальше я гружу ядро с параметрами video=eDP-1:1920x1080 video=HDMI-A-1:1920x1080.

Но вернёмся к задаче. Вопрос не об inteldrmfb и не о KMS – вопрос именно о включении VGA- или VESA-режимов. Основная проблема в том, что перевести фреймбуфер

  • в разрешение 720x400x16 (текстовая VGA-консоль 80x25)
  • либо в 640x480x16 (VGA16)
  • либо в любое из VESA-разрешений (хотя бы 800x600)

– я не могу. В худшем случае после меню GRUB я вижу просто чёрный экран, в лучшем – для вывода используется узкая полоска высотой 20px вверху экрана (похоже, что ядро просто пишет в самое начало видеопамяти, да ещё предполагает глубину цвета 4bpp вместо 32bpp). В обоих случаях приходится заходить на компьютер по сети.

Ход эксперимента

Варианты, которые я использовал:

  • текстовая консоль VGA (CONFIG_FB_VGA16 is not set, CONFIG_VGA_CONSOLE=y)
  • vesafb (CONFIG_FB_BOOT_VESA_SUPPORT=y, CONFIG_FB_VESA=y)
  • vga16fb (CONFIG_FB_VGA16=m)
  • uvesafb, VESA framebuffer в userspace, использующий «виртуальный» x86 BIOS (CONFIG_FB_VGA16=m, CONFIG_FB_UVESA=m, v86d установлен)

В случае с vga16fb у меня даже появляются /dev/fb0 и /sys/class/graphics/fb0/*, но, ещё раз, вывод приходится на самое начало видеопамяти .

Что я пытался сделать:

  1. Включал/выключал KMS (nomodeset, i915.modeset=0, вот это всё). В конце концов для чистоты эксперимента просто перестал собирать модули i915 и amdgpu.
  2. Играл с параметрами video= и vga=, как описано здесь, здесь здесь и здесь. Варианты vga=normal, vga=extended, vga=ask, vga=301, video=vga16fb:640x480-4, video=vesa, video=uvesafb н к чему не приводят, ядро на них кладёт.
  3. Играл с настройками GRUB. Команда vbeinfo отсутствует, команда videoinfo выводит пустой список видеорежимов. Установка GRUB_GFXPAYLOAD_LINUX=text приводит к тому, что GRUB радостно сообщает: «text» mode is not available и продолжает загрузку в слепом (blind) режиме. Т. е. это тоже чёрный экран, но уже средствами не ядра, а GRUB.
  4. Запускал hwinfo --framebuffer. Пустой список.

В сухом остатке – у меня ощущение, что я косячу либо с настройками GRUB, либо с параметрами ядра (в последнем случае не скажешь наверняка, т. к. документация на тот же vesafb была написана 20 лет назад, и хрен поймёт, насколько она актуальна сейчас).

Либо же то, что я наблюдаю – особенности именно интеловского фреймбуфера.

Либо же VGA- и VESA-режимы вообще недоступны пр загрузке через UEFI, но подтверждения этому я нигде не нашёл. Но, с другой стороны, x86 BIOS недоступен, да.

Вопрос

Собственно, вопрос. Оно вообще возможно – VGA или VESA через UEFI? Если да – то какие настройки GRUB и параметры ядра должны быть?

P.S. Смотрел в /boot/grub/x86_64-efi/video.lst – там только efi_gop, efi_uga, video_bochs, video_cirrus, что, в общем, закономерно. Никакого vbe там нет.

P.P.S. Ядро 4.19.251, хотя это и не важно. Модули, которые меня интересуют, не менялись десятилетиями.

 , , , ,

Bass
()

Как «прикрутить» свой собственный linter к Vim?

Форум — Development

Всем здравствуйте.

Хочется странного. Хочется привязать линтер X к типу файлов Y в редакторе Z (причём Z == Vim).

Я так понимаю, есть два пути:

  1. Создать свой compiler plug-in, который бы определял makeprg и errorformat и положить его ~/.vim/compiler:

    CompilerSet makeprg=...
    CompilerSet errorformat=...
    

    а затем динамически включать и выключать описанный «компилятор» при смене типа файла:

    autocmd Filetype Y compiler X
    
  2. Внедриться в syntastic, который и так уже поддерживает 100500 статических анализаторов кода.

Вопросы:

  1. Какие ещё пути существуют?
  2. Как обычно решается вопрос с проверкой содержимого «безымянного» буфера, у которого уже есть filetype, но которому не соответствует никакой файл на диске?
  3. Стоит ли заморачиваться с написанием модулей расширений на Python или Ruby?
  4. Есть ли возможность непрерывно, как это делают современные IDE, анализировать код по мере ввода текста?
  5. Есть ли возможность выводить результаты анализа не в «линейке редактора» («editor gutter»), как это делают syntastic и vim-gitgutter и не в Error Window (:copen), а прямо в буфере с кодом (возможно, до след. redraw)?

Есть ли расширения Vim, которые уже делают что-то подобное?

 

Bass
()

Как работать с Makefile-проектами в среде CLion

Новости — Документация
Группа Документация

За последние несколько лет мне пришлось столкнуться с множеством вопросов, которые были сформулированы примерно так: «мой проект не открывается в среде CLion». В свою очередь, это приводило к необходимости из раза в раз объяснять разным людям примерно одно и то же. Статья имеет целью сохранить тот опыт, который был накоплен в процессе анализа десятков разных проектов.

( читать дальше... )

 , , , ,

Bass
()

Миграция почтового ящика IMAP

Форум — General

Всем здравствуйте.

Допустим, есть один или несколько почтовых ящиков у одного оператора (скажем, gmail.com), и необходимо выполнить миграцию (или банально продублировать) всей почты к другому оператору (скажем, ya.ru).

Какими средствами это лучше сделать? Перетаскивание мышкой в Thunderbird/Claws Mail не предлагать.

Про mail forwarding в настройках исходного оператора я в курсе. Интересует миграция именно исторической почты.

P. S. Уже нашёл imapsync. Что ещё можете порекомендовать? Каков был опыт непосредственно с imapsync?

 ,

Bass
()

TabNine — троян?

Форум — Admin

Всем здравствуйте.

Решил попробовать модуль TabNine для Vim, но предварительно запустил антивирусную проверку. Из-под оффтопика, но это не так важно.

И DrWeb мне говорит, что TabNine заражён Linux.Siggen.2488 (снимок экрана).

Конечно, это вновь наводит на мысль, что бинарные «блобы» хрен знает, откуда, лучше не качать. Особенно радуют пути вида

/root/.config
/root/.config/TabNine
/root/.config/TabNine/.atomicwrite.MhUOrZxqnoBr
/root/.w3m

– видимо, тот, кто впервые сообщил о вредоносном поведении, запускал TabNine из-под рута.

Что думаете?

Обсуждалась ли эта проблема ранее?

 , tabnine,

Bass
()

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