1{ stdenv
2, lib
3, makeWrapper
4, p7zip
5, gawk
6, util-linux
7, xorg
8, glib
9, dbus-glib
10, zlib
11, bbe
12, bash
13, timetrap
14, netcat
15, cups
16, kernel ? null
17, libsOnly ? false
18, fetchurl
19, undmg
20, perl
21, autoPatchelfHook
22}:
23
24assert (!libsOnly) -> kernel != null;
25
26stdenv.mkDerivation rec {
27 version = "18.1.0-53311";
28 pname = "prl-tools";
29
30 # We download the full distribution to extract prl-tools-lin.iso from
31 # => ${dmg}/Parallels\ Desktop.app/Contents/Resources/Tools/prl-tools-lin.iso
32 src = fetchurl {
33 url = "https://download.parallels.com/desktop/v${lib.versions.major version}/${version}/ParallelsDesktop-${version}.dmg";
34 sha256 = "sha256-2ROPFIDoV2/sMVsVhcSyn0m1QVMCNb399WzKd/cozws=";
35 };
36
37 hardeningDisable = [ "pic" "format" ];
38
39 nativeBuildInputs = [ p7zip undmg perl bbe autoPatchelfHook ]
40 ++ lib.optionals (!libsOnly) [ makeWrapper ] ++ kernel.moduleBuildDependencies;
41
42 buildInputs = with xorg; [ libXrandr libXext libX11 libXcomposite libXinerama ]
43 ++ lib.optionals (!libsOnly) [ libXi glib dbus-glib zlib ];
44
45 runtimeDependencies = [ glib xorg.libXrandr ];
46
47 inherit libsOnly;
48
49 unpackPhase = ''
50 undmg $src
51 export sourceRoot=prl-tools-build
52 7z x "Parallels Desktop.app/Contents/Resources/Tools/prl-tools-lin${lib.optionalString stdenv.isAarch64 "-arm"}.iso" -o$sourceRoot
53 if test -z "$libsOnly"; then
54 ( cd $sourceRoot/kmods; tar -xaf prl_mod.tar.gz )
55 fi
56 '';
57
58 kernelVersion = lib.optionalString (!libsOnly) kernel.modDirVersion;
59 kernelDir = lib.optionalString (!libsOnly) "${kernel.dev}/lib/modules/${kernelVersion}";
60
61 libPath = lib.concatStringsSep ":" [ "${glib.out}/lib" "${xorg.libXrandr}/lib" ];
62
63 scriptPath = lib.concatStringsSep ":" (lib.optionals (!libsOnly) [
64 "${util-linux}/bin"
65 "${gawk}/bin"
66 "${bash}/bin"
67 "${timetrap}/bin"
68 "${netcat}/bin"
69 "${cups}/sbin"
70 ]);
71
72 buildPhase = ''
73 if test -z "$libsOnly"; then
74 ( # kernel modules
75 cd kmods
76 make -f Makefile.kmods \
77 KSRC=$kernelDir/source \
78 HEADERS_CHECK_DIR=$kernelDir/source \
79 KERNEL_DIR=$kernelDir/build \
80 SRC=$kernelDir/build \
81 KVER=$kernelVersion
82 )
83 fi
84 '';
85
86 installPhase = ''
87 if test -z "$libsOnly"; then
88 ( # kernel modules
89 cd kmods
90 mkdir -p $out/lib/modules/${kernelVersion}/extra
91 cp prl_fs/SharedFolders/Guest/Linux/prl_fs/prl_fs.ko $out/lib/modules/${kernelVersion}/extra
92 cp prl_fs_freeze/Snapshot/Guest/Linux/prl_freeze/prl_fs_freeze.ko $out/lib/modules/${kernelVersion}/extra
93 cp prl_tg/Toolgate/Guest/Linux/prl_tg/prl_tg.ko $out/lib/modules/${kernelVersion}/extra
94 ${lib.optionalString stdenv.isAarch64
95 "cp prl_notifier/Installation/lnx/prl_notifier/prl_notifier.ko $out/lib/modules/${kernelVersion}/extra"}
96 )
97 fi
98
99 ( # tools
100 cd tools/tools${if stdenv.isAarch64 then "-arm64" else if stdenv.isx86_64 then "64" else "32"}
101 mkdir -p $out/lib
102
103 if test -z "$libsOnly"; then
104 # prltoolsd contains hardcoded /bin/bash path
105 # we're lucky because it uses only -c command
106 # => replace to /bin/sh
107 bbe -e "s:/bin/bash:/bin/sh\x00\x00:" -o bin/prltoolsd.tmp bin/prltoolsd
108 rm -f bin/prltoolsd
109 mv bin/prltoolsd.tmp bin/prltoolsd
110
111 # install binaries
112 for i in bin/* sbin/prl_nettool sbin/prl_snapshot; do
113 # also patch binaries to replace /usr/bin/XXX to XXX
114 # here a two possible cases:
115 # 1. it is uses as null terminated string and should be truncated by null;
116 # 2. it is uses inside shell script and should be truncated by space.
117 for p in bin/* sbin/prl_nettool sbin/prl_snapshot sbin/prlfsmountd; do
118 p=$(basename $p)
119 bbe -e "s:/usr/bin/$p\x00:./$p\x00\x00\x00\x00\x00\x00\x00\x00:" -o $i.tmp $i
120 bbe -e "s:/usr/sbin/$p\x00:./$p\x00\x00\x00\x00\x00\x00\x00\x00 :" -o $i $i.tmp
121 bbe -e "s:/usr/bin/$p:$p :" -o $i.tmp $i
122 bbe -e "s:/usr/sbin/$p:$p :" -o $i $i.tmp
123 done
124
125 install -Dm755 $i $out/$i
126 done
127
128 install -Dm755 ../../tools/prlfsmountd.sh $out/sbin/prlfsmountd
129 for f in $out/bin/* $out/sbin/*; do
130 wrapProgram $f \
131 --prefix LD_LIBRARY_PATH ':' "$libPath" \
132 --prefix PATH ':' "$scriptPath"
133 done
134
135 for i in lib/libPrl*.0.0; do
136 cp $i $out/lib
137 ln -s $out/$i $out/''${i%.0.0}
138 done
139
140 mkdir -p $out/share/man/man8
141 install -Dm644 ../mount.prl_fs.8 $out/share/man/man8
142
143 substituteInPlace ../99prltoolsd-hibernate \
144 --replace "/bin/bash" "${bash}/bin/bash"
145
146 mkdir -p $out/etc/pm/sleep.d
147 install -Dm644 ../99prltoolsd-hibernate $out/etc/pm/sleep.d
148 fi
149 )
150 '';
151
152 meta = with lib; {
153 description = "Parallels Tools for Linux guests";
154 homepage = "https://parallels.com";
155 platforms = platforms.linux;
156 license = licenses.unfree;
157 maintainers = with maintainers; [ catap wegank ];
158 };
159}