504468ba910365baf2fe8fd4f904de023b66926e
[profile/ivi/dlt-daemon.git] / src / system / dlt-system-filetransfer.c
1 /**
2  * @licence app begin@
3  * Copyright (C) 2012  BMW AG
4  *
5  * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
6  *
7  * Contributions are licensed to the GENIVI Alliance under one or more
8  * Contribution License Agreements.
9  *
10  * \copyright
11  * This Source Code Form is subject to the terms of the
12  * Mozilla Public License, v. 2.0. If a  copy of the MPL was not distributed with
13  * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
14  *
15  *
16  * \author Lassi Marttala <lassi.lm.marttala@partner.bmw.de> BMW 2012
17  *
18  * \file dlt-system-filetransfer.c
19  * For further information see http://www.genivi.org/.
20  * @licence end@
21  */
22
23 /*******************************************************************************
24 **                                                                            **
25 **  SRC-MODULE: dlt-system-filetransfer.c                                                  **
26 **                                                                            **
27 **  TARGET    : linux                                                         **
28 **                                                                            **
29 **  PROJECT   : DLT                                                           **
30 **                                                                            **
31 **  AUTHOR    : Lassi Marttala <lassi.lm.marttala@partner.bmw.de>             **
32 **              Alexander Wenzel Alexander.AW.Wenzel@bmw.de                   **
33 **                                                                            **
34 **  PURPOSE   :                                                               **
35 **                                                                            **
36 **  REMARKS   :                                                               **
37 **                                                                            **
38 **  PLATFORM DEPENDANT [yes/no]: yes                                          **
39 **                                                                            **
40 **  TO BE CHANGED BY USER [yes/no]: no                                        **
41 **                                                                            **
42 *******************************************************************************/
43
44
45 #include <pthread.h>
46 #include <unistd.h>
47 #include <sys/inotify.h>
48 #include <libgen.h>
49 #include <dirent.h>
50 #include <zlib.h>
51 #include <time.h>
52 #include <stdlib.h>
53 #include <string.h>
54
55 #include "dlt-system.h"
56 #include "dlt.h"
57 #include "dlt_filetransfer.h"
58
59 #define INOTIFY_SZ (sizeof(struct inotify_event))
60 #define INOTIFY_LEN (INOTIFY_SZ + NAME_MAX + 1)
61 #define Z_CHUNK_SZ 1024*128
62 #define COMPRESS_EXTENSION ".gz"
63 #define SUBDIR_COMPRESS ".tocompress"
64 #define SUBDIR_TOSEND ".tosend"
65
66
67
68 extern DltSystemThreads threads;
69 // From dlt_filetransfer
70 extern unsigned long getFileSerialNumber(const char* file);
71
72 DLT_IMPORT_CONTEXT(dltsystem);
73 DLT_DECLARE_CONTEXT(filetransferContext)
74
75 typedef struct {
76     int handle;
77     int fd[DLT_SYSTEM_LOG_DIRS_MAX];
78 } s_ft_inotify;
79
80 s_ft_inotify ino;
81
82
83 char *origin_name(char *src){
84     if (strlen( (char*) basename(src)) > 10 ){
85         return (char*)(basename(src)+10);
86     }
87     else{
88         DLT_LOG(dltsystem, DLT_LOG_ERROR,
89                 DLT_STRING("dlt-system-filetransfer, error in recreating origin name!"));
90         return NULL;
91     }
92 }
93
94 char *unique_name(char *src)
95 {
96     DLT_LOG(dltsystem, DLT_LOG_DEBUG,
97             DLT_STRING("dlt-system-filetransfer, creating unique temporary file name."));
98     time_t t = time(NULL);
99     unsigned long l = getFileSerialNumber(src) ^ t;
100     // Length of ULONG_MAX + 1
101     //char *ret = malloc(11);
102
103     char *basename_f = basename(src);
104     // Length of ULONG_MAX + 1
105     int len = 11+strlen(basename_f);
106     if (len > NAME_MAX){
107         DLT_LOG(dltsystem, DLT_LOG_WARN,
108                 DLT_STRING("dlt-system-filetransfer, unique name creation needs to shorten the filename:"),DLT_STRING(basename_f));
109         len = NAME_MAX;
110     }
111
112     char *ret = malloc(len);
113
114     MALLOC_ASSERT(ret);
115     snprintf(ret, len, "%lu%s", l,basename_f);
116     return ret;
117 }
118
119 /**
120   * Function which only calls the relevant part to transfer the payload
121   */
122
123 void send_dumped_file(FiletransferOptions const *opts,char *dst_tosend){
124
125
126     char *fn = origin_name(dst_tosend);
127     DLT_LOG(dltsystem, DLT_LOG_DEBUG,
128             DLT_STRING("dlt-system-filetransfer, sending dumped file:"),DLT_STRING(fn));
129     if(dlt_user_log_file_header_alias(&filetransferContext, dst_tosend, fn) == 0)
130     {
131         int pkgcount = dlt_user_log_file_packagesCount(&filetransferContext, dst_tosend);
132         int lastpkg = 0;
133         int success = 1;
134         while(lastpkg < pkgcount)
135         {
136             int total = 2;
137             int used = 2;
138             dlt_user_check_buffer(&total, &used);
139             while((total-used) < (total/2))
140             {
141                 struct timespec t;
142                 t.tv_sec = 0;
143                 t.tv_nsec = 1000000ul*opts->TimeoutBetweenLogs;
144                 nanosleep(&t, NULL);
145                 dlt_user_check_buffer(&total, &used);
146             }
147             lastpkg++;
148             if(dlt_user_log_file_data(&filetransferContext, dst_tosend, lastpkg, opts->TimeoutBetweenLogs) < 0)
149             {
150                 success = 0;
151                 break;
152             }
153         }
154         if (success)
155             dlt_user_log_file_end(&filetransferContext, dst_tosend, 1);
156     }
157     DLT_LOG(dltsystem, DLT_LOG_DEBUG,
158             DLT_STRING("dlt-system-filetransfer, sent dumped file"));
159 }
160
161 /**
162  * compress file, delete the source file
163  * modification: compress into subdirectory
164  * File whis is compress will be deleted afterwards
165  *  @param src File to be sent
166  *  @param dst destination where to compress the file
167  * @param level of compression
168 **/
169 int compress_file_to(char *src, char *dst, int level)
170 {
171     DLT_LOG(dltsystem, DLT_LOG_DEBUG,
172             DLT_STRING("dlt-system-filetransfer, compressing file from:"),DLT_STRING(src),DLT_STRING("to:"),DLT_STRING(dst));
173     char *buf;
174
175
176     char dst_mode[8];
177     snprintf(dst_mode,8, "wb%d", level);
178
179     gzFile dst_file;
180     FILE *src_file;
181
182     dst_file = gzopen(dst, dst_mode);
183     if(dst_file == Z_NULL)
184     {
185
186         return -1;
187     }
188
189     src_file = fopen(src, "r");
190
191     if(src_file == NULL)
192     {
193         gzclose(dst_file);
194
195         return -1;
196     }
197
198     buf = malloc(Z_CHUNK_SZ);
199     MALLOC_ASSERT(buf);
200
201     while(!feof(src_file))
202     {
203         int read = fread(buf, 1, Z_CHUNK_SZ, src_file);
204         if(ferror(src_file))
205         {
206             free(buf);
207
208             gzclose(dst_file);
209             fclose(src_file);
210             return -1;
211         }
212         gzwrite(dst_file, buf, read);
213     }
214
215     if(remove(src) < 0)
216         DLT_LOG(dltsystem, DLT_LOG_WARN, DLT_STRING("Could not remove file"), DLT_STRING(src));
217     free(buf);
218     fclose(src_file);
219     gzclose(dst_file);
220
221     return 0;
222 }
223
224 //!Sends one file over DLT.
225 /**
226  * If configured in opts, compresses it, then sends it.
227  * uses subdirecties for compressing and before sending, to avoid that those files get changed in the meanwhile
228  *
229  */
230 int send_one(char *src, FiletransferOptions const *opts, int which)
231 {
232     DLT_LOG(dltsystem, DLT_LOG_DEBUG,
233             DLT_STRING("dlt-system-filetransfer, sending a file."));
234     sleep(opts->TimeDelay);
235
236     // Prepare all needed file names
237     char *fn = basename(src);
238     char *fdir = malloc(strlen(src)+1);
239     MALLOC_ASSERT(fdir);
240     strncpy(fdir,src,strlen(src));
241     *(fdir+strlen(fdir))='\0';
242     fdir = dirname(fdir);//dirname overwrites its argument anyway
243     char *dst_tosend;//file which is going to be sent
244
245     char *rn = unique_name(src);//new unique filename based on inode
246
247
248     MALLOC_ASSERT(fn);
249     MALLOC_ASSERT(rn);
250
251     // Compress if needed
252     if(opts->Compression[which] > 0)
253     {
254         DLT_LOG(dltsystem, DLT_LOG_DEBUG,
255                 DLT_STRING("dlt-system-filetransfer, Moving file to tmp directory for compressing it."));
256
257         char *dst_tocompress;//file which is going to be compressed, the compressed one is named dst_tosend
258
259
260         int len = strlen(fdir)+strlen(SUBDIR_COMPRESS)+strlen(rn)+3;//the filename in .tocompress +2 for 2*"/", +1 for \0
261         dst_tocompress = malloc(len);
262         MALLOC_ASSERT(dst_tocompress);
263
264         snprintf(dst_tocompress,len,"%s/%s/%s",fdir,SUBDIR_COMPRESS,rn);
265
266
267
268
269         //moving in subdir, from where it can be compressed
270         if(rename(src, dst_tocompress) < 0)
271         {
272             DLT_LOG(dltsystem, DLT_LOG_ERROR,
273                     DLT_STRING("Could not move file"),
274                     DLT_STRING(src),
275                     DLT_STRING(dst_tocompress));
276             free(rn);
277             free(dst_tocompress);
278             free(fdir);
279             return -1;
280         }
281         len = strlen(fdir)+strlen(SUBDIR_TOSEND)+strlen(rn)+strlen(COMPRESS_EXTENSION)+3;//the resulting filename in .tosend +2 for 2*"/", +1 for \0
282         dst_tosend = malloc(len);
283         MALLOC_ASSERT(dst_tosend);
284         snprintf(dst_tosend,len,"%s/%s/%s%s",fdir,SUBDIR_TOSEND,rn,COMPRESS_EXTENSION);
285
286
287
288         if (compress_file_to(dst_tocompress,dst_tosend, opts->CompressionLevel[which]) != 0){
289             free(rn);
290             free(dst_tosend);
291             free(dst_tocompress);
292             free(fdir);
293             return -1;
294         }
295         free(dst_tocompress);
296
297     }
298     else{
299         //move it directly into "tosend"
300         DLT_LOG(dltsystem, DLT_LOG_DEBUG,
301                 DLT_STRING("dlt-system-filetransfer, Moving file to tmp directory."));
302         int len = strlen(fdir)+strlen(SUBDIR_TOSEND)+strlen(rn)+3;
303         dst_tosend = malloc(len);//the resulting filename in .tosend +2 for 2*"/", +1 for \0
304
305         snprintf(dst_tosend,len,"%s/%s/%s",fdir,SUBDIR_TOSEND,rn);
306
307         DLT_LOG(dltsystem, DLT_LOG_DEBUG,
308                 DLT_STRING("dlt-system-filetransfer, Rename:"),DLT_STRING(src),DLT_STRING("to: "),DLT_STRING(dst_tosend));
309         //moving in subdir, from where it can be compressed
310         if(rename(src, dst_tosend) < 0)
311         {
312             DLT_LOG(dltsystem, DLT_LOG_ERROR,
313                     DLT_STRING("Could not move file"),
314                     DLT_STRING(src),
315                     DLT_STRING(dst_tosend));
316             free(rn);
317             free(dst_tosend);
318             free(fdir);
319             return -1;
320         }
321
322     }
323
324     DLT_LOG(dltsystem, DLT_LOG_DEBUG,
325             DLT_STRING("dlt-system-filetransfer, File ready to send"));
326
327     send_dumped_file(opts,dst_tosend);
328
329
330     free(rn);
331     free(dst_tosend);
332     free(fdir);
333
334     return 0;
335 }
336
337
338 int flush_dir_send(FiletransferOptions const *opts, const char *compress_dir,  const char *send_dir){
339
340     struct dirent *dp;
341     DIR *dir;
342     dir = opendir(send_dir);
343
344     if(dir != NULL)
345     {
346         while((dp = readdir(dir)) != NULL)
347         {
348             if(dp->d_type != DT_REG)
349                 continue;
350             char *fn;
351             DLT_LOG(dltsystem, DLT_LOG_DEBUG,
352                     DLT_STRING("dlt-system-filetransfer, old compressed file found in send directory:"),DLT_STRING(dp->d_name));
353             int len = strlen(send_dir)+strlen(dp->d_name)+2;
354             fn = malloc(len);
355             MALLOC_ASSERT(fn);
356             snprintf(fn,len, "%s/%s", send_dir, dp->d_name);
357
358
359             //if we have a file here and in the to_compress dir, we delete the to_send file: we can not be sure, that it has been properly compressed!
360             if (!strncmp( dp->d_name+strlen(dp->d_name)-strlen(COMPRESS_EXTENSION),COMPRESS_EXTENSION,strlen(COMPRESS_EXTENSION)))
361             {
362
363                 //ends with ".gz"
364                 //old file name (not: path) would have been:
365                 char tmp[strlen(dp->d_name)-strlen(COMPRESS_EXTENSION)+1];
366                 strncpy(tmp,dp->d_name,strlen(dp->d_name)-strlen(COMPRESS_EXTENSION));
367                 tmp[strlen(dp->d_name)-3]='\0';
368
369                 int len = strlen(tmp)+strlen(compress_dir)+1+1;//2 sizes + 1*"/" + \0
370                 char *path_uncompressed = malloc(len);
371                 MALLOC_ASSERT(path_uncompressed);
372                 snprintf(path_uncompressed,len,"%s/%s",compress_dir,tmp);
373
374                 struct stat sb;
375                 if (stat(path_uncompressed,&sb)==-1)
376                 {
377                     //uncompressed equivalent does not exist. We can send it out.
378                     DLT_LOG(dltsystem, DLT_LOG_DEBUG,
379                             DLT_STRING("dlt-system-filetransfer, sending file."));
380
381                     send_dumped_file(opts,fn);
382                 }
383                 else
384                 {
385                     //There is an uncompressed file. Compression seems to have been interrupted -> delete the compressed file instead of sending it!
386                     DLT_LOG(dltsystem, DLT_LOG_DEBUG,
387                             DLT_STRING("dlt-system-filetransfer, uncompressed version exists. Deleting partially compressed version."));
388                     if (sb.st_mode & S_IFREG)
389                     {
390
391
392                         if( remove(fn ) != 0 )
393                         {
394                             //"Error deleting file". Continue? If we would cancel, maybe the dump is never sent! Deletion would again be tried in next LC.
395                             DLT_LOG(dltsystem, DLT_LOG_ERROR,
396                                     DLT_STRING("Error deleting file:"),DLT_STRING(fn));
397                         }
398                     }
399                     else
400                     {
401                         //"Oldfile is a not reg file. Is this possible? Can we compress a directory?: %s\n",path_uncompressed);
402                         DLT_LOG(dltsystem, DLT_LOG_DEBUG,
403                                 DLT_STRING("dlt-system-filetransfer, Oldfile is a not regular file! Do we have a problem?"),DLT_STRING(fn));
404                     }
405
406                 }
407                 free(path_uncompressed);//it is no more used. It would be transferred in next step.
408             }//it is a .gz file
409             else{
410                 //uncompressed file. We can just resend it, the action to put it here was a move action.
411                 DLT_LOG(dltsystem, DLT_LOG_DEBUG,
412                         DLT_STRING("dlt-system-filetransfer, Sending uncompressed file from previous LC."),DLT_STRING(fn));
413                 send_dumped_file(opts,fn);
414             }
415             free(fn);
416         }
417     }
418     else
419     {
420         DLT_LOG(dltsystem, DLT_LOG_ERROR,
421                 DLT_STRING("Could not open directory"),
422                 DLT_STRING(send_dir));
423         return -1;
424     }
425     closedir(dir);//end: send_dir
426     return 0;
427 }
428
429
430 int flush_dir_compress(FiletransferOptions const *opts, int which, const char *compress_dir, const char *send_dir){
431
432     //check for files in compress_dir. Assumption: a file which lies here, should have been compressed, but that action was interrupted.
433     //As it can arrive here only by a rename, it is most likely to be a complete file
434     struct dirent *dp;
435     DIR *dir;
436     dir = opendir(compress_dir);
437     if(dir != NULL)
438     {
439         while((dp = readdir(dir)) != NULL)
440         {
441             if(dp->d_type != DT_REG)
442                 continue;
443             DLT_LOG(dltsystem, DLT_LOG_DEBUG,
444                     DLT_STRING("dlt-system-filetransfer, old file found in compress-directory."));
445
446
447             //compress file into to_send dir
448             int len = strlen(compress_dir)+strlen(dp->d_name)+2;
449             char *cd_filename = malloc(len);
450             MALLOC_ASSERT(cd_filename);
451             snprintf(cd_filename,len,"%s/%s",compress_dir,dp->d_name);
452
453
454             len = strlen(send_dir)+strlen(dp->d_name)+strlen(COMPRESS_EXTENSION)+2;
455             char *dst_tosend = malloc(len);//the resulting filename in .tosend +2 for 1*"/", +1 for \0 + .gz
456             MALLOC_ASSERT(dst_tosend);
457             snprintf(dst_tosend,len,"%s/%s%s",send_dir,dp->d_name,COMPRESS_EXTENSION);
458
459             if (compress_file_to(cd_filename,dst_tosend, opts->CompressionLevel[which]) != 0){
460                 free(dst_tosend);
461                 free(cd_filename);
462                 closedir(dir);
463                 return -1;
464             }
465
466             //send file
467             send_dumped_file(opts,dst_tosend);
468             free(dst_tosend);
469             free(cd_filename);
470         }
471     }
472     else
473     {
474         DLT_LOG(dltsystem, DLT_LOG_ERROR,
475                 DLT_STRING("Could not open directory"),
476                 DLT_STRING(compress_dir));
477         return -1;
478     }
479     closedir(dir);//end: compress_dir
480
481     return 0;
482 }
483
484 int flush_dir_original(FiletransferOptions const *opts, int which){
485     struct dirent *dp;
486     DIR *dir;
487     const char *sdir = opts->Directory[which];
488     dir = opendir(sdir);
489     if(dir != NULL)
490     {
491         while((dp = readdir(dir)) != NULL)
492         {
493             if(dp->d_type != DT_REG){
494                 //we don't send directories
495                 continue;
496             }
497             DLT_LOG(dltsystem, DLT_LOG_DEBUG,
498                     DLT_STRING("dlt-system-filetransfer, old file found in directory."));
499             int len = strlen(sdir)+strlen(dp->d_name)+2;
500             char *fn = malloc(len);
501             MALLOC_ASSERT(fn);
502             snprintf(fn,len, "%s/%s", sdir, dp->d_name);
503             if(send_one(fn, opts, which) < 0)
504             {
505                 closedir(dir);
506                 free(fn);
507                 return -1;
508             }
509             free(fn);
510         }
511     }
512     else
513     {
514         DLT_LOG(dltsystem, DLT_LOG_ERROR,
515                 DLT_STRING("Could not open directory"),
516                 DLT_STRING(sdir));
517         return -1;
518     }
519     closedir(dir);
520     return 0;
521 }
522
523 //!Cleans the surveyed directories and subdirectories. Sends residing files into trace
524 /**
525  * @param opts FiletransferOptions
526  * @param which which directory is affected -> position in list of opts->Directory
527  * @return Returns 0 if everything was okay. If there was a failure a value < 0 will be returned.
528  */
529 int flush_dir(FiletransferOptions const *opts, int which)
530 {
531
532
533     DLT_LOG(dltsystem, DLT_LOG_DEBUG,
534             DLT_STRING("dlt-system-filetransfer, flush directory of old files."));
535
536     char *compress_dir;
537     char *send_dir;
538     int len = strlen(opts->Directory[which])+strlen(SUBDIR_COMPRESS)+2;
539     compress_dir = malloc (len);
540     MALLOC_ASSERT(compress_dir);
541     snprintf(compress_dir,len,"%s/%s",opts->Directory[which],SUBDIR_COMPRESS);
542
543     len = strlen(opts->Directory[which])+strlen(SUBDIR_TOSEND)+2;
544     send_dir = malloc (len);
545     MALLOC_ASSERT(send_dir);
546     snprintf(send_dir,len,"%s/%s",opts->Directory[which],SUBDIR_TOSEND);
547
548     //1st: scan the tosend directory.
549     if ( 0 != flush_dir_send(opts, compress_dir, send_dir) ){
550         free(send_dir);
551         free(compress_dir);
552         return -1;
553     }
554
555     //1nd: scan the tocompress directory.
556     if (0 != flush_dir_compress(opts, which, compress_dir, send_dir)){
557         free(send_dir);
558         free(compress_dir);
559         return -1;
560     }
561
562     free(send_dir);//no more used
563     free(compress_dir);
564
565     //last step: scan the original directory - we can reuse the send_one function
566     if ( 0 != flush_dir_original(opts,which)){
567         return -1;
568     }
569
570     return 0;
571 }
572
573 //!Initializes the surveyed directories
574 /**On startup, the inotifiy handlers are created, and existing files shall be sent into DLT stream
575  * @param opts FiletransferOptions
576  * @return Returns 0 if everything was okay. If there was a failure a value < 0 will be returned.
577  */
578 int init_filetransfer_dirs(FiletransferOptions const *opts)
579 {
580     DLT_LOG(dltsystem, DLT_LOG_DEBUG,
581             DLT_STRING("dlt-system-filetransfer, initializing inotify on directories."));
582     ino.handle = inotify_init();
583     int i;
584
585     if(ino.handle < 0)
586     {
587         DLT_LOG(filetransferContext, DLT_LOG_FATAL,
588                 DLT_STRING("Failed to initialize inotify in dlt-system file transfer."));
589         return -1;
590     }
591
592     for(i = 0;i < opts->Count;i++)
593     {
594         //create subdirectories for processing the files
595
596         char *subdirpath;
597         int len = strlen(opts->Directory[i])+strlen(SUBDIR_COMPRESS)+2;
598         subdirpath= malloc (len);
599         MALLOC_ASSERT(subdirpath);
600         snprintf(subdirpath,len,"%s/%s",opts->Directory[i],SUBDIR_COMPRESS);
601         int ret = mkdir(subdirpath,0777);
602
603         if (0 != ret && EEXIST != errno){
604             DLT_LOG(dltsystem, DLT_LOG_ERROR,
605                     DLT_STRING("dlt-system-filetransfer, error creating subdirectory: "),DLT_STRING(subdirpath),DLT_STRING(" Errorcode: "),DLT_INT(errno));
606             free (subdirpath);
607             return -1;
608         }
609         free(subdirpath);
610
611         len = strlen(opts->Directory[i])+strlen(SUBDIR_TOSEND)+2;
612         subdirpath= malloc (len);
613         MALLOC_ASSERT(subdirpath);
614         snprintf(subdirpath,len,"%s/%s",opts->Directory[i],SUBDIR_TOSEND);
615         ret = mkdir(subdirpath,0777);
616         if (0 != ret && EEXIST != errno){
617             DLT_LOG(dltsystem, DLT_LOG_ERROR,
618                     DLT_STRING("dlt-system-filetransfer, error creating subdirectory: "),DLT_STRING(subdirpath),DLT_STRING(" Errorcode: "),DLT_INT(errno));
619             free (subdirpath);
620             return -1;
621         }
622         free(subdirpath);
623
624
625         ino.fd[i] = inotify_add_watch(ino.handle, opts->Directory[i],
626                                       IN_CLOSE_WRITE|IN_MOVED_TO);
627         if(ino.fd[i] < 0)
628         {
629             char buf[1024];
630             snprintf(buf, 1024, "Failed to add inotify watch to directory %s in dlt-system file transfer.",
631                      opts->Directory[i]);
632             DLT_LOG(filetransferContext, DLT_LOG_FATAL,
633                     DLT_STRING(buf));
634             return -1;
635         }
636
637
638         flush_dir(opts, i);
639
640     }
641     return 0;
642 }
643
644 int wait_for_files(FiletransferOptions const *opts)
645 {
646     DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, waiting for files."));
647     static char buf[INOTIFY_LEN];
648     ssize_t len = read(ino.handle, buf, INOTIFY_LEN);
649     if(len < 0)
650     {
651         DLT_LOG(filetransferContext, DLT_LOG_ERROR,
652                 DLT_STRING("Error while waiting for files in dlt-system file transfer."));
653         return -1;
654     }
655
656     unsigned int i = 0;
657     while(i < (len-INOTIFY_SZ))
658     {
659         struct inotify_event *ie = (struct inotify_event *)&buf[i];
660         if(ie->len > 0)
661         {
662             if((ie->mask & IN_CLOSE_WRITE) || (ie->mask & IN_MOVED_TO))
663             {
664                 int j;
665                 for(j = 0;j < opts->Count;j++)
666                 {
667                     if(ie->wd == ino.fd[j])
668                     {
669                         DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, found new file."));
670                         int length = strlen(opts->Directory[j])+ie->len+1;
671                         char *tosend = malloc(length);
672                         snprintf(tosend,length, "%s/%s", opts->Directory[j], ie->name);
673                         send_one(tosend, opts, j);
674                         free(tosend);
675                     }
676                 }
677             }
678         }
679         i += INOTIFY_SZ + ie->len;
680     }
681     return 0;
682 }
683
684 void filetransfer_thread(void *v_conf)
685 {
686     DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, in thread."));
687     DltSystemConfiguration *conf = (DltSystemConfiguration *) v_conf;
688     DLT_REGISTER_CONTEXT(filetransferContext, conf->Filetransfer.ContextId,
689                          "File transfer manager.");
690
691     sleep(conf->Filetransfer.TimeStartup);
692
693     if(init_filetransfer_dirs(&(conf->Filetransfer)) < 0)
694         return;
695
696     while(!threads.shutdown)
697     {
698         if(wait_for_files(&(conf->Filetransfer)) < 0)
699         {
700             DLT_LOG(dltsystem, DLT_LOG_ERROR, DLT_STRING("Error while waiting files. File transfer shutdown."));
701             return;
702         }
703         sleep(conf->Filetransfer.TimeDelay);
704     }
705 }
706
707 void start_filetransfer(DltSystemConfiguration *conf)
708 {
709     DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, start."));
710     static pthread_attr_t t_attr;
711     static pthread_t pt;
712     pthread_create(&pt, &t_attr, (void *)filetransfer_thread, conf);
713     threads.threads[threads.count++] = pt;
714 }