1 /**************************************************************************
3 Copyright (c) 2005-13 Simon Peter
4 Copyright (c) 2007 Alexander Larsson
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 **************************************************************************/
28 #include <sys/types.h>
40 /* ======================================================== Start helper functions for icon extraction */
42 Constructs the name of the thumbnail image for $HOME/.thumbnails for the executable that is itself
43 See http://people.freedesktop.org/~vuntz/thumbnail-spec-cache/
45 http://www.google.com/codesearch#n76pnUnMG18/trunk/blender/imbuf/intern/thumbs.c&q=.thumbnails/normal%20lang:c%20md5&type=cs
54 #define URI_MAX FILE_MAX*3 + 8
56 /* --- begin of adapted code from glib ---
57 * The following code is adapted from function g_escape_uri_string from the gnome glib
58 * Source: http://svn.gnome.org/viewcvs/glib/trunk/glib/gconvert.c?view=markup
59 * released under the Gnu General Public License.
60 * NOTE THIS DOESN'T WORK PROPERLY FOR öäüß - FIXME
64 UNSAFE_ALL
= 0x1, /* Escape all unsafe characters */
65 UNSAFE_ALLOW_PLUS
= 0x2, /* Allows '+' */
66 UNSAFE_PATH
= 0x8, /* Allows '/', '&', '=', ':', '@', '+', '$' and ',' */
67 UNSAFE_HOST
= 0x10, /* Allows '/' and ':' and '@' */
68 UNSAFE_SLASHES
= 0x20 /* Allows all characters except for '/' and '%' */
71 static const unsigned char acceptable
[96] = {
72 /* A table of the ASCII chars from space (32) to DEL (127) */
73 0x00,0x3F,0x20,0x20,0x28,0x00,0x2C,0x3F,0x3F,0x3F,0x3F,0x2A,0x28,0x3F,0x3F,0x1C,
74 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x38,0x20,0x20,0x2C,0x20,0x20,
75 0x38,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
76 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x20,0x3F,
77 0x20,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
78 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x3F,0x20
81 static const char hex
[17] = "0123456789abcdef";
83 void escape_uri_string (const char *string
, char* escaped_string
, int len
,UnsafeCharacterSet mask
)
85 #define ACCEPTABLE(a) ((a)>=32 && (a)<128 && (acceptable[(a)-32] & use_mask))
90 UnsafeCharacterSet use_mask
;
93 for (q
= escaped_string
, p
= string
; (*p
!= '\0') && len
; p
++) {
94 c
= (unsigned char) *p
;
97 if (!ACCEPTABLE (c
)) {
98 *q
++ = '%'; /* means hex coming */
109 void to_hex_char(char* hexbytes
, const unsigned char* bytes
, int len
)
111 const unsigned char *p
;
114 for (q
= hexbytes
, p
= bytes
; len
; p
++) {
115 const unsigned char c
= (unsigned char) *p
;
122 /* --- end of adapted code from glib --- */
124 static int uri_from_filename( const char *dir
, char *newuri
)
127 sprintf (uri
, "file://%s", dir
);
128 char newstring
[URI_MAX
];
129 strncpy(newstring
, uri
, URI_MAX
);
130 newstring
[URI_MAX
- 1] = 0;
132 escape_uri_string(newstring
, newuri
, FILE_MAX
*3+8, UNSAFE_PATH
);
137 static void thumbname_from_uri(const char* uri
, char* thumb
)
140 unsigned char digest
[16];
141 md5_buffer( uri
, strlen(uri
), digest
);
143 to_hex_char(hexdigest
, digest
, 16);
144 hexdigest
[32] = '\0';
145 sprintf(thumb
, "%s.png", hexdigest
);
149 /* ======================================================== End helper functions for icon extraction */
151 extern int ext2_main(int argc
, char *argv
[], void (*mounted
) (void));
152 extern void ext2_quit(void);
154 static pid_t fuse_pid
;
155 static int keepalive_pipe
[2];
158 write_pipe_thread (void *arg
)
162 // sprintf(stderr, "Called write_pipe_thread");
163 memset (c
, 'x', sizeof (c
));
165 /* Write until we block, on broken pipe, exit */
166 res
= write (keepalive_pipe
[1], c
, sizeof (c
));
168 kill (fuse_pid
, SIGHUP
);
176 run_when_fuse_fs_mounted (void)
179 // sprintf(stderr, "Called run_when_fuse_fs_mounted");
184 res
= pthread_create(&thread
, NULL
, write_pipe_thread
, keepalive_pipe
);
187 char* getArg(int argc
, char *argv
[],char chr
)
190 for (i
=1; i
<argc
; ++i
)
191 if ((argv
[i
][0]=='-') && (argv
[i
][1]==chr
))
192 return &(argv
[i
][2]);
198 main (int argc
, char *argv
[])
201 char mount_dir
[] = "/tmp/.mount_XXXXXX"; /* create mountpoint */
202 char filename
[100]; /* enough for mount_dir + "/AppRun" */
207 // We are using glib anyway for fuseiso, so we can use it here too to make our life easier
208 char *xdg_cache_home
;
209 char thumbnails_medium_dir
[FILE_MAX
];
210 xdg_cache_home
= (getenv("XDG_CACHE_HOME") == NULL
211 ? g_build_filename(g_get_home_dir(), ".cache", NULL
)
212 : g_strdup(getenv("XDG_CACHE_HOME")));
213 sprintf(thumbnails_medium_dir
, "%s/thumbnails/normal/", xdg_cache_home
);
214 /* printf("%s\n", thumbnails_medium_dir); */
216 if (mkdtemp(mount_dir
) == NULL
) {
220 if (pipe (keepalive_pipe
) == -1) {
221 perror ("pipe error: ");
227 perror ("fork error: ");
236 /* close read pipe */
237 close (keepalive_pipe
[0]);
240 char *dir
= realpath( "/proc/self/exe", NULL
);
243 child_argv
[1] = mount_dir
;
244 child_argv
[2] = "-o";
245 child_argv
[3] = "ro";
246 child_argv
[4] = NULL
;
248 ext2_main (4, child_argv
, NULL
);
250 /* in parent, child is $pid */
253 /* close write pipe */
254 close (keepalive_pipe
[1]);
256 /* Pause until mounted */
257 read (keepalive_pipe
[0], &c
, 1);
260 dir_fd
= open (mount_dir
, O_RDONLY
);
262 perror ("open dir error: ");
266 res
= dup2 (dir_fd
, 1023);
268 perror ("dup2 error: ");
273 strcpy (filename
, mount_dir
);
274 strcat (filename
, "/AppRun");
276 real_argv
= malloc (sizeof (char *) * (argc
+ 1));
277 for (i
= 0; i
< argc
; i
++) {
278 real_argv
[i
] = argv
[i
];
284 /* ======================================================== Start icon extraction */
287 char fullpath
[FILE_MAX
];
288 length
= readlink("/proc/self/exe", fullpath
, sizeof(fullpath
));
289 fullpath
[length
] = '\0';
290 /* printf("%s\n", fullpath); */
291 char theuri
[URI_MAX
];
292 uri_from_filename(fullpath
, theuri
);
293 /* printf("%s\n", theuri); */
294 char path_to_thumbnail
[URI_MAX
];
295 char thumbname
[URI_MAX
];
296 thumbname_from_uri(theuri
, thumbname
);
297 sprintf(path_to_thumbnail
, "%s%s", thumbnails_medium_dir
, thumbname
);
302 char diricon
[FILE_MAX
];
303 sprintf (diricon
, "%s/.DirIcon", mount_dir
);
305 /* open source file */
306 if((from
= fopen(diricon
, "rb"))==NULL
) {
307 printf("Cannot open %s\n", diricon
);
311 /* open destination file */
312 char mkcmd
[FILE_MAX
];
313 char iconsdir
[FILE_MAX
];
315 sprintf(mkcmd
, "mkdir -p '%s'", thumbnails_medium_dir
);
317 if((to
= fopen(path_to_thumbnail
, "wb"))==NULL
) {
318 printf("Cannot open %s for writing\n", path_to_thumbnail
);
326 printf("Error reading source file\n");
329 if(!feof(from
)) fputc(ch
, to
);
331 printf("Error writing destination file\n");
336 if(fclose(from
)==EOF
) {
337 printf("Error closing source file\n");
341 if(fclose(to
)==EOF
) {
342 printf("Error closing destination file\n");
347 /* If called with --icon, then do not run the main app, just print print a message and exit after extracting the icon */
349 arg
=getArg(argc
,argv
,'-');
350 if (arg
&& strcmp(arg
,"icon")==0) {
351 printf("Written %s\n", path_to_thumbnail
);
355 /* ======================================================== End icon extraction */
357 /* Setting some environment variables that the app "inside" might use */
358 setenv( "APPIMAGE", fullpath
, 0 );
359 setenv( "APPDIR", mount_dir
, 0 );
360 execv (filename
, real_argv
);
361 /* Error if we continue here */
362 perror ("execv error: ");