libgphoto2 photo camera library (libgphoto2) Internals  2.5.23
gphoto2-file.c
Go to the documentation of this file.
1 
27 #define _POSIX_SOURCE
28 #define _DEFAULT_SOURCE
29 
30 #include "config.h"
31 #include <gphoto2/gphoto2-file.h>
32 
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <errno.h>
36 #include <string.h>
37 #include <sys/stat.h>
38 #include <utime.h>
39 
42 
43 #include <gphoto2/gphoto2-result.h>
44 
45 #define CHECK_RESULT(result) {int r = (result); if (r < 0) return (r);}
46 
47 /* lengt of one path component */
48 #ifndef MAX_PATH
49 # define MAX_PATH 256
50 #endif
51 
55 struct _CameraFile {
56  char mime_type [64];
57  char name [MAX_PATH];
58  int ref_count;
59  time_t mtime;
60 
62 
63  /* for GP_FILE_ACCESSTYPE_MEMORY files */
64  unsigned long size;
65  unsigned char *data;
66  unsigned long offset; /* read pointer */
67 
68  /* for GP_FILE_ACCESSTYPE_FD files */
69  int fd;
70 
71  /* for GP_FILE_ACCESSTYPE_HANDLER files */
73  void *private;
74 };
75 
76 
82 int
84 {
85  C_PARAMS (file);
86 
87  C_MEM (*file = calloc (1, sizeof (CameraFile)));
88 
89  strcpy ((*file)->mime_type, "unknown/unknown");
90  (*file)->ref_count = 1;
91  (*file)->accesstype = GP_FILE_ACCESSTYPE_MEMORY;
92  return (GP_OK);
93 }
94 
95 
104 int
106 {
107  C_PARAMS (file);
108 
109  C_MEM (*file = calloc (1, sizeof (CameraFile)));
110 
111  strcpy ((*file)->mime_type, "unknown/unknown");
112  (*file)->ref_count = 1;
113  (*file)->accesstype = GP_FILE_ACCESSTYPE_FD;
114  (*file)->fd = fd;
115  return (GP_OK);
116 }
117 
125 int
126 gp_file_new_from_handler (CameraFile **file, CameraFileHandler* handler, void*private)
127 {
128  C_PARAMS (file);
129 
130  C_MEM (*file = calloc (1, sizeof (CameraFile)));
131 
132  strcpy ((*file)->mime_type, "unknown/unknown");
133  (*file)->ref_count = 1;
134  (*file)->accesstype = GP_FILE_ACCESSTYPE_HANDLER;
135  (*file)->handler = handler;
136  (*file)->private = private;
137  return (GP_OK);
138 }
139 
140 
141 
148 {
149  C_PARAMS (file);
150 
151  CHECK_RESULT (gp_file_clean (file));
152 
153  if (file->accesstype == GP_FILE_ACCESSTYPE_FD)
154  close (file->fd);
155 
156  free (file);
157  return (GP_OK);
158 }
159 
160 
166 int
168 {
169  C_PARAMS (file);
170 
171  file->ref_count += 1;
172 
173  return (GP_OK);
174 }
175 
176 
183 int
185 {
186  C_PARAMS (file);
187 
188  file->ref_count -= 1;
189 
190  if (file->ref_count == 0)
191  CHECK_RESULT (gp_file_free (file));
192 
193  return (GP_OK);
194 }
195 
196 
204 int
205 gp_file_append (CameraFile *file, const char *data,
206  unsigned long int size)
207 {
208  C_PARAMS (file);
209 
210  switch (file->accesstype) {
212  C_MEM (file->data = realloc (file->data, sizeof (char) * (file->size + size)));
213  memcpy (&file->data[file->size], data, size);
214  file->size += size;
215  break;
216  case GP_FILE_ACCESSTYPE_FD: {
217  unsigned long int curwritten = 0;
218  while (curwritten < size) {
219  ssize_t res = write (file->fd, data+curwritten, size-curwritten);
220  if (res == -1) {
221  GP_LOG_E ("Encountered error %d writing to fd.", errno);
222  return GP_ERROR_IO_WRITE;
223  }
224  if (!res) { /* no progress is bad too */
225  GP_LOG_E ("Encountered 0 bytes written to fd.");
226  return GP_ERROR_IO_WRITE;
227  }
228  curwritten += res;
229  }
230  break;
231  }
233  uint64_t xsize = size;
234  /* FIXME: assume we write one blob */
235  C_PARAMS (file->handler->write);
236  return file->handler->write (file->private, (unsigned char*)data, &xsize);
237  }
238  default:
239  GP_LOG_E ("Unknown file access type %d", file->accesstype);
240  return GP_ERROR;
241  }
242  return (GP_OK);
243 }
244 
253 int
254 gp_file_slurp (CameraFile *file, char *data,
255  size_t size, size_t *readlen
256 ) {
257  C_PARAMS (file);
258 
259  switch (file->accesstype) {
261  if (size > file->size-file->offset)
262  size = file->size - file->offset;
263  memcpy (data, &file->data[file->offset], size);
264  file->offset += size;
265  if (readlen) *readlen = size;
266  break;
267  case GP_FILE_ACCESSTYPE_FD: {
268  unsigned long int curread = 0;
269  while (curread < size) {
270  ssize_t res = read (file->fd, data+curread, size-curread);
271  if (res == -1) {
272  GP_LOG_E ("Encountered error %d reading from fd.", errno);
273  return GP_ERROR_IO_READ;
274  }
275  if (!res) { /* no progress is bad too */
276  GP_LOG_E ("Encountered 0 bytes reading from fd.");
277  return GP_ERROR_IO_READ;
278  }
279  curread += res;
280  if (readlen)
281  *readlen = curread;
282  }
283  break;
284  }
286  uint64_t xsize = size;
287  int ret;
288 
289  C_PARAMS (file->handler->read);
290  ret = file->handler->read (file->private, (unsigned char*)data, &xsize);
291  *readlen = xsize;
292  if (ret != GP_OK)
293  GP_LOG_E ("File handler read returned %d", ret);
294  return ret;
295  }
296  default:
297  GP_LOG_E ("Unknown file access type %d", file->accesstype);
298  return GP_ERROR;
299  }
300  return (GP_OK);
301 }
302 
303 
304 
312 int
314  unsigned long int size)
315 {
316  C_PARAMS (file);
317 
318  switch (file->accesstype) {
320  free (file->data);
321  file->data = (unsigned char*)data;
322  file->size = size;
323  break;
324  case GP_FILE_ACCESSTYPE_FD: {
325  unsigned int curwritten = 0;
326 
327  /* truncate */
328  if (-1 == lseek (file->fd, 0, SEEK_SET)) {
329  GP_LOG_E ("Encountered error %d lseeking to 0.", errno);
330  /* might happen on pipes ... just ignore it */
331  }
332  if (-1 == ftruncate (file->fd, 0)) {
333  GP_LOG_E ("Encountered error %d ftruncating to 0.", errno);
334  /* might happen on pipes ... just ignore it */
335  }
336  while (curwritten < size) {
337  ssize_t res = write (file->fd, data+curwritten, size-curwritten);
338  if (res == -1) {
339  GP_LOG_E ("Encountered error %d writing to fd.", errno);
340  return GP_ERROR_IO_WRITE;
341  }
342  if (!res) { /* no progress is bad too */
343  GP_LOG_E ("Encountered 0 bytes written to fd.");
344  return GP_ERROR_IO_WRITE;
345  }
346  curwritten += res;
347  }
348  /* This function takes over the responsibility for "data", aka
349  * it has to free it. So we do.
350  */
351  free (data);
352  break;
353  }
355  uint64_t xsize = size;
356  int ret;
357 
358  C_PARAMS (file->handler->write);
359  /* FIXME: handle multiple blob writes */
360  ret = file->handler->write (file->private, (unsigned char*)data, &xsize);
361  if (ret != GP_OK) {
362  GP_LOG_E ("Handler data() returned %d", ret);
363  return ret;
364  }
365  /* This function takes over the responsibility for "data", aka
366  * it has to free it. So we do.
367  */
368  free (data);
369  return GP_OK;
370  }
371  default:
372  GP_LOG_E ("Unknown file access type %d", file->accesstype);
373  return GP_ERROR;
374  }
375  return (GP_OK);
376 }
377 
378 
397 int
398 gp_file_get_data_and_size (CameraFile *file, const char **data,
399  unsigned long int *size)
400 {
401  C_PARAMS (file);
402 
403  switch (file->accesstype) {
405  if (data)
406  *data = (char*)file->data;
407  if (size)
408  *size = file->size;
409  break;
410  case GP_FILE_ACCESSTYPE_FD: {
411  off_t offset;
412  unsigned long int curread = 0;
413 
414  if (-1 == lseek (file->fd, 0, SEEK_END)) {
415  if (errno == EBADF) return GP_ERROR_IO;
416  /* Might happen for pipes or sockets. Umm. Hard. */
417  /* FIXME */
418  }
419  if (-1 == (offset = lseek (file->fd, 0, SEEK_CUR))) {
420  /* should not happen if we passed the above case */
421  GP_LOG_E ("Encountered error %d lseekin to CUR.", errno);
422  return GP_ERROR_IO_READ;
423  }
424  if (-1 == lseek (file->fd, 0, SEEK_SET)) {
425  /* should not happen if we passed the above cases */
426  GP_LOG_E ("Encountered error %d lseekin to CUR.", errno);
427  return GP_ERROR_IO_READ;
428  }
429  if (size) *size = offset;
430  if (!data) /* just the size... */
431  return GP_OK;
432  C_MEM (*data = malloc (offset));
433  while (curread < offset) {
434  ssize_t res = read (file->fd, (char*)((*data)+curread), offset-curread);
435  if (res == -1) {
436  free ((char*)*data);
437  GP_LOG_E ("Encountered error %d reading.", errno);
438  return GP_ERROR_IO_READ;
439  }
440  if (res == 0) {
441  free ((char*)*data);
442  GP_LOG_E ("No progress during reading.");
443  return GP_ERROR_IO_READ;
444  }
445  curread += res;
446  }
447  break;
448  }
450  uint64_t xsize = 0;
451  int ret;
452 
453  C_PARAMS (file->handler->read);
454  ret = file->handler->size (file->private, &xsize);
455  if (ret != GP_OK) {
456  GP_LOG_E ("Encountered error %d querying size().", ret);
457  return ret;
458  }
459  if (size) *size = xsize;
460  if (!data) /* just the size... */
461  return GP_OK;
462  C_MEM (*data = malloc (xsize));
463  ret = file->handler->read (file->private, (unsigned char*)*data, &xsize);
464  if (ret != GP_OK) {
465  GP_LOG_E ("Encountered error %d getting data().", ret);
466  free ((char*)*data);
467  *data = NULL;
468  }
469  return ret;
470  }
471  default:
472  GP_LOG_E ("Unknown file access type %d", file->accesstype);
473  return GP_ERROR;
474  }
475  return (GP_OK);
476 }
477 
478 
485 int
486 gp_file_save (CameraFile *file, const char *filename)
487 {
488  FILE *fp;
489  struct utimbuf u;
490 
491  C_PARAMS (file && filename);
492 
493  switch (file->accesstype) {
495  if (!(fp = fopen (filename, "wb")))
496  return GP_ERROR;
497  if (fwrite (file->data, (size_t)sizeof(char), (size_t)file->size, fp) != (size_t)file->size) {
498  GP_LOG_E ("Not enough space on device in order to save '%s'.", filename);
499  fclose (fp);
500  unlink (filename);
501  return GP_ERROR;
502  }
503  fclose (fp);
504  break;
505  case GP_FILE_ACCESSTYPE_FD: {
506  char *data;
507  unsigned long int curread = 0;
508  off_t offset;
509 
510  if (-1 == lseek (file->fd, 0, SEEK_END))
511  return GP_ERROR_IO;
512  if (-1 == (offset = lseek (file->fd, 0, SEEK_CUR))) {
513  /* should not happen if we passed the above case */
514  GP_LOG_E ("Encountered error %d lseekin to CUR.", errno);
515  return GP_ERROR_IO_READ;
516  }
517  if (-1 == lseek (file->fd, 0, SEEK_SET)) {
518  /* should not happen if we passed the above case */
519  GP_LOG_E ("Encountered error %d lseekin to BEGIN.", errno);
520  return GP_ERROR_IO_READ;
521  }
522  C_MEM (data = malloc(65536));
523  if (!(fp = fopen (filename, "wb"))) {
524  free (data);
525  return GP_ERROR;
526  }
527  while (curread < offset) {
528  int toread, res;
529 
530  toread = 65536;
531  if (toread > (offset-curread))
532  toread = offset-curread;
533  res = read (file->fd, data, toread);
534  if (res <= 0) {
535  free (data);
536  fclose (fp);
537  unlink (filename);
538  return GP_ERROR_IO_READ;
539  }
540  if (fwrite (data, 1, res, fp) != res) {
541  GP_LOG_E ("Not enough space on device in order to save '%s'.", filename);
542  free (data);
543  fclose (fp);
544  unlink (filename);
545  return GP_ERROR;
546  }
547  curread += res;
548  }
549  free (data);
550  fclose (fp);
551  break;
552  }
553  default:
554  GP_LOG_E ("Unknown file access type %d", file->accesstype);
555  return GP_ERROR;
556  }
557 
558  if (file->mtime) {
559  u.actime = file->mtime;
560  u.modtime = file->mtime;
561  utime (filename, &u);
562  }
563 
564  return (GP_OK);
565 }
566 
567 
568 /*
569  * mime types that cannot be determined by the filename
570  * extension. Better hack would be to use library that examine
571  * file content instead, like gnome-vfs mime handling, or
572  * gnome-mime, whatever.
573  * See also the GP_MIME_* definitions.
574  */
575 static const char *mime_table[] = {
576  "bmp", GP_MIME_BMP,
577  "jpg", GP_MIME_JPEG,
578  "tif", GP_MIME_TIFF,
579  "ppm", GP_MIME_PPM,
580  "pgm", GP_MIME_PGM,
581  "pnm", GP_MIME_PNM,
582  "png", GP_MIME_PNG,
583  "wav", GP_MIME_WAV,
584  "avi", GP_MIME_AVI,
585  "mp3", GP_MIME_MP3,
586  "wma", GP_MIME_WMA,
587  "asf", GP_MIME_ASF,
588  "ogg", GP_MIME_OGG,
589  "mpg", GP_MIME_MPEG,
590  "raw", GP_MIME_RAW,
591  "mts", GP_MIME_AVCHD,
592  "m2ts", GP_MIME_AVCHD,
593  "arw", GP_MIME_ARW,
594  "txt", GP_MIME_TXT,
595  NULL};
602 int
603 gp_file_open (CameraFile *file, const char *filename)
604 {
605  FILE *fp;
606  char *name, *dot;
607  long size, size_read;
608  int i;
609  struct stat s;
610 
611 
612  C_PARAMS (file && filename);
613 
614  CHECK_RESULT (gp_file_clean (file));
615 
616  fp = fopen(filename, "r");
617  if (!fp)
618  return (GP_ERROR);
619  fseek (fp, 0, SEEK_END);
620  size = ftell (fp);
621  rewind (fp);
622 
623  switch (file->accesstype) {
625  file->data = malloc (sizeof(char)*(size + 1));
626  if (!file->data) {
627  fclose (fp);
628  return (GP_ERROR_NO_MEMORY);
629  }
630  size_read = fread (file->data, (size_t)sizeof(char), (size_t)size, fp);
631  if (ferror(fp)) {
632  gp_file_clean (file);
633  fclose (fp);
634  return (GP_ERROR);
635  }
636  fclose(fp);
637  file->size = size_read;
638  file->data[size_read] = 0;
639  break;
640  case GP_FILE_ACCESSTYPE_FD: {
641  if (file->fd == -1) {
642  file->fd = dup(fileno(fp));
643  fclose (fp);
644  break;
645  }
646  GP_LOG_E ("Needs to be initialized with fd=-1 to work");
647  fclose (fp);
648  return GP_ERROR;
649  }
650  default:
651  break;
652  }
653 
654  name = strrchr (filename, '/');
655  if (name)
656  strncpy (file->name, name + 1, sizeof (file->name));
657  else
658  strncpy (file->name, filename, sizeof (file->name));
659 
660  /* MIME lookup */
661  dot = strrchr (filename, '.');
662  if (dot) {
663  for (i = 0; mime_table[i] ; i+=2)
664  if (!strcasecmp (mime_table[i], dot+1)) {
665  strncpy (file->mime_type, mime_table[i+1], sizeof(file->mime_type));
666  break;
667  }
668  if (!mime_table[i])
669  /*
670  * We did not found the type in the lookup table,
671  * so we use the file suffix as mime type.
672  * Note: This should probably use GP_MIME_UNKNOWN instead
673  * of returning a non-standard type.
674  */
675  sprintf(file->mime_type, "image/%s", dot + 1);
676  } else
677  /*
678  * Damn, no filename suffix...
679  */
680  strncpy (file->mime_type, GP_MIME_UNKNOWN,
681  sizeof (file->mime_type));
682 
683  if (stat (filename, &s) != -1) {
684  file->mtime = s.st_mtime;
685  } else {
686  file->mtime = time (NULL);
687  }
688 
689  return (GP_OK);
690 }
691 
692 
698 int
700 {
701  /*
702  * Frees a CameraFile's components, not the CameraFile itself.
703  * This is used to prep a CameraFile struct to be filled.
704  */
705 
706  C_PARAMS (file);
707 
708  switch (file->accesstype) {
710  free (file->data);
711  file->data = NULL;
712  file->size = 0;
713  break;
715  break;
716  default:break;
717  }
718  strcpy (file->name, "");
719  return (GP_OK);
720 }
721 
728 int
729 gp_file_copy (CameraFile *destination, CameraFile *source)
730 {
731  C_PARAMS (destination && source);
732 
733  GP_LOG_D ("Copying '%s' onto '%s'...", source->name, destination->name);
734 
735  /* struct members we can just copy. All generic ones, but not refcount. */
736  memcpy (destination->name, source->name, sizeof (source->name));
737  memcpy (destination->mime_type, source->mime_type, sizeof (source->mime_type));
738  destination->mtime = source->mtime;
739 
740  if ((destination->accesstype == GP_FILE_ACCESSTYPE_MEMORY) &&
741  (source->accesstype == GP_FILE_ACCESSTYPE_MEMORY)) {
742  free (destination->data);
743  destination->data = NULL;
744  destination->size = source->size;
745  C_MEM (destination->data = malloc (sizeof (char) * source->size));
746  memcpy (destination->data, source->data, source->size);
747  return (GP_OK);
748  }
749  if ( (destination->accesstype == GP_FILE_ACCESSTYPE_MEMORY) &&
750  (source->accesstype == GP_FILE_ACCESSTYPE_FD)
751  ) {
752  off_t offset;
753  unsigned long int curread = 0;
754 
755  free (destination->data);
756  destination->data = NULL;
757 
758  if (-1 == lseek (source->fd, 0, SEEK_END)) {
759  if (errno == EBADF) return GP_ERROR_IO;
760  /* Might happen for pipes or sockets. Umm. Hard. */
761  /* FIXME */
762  }
763  if (-1 == (offset = lseek (source->fd, 0, SEEK_CUR))) {
764  /* should not happen if we passed the above case */
765  GP_LOG_E ("Encountered error %d lseekin to CUR.", errno);
766  return GP_ERROR_IO_READ;
767  }
768  if (-1 == lseek (source->fd, 0, SEEK_SET)) {
769  /* should not happen if we passed the above cases */
770  GP_LOG_E ("Encountered error %d lseekin to CUR.", errno);
771  return GP_ERROR_IO_READ;
772  }
773  destination->size = offset;
774  C_MEM (destination->data = malloc (offset));
775  while (curread < offset) {
776  ssize_t res = read (source->fd, destination->data+curread, offset-curread);
777  if (res == -1) {
778  free (destination->data);
779  GP_LOG_E ("Encountered error %d reading.", errno);
780  return GP_ERROR_IO_READ;
781  }
782  if (res == 0) {
783  free (destination->data);
784  GP_LOG_E ("No progress during reading.");
785  return GP_ERROR_IO_READ;
786  }
787  curread += res;
788  }
789  return GP_OK;
790  }
791  if ( (destination->accesstype == GP_FILE_ACCESSTYPE_FD) &&
792  (source->accesstype == GP_FILE_ACCESSTYPE_FD)
793  ) {
794  char *data;
795 
796  lseek (destination->fd, 0, SEEK_SET);
797  if (-1 == ftruncate (destination->fd, 0))
798  perror("ftruncate");
799  lseek (source->fd, 0, SEEK_SET);
800  C_MEM (data = malloc (65536));
801  while (1) {
802  unsigned long curwritten = 0;
803  ssize_t res;
804 
805  res = read (source->fd, data, 65536);
806  if (res == -1) {
807  free (data);
808  return GP_ERROR_IO_READ;
809  }
810  if (res == 0)
811  break;
812  while (curwritten < res) {
813  ssize_t res2 = write (destination->fd, data+curwritten, res-curwritten);
814  if (res2 == -1) {
815  free (data);
816  return GP_ERROR_IO_WRITE;
817  }
818  if (res2 == 0)
819  break;
820  curwritten += res2;
821  }
822  if (res < 65536) /* end of file */
823  break;
824  }
825  free (data);
826  return GP_OK;
827  }
828  if ( (destination->accesstype == GP_FILE_ACCESSTYPE_FD) &&
829  (source->accesstype == GP_FILE_ACCESSTYPE_MEMORY)
830  ) {
831  unsigned long curwritten = 0;
832  while (curwritten < source->size) {
833  int res = write (destination->fd, source->data+curwritten, source->size-curwritten);
834 
835  if (res == -1)
836  return GP_ERROR_IO_WRITE;
837  if (!res) /* no progress? */
838  return GP_ERROR_IO_WRITE;
839  curwritten += res;
840  }
841  return GP_OK;
842  }
843  if ( (destination->accesstype == GP_FILE_ACCESSTYPE_HANDLER) &&
844  (source->accesstype == GP_FILE_ACCESSTYPE_MEMORY)
845  ) {
846  uint64_t xsize = source->size;
847  unsigned long curwritten = 0;
848 
849  destination->handler->size (destination->private, &xsize);
850  while (curwritten < source->size) {
851  uint64_t tmpsize = source->size - curwritten;
852  int res = destination->handler->write (destination->private, source->data+curwritten, &tmpsize);
853 
854  if (res < GP_OK)
855  return res;
856  if (!tmpsize) /* no progress? */
857  return GP_ERROR_IO_WRITE;
858  curwritten += tmpsize;
859  }
860  return GP_OK;
861  }
862  GP_LOG_E ("Unhandled cases in gp_copy_file. Bad!");
863  return GP_ERROR;
864 }
865 
872 int
873 gp_file_get_name (CameraFile *file, const char **name)
874 {
875  C_PARAMS (file && name);
876 
877  *name = file->name;
878 
879  return (GP_OK);
880 }
881 
898 int
899 gp_file_get_name_by_type (CameraFile *file, const char *basename, CameraFileType type, char **newname)
900 {
901  char *prefix = NULL, *s, *new, *slash = NULL;
902  const char *suffix = NULL;
903  int i;
904 
905  C_PARAMS (file && basename && newname);
906  *newname = NULL;
907 
908  /* the easy case, always map 1:1, if it has a suffix already. */
909  if ((type == GP_FILE_TYPE_NORMAL) && strchr(basename,'.')) {
910  C_MEM (*newname = strdup (basename));
911  return GP_OK;
912  }
913 
914  for (i=0;mime_table[i];i+=2) {
915  if (!strcmp (mime_table[i+1],file->mime_type)) {
916  suffix = mime_table[i];
917  break;
918  }
919  }
920  s = strrchr(basename,'.');
921  slash = strrchr(basename,'/');
922  if (slash > s) /* --filename foo.bar/foo */
923  s = NULL;
924  switch (type) {
925  case GP_FILE_TYPE_RAW: prefix = "raw_";break;
926  case GP_FILE_TYPE_EXIF: prefix = "exif_";break;
927  case GP_FILE_TYPE_PREVIEW: prefix = "thumb_";break;
928  case GP_FILE_TYPE_METADATA: prefix = "meta_";break;
929  case GP_FILE_TYPE_AUDIO: prefix = "audio_";break;
930  default: prefix = ""; break;
931  }
932  if (s) {
933  int xlen;
934 
935  if (!suffix)
936  suffix = s+1;
937 
938  C_MEM (new = calloc (strlen(prefix) + (s-basename+1) + strlen (suffix) + 1, 1));
939 
940  xlen = strlen (prefix);
941  if (slash) {
942  memcpy (new, basename, slash-basename+1);
943  strcat (new, prefix);
944  memcpy (new + strlen (new), slash+1, s-slash+1);
945  } else {
946  strcpy (new, prefix);
947  memcpy (new + strlen (new), basename, s-basename+1);
948  }
949  new[xlen+(s-basename)+1]='\0';
950  strcat (new, suffix);
951  } else { /* no dot in basename? */
952  if (!suffix) suffix = "";
953  C_MEM (new = calloc (strlen(prefix) + strlen(basename) + 1 + strlen (suffix) + 1, 1));
954  if (slash) {
955  memcpy (new, basename, slash-basename+1); /* with / */
956  strcat (new, prefix);
957  strcat (new, slash+1);
958  } else {
959  strcpy (new, prefix);
960  strcat (new, basename);
961  }
962  if (strlen(suffix)) {
963  strcat (new, ".");
964  strcat (new, suffix);
965  }
966  }
967  *newname = new;
968  return (GP_OK);
969 }
970 
971 
978 int
979 gp_file_get_mime_type (CameraFile *file, const char **mime_type)
980 {
981  C_PARAMS (file && mime_type);
982 
983  *mime_type = file->mime_type;
984 
985  return (GP_OK);
986 }
987 
988 
995 int
996 gp_file_set_name (CameraFile *file, const char *name)
997 {
998  C_PARAMS (file && name);
999 
1000  strncpy (file->name, name, sizeof (file->name));
1001 
1002  return (GP_OK);
1003 }
1004 
1005 
1012 int
1013 gp_file_set_mime_type (CameraFile *file, const char *mime_type)
1014 {
1015  C_PARAMS (file && mime_type);
1016 
1017  strncpy (file->mime_type, mime_type, sizeof (file->mime_type));
1018 
1019  return (GP_OK);
1020 }
1021 
1022 
1028 int
1030 {
1031  const char TIFF_SOI_MARKER[] = {(char) 0x49, (char) 0x49, (char) 0x2A,
1032  (char) 0x00, (char) 0x08, '\0' };
1033  const char JPEG_SOI_MARKER[] = {(char) 0xFF, (char) 0xD8, '\0' };
1034 
1035  C_PARAMS (file);
1036 
1037  switch (file->accesstype) {
1039  /* image/tiff */
1040  if ((file->size >= 5) && !memcmp (file->data, TIFF_SOI_MARKER, 5))
1042 
1043  /* image/jpeg */
1044  else if ((file->size >= 2) && !memcmp (file->data, JPEG_SOI_MARKER, 2))
1046  else
1048  return GP_OK;
1049  case GP_FILE_ACCESSTYPE_FD: {
1050  char data[5];
1051  off_t offset;
1052  int res;
1053 
1054  offset = lseek (file->fd, 0, SEEK_SET);
1055  res = read (file->fd, data, sizeof(data));
1056  if (res == -1)
1057  return GP_ERROR_IO_READ;
1058  /* image/tiff */
1059  if ((res >= 5) && !memcmp (data, TIFF_SOI_MARKER, 5))
1061 
1062  /* image/jpeg */
1063  else if ((res >= 2) && !memcmp (data, JPEG_SOI_MARKER, 2))
1065  else
1067  lseek (file->fd, offset, SEEK_SET);
1068  break;
1069  }
1070  default:
1071  break;
1072  }
1073  return GP_OK;
1074 }
1075 
1076 
1082 int
1084 {
1085  int x;
1086  char *suffix;
1087  const char *table[] = {
1088  GP_MIME_RAW, "raw",
1089  GP_MIME_JPEG, "jpg",
1090  GP_MIME_PNG, "png",
1091  GP_MIME_PPM, "ppm",
1092  GP_MIME_PGM, "pgm",
1093  GP_MIME_PNM, "pnm",
1094  GP_MIME_TIFF, "tif",
1095  GP_MIME_WAV, "wav",
1096  GP_MIME_BMP, "bmp",
1097  GP_MIME_AVI, "avi",
1098  GP_MIME_CRW, "crw",
1099  GP_MIME_CR2, "cr2",
1100  GP_MIME_NEF, "nef",
1101  GP_MIME_TXT, "txt",
1102  NULL};
1103 
1104  C_PARAMS (file);
1105 
1106  GP_LOG_D ("Adjusting file name for mime type '%s'...", file->mime_type);
1107  for (x = 0; table[x]; x += 2)
1108  if (!strcmp (file->mime_type, table[x])) {
1109 
1110  /* Search the current suffix and erase it */
1111  suffix = strrchr (file->name, '.');
1112  if (suffix++)
1113  *suffix = '\0';
1114  strcat (file->name, table[x + 1]);
1115  break;
1116  }
1117  GP_LOG_D ("Name adjusted to '%s'.", file->name);
1118 
1119  return (GP_OK);
1120 }
1121 
1122 
1129 int
1130 gp_file_get_mtime (CameraFile *file, time_t *mtime)
1131 {
1132  C_PARAMS (file && mtime);
1133 
1134  *mtime = file->mtime;
1135 
1136  return (GP_OK);
1137 }
1138 
1139 
1146 int
1147 gp_file_set_mtime (CameraFile *file, time_t mtime)
1148 {
1149  C_PARAMS (file);
1150 
1151  file->mtime = mtime;
1152 
1153  return (GP_OK);
1154 }
gp_file_set_mime_type
int gp_file_set_mime_type(CameraFile *file, const char *mime_type)
Definition: gphoto2-file.c:1013
gp_file_unref
int gp_file_unref(CameraFile *file)
Decrease reference counter for CameraFile object.
Definition: gphoto2-file.c:184
GP_MIME_UNKNOWN
#define GP_MIME_UNKNOWN
Definition: gphoto2-file.h:52
gp_file_adjust_name_for_mime_type
int gp_file_adjust_name_for_mime_type(CameraFile *file)
Definition: gphoto2-file.c:1083
_CameraFile::ref_count
int ref_count
Definition: gphoto2-file.c:58
mime_table
static const char * mime_table[]
Definition: gphoto2-file.c:575
gp_file_get_mtime
int gp_file_get_mtime(CameraFile *file, time_t *mtime)
Definition: gphoto2-file.c:1130
gp_file_new
int gp_file_new(CameraFile **file)
Definition: gphoto2-file.c:83
GP_MIME_BMP
#define GP_MIME_BMP
Definition: gphoto2-file.h:45
gp_file_append
int gp_file_append(CameraFile *file, const char *data, unsigned long int size)
Definition: gphoto2-file.c:205
GP_ERROR_IO
#define GP_ERROR_IO
Generic I/O error.
Definition: gphoto2-port-result.h:58
GP_MIME_PNM
#define GP_MIME_PNM
Definition: gphoto2-file.h:42
_CameraFile::accesstype
CameraFileAccessType accesstype
Definition: gphoto2-file.c:61
_CameraFile::handler
CameraFileHandler * handler
Definition: gphoto2-file.c:72
_CameraFile
Definition: gphoto2-file.c:55
CameraFile
File structure.
GP_MIME_CRW
#define GP_MIME_CRW
Definition: gphoto2-file.h:48
_CameraFile::mtime
time_t mtime
Definition: gphoto2-file.c:59
GP_ERROR_IO_READ
#define GP_ERROR_IO_READ
I/O during read.
Definition: gphoto2-port-result.h:84
GP_FILE_TYPE_PREVIEW
@ GP_FILE_TYPE_PREVIEW
Definition: gphoto2-file.h:74
GP_ERROR_NO_MEMORY
#define GP_ERROR_NO_MEMORY
Out of memory.
Definition: gphoto2-port-result.h:42
GP_MIME_AVCHD
#define GP_MIME_AVCHD
Definition: gphoto2-file.h:59
CameraFileType
CameraFileType
The type of view on the specified file.
Definition: gphoto2-file.h:73
gp_file_get_data_and_size
int gp_file_get_data_and_size(CameraFile *file, const char **data, unsigned long int *size)
Definition: gphoto2-file.c:398
GP_FILE_ACCESSTYPE_MEMORY
@ GP_FILE_ACCESSTYPE_MEMORY
Definition: gphoto2-file.h:91
gp_file_free
int gp_file_free(CameraFile *file)
descruct a CameraFile object.
Definition: gphoto2-file.c:147
gp_file_set_name
int gp_file_set_name(CameraFile *file, const char *name)
Definition: gphoto2-file.c:996
GP_MIME_PNG
#define GP_MIME_PNG
Definition: gphoto2-file.h:39
GP_ERROR_IO_WRITE
#define GP_ERROR_IO_WRITE
I/O during write.
Definition: gphoto2-port-result.h:88
GP_FILE_TYPE_NORMAL
@ GP_FILE_TYPE_NORMAL
Definition: gphoto2-file.h:75
_CameraFile::mime_type
char mime_type[64]
Definition: gphoto2-file.c:56
gphoto2-result.h
GP_MIME_ASF
#define GP_MIME_ASF
Definition: gphoto2-file.h:57
GP_MIME_WMA
#define GP_MIME_WMA
Definition: gphoto2-file.h:56
_CameraFileHandler
Definition: gphoto2-file.h:97
GP_MIME_TXT
#define GP_MIME_TXT
Definition: gphoto2-file.h:36
GP_FILE_TYPE_RAW
@ GP_FILE_TYPE_RAW
Definition: gphoto2-file.h:76
GP_MIME_TIFF
#define GP_MIME_TIFF
Definition: gphoto2-file.h:44
_CameraFile::fd
int fd
Definition: gphoto2-file.c:69
GP_OK
#define GP_OK
Everything is OK.
Definition: gphoto2-port-result.h:30
gp_file_get_name
int gp_file_get_name(CameraFile *file, const char **name)
Definition: gphoto2-file.c:873
CHECK_RESULT
#define CHECK_RESULT(result)
Definition: gphoto2-file.c:45
gp_file_get_mime_type
int gp_file_get_mime_type(CameraFile *file, const char **mime_type)
Definition: gphoto2-file.c:979
GP_FILE_TYPE_EXIF
@ GP_FILE_TYPE_EXIF
Definition: gphoto2-file.h:80
gp_file_ref
int gp_file_ref(CameraFile *file)
Increase reference counter for CameraFile object.
Definition: gphoto2-file.c:167
GP_MIME_MP3
#define GP_MIME_MP3
Definition: gphoto2-file.h:54
gp_file_clean
int gp_file_clean(CameraFile *file)
Definition: gphoto2-file.c:699
gp_file_new_from_fd
int gp_file_new_from_fd(CameraFile **file, int fd)
Definition: gphoto2-file.c:105
GP_MIME_ARW
#define GP_MIME_ARW
Definition: gphoto2-file.h:61
GP_MIME_MPEG
#define GP_MIME_MPEG
Definition: gphoto2-file.h:58
GP_MIME_OGG
#define GP_MIME_OGG
Definition: gphoto2-file.h:55
_CameraFile::offset
unsigned long offset
Definition: gphoto2-file.c:66
_CameraFile::name
char name[MAX_PATH]
Definition: gphoto2-file.c:57
GP_ERROR
#define GP_ERROR
Generic Error.
Definition: gphoto2-port-result.h:34
_CameraFile::size
unsigned long size
Definition: gphoto2-file.c:64
gp_file_save
int gp_file_save(CameraFile *file, const char *filename)
Definition: gphoto2-file.c:486
gp_file_slurp
int gp_file_slurp(CameraFile *file, char *data, size_t size, size_t *readlen)
Definition: gphoto2-file.c:254
GP_FILE_TYPE_AUDIO
@ GP_FILE_TYPE_AUDIO
Definition: gphoto2-file.h:79
GP_MIME_WAV
#define GP_MIME_WAV
Definition: gphoto2-file.h:37
GP_MIME_PPM
#define GP_MIME_PPM
Definition: gphoto2-file.h:41
gp_file_set_mtime
int gp_file_set_mtime(CameraFile *file, time_t mtime)
Definition: gphoto2-file.c:1147
GP_MIME_NEF
#define GP_MIME_NEF
Definition: gphoto2-file.h:51
gp_file_new_from_handler
int gp_file_new_from_handler(CameraFile **file, CameraFileHandler *handler, void *private)
Definition: gphoto2-file.c:126
GP_MIME_PGM
#define GP_MIME_PGM
Definition: gphoto2-file.h:40
GP_FILE_ACCESSTYPE_HANDLER
@ GP_FILE_ACCESSTYPE_HANDLER
Definition: gphoto2-file.h:93
gp_file_detect_mime_type
int gp_file_detect_mime_type(CameraFile *file)
Definition: gphoto2-file.c:1029
MAX_PATH
#define MAX_PATH
Definition: gphoto2-file.c:49
gphoto2-port-log.h
gp_file_copy
int gp_file_copy(CameraFile *destination, CameraFile *source)
Definition: gphoto2-file.c:729
CameraFileAccessType
CameraFileAccessType
File storage type.
Definition: gphoto2-file.h:90
GP_MIME_JPEG
#define GP_MIME_JPEG
Definition: gphoto2-file.h:43
GP_FILE_TYPE_METADATA
@ GP_FILE_TYPE_METADATA
Definition: gphoto2-file.h:81
GP_MIME_AVI
#define GP_MIME_AVI
Definition: gphoto2-file.h:47
gp_file_open
int gp_file_open(CameraFile *file, const char *filename)
Definition: gphoto2-file.c:603
gp_file_set_data_and_size
int gp_file_set_data_and_size(CameraFile *file, char *data, unsigned long int size)
Definition: gphoto2-file.c:313
gphoto2-port-portability.h
GP_MIME_CR2
#define GP_MIME_CR2
Definition: gphoto2-file.h:49
gphoto2-file.h
Abstracted gphoto2 file operations.
gp_file_get_name_by_type
int gp_file_get_name_by_type(CameraFile *file, const char *basename, CameraFileType type, char **newname)
Definition: gphoto2-file.c:899
GP_FILE_ACCESSTYPE_FD
@ GP_FILE_ACCESSTYPE_FD
Definition: gphoto2-file.h:92
_CameraFile::data
unsigned char * data
Definition: gphoto2-file.c:65
GP_MIME_RAW
#define GP_MIME_RAW
Definition: gphoto2-file.h:38