backport r882:893 to openjpeg-1.5 branch
[openjpeg.git] / applications / jpip / libopenjpip / target_manager.c
1 /*
2  * $Id: target_manager.c 44 2011-02-15 12:32:29Z kaori $
3  *
4  * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
5  * Copyright (c) 2002-2011, Professor Benoit Macq
6  * Copyright (c) 2010-2011, Kaori Hagihara
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <time.h>
39 #include "target_manager.h"
40
41 #ifdef SERVER
42 #include "fcgi_stdio.h"
43 #define logstream FCGI_stdout
44 #else
45 #define FCGI_stdout stdout
46 #define FCGI_stderr stderr
47 #define logstream stderr
48 #endif //SERVER
49
50
51 targetlist_param_t * gene_targetlist()
52 {
53   targetlist_param_t *targetlist;
54
55   targetlist = (targetlist_param_t *)malloc( sizeof(targetlist_param_t));
56   
57   targetlist->first = NULL;
58   targetlist->last  = NULL;
59
60   return targetlist;
61 }
62
63
64 /**
65  * open jp2 format image file
66  *
67  * @param[in] filename file name (.jp2)
68  * @return             file descriptor
69  */
70 int open_jp2file( char filename[]);
71
72 target_param_t * gene_target( targetlist_param_t *targetlist, char *targetname)
73 {
74   target_param_t *target;
75   int fd;
76   index_param_t *jp2idx;
77   static int last_csn = 0;
78
79   if( targetname[0]=='\0'){
80     fprintf( FCGI_stderr, "Error: exception, no targetname in gene_target()\n");
81     return NULL;
82   }
83
84   if((fd = open_jp2file( targetname)) == -1){
85     fprintf( FCGI_stdout, "Status: 404\r\n"); 
86     return NULL;
87   }
88   
89   if( !(jp2idx = parse_jp2file( fd))){
90     fprintf( FCGI_stdout, "Status: 501\r\n");
91     return NULL;
92   }
93
94   target = (target_param_t *)malloc( sizeof(target_param_t));
95   snprintf( target->tid, MAX_LENOFTID, "%x-%x", (unsigned int)time(NULL), (unsigned int)rand());
96   strcpy( target->filename, targetname); 
97   target->fd = fd;
98   target->csn = last_csn++;
99   target->codeidx = jp2idx;
100   target->num_of_use = 0;
101   
102   target->next=NULL;
103
104   if( targetlist->first) // there are one or more entries
105     targetlist->last->next = target;
106   else                   // first entry
107     targetlist->first = target;
108   targetlist->last = target;
109
110 #ifndef SERVER
111   fprintf( logstream, "local log: target %s generated\n", targetname);
112 #endif
113   
114   return target;
115 }
116
117 void refer_target( target_param_t *reftarget, target_param_t **ptr)
118 {
119   *ptr = reftarget;
120   reftarget->num_of_use++;
121 }
122
123 void unrefer_target( target_param_t *target)
124 {
125   target->num_of_use--;
126 }
127
128 void delete_target( target_param_t **target)
129 {
130   close( (*target)->fd);
131   delete_index ( &(*target)->codeidx);
132
133 #ifndef SERVER
134   fprintf( logstream, "local log: target: %s deleted\n", (*target)->filename);
135 #endif
136   free(*target);
137 }
138
139 void delete_target_in_list( target_param_t **target, targetlist_param_t *targetlist)
140 {
141   target_param_t *ptr;
142
143   if( *target == targetlist->first)
144     targetlist->first = (*target)->next;
145   else{
146     ptr = targetlist->first;
147     while( ptr->next != *target){
148       ptr=ptr->next;
149     }
150     
151     ptr->next = (*target)->next;
152     
153     if( *target == targetlist->last)
154       targetlist->last = ptr;
155   }
156   delete_target( target);
157 }
158
159 void delete_targetlist(targetlist_param_t **targetlist)
160 {
161   target_param_t *targetPtr, *targetNext;
162   
163   targetPtr = (*targetlist)->first;
164   while( targetPtr != NULL){
165     targetNext=targetPtr->next;
166     delete_target( &targetPtr);
167     targetPtr=targetNext;
168   }
169   free( *targetlist);
170 }
171
172 void print_target( target_param_t *target)
173 {
174   fprintf( logstream, "target:\n");
175   fprintf( logstream, "\t tid=%s\n", target->tid);
176   fprintf( logstream, "\t csn=%d\n", target->csn);
177   fprintf( logstream, "\t target=%s\n\n", target->filename);
178 }
179
180 void print_alltarget( targetlist_param_t *targetlist)
181 {
182   target_param_t *ptr;
183
184   ptr = targetlist->first;
185   while( ptr != NULL){
186     print_target( ptr);
187     ptr=ptr->next;
188   }
189 }
190
191 target_param_t * search_target( char targetname[], targetlist_param_t *targetlist)
192 {
193   target_param_t *foundtarget;
194
195   foundtarget = targetlist->first;
196   
197   while( foundtarget != NULL){
198     
199     if( strcmp( targetname, foundtarget->filename) == 0)
200       return foundtarget;
201       
202     foundtarget = foundtarget->next;
203   }
204   return NULL;
205 }
206
207 target_param_t * search_targetBytid( char tid[], targetlist_param_t *targetlist)
208 {
209   target_param_t *foundtarget;
210   
211   foundtarget = targetlist->first;
212   
213   while( foundtarget != NULL){
214     
215     if( strcmp( tid, foundtarget->tid) == 0)
216       return foundtarget;
217       
218     foundtarget = foundtarget->next;
219   }
220
221   return NULL;
222 }
223
224 int open_jp2file( char filename[])
225 {
226   int fd;
227   char *data;
228
229   if( (fd = open( filename, O_RDONLY)) == -1){
230     fprintf( FCGI_stdout, "Reason: Target %s not found\r\n", filename);
231     return -1;
232   }
233   // Check resource is a JP family file.
234   if( lseek( fd, 0, SEEK_SET)==-1){
235     close(fd);
236     fprintf( FCGI_stdout, "Reason: Target %s broken (lseek error)\r\n", filename);
237     return -1;
238   }
239   
240   data = (char *)malloc( 12); // size of header
241   if( read( fd, data, 12) != 12){
242     free( data);
243     close(fd);
244     fprintf( FCGI_stdout, "Reason: Target %s broken (read error)\r\n", filename);
245     return -1;
246   }
247     
248   if( *data || *(data + 1) || *(data + 2) ||
249       *(data + 3) != 12 || strncmp (data + 4, "jP  \r\n\x87\n", 8)){
250     free( data);
251     close(fd);
252     fprintf( FCGI_stdout, "Reason: No JPEG 2000 Signature box in target %s\r\n", filename);
253     return -1;
254   } 
255   free( data);
256   return fd;
257 }