11/**************************************************************************
2- *
2+ *
33 * Copyright (c) 2004-19 Simon Peter
4- *
4+ *
55 * All Rights Reserved.
6- *
6+ *
77 * Permission is hereby granted, free of charge, to any person obtaining a copy
88 * of this software and associated documentation files (the "Software"), to deal
99 * in the Software without restriction, including without limitation the rights
1010 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1111 * copies of the Software, and to permit persons to whom the Software is
1212 * furnished to do so, subject to the following conditions:
13- *
13+ *
1414 * The above copyright notice and this permission notice shall be included in
1515 * all copies or substantial portions of the Software.
16- *
16+ *
1717 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1818 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1919 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2020 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2121 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2222 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2323 * THE SOFTWARE.
24- *
24+ *
2525 **************************************************************************/
2626
2727#ident "AppImage by Simon Peter, http://appimage.org/"
@@ -65,7 +65,7 @@ extern char runtime[];
6565extern unsigned int runtime_len ;
6666#endif
6767
68- enum fARCH {
68+ enum fARCH {
6969 fARCH_i386 ,
7070 fARCH_x86_64 ,
7171 fARCH_arm ,
@@ -105,7 +105,7 @@ int sfs_ls(char* image) {
105105 sqfs_err err = SQFS_OK ;
106106 sqfs_traverse trv ;
107107 sqfs fs ;
108-
108+
109109 ssize_t fs_offset = appimage_get_elf_size (image );
110110
111111 // error check
@@ -114,7 +114,7 @@ int sfs_ls(char* image) {
114114
115115 if ((err = sqfs_open_image (& fs , image , fs_offset )))
116116 die ("sqfs_open_image error" );
117-
117+
118118 if ((err = sqfs_traverse_open (& trv , & fs , sqfs_inode_root (& fs ))))
119119 die ("sqfs_traverse_open error" );
120120 while (sqfs_traverse_next (& trv , & err )) {
@@ -125,12 +125,12 @@ int sfs_ls(char* image) {
125125 if (err )
126126 die ("sqfs_traverse_next error" );
127127 sqfs_traverse_close (& trv );
128-
128+
129129 sqfs_fd_close (fs .fd );
130130 return 0 ;
131131}
132132
133- /* Generate a squashfs filesystem using mksquashfs on the $PATH
133+ /* Generate a squashfs filesystem using mksquashfs on the $PATH
134134* execlp(), execvp(), and execvpe() search on the $PATH */
135135int sfs_mksquashfs (char * source , char * destination , int offset ) {
136136 pid_t pid = fork ();
@@ -146,13 +146,13 @@ int sfs_mksquashfs(char *source, char *destination, int offset) {
146146 perror ("sfs_mksquashfs waitpid() failed" );
147147 return (-1 );
148148 }
149-
149+
150150 int retcode = WEXITSTATUS (status );
151151 if (retcode ) {
152152 fprintf (stderr , "mksquashfs (pid %d) exited with code %d\n" , pid , retcode );
153153 return (-1 );
154154 }
155-
155+
156156 return 0 ;
157157 } else {
158158 // we are the child
@@ -272,7 +272,7 @@ int validate_desktop_file(char *file) {
272272}
273273
274274/* Generate a squashfs filesystem
275- * The following would work if we link to mksquashfs.o after we renamed
275+ * The following would work if we link to mksquashfs.o after we renamed
276276* main() to mksquashfs_main() in mksquashfs.c but we don't want to actually do
277277* this because squashfs-tools is not under a permissive license
278278* i *nt sfs_mksquashfs(char *source, char *destination) {
@@ -291,19 +291,19 @@ int validate_desktop_file(char *file) {
291291static void replacestr (char * line , const char * search , const char * replace )
292292{
293293 char * sp = NULL ;
294-
294+
295295 if ((sp = strstr (line , search )) == NULL ) {
296296 return ;
297297 }
298298 int search_len = strlen (search );
299299 int replace_len = strlen (replace );
300300 int tail_len = strlen (sp + search_len );
301-
301+
302302 memmove (sp + replace_len ,sp + search_len ,tail_len + 1 );
303303 memcpy (sp , replace , replace_len );
304-
304+
305305 /* Do it recursively again until no more work to do */
306-
306+
307307 if ((sp = strstr (line , search ))) {
308308 replacestr (line , search , replace );
309309 }
@@ -447,7 +447,7 @@ gchar* find_first_matching_file_nonrecursive(const gchar *real_path, const gchar
447447 }
448448 g_dir_close (dir );
449449 }
450- else {
450+ else {
451451 g_warning ("%s: %s" , real_path , g_strerror (errno ));
452452 }
453453 return NULL ;
@@ -477,7 +477,7 @@ bool readFile(char* filename, int* size, char** buffer) {
477477 fread (indata , fsize , 1 , f );
478478 fclose (f );
479479 * size = (int )fsize ;
480- * buffer = indata ;
480+ * buffer = indata ;
481481 return TRUE;
482482}
483483
542542main (int argc , char * argv [])
543543{
544544
545- /* Parse Travis CI environment variables.
545+ /* Parse Travis CI environment variables.
546546 * https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables
547547 * TRAVIS_COMMIT: The commit that the current build is testing.
548548 * TRAVIS_REPO_SLUG: The slug (in form: owner_name/repo_name) of the repository currently being built.
@@ -563,18 +563,18 @@ main (int argc, char *argv[])
563563 /* Parse GitLab CI environment variables.
564564 * https://docs.gitlab.com/ee/ci/variables/#predefined-variables-environment-variables
565565 * echo "${CI_PROJECT_URL}/-/jobs/artifacts/${CI_COMMIT_REF_NAME}/raw/QtQuickApp-x86_64.AppImage?job=${CI_JOB_NAME}"
566- */
566+ */
567567 char * CI_PROJECT_URL ;
568568 CI_PROJECT_URL = getenv ("CI_PROJECT_URL" );
569569 char * CI_COMMIT_REF_NAME ;
570570 CI_COMMIT_REF_NAME = getenv ("CI_COMMIT_REF_NAME" ); // The branch or tag name for which project is built
571571 char * CI_JOB_NAME ;
572572 CI_JOB_NAME = getenv ("CI_JOB_NAME" ); // The name of the job as defined in .gitlab-ci.yml
573-
573+
574574 /* Parse OWD environment variable.
575575 * If it is available then cd there. It is the original CWD prior to running AppRun */
576576 char * owd_env = NULL ;
577- owd_env = getenv ("OWD" );
577+ owd_env = getenv ("OWD" );
578578 if (NULL != owd_env ){
579579 int ret ;
580580 ret = chdir (owd_env );
@@ -583,13 +583,13 @@ main (int argc, char *argv[])
583583 exit (1 );
584584 }
585585 }
586-
586+
587587 GError * error = NULL ;
588588 GOptionContext * context ;
589589
590590 // initialize help text of argument
591591 sprintf (_exclude_file_desc , "Uses given file as exclude file for mksquashfs, in addition to %s." , APPIMAGEIGNORE );
592-
592+
593593 context = g_option_context_new ("SOURCE [DESTINATION] - Generate, extract, and inspect AppImages" );
594594 g_option_context_add_main_entries (context , entries , NULL );
595595 // g_option_context_add_group (context, gtk_get_option_group (TRUE));
@@ -646,16 +646,16 @@ main (int argc, char *argv[])
646646 g_print ("WARNING: gpg2 or gpg command is missing, please install it if you want to create digital signatures\n" );
647647 if (! g_find_program_in_path ("sha256sum" ) && ! g_find_program_in_path ("shasum" ))
648648 g_print ("WARNING: sha256sum or shasum command is missing, please install it if you want to create digital signatures\n" );
649-
649+
650650 if (!& remaining_args [0 ])
651651 die ("SOURCE is missing" );
652-
652+
653653 /* If in list mode */
654654 if (list ){
655655 sfs_ls (remaining_args [0 ]);
656656 exit (0 );
657657 }
658-
658+
659659 /* If the first argument is a directory, then we assume that we should package it */
660660 if (g_file_test (remaining_args [0 ], G_FILE_TEST_IS_DIR )) {
661661 /* Parse VERSION environment variable.
@@ -709,7 +709,7 @@ main (int argc, char *argv[])
709709 char * destination ;
710710 char source [PATH_MAX ];
711711 realpath (remaining_args [0 ], source );
712-
712+
713713 /* Check if *.desktop file is present in source AppDir */
714714 gchar * desktop_file = find_first_matching_file_nonrecursive (source , "*.desktop" );
715715 if (desktop_file == NULL ){
@@ -732,7 +732,7 @@ main (int argc, char *argv[])
732732 die (".desktop file cannot be parsed" );
733733 if (!get_desktop_entry (kf , "Categories" ))
734734 die (".desktop file is missing a Categories= key" );
735-
735+
736736 if (verbose ){
737737 fprintf (stderr ,"Name: %s\n" , get_desktop_entry (kf , "Name" ));
738738 fprintf (stderr ,"Icon: %s\n" , get_desktop_entry (kf , "Icon" ));
@@ -765,10 +765,10 @@ main (int argc, char *argv[])
765765 char app_name_for_filename [PATH_MAX ];
766766 sprintf (app_name_for_filename , "%s" , get_desktop_entry (kf , "Name" ));
767767 replacestr (app_name_for_filename , " " , "_" );
768-
768+
769769 if (verbose )
770770 fprintf (stderr ,"App name for filename: %s\n" , app_name_for_filename );
771-
771+
772772 if (remaining_args [1 ]) {
773773 destination = remaining_args [1 ];
774774 } else {
@@ -821,10 +821,10 @@ main (int argc, char *argv[])
821821 fprintf (stderr , "%s\n" , example_path );
822822 exit (1 );
823823 }
824-
824+
825825 /* Check if .DirIcon is present in source AppDir */
826826 gchar * diricon_path = g_build_filename (source , ".DirIcon" , NULL );
827-
827+
828828 if (! g_file_test (diricon_path , G_FILE_TEST_EXISTS )){
829829 fprintf (stderr , "Deleting pre-existing .DirIcon\n" );
830830 g_unlink (diricon_path );
@@ -835,20 +835,43 @@ main (int argc, char *argv[])
835835 if (res )
836836 die ("Could not symlink .DirIcon" );
837837 }
838-
838+
839839 /* Check if AppStream upstream metadata is present in source AppDir */
840840 if (! no_appstream ){
841- char application_id [PATH_MAX ];
842- sprintf (application_id , "%s" , basename (desktop_file ));
843- replacestr (application_id , ".desktop" , ".appdata.xml" );
844- gchar * appdata_path = g_build_filename (source , "/usr/share/metainfo/" , application_id , NULL );
845- if (! g_file_test (appdata_path , G_FILE_TEST_IS_REGULAR )){
846- fprintf (stderr , "WARNING: AppStream upstream metadata is missing, please consider creating it\n" );
847- fprintf (stderr , " in usr/share/metainfo/%s\n" , application_id );
848- fprintf (stderr , " Please see https://www.freedesktop.org/software/appstream/docs/chap-Quickstart.html#sect-Quickstart-DesktopApps\n" );
849- fprintf (stderr , " for more information or use the generator at http://output.jsbin.com/qoqukof.\n" );
850- } else {
851- fprintf (stderr , "AppStream upstream metadata found in usr/share/metainfo/%s\n" , application_id );
841+ bool appstream_found = false;
842+ char * appstream_filename ;
843+ gchar * * appstream_path ;
844+
845+ char metainfo_filename [PATH_MAX ];
846+ sprintf (metainfo_filename , "%s" , basename (desktop_file ));
847+ replacestr (metainfo_filename , ".desktop" , ".metainfo.xml" );
848+ gchar * metainfo_path = g_build_filename (source , "/usr/share/metainfo/" , metainfo_filename , NULL );
849+ if (!g_file_test (metainfo_path , G_FILE_TEST_IS_REGULAR )) {
850+ char appdata_filename [PATH_MAX ];
851+ sprintf (appdata_filename , "%s" , basename (desktop_file ));
852+ replacestr (appdata_filename , ".desktop" , ".appdata.xml" );
853+ gchar * appdata_path = g_build_filename (source , "/usr/share/metainfo/" , appdata_filename , NULL );
854+ if (!g_file_test (appdata_path , G_FILE_TEST_IS_REGULAR )) {
855+ fprintf (stderr , "WARNING: AppStream upstream metadata is missing, please consider creating it\n" );
856+ fprintf (stderr , " in usr/share/metainfo/%s\n" , metainfo_filename );
857+ fprintf (stderr , " Please see https://www.freedesktop.org/software/appstream/docs/chap-Quickstart.html#sect-Quickstart-DesktopApps\n" );
858+ fprintf (stderr , " for more information or use the generator at https://docs.appimage.org/packaging-guide/optional/appstream.html.\n" );
859+ } else {
860+ appstream_found = true;
861+ appstream_filename = & appdata_filename ;
862+ appstream_path = & appdata_path ;
863+ fprintf (stderr , "WARNING: The appstream upstream metadata file should be named %s.\n" , metainfo_filename );
864+ fprintf (stderr , " .appdata.xml is a legacy file ending and shouldn't be used in new AppImages anymore.\n" );
865+ fprintf (stderr , " See https://www.freedesktop.org/software/appstream/docs/sect-Metadata-Application.html.\n" );
866+ }
867+ } else {
868+ appstream_found = true;
869+ appstream_filename = & metainfo_filename ;
870+ appstream_path = & metainfo_path ;
871+ }
872+
873+ if (appstream_found ) {
874+ fprintf (stderr , "AppStream upstream metadata found in usr/share/metainfo/%s\n" , * appstream_filename );
852875 /* Use ximion's appstreamcli to make sure that desktop file and appdata match together */
853876 if (g_find_program_in_path ("appstreamcli" )) {
854877 char * args [] = {
@@ -868,7 +891,7 @@ main (int argc, char *argv[])
868891 char * args [] = {
869892 "appstream-util" ,
870893 "validate-relax" ,
871- appdata_path ,
894+ * appstream_path ,
872895 NULL
873896 };
874897 g_print ("Trying to validate AppStream information with the appstream-util tool\n" );
@@ -879,7 +902,7 @@ main (int argc, char *argv[])
879902 }
880903 }
881904 }
882-
905+
883906 /* Upstream mksquashfs can currently not start writing at an offset,
884907 * so we need a patched one. https://github.com/plougher/squashfs-tools/pull/13
885908 * should hopefully change that. */
@@ -904,11 +927,11 @@ main (int argc, char *argv[])
904927 }
905928 if (verbose )
906929 printf ("Size of the embedded runtime: %d bytes\n" , size );
907-
930+
908931 int result = sfs_mksquashfs (source , destination , size );
909932 if (result != 0 )
910933 die ("sfs_mksquashfs error" );
911-
934+
912935 fprintf (stderr , "Embedding ELF...\n" );
913936 FILE * fpdst = fopen (destination , "rb+" );
914937 if (fpdst == NULL ) {
@@ -926,7 +949,7 @@ main (int argc, char *argv[])
926949 printf ("Could not set executable bit, aborting\n" );
927950 exit (1 );
928951 }
929-
952+
930953 if (bintray_user != NULL ){
931954 if (bintray_repo != NULL ){
932955 char buf [1024 ];
@@ -935,7 +958,7 @@ main (int argc, char *argv[])
935958 printf ("%s\n" , updateinformation );
936959 }
937960 }
938-
961+
939962 /* If the user has not provided update information but we know this is a Travis CI build,
940963 * then fill in update information based on TRAVIS_REPO_SLUG */
941964 if (guess_update_information ){
@@ -953,7 +976,7 @@ main (int argc, char *argv[])
953976 if (zsyncmake_path ){
954977 char buf [1024 ];
955978 gchar * * parts = g_strsplit (travis_repo_slug , "/" , 2 );
956- /* https://github.com/AppImage/AppImageSpec/blob/master/draft.md#github-releases
979+ /* https://github.com/AppImage/AppImageSpec/blob/master/draft.md#github-releases
957980 * gh-releases-zsync|probono|AppImages|latest|Subsurface*-x86_64.AppImage.zsync */
958981 gchar * channel = "continuous" ;
959982 if (travis_tag != NULL ){
@@ -983,22 +1006,22 @@ main (int argc, char *argv[])
9831006 }
9841007 }
9851008 }
986-
1009+
9871010 /* If updateinformation was provided, then we check and embed it */
9881011 if (updateinformation != NULL ){
9891012 if (!g_str_has_prefix (updateinformation ,"zsync|" ))
9901013 if (!g_str_has_prefix (updateinformation ,"bintray-zsync|" ))
9911014 if (!g_str_has_prefix (updateinformation ,"gh-releases-zsync|" ))
9921015 if (!g_str_has_prefix (updateinformation ,"pling-v1-zsync|" ))
9931016 die ("The provided updateinformation is not in a recognized format" );
994-
1017+
9951018 gchar * * ui_type = g_strsplit_set (updateinformation , "|" , -1 );
996-
1019+
9971020 if (verbose )
9981021 printf ("updateinformation type: %s\n" , ui_type [0 ]);
9991022 /* TODO: Further checking of the updateinformation */
1000-
1001-
1023+
1024+
10021025 unsigned long ui_offset = 0 ;
10031026 unsigned long ui_length = 0 ;
10041027
0 commit comments