Skip to content
This repository has been archived by the owner on Dec 24, 2022. It is now read-only.

Commit

Permalink
Make nvidia apply_extra a static binary and run it without runtime
Browse files Browse the repository at this point in the history
This is needed to fix flatpak/flatpak#595
  • Loading branch information
alexlarsson committed Feb 28, 2017
1 parent f2e31d2 commit 80d3746
Show file tree
Hide file tree
Showing 5 changed files with 343 additions and 57 deletions.
11 changes: 0 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ nvidia-%:
-e 's/@@NVIDIA_SHA256@@/${NVIDIA_SHA256}/g' \
-e 's/@@NVIDIA_SIZE@@/${NVIDIA_SIZE}/g' \
-e 's%@@NVIDIA_URL@@%${NVIDIA_URL}%g' \
-e 's%@@NVIDIA_OLD@@%${NVIDIA_OLD}%g' \
org.freedesktop.Platform.GL.nvidia.json.in > org.freedesktop.Platform.GL.nvidia.json.tmp && mv org.freedesktop.Platform.GL.nvidia.json.tmp org.freedesktop.Platform.GL.nvidia-${NVIDIA_VERSION}.json || exit 1;
flatpak-builder --force-clean --ccache --require-changes --repo=${REPO} --arch=${ARCH} \
--subject="build of , org.freedesktop.Platform.GL.nvidia `date`" \
Expand All @@ -87,31 +86,26 @@ nvidia-i386-367-57: NVIDIA_VERSION=367-57
nvidia-i386-367-57: NVIDIA_SHA256=43d4e926f71ac6c581018badf467458709822e97a7564ed9f1b521b7b63d88bb
nvidia-i386-367-57: NVIDIA_SIZE=44731570
nvidia-i386-367-57: NVIDIA_URL=http://http.download.nvidia.com/XFree86/Linux-x86/367.57/NVIDIA-Linux-x86-367.57.run
nvidia-i386-367-57: NVIDIA_OLD=old-

nvidia-i386-340-102: NVIDIA_VERSION=340-102
nvidia-i386-340-102: NVIDIA_SHA256=61b13d5dae0f6f5d788a4d8c4c98e8d971d19cb90b606058060d007946248828
nvidia-i386-340-102: NVIDIA_SIZE=38779756
nvidia-i386-340-102: NVIDIA_URL=http://http.download.nvidia.com/XFree86/Linux-x86/340.102/NVIDIA-Linux-x86-340.102.run
nvidia-i386-340-102: NVIDIA_OLD=old-

nvidia-i386-340-101: NVIDIA_VERSION=340-101
nvidia-i386-340-101: NVIDIA_SHA256=5f5eda9c3d9bf53b56ef4f546dd1be5317eed46df425edbdd2c34023fb9eb062
nvidia-i386-340-101: NVIDIA_SIZE=38932143
nvidia-i386-340-101: NVIDIA_URL=http://http.download.nvidia.com/XFree86/Linux-x86/340.101/NVIDIA-Linux-x86-340.101.run
nvidia-i386-340-101: NVIDIA_OLD=old-

nvidia-i386-304-135: NVIDIA_VERSION=304-135
nvidia-i386-304-135: NVIDIA_SHA256=5cb0a191ddca7b4c72b3c26cd57b7d719878ce628d24b5b026a0e5c8d3a00d93
nvidia-i386-304-135: NVIDIA_SIZE=41202842
nvidia-i386-304-135: NVIDIA_URL=http://http.download.nvidia.com/XFree86/Linux-x86/304.135/NVIDIA-Linux-x86-304.135.run
nvidia-i386-304-135: NVIDIA_OLD=old-

nvidia-i386-304-134: NVIDIA_VERSION=304-134
nvidia-i386-304-134: NVIDIA_SHA256=84f7891af131bb9f9a8a34401dfef4288218019406dfa4ae57b6d52b14e81c9d
nvidia-i386-304-134: NVIDIA_SIZE=41201159
nvidia-i386-304-134: NVIDIA_URL=http://http.download.nvidia.com/XFree86/Linux-x86/304.134/NVIDIA-Linux-x86-304.134.run
nvidia-i386-304-134: NVIDIA_OLD=old-

nvidia-x86_64-375-39: NVIDIA_VERSION=375-39
nvidia-x86_64-375-39: NVIDIA_SHA256=95a3221292f357fbd77697b9bb78d1694def5761202f695ef2065c61efb2ddd8
Expand All @@ -132,31 +126,26 @@ nvidia-x86_64-367-57: NVIDIA_VERSION=367-57
nvidia-x86_64-367-57: NVIDIA_SHA256=b94a8ab6a1da464b44ba9bbb25e1e220441ae8340221de3bd159df00445dd6e4
nvidia-x86_64-367-57: NVIDIA_SIZE=42984178
nvidia-x86_64-367-57: NVIDIA_URL=http://http.download.nvidia.com/XFree86/Linux-x86_64/367.57/NVIDIA-Linux-x86_64-367.57-no-compat32.run
nvidia-x86_64-367-57: NVIDIA_OLD=old-

nvidia-x86_64-340-102: NVIDIA_VERSION=340-102
nvidia-x86_64-340-102: NVIDIA_SHA256=6a36bd9a0033769ecd11ce2aa60aeb41b50b20616c43fd19c55e027c451f585e
nvidia-x86_64-340-102: NVIDIA_SIZE=38598444
nvidia-x86_64-340-102: NVIDIA_URL=http://http.download.nvidia.com/XFree86/Linux-x86_64/340.102/NVIDIA-Linux-x86_64-340.102-no-compat32.run
nvidia-x86_64-340-102: NVIDIA_OLD=old-

nvidia-x86_64-340-101: NVIDIA_VERSION=340-101
nvidia-x86_64-340-101: NVIDIA_SHA256=5ef62e073ba18d4ca745dcaa53c5fbf3d1de4b84cc1739a6cc3f7f746a77c752
nvidia-x86_64-340-101: NVIDIA_SIZE=38664384
nvidia-x86_64-340-101: NVIDIA_URL=http://http.download.nvidia.com/XFree86/Linux-x86_64/340.101/NVIDIA-Linux-x86_64-340.101-no-compat32.run
nvidia-x86_64-340-101: NVIDIA_OLD=old-

nvidia-x86_64-304-135: NVIDIA_VERSION=304-135
nvidia-x86_64-304-135: NVIDIA_SHA256=352f4a4d5ef692b26383e2cf9ec866f6973f905d53eb6bc9f2161b6ba2afae5a
nvidia-x86_64-304-135: NVIDIA_SIZE=42205949
nvidia-x86_64-304-135: NVIDIA_URL=http://http.download.nvidia.com/XFree86/Linux-x86_64/304.135/NVIDIA-Linux-x86_64-304.135-no-compat32.run
nvidia-x86_64-304-135: NVIDIA_OLD=old-

nvidia-x86_64-304-134: NVIDIA_VERSION=304-134
nvidia-x86_64-304-134: NVIDIA_SHA256=42213765cd28078314657d3c1ba382584f09e5e57598240596021f4f76c0c443
nvidia-x86_64-304-134: NVIDIA_SIZE=42217254
nvidia-x86_64-304-134: NVIDIA_URL=http://http.download.nvidia.com/XFree86/Linux-x86_64/304.134/NVIDIA-Linux-x86_64-304.134-no-compat32.run
nvidia-x86_64-304-134: NVIDIA_OLD=old-

mesa-git:
$(call subst-metadata)
Expand Down
5 changes: 3 additions & 2 deletions nvidia-Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
all:
true
gcc -o apply_extra -Wall -static -DNVIDIA_VERSION='"'$(subst -,.,${NVIDIA_VERSION})'"' -DNVIDIA_BASENAME='"'$(notdir ${NVIDIA_URL})'"' nvidia-apply-extra.c $(CFLAGS) ${LDFLAGS} -larchive -lz -llzma

install:
mkdir -p ${FLATPAK_DEST}/bin
cp apply_extra ${FLATPAK_DEST}/bin/apply_extra
install -s apply_extra ${FLATPAK_DEST}/bin/apply_extra
rm -rf ${FLATPAK_DEST}/lib
ln -s extra ${FLATPAK_DEST}/lib
ln -s extra/glvnd ${FLATPAK_DEST}/glvnd
ln -s extra/vulkan ${FLATPAK_DEST}/vulkan
311 changes: 311 additions & 0 deletions nvidia-apply-extra.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,311 @@
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <archive.h>
#include <archive_entry.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

int nvidia_major_version;

void
die_with_error (const char *format, ...)
{
va_list args;
int errsv;

errsv = errno;

va_start (args, format);
vfprintf (stderr, format, args);
va_end (args);

fprintf (stderr, ": %s\n", strerror (errsv));

exit (1);
}

void
die_with_libarchive (struct archive *ar, const char *format)
{
fprintf (stderr, format, archive_error_string (ar));
exit (1);
}

void
die (const char *format, ...)
{
va_list args;

va_start (args, format);
vfprintf (stderr, format, args);
va_end (args);

fprintf (stderr, "\n");

exit (1);
}

static int
has_prefix (const char *str,
const char *prefix)
{
return strncmp (str, prefix, strlen (prefix)) == 0;
}

static int
has_suffix (const char *str, const char *suffix)
{
int str_len;
int suffix_len;

str_len = strlen (str);
suffix_len = strlen (suffix);

if (str_len < suffix_len)
return 0;

return strcmp (str + str_len - suffix_len, suffix) == 0;
}

static void
copy_archive (struct archive *ar,
struct archive *aw)
{
int r;
const void *buff;
size_t size;
int64_t offset;

while (1)
{
r = archive_read_data_block (ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
break;
if (r != ARCHIVE_OK)
die_with_libarchive (ar, "archive_write_data_block: %s");

r = archive_write_data_block (aw, buff, size, offset);
if (r != ARCHIVE_OK)
die_with_libarchive (aw, "archive_write_data_block: %s");
}
}

static int
should_extract (struct archive_entry *entry)
{
const char *path = archive_entry_pathname (entry);

if (has_prefix (path, "./"))
path += 2;

/* Skip these as we're using GLVND on majod > 367*/
if (nvidia_major_version > 367 &&
(has_prefix (path, "libGL.so") ||
has_prefix (path, "libEGL.so")))
return 0;

if ((has_prefix (path, "lib") ||
has_prefix (path, "tls/lib"))&&
has_suffix (path, ".so." NVIDIA_VERSION))
return 1;

if (strcmp (path, "nvidia_icd.json") == 0)
{
archive_entry_set_pathname (entry, "./vulkan/icd.d/nvidia_icd.json");
return 1;
}
if (strcmp (path, "10_nvidia.json") == 0)
{
archive_entry_set_pathname (entry, "./glvnd/egl_vendor.d/10_nvidia.json");
return 1;
}

return 0;
}

static void
extract (int fd)
{
struct archive *a;
struct archive *ext;
struct archive_entry *entry;
int r;

a = archive_read_new ();
ext = archive_write_disk_new ();
archive_read_support_format_tar (a);
archive_read_support_filter_xz (a);
archive_read_support_filter_gzip (a);

if ((r = archive_read_open_fd (a, fd, 16*1024)))
die_with_libarchive (a, "archive_read_open_fd: %s");

while (1)
{
r = archive_read_next_header (a, &entry);
if (r == ARCHIVE_EOF)
break;

if (r != ARCHIVE_OK)
die_with_libarchive (a, "archive_read_next_header: %s");

if (!should_extract (entry))
continue;

r = archive_write_header (ext, entry);
if (r != ARCHIVE_OK)
die_with_libarchive (ext, "archive_write_header: %s");
else
{
copy_archive (a, ext);
r = archive_write_finish_entry (ext);
if (r != ARCHIVE_OK)
die_with_libarchive (ext, "archive_write_finish_entry: %s");
}
}

archive_read_close (a);
archive_read_free (a);

archive_write_close (ext);
archive_write_free (ext);
}

static int
find_skip_lines (int fd)
{
char buffer[1024];
ssize_t size;
char *line_start, *line_end, *buffer_end;
char *skip_str = NULL;
int skip_lines;

size = pread (fd, buffer, sizeof buffer - 1, 0);
if (size == -1)
die_with_error ("read extra data");

buffer[size] = 0; /* Ensure zero termination */
buffer_end = buffer + size;

line_start = buffer;
while (line_start < buffer_end)
{
line_end = strchr (line_start, '\n');
if (line_end != NULL)
{
*line_end = 0;
line_end += 1;
}
else
line_end = buffer_end;

if (has_prefix (line_start, "skip="))
{
skip_str = line_start + 5;
break;
}

line_start = line_end;
}

if (skip_str == NULL)
die ("Can't find skip size");

skip_lines = atoi (skip_str);

if (skip_lines == 0)
die ("Can't parse skip=%s", skip_str);

return skip_lines;
}

static off_t
find_line_offset (int fd, int skip_lines)
{
off_t offset, buf_offset;
int n_lines;
ssize_t size;
char buffer[16*1024];

offset = 0;
buf_offset = 0;
n_lines = 1;

while (1)
{
size = pread (fd, buffer, sizeof buffer, offset);
if (size == -1)
die_with_error ("read data");

buf_offset = 0;
while (buf_offset < size)
{
if (buffer[buf_offset] == '\n')
{
n_lines ++;
if (n_lines == skip_lines)
return offset + buf_offset + 1;
}

buf_offset++;
}

offset += size;
}

/* Should not happen */
return 0;
}

int
main (int argc, char *argv[])
{
int fd;
int skip_lines;
off_t tar_start;

nvidia_major_version = atoi (NVIDIA_VERSION);

fd = open (NVIDIA_BASENAME, O_RDONLY);
if (fd == -1)
die_with_error ("open extra data");

skip_lines = find_skip_lines (fd);
tar_start = find_line_offset (fd, skip_lines);

if (lseek (fd, tar_start, SEEK_SET)!= tar_start)
die ("Can't seek to tar");

extract (fd);

close (fd);

unlink (NVIDIA_BASENAME);

if (nvidia_major_version > 367)
{
/* GLVND */
/* Default to nvidia */
symlink ("libGLX_nvidia.so." NVIDIA_VERSION, "libGLX_indirect.so.0");

/* unversioned */
symlink ("libEGL_nvidia.so." NVIDIA_VERSION, "libEGL_nvidia.so.0");
symlink ("libGLESv2_nvidia.so." NVIDIA_VERSION, "libGLESv2_nvidia.so.2");
symlink ("libGLX_nvidia.so." NVIDIA_VERSION, "libGLX_nvidia.so.0");
}
else
{
/* Non GLVND */

symlink ("libEGL.so." NVIDIA_VERSION, "libEGL.so.1");
symlink ("libGL.so." NVIDIA_VERSION, "libGL.so.1");
symlink ("libglx.so." NVIDIA_VERSION, "libglx.so.1");
symlink ("libGLESv2.so." NVIDIA_VERSION, "libGLESv2.so.1");
}

return 0;
}
Loading

0 comments on commit 80d3746

Please sign in to comment.