Делаем pkgsrc для WebDAV-сервера WebDAV-Daemon
Содержание
Введение
На этот раз не буду описывать весь процесс подготовки pkgsrc, поскольку для сборки этого пакета понадобилось внести большое количество исправлений в исходные тексты: добавить пропущенные заголовочные файлы, переписать Makefile
для сборки программы из исходных текстов и добавить реализацию функции clearenv
, отсутствующей в стандартах POSIX и библиотеке libc
из NetBSD. Я просто приведу получившиеся значимые файлы.
net/webdavd/Makefile
Сначала приведу содержимое файла net/webdavd/Makefile
:
# $NetBSD$
DISTNAME= webdavd
PKGNAME= ${DISTNAME}-1.1
CATEGORIES= net
MASTER_SITES= ${MASTER_SITE_GITHUB:=couling/}
GITHUB_PROJECT= WebDAV-Daemon
#PKGREVISION= 1
GITHUB_TAG= bb317905fbbb640a88276d451ac1852190d68807
MAINTAINER= vladimir@stupin.su
HOMEPAGE= https://github.com/couling/WebDAV-Daemon
COMMENT= webdavd is a WebDAV server designed to be a replace for SAMBA
LICENSE= mit
USE_LANGUAGES= c
USE_TOOLS+= gmake
CFLAGS+= -I${BUILDLINK_PREFIX.libxml2}/include/libxml2/
post-extract:
${CP} ${FILESDIR}/Makefile ${WRKSRC}/
post-install:
${INSTALL} -c ${FILESDIR}/mime.types ${DESTDIR}${LOCALBASE}/share/examples/webdavd/
.include "../../devel/libuuid/buildlink3.mk"
.include "../../www/libmicrohttpd/buildlink3.mk"
.include "../../security/gnutls/buildlink3.mk"
.include "../../textproc/icu/buildlink3.mk"
.include "../../textproc/libxml2/buildlink3.mk"
.include "../../mk/bsd.pkg.mk"
Исходные тексты скачиваются из репозитория на github. Используется самая свежая на момент подготовки этого файла фиксация из репозитория, сделанная после метки версии 1.1. Поэтому пакет будет иметь версию 1.1, но собираться будет из чуть более поздних исходных текстов. При необходимости собрать новую версию надо будет только указать хэш новой фиксации из репозитория в переменной GITHUB_TAG
и, раскомментировать переменную PKGREVISION
и указать в ней номер ревизии в переменной.
В процессе сборки используются зависимости - библиотеки libxml2
, icu
, gnutls
, libmicrohttpd
и libuuid
. Для того, чтобы компилятор смог найти заголовочные файлы библиотеки libxml2
, в Makefile
к переменной CFLAGS
добавляется путь к этим заголовочным файлам, описанный в Makefile
pkgsrc textproc/libxml2
.
Для сборки используется компилятор языка Си и утилита GMake.
Кроме файлов, имевшихся в исходных текстах, для запуска демона мне понадобился файл mime.types
, который я взял из пакета nginx
. Он добавляется к пакету уже после окончания сборки и установки файлов в промежуточный каталог net/webdavd/work/.destdir
.
net/webdavd/files/Makefile
Для сборки используется собственный Makefile
, который копируется в исходные тексты программы сразу после их распаковки из архива. Приведу содержимое этого файла net/webdavd/files/Makefile
:
all: rap webdavd
install: rap webdavd
install -d $(DESTDIR)$(LOCALBASE)/libexec/
install -c rap $(DESTDIR)$(LOCALBASE)/libexec/
install -d $(DESTDIR)$(LOCALBASE)/sbin/
install -c webdavd $(DESTDIR)$(LOCALBASE)/sbin/
install -d $(DESTDIR)$(LOCALBASE)/share/webdavd/
install -c package-with/share/HTTP_BAD_REQUEST.html $(DESTDIR)$(LOCALBASE)/share/webdavd/
install -c package-with/share/HTTP_CONFLICT.html $(DESTDIR)$(LOCALBASE)/share/webdavd/
install -c package-with/share/HTTP_FORBIDDEN.html $(DESTDIR)$(LOCALBASE)/share/webdavd/
install -c package-with/share/HTTP_INSUFFICIENT_STORAGE.html $(DESTDIR)$(LOCALBASE)/share/webdavd/
install -c package-with/share/HTTP_INTERNAL_SERVER_ERROR.html $(DESTDIR)$(LOCALBASE)/share/webdavd/
install -c package-with/share/HTTP_METHOD_NOT_SUPPORTED.html $(DESTDIR)$(LOCALBASE)/share/webdavd/
install -c package-with/share/HTTP_NOT_FOUND.html $(DESTDIR)$(LOCALBASE)/share/webdavd/
install -c package-with/share/HTTP_OK.html $(DESTDIR)$(LOCALBASE)/share/webdavd/
install -c package-with/share/HTTP_UNAUTHORIZED.html $(DESTDIR)$(LOCALBASE)/share/webdavd/
install -c package-with/share/HTTP_UPLOAD_COMPLETE.html $(DESTDIR)$(LOCALBASE)/share/webdavd/
install -c package-with/share/OPTIONS.html $(DESTDIR)$(LOCALBASE)/share/webdavd/
install -d $(DESTDIR)$(LOCALBASE)/share/doc/webdavd/
install -c README.md $(DESTDIR)$(LOCALBASE)/share/doc/webdavd/
install -c LICENCE.md $(DESTDIR)$(LOCALBASE)/share/doc/webdavd/LICENSE.md
install -c Configuration.md $(DESTDIR)$(LOCALBASE)/share/doc/webdavd/CONFIG.md
install -d $(DESTDIR)$(LOCALBASE)/share/examples/webdavd/
install -c useful/conf.xml $(DESTDIR)$(LOCALBASE)/share/examples/webdavd/webdavd.xml.sample
install -c package-with/conf.xml $(DESTDIR)$(LOCALBASE)/share/examples/webdavd/webdavd.xml.full
install -c package-with/logrotate.conf $(DESTDIR)$(LOCALBASE)/share/examples/webdavd/
install -c package-with/pam-rhel.conf $(DESTDIR)$(LOCALBASE)/share/examples/webdavd/
install -c package-with/pam.conf $(DESTDIR)$(LOCALBASE)/share/examples/webdavd/
install -c package-with/systemd.service $(DESTDIR)$(LOCALBASE)/share/examples/webdavd/
webdavd: webdavd.o shared.o configuration.o xml.o
$(CC) $(LDFLAGS) -lmicrohttpd -lxml2 -lgnutls -luuid $^ -o $@
rap: rap.o shared.o xml.o
$(CC) $(LDFLAGS) -lxml2 -lpam $^ -o $@
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -rf rap webdavd *.o
.PHONY: all install clean
В этом Makefile
я предусмотрел установку двоичных файлов и всех дополнительных файлов в каталоги, которые принято использовать в NetBSD. Возможно этот Makefile
не соответствует правилам других операционных систем. В таком случае часть команд установки стоит перенести в Makefile
pkgsrc.
net/webdavd/DESCR
Файл net/webdavd/DESCR
имеет следующий вид:
webdavd is a WebDAV server designed to be a replace for SAMBA providing access
to a system's files without taking ownership of them. It aims to differ from
most WebDAV servers on a number of points:
* Users are authenticated through PAM and are always operating system users.
* The webserver switches OS user to match the authenticated user before
accessing any files.
* The daemon operates without any prior knowledge of the files it's serving.
* The daemon does NOT take ownership of the files it modifies and serves. It
does not take ownership of any files in any way. Even locking operations are
implemented using the native OS flock() function.
net/webdavd/patches
Теперь приведу заплатки, в которых к исходным текстам добавлены пропущенные заголовочные файлы и внесены доработки.
net/webdavd/patches/patch-configuration.c
Первая заплатка находится в файле net/webdavd/patches/patch-configuration.c
:
$NetBSD$
--- configuration.c.orig 2024-05-02 21:51:32.315470624 +0000
+++ configuration.c
@@ -4,6 +4,7 @@
#include "xml.h"
+#include <stdlib.h>
#include <string.h>
#include <errno.h>
WebdavdConfiguration config;
Как видно, тут добавлен только заголовочный файл stdlib.h
.
net/webdavd/patches/patch-webdavd.c
Вторая заплатка находится в файле net/webdavd/patches/patch-webdavd.c
:
$NetBSD$
--- webdavd.c.orig 2024-05-02 21:41:33.881119264 +0000
+++ webdavd.c
@@ -10,12 +10,14 @@
#include <pthread.h>
#include <search.h>
#include <semaphore.h>
+#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <netdb.h>
+#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
#include <uuid/uuid.h>
Тут добавлены заголовочные файлы signal.h
и netinet/in.h
.
net/webdavd/patches/patch-rap.c
Третья заплатка находится в файле net/webdavd/patches/patch-rap.c
:
$NetBSD$
--- rap.c.orig 2023-10-14 21:54:29.000000000 +0000
+++ rap.c
@@ -1481,6 +1481,47 @@ static void pamCleanup() {
pam_end(pamh, pamResult);
}
+#ifndef clearenv
+extern char **environ;
+
+// Simple implementation, but may be incorrect
+static void _clearenv() {
+ if (environ != NULL) {
+ environ[0] = NULL;
+ }
+}
+
+// More complex, but more correct implementation
+static void clearenv() {
+ char *name = NULL;
+ size_t name_max_len = 0;
+ while (environ[0] != NULL) {
+ char *p = strchr(environ[0], '=');
+ if (p == NULL) {
+ unsetenv(environ[0]);
+ continue;
+ }
+
+ size_t name_len = p - environ[0];
+ if (name_len > name_max_len) {
+ p = realloc(name, name_len + 1);
+ if (p == NULL) {
+ // infinite loop may occured when low memory
+ continue;
+ }
+ name_max_len = name_len;
+ name = p;
+ }
+
+ strncpy(name, environ[0], name_len);
+ name[name_len] = '\0';
+
+ unsetenv(name);
+ }
+ free(name);
+}
+#endif
+
static int pamAuthenticate(const char * user, const char * password, const char * hostname) {
static struct pam_conv pamc = { .conv = (int (*)(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)) &pamConverse };
Дело в том, что в стандартной библиотеке libc
NetBSD нет функции clearenv
, которая доступна только в GNU libc и не описана в принятых стандартах POSIX. Я написал две реализации этой функции - простую и быструю, которая просто присваивает первому элементу массива с переменными окружения значение NULL
, таким образом очищая его.
Но я не знаю деталей реализации, каким образом распределяется память для элементов массива. На всякий случай, чтобы исключить утечки памяти, я написал второй вариант этой же функции с использованием функции unsetenv
, которая умеет удалять из массива переменных окружения только одну переменную. Я надеюсь, что она корректно освобождает оперативную память, занятую элементами массива. Для удаления всех элементов в массиве функция вызывается в цикле для очистки первой переменной окружения до тех пор, пока первая переменная окружения не станет пустой.
net/webdavd/distinfo
Для формирования содержимого файла net/webdavd/distinfo
можно воспользоваться командой:
# make distinfo
net/webdavd/PLIST
Для формирования содержимого файла net/webdavd/PLIST
после успешной сборки двоичных файлов из исходных текстов можно воспользоваться командой:
# make print-PLIST > PLIST