1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/wait.h>
5 #include <string.h>
6
7 #include "autoOpen.h"
8
9 // Implementation of "popen" that ignores stderr
popenNoStderr(const char * exe,const char * const argv[],int * retPid)10 static FILE* popenNoStderr(const char *exe, const char *const argv[], int* retPid)
11 {
12 int out[2];
13 int pid;
14 int rc;
15
16 rc = pipe(out);
17 if (rc<0)
18 goto error_out;
19
20 pid = fork();
21 if (pid > 0) { // parent
22 close(out[1]);
23 *retPid = pid;
24 return fdopen(out[0], "r");
25 } else if (pid == 0) { // child
26 close(out[0]);
27 close(1);
28 dup(out[1]);
29
30 close(0); // Don't let child inherit stdin, nor stderr
31 close(2);
32
33 execvp(exe, (char**)argv);
34 exit(1);
35 } else
36 goto error_fork;
37
38 return NULL;
39
40 error_fork:
41 close(out[0]);
42 close(out[1]);
43 error_out:
44 return NULL;
45 }
46
pcloseNoStderr(int pid,FILE * out)47 static int pcloseNoStderr(int pid, FILE* out)
48 {
49 int rc, status;
50 fclose(out);
51 rc = waitpid(pid, &status, 0);
52 return status;
53 }
54
55
56 static const char const* decompressors[] = {"","pigz", "gunzip", "pbunzip2", "bunzip2", NULL};
57
openFileAuto(char * filename)58 AutoFile* openFileAuto(char*filename)
59 {
60 AutoFile* seqFile = calloc(1, sizeof(AutoFile));
61 int i;
62
63 if (strcmp(filename, "-")==0)
64 exitErrorf(EXIT_FAILURE, false, "Cannot read from stdin in auto mode\n");
65
66 for (i=0; decompressors[i] ; i++) {
67 if (strlen(decompressors[i])==0) {
68 seqFile->file = fopen(filename, "r");
69 seqFile->pid = 0;
70 seqFile->decompressor = "Raw read";
71 } else {
72 //printf("Trying : %s\n", decompressors[i]);
73 char const* args[] = {decompressors[i], "-c", "-d", filename, NULL};
74 seqFile->file = popenNoStderr(args[0], args, &(seqFile->pid));
75 seqFile->decompressor = decompressors[i];
76 }
77
78 if (!seqFile->file)
79 continue;
80
81 int c = fgetc(seqFile->file);
82 if (c=='>' || c=='@') {
83 // Ok, looks like FASTA or FASTQ
84 ungetc(c, seqFile->file);
85 seqFile->first_char = c;
86 return seqFile;
87 } else {
88 if (seqFile->pid)
89 pcloseNoStderr(seqFile->pid, seqFile->file);
90 else
91 fclose(seqFile->file);
92 }
93 }
94 //printf("Unable to determine file type\n");
95 return NULL;
96 }
97
closeFileAuto(AutoFile * seqFile)98 void closeFileAuto(AutoFile* seqFile)
99 {
100 if (!seqFile)
101 return;
102
103 if (seqFile->pid)
104 pcloseNoStderr(seqFile->pid, seqFile->file);
105 else
106 fclose(seqFile->file);
107 }
108