"Fossies" - the Fresh Open Source Software Archive

Member "libgphoto2-2.5.27/camlibs/directory/directory.c" (26 Oct 2020, 20442 Bytes) of package /linux/privat/libgphoto2-2.5.27.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "directory.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.5.26_vs_2.5.27.

    1 /* directory.c
    2  *
    3  * Copyright (c) 2001 Lutz Mueller <lutz@users.sf.net>
    4  * Copyright (c) 2005 Marcus Meissner <marcus@jet.franken.de>
    5  * Copyright (c) 2007 Hubert Figuiere <hub@figuiere.net>
    6  *
    7  * This library is free software; you can redistribute it and/or
    8  * modify it under the terms of the GNU Lesser General Public
    9  * License as published by the Free Software Foundation; either
   10  * version 2 of the License, or (at your option) any later version.
   11  *
   12  * This library is distributed in the hope that it will be useful,
   13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15  * Lesser General Public License for more details.
   16  *
   17  * You should have received a copy of the GNU Lesser General Public
   18  * License along with this library; if not, write to the
   19  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   20  * Boston, MA  02110-1301  USA
   21  */
   22 
   23 #define _DEFAULT_SOURCE
   24 
   25 #include "config.h"
   26 
   27 #include <errno.h>
   28 #include <stdio.h>
   29 #include <stdlib.h>
   30 #include <string.h>
   31 #include <sys/types.h>
   32 #include <utime.h>
   33 #ifdef HAVE_SYS_STATVFS_H
   34 # include <sys/statvfs.h>
   35 #endif
   36 #ifdef HAVE_SYS_PARAM_H
   37 # include <sys/param.h>
   38 #endif
   39 #ifdef HAVE_SYS_VFS_H
   40 # include <sys/vfs.h>
   41 #endif
   42 #ifdef HAVE_SYS_MOUNT_H
   43 # include <sys/mount.h>
   44 #endif
   45 #include <fcntl.h>
   46 
   47 /* will happen only on Win32 */
   48 #ifndef HAVE_LSTAT
   49 #define lstat stat
   50 #endif
   51 
   52 #ifdef HAVE_LIBEXIF
   53 #include <libexif/exif-data.h>
   54 #endif
   55 
   56 #include <gphoto2/gphoto2-setting.h>
   57 #include <gphoto2/gphoto2-library.h>
   58 #include <gphoto2/gphoto2-port.h>
   59 #include <gphoto2/gphoto2-port-log.h>
   60 #include <gphoto2/gphoto2-port-portability.h>
   61 
   62 #ifdef ENABLE_NLS
   63 #  include <libintl.h>
   64 #  undef _
   65 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
   66 #  ifdef gettext_noop
   67 #    define N_(String) gettext_noop (String)
   68 #  else
   69 #    define N_(String) (String)
   70 #  endif
   71 #else
   72 #  define textdomain(String) (String)
   73 #  define gettext(String) (String)
   74 #  define dgettext(Domain,Message) (Message)
   75 #  define dcgettext(Domain,Message,Type) (Message)
   76 #  define bindtextdomain(Domain,Directory) (Domain)
   77 #  define _(String) (String)
   78 #  define N_(String) (String)
   79 #endif
   80 
   81 static const struct {
   82     const char *extension;
   83     const char *mime_type;
   84 } mime_table[] = {
   85     {"jpeg", GP_MIME_JPEG},
   86     {"jpg",  GP_MIME_JPEG},
   87     {"thm",  GP_MIME_JPEG},
   88     {"tif",  GP_MIME_TIFF},
   89     {"ppm",  GP_MIME_PPM},
   90     {"pgm",  GP_MIME_PGM},
   91     {"avi",  GP_MIME_AVI},
   92     {"mov",  GP_MIME_QUICKTIME},
   93     {"moov", GP_MIME_QUICKTIME},
   94     {"qt",   GP_MIME_QUICKTIME},
   95     {"qtvr", GP_MIME_QUICKTIME},
   96     {"mp2",  GP_MIME_MPEG},
   97     {"mp3",  GP_MIME_MPEG},
   98     {"mp4",  GP_MIME_MPEG},
   99     {"mpg",  GP_MIME_MPEG},
  100     {"mpeg", GP_MIME_MPEG},
  101     {"mpe",  GP_MIME_MPEG},
  102     {"ogg",  GP_MIME_OGG},
  103     {"mts",  GP_MIME_AVCHD},
  104     {"m2ts", GP_MIME_AVCHD},
  105     {"pbm", "image/x-portable-bitmap"},
  106     {"crw",  GP_MIME_CRW},
  107     {"rw2",  GP_MIME_RW2},
  108     {"cr2",  GP_MIME_RAW},
  109     {"cr3",  GP_MIME_RAW},
  110     {"nef",  GP_MIME_RAW},
  111     {"mrw",  GP_MIME_RAW},
  112     {"dng",  GP_MIME_RAW},
  113     {"sr2",  GP_MIME_RAW},
  114     {"raf",  GP_MIME_RAW},
  115     {"erf",  GP_MIME_RAW},
  116     {"orf",  GP_MIME_RAW},
  117     {"arw",  GP_MIME_RAW},
  118     {"pef",  GP_MIME_RAW},
  119     {"raw",  GP_MIME_RAW},
  120     {"dcr",  GP_MIME_RAW},
  121     {"x3f",  GP_MIME_RAW},
  122     {"srw",  GP_MIME_RAW},
  123     {"gf1",  GP_MIME_RAW},
  124     {"srw",  GP_MIME_RAW},
  125     {"nrw",  GP_MIME_RAW},
  126     {"png",  GP_MIME_PNG},
  127     {"wav",  GP_MIME_WAV},
  128     {"3gp",  "video/3gpp"},
  129     {"3g2",  "video/x-3gpp2"},
  130     {"dif",  "video/dv"},
  131     {NULL, NULL}
  132 };
  133 
  134 /* #define DEBUG */
  135 /* #define FOLLOW_LINKS */
  136 
  137 #define GP_MODULE "directory"
  138 
  139 static const char *
  140 get_mime_type (const char *filename)
  141 {
  142 
  143         char *dot;
  144         int x=0;
  145 
  146         dot = strrchr(filename, '.');
  147         if (dot) {
  148         for (x = 0; mime_table[x].extension; x++) {
  149 #ifdef OS2
  150             if (!stricmp(mime_table[x].extension, dot+1))
  151 #else
  152             if (!strcasecmp (mime_table[x].extension, dot+1))
  153 #endif
  154                 return (mime_table[x].mime_type);
  155                 }
  156     }
  157 
  158         return (NULL);
  159 }
  160 
  161 int camera_id (CameraText *id)
  162 {
  163         strcpy(id->text, "directory");
  164 
  165         return (GP_OK);
  166 }
  167 
  168 
  169 int camera_abilities (CameraAbilitiesList *list)
  170 {
  171         CameraAbilities a;
  172 
  173     memset(&a, 0, sizeof(a));
  174         strcpy(a.model, "Directory Browse");
  175     a.status = GP_DRIVER_STATUS_PRODUCTION;
  176         a.port     = GP_PORT_DISK;
  177         a.speed[0] = 0;
  178 
  179         a.operations = GP_OPERATION_NONE;
  180 
  181 #ifdef DEBUG
  182         a.file_operations = GP_FILE_OPERATION_PREVIEW |
  183                 GP_FILE_OPERATION_DELETE |
  184                 GP_FILE_OPERATION_EXIF;
  185 #else
  186     a.file_operations = GP_FILE_OPERATION_DELETE |
  187                 GP_FILE_OPERATION_EXIF;
  188 #endif
  189         a.folder_operations = GP_FOLDER_OPERATION_MAKE_DIR |
  190                   GP_FOLDER_OPERATION_REMOVE_DIR |
  191                   GP_FOLDER_OPERATION_PUT_FILE;
  192 
  193         gp_abilities_list_append(list, a);
  194 
  195     /* Since "Directory Browse" is hardcoded in clients,
  196      * better also add a new name here.
  197      */
  198         strcpy(a.model, "Mass Storage Camera");
  199         gp_abilities_list_append(list, a);
  200         return (GP_OK);
  201 }
  202 
  203 static int
  204 _get_mountpoint(GPPort *port, char **path) {
  205     GPPortInfo  info;
  206     int ret;
  207     char *p;
  208 
  209     ret = gp_port_get_info (port, &info);
  210     if (ret < GP_OK)
  211         return ret;
  212     ret = gp_port_info_get_path (info, path);
  213     if (ret < GP_OK)
  214         return ret;
  215     p = strchr (*path, ':');
  216     if (p) *path = p+1;
  217     return GP_OK;
  218 }
  219 
  220 static int
  221 _get_path (GPPort *port, const char *folder, const char *file, char *path, unsigned int size) {
  222     if (port->type == GP_PORT_DISK) {
  223         int ret;
  224         char *xpath;
  225 
  226         ret = _get_mountpoint (port, &xpath);
  227         if (ret < GP_OK)
  228             return ret;
  229         snprintf (path, size, "%s/%s/%s", xpath, folder, file);
  230     } else {
  231         /* old style access */
  232         snprintf (path, size, "%s/%s", folder, file);
  233     }
  234     return GP_OK;
  235 }
  236 
  237 
  238 static int
  239 file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
  240         void *data, GPContext *context)
  241 {
  242     gp_system_dir dir;
  243     gp_system_dirent de;
  244     char buf[1024], f[1024];
  245     unsigned int id, n;
  246     int ret;
  247     Camera *camera = (Camera*)data;
  248 
  249     if (camera->port->type == GP_PORT_DISK) {
  250         char *path;
  251 
  252         ret = _get_mountpoint (camera->port, &path);
  253         if (ret < GP_OK)
  254             return ret;
  255         snprintf (f, sizeof(f), "%s/%s/", path, folder);
  256         /* UNIX / is empty, or we recurse through the whole fs */
  257         if (    (!strcmp(path, "") || !strcmp(path, "/")) &&
  258             !strcmp(folder,"/")
  259         )
  260             return GP_OK;
  261     } else {
  262         /* old style access */
  263         if (folder[strlen(folder)-1] != '/') {
  264             snprintf (f, sizeof(f), "%s%c", folder, '/');
  265         } else {
  266             strncpy (f, folder, sizeof(f));
  267         }
  268     }
  269     dir = gp_system_opendir ((char*) f);
  270     if (!dir)
  271         return (GP_ERROR);
  272 
  273     /* Make sure we have 1 delimiter */
  274 
  275     /* Count the files */
  276     n = 0;
  277     while (gp_system_readdir (dir))
  278         n++;
  279 
  280     gp_system_closedir (dir);
  281     dir = gp_system_opendir (f);
  282     if (!dir)
  283         return (GP_ERROR);
  284     id = gp_context_progress_start (context, n, _("Listing files in "
  285                 "'%s'..."), f);
  286     n = 0;
  287     while ((de = gp_system_readdir(dir))) {
  288         const char * filename = NULL;
  289         /* Give some feedback */
  290         gp_context_progress_update (context, id, n + 1);
  291         gp_context_idle (context);
  292         if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
  293             gp_system_closedir (dir);
  294             return (GP_ERROR_CANCEL);
  295         }
  296 
  297         filename = gp_system_filename(de);
  298         if (*filename != '.') {
  299             snprintf (buf, sizeof(buf), "%s%s", f, filename);
  300             if (gp_system_is_file (buf) && (get_mime_type (buf))) {
  301                 gp_list_append (list, filename, NULL);
  302             }
  303         }
  304         n++;
  305     }
  306     gp_system_closedir (dir);
  307     gp_context_progress_stop (context, id);
  308 
  309     return (GP_OK);
  310 }
  311 
  312 static int
  313 folder_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
  314           void *data, GPContext *context)
  315 {
  316     gp_system_dir dir;
  317     gp_system_dirent de;
  318     char buf[1024], f[1024];
  319     unsigned int id, n;
  320     struct stat st;
  321     Camera *camera = (Camera*)data;
  322 
  323     if (camera->port->type == GP_PORT_DISK) {
  324         char *path;
  325         int ret;
  326 
  327         ret = _get_mountpoint (camera->port, &path);
  328         if (ret < GP_OK)
  329             return ret;
  330 
  331         snprintf (f, sizeof(f), "%s/%s/", path, folder);
  332         /* UNIX / is empty, or we recurse through the whole fs */
  333         if (    (!strcmp(path, "") || !strcmp(path, "/")) &&
  334             !strcmp(folder,"/")
  335         )
  336             return GP_OK;
  337     } else {
  338         /* old style access */
  339         /* Make sure we have 1 delimiter */
  340         if (folder[strlen(folder)-1] != '/') {
  341             snprintf (f, sizeof(f), "%s%c", folder, '/');
  342         } else {
  343             strncpy (f, folder, sizeof(f));
  344         }
  345     }
  346     dir = gp_system_opendir ((char*) f);
  347     if (!dir)
  348         return GP_ERROR;
  349     /* Count the files */
  350     n = 0;
  351     while (gp_system_readdir (dir))
  352         n++;
  353     gp_system_closedir (dir);
  354 
  355     dir = gp_system_opendir (f);
  356     if (!dir)
  357         return GP_ERROR;
  358     id = gp_context_progress_start (context, n, _("Listing folders in "
  359                     "'%s'..."), folder);
  360     n = 0;
  361     while ((de = gp_system_readdir (dir))) {
  362         const char * filename = NULL;
  363 
  364         /* Give some feedback */
  365         gp_context_progress_update (context, id, n + 1);
  366         gp_context_idle (context);
  367         if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
  368             gp_system_closedir (dir);
  369             return GP_ERROR_CANCEL;
  370         }
  371         filename = gp_system_filename (de);
  372         if (*filename != '.') {
  373             snprintf (buf, sizeof(buf), "%s%s", f, filename);
  374 
  375             /* lstat ... do not follow symlinks */
  376             if (lstat (buf, &st) != 0) {
  377                 int saved_errno = errno;
  378                 gp_context_error (context, _("Could not get information "
  379                                  "about '%s' (%s)."),
  380                           buf, strerror(saved_errno));
  381                 gp_system_closedir (dir);
  382                 return GP_ERROR;
  383             }
  384             if (S_ISDIR (st.st_mode)) {
  385                 gp_list_append(list,    filename,   NULL);
  386             }
  387         }
  388         n++;
  389     }
  390     gp_system_closedir (dir);
  391     gp_context_progress_stop (context, id);
  392     return (GP_OK);
  393 }
  394 
  395 static int
  396 get_info_func (CameraFilesystem *fs, const char *folder, const char *file,
  397               CameraFileInfo *info, void *data, GPContext *context)
  398 {
  399     char path[1024];
  400     const char *mime_type;
  401     struct stat st;
  402     Camera *camera = (Camera*)data;
  403     int result;
  404 
  405     result = _get_path (camera->port, folder, file, path, sizeof(path));
  406     if (result < GP_OK)
  407         return result;
  408 
  409     if (lstat (path, &st) != 0) {
  410         int saved_errno = errno;
  411         gp_context_error (context, _("Could not get information "
  412                          "about '%s' in '%s' (%s)."),
  413                   file, folder, strerror(saved_errno));
  414         return (GP_ERROR);
  415     }
  416 
  417         info->preview.fields = GP_FILE_INFO_NONE;
  418         info->file.fields = GP_FILE_INFO_SIZE |
  419                             GP_FILE_INFO_TYPE | GP_FILE_INFO_PERMISSIONS |
  420                 GP_FILE_INFO_MTIME;
  421 
  422     info->file.mtime = st.st_mtime;
  423     info->file.permissions = GP_FILE_PERM_NONE;
  424     if (st.st_mode & S_IRUSR)
  425         info->file.permissions |= GP_FILE_PERM_READ;
  426     if (st.st_mode & S_IWUSR)
  427         info->file.permissions |= GP_FILE_PERM_DELETE;
  428         info->file.size = st.st_size;
  429     mime_type = get_mime_type (file);
  430     if (!mime_type)
  431         mime_type = GP_MIME_UNKNOWN;
  432     strcpy (info->file.type, mime_type);
  433         return (GP_OK);
  434 }
  435 
  436 static int
  437 set_info_func (CameraFilesystem *fs, const char *folder, const char *file,
  438            CameraFileInfo info, void *data, GPContext *context)
  439 {
  440     int retval;
  441     char path[1024];
  442     Camera *camera = (Camera*)data;
  443 
  444     retval = _get_path (camera->port, folder, file, path, sizeof(path));
  445     if (retval < GP_OK)
  446         return retval;
  447 
  448     /* We don't support updating permissions (yet) */
  449     if (info.file.fields & GP_FILE_INFO_PERMISSIONS)
  450         return (GP_ERROR_NOT_SUPPORTED);
  451 
  452     if (info.file.fields & GP_FILE_INFO_MTIME) {
  453         struct utimbuf utimbuf;
  454 
  455         utimbuf.actime  = info.file.mtime;
  456         utimbuf.modtime = info.file.mtime;
  457         if (utime (path, &utimbuf) != 0) {
  458             int saved_errno = errno;
  459             gp_context_error (context, _("Could not change "
  460                              "time of file '%s' in '%s' (%s)."),
  461                       file, folder, strerror(saved_errno));
  462             return (GP_ERROR);
  463         }
  464     }
  465 
  466 #if 0 /* implement this using new api -Marcus */
  467     if (info.file.fields & GP_FILE_INFO_NAME) {
  468             if (!strcasecmp (info.file.name, file))
  469                     return (GP_OK);
  470 
  471             /* We really have to rename the poor file... */
  472         if (strlen (folder) == 1) {
  473             snprintf (path_old, sizeof (path_old), "/%s",
  474                   file);
  475             snprintf (path_new, sizeof (path_new), "/%s",
  476                   info.file.name);
  477         } else {
  478             snprintf (path_old, sizeof (path_old), "%s/%s",
  479                   folder, file);
  480             snprintf (path_new, sizeof (path_new), "%s/%s",
  481                   folder, info.file.name);
  482         }
  483                 retval = rename (path_old, path_new);
  484         if (retval != 0) {
  485                     switch (errno) {
  486                     case EISDIR:
  487                             return (GP_ERROR_DIRECTORY_EXISTS);
  488                     case EEXIST:
  489                             return (GP_ERROR_FILE_EXISTS);
  490                     case EINVAL:
  491                             return (GP_ERROR_BAD_PARAMETERS);
  492                     case EIO:
  493                             return (GP_ERROR_IO);
  494                     case ENOMEM:
  495                             return (GP_ERROR_NO_MEMORY);
  496                     case ENOENT:
  497                             return (GP_ERROR_FILE_NOT_FOUND);
  498                     default:
  499                             return (GP_ERROR);
  500                     }
  501             }
  502     }
  503 #endif
  504 
  505         return (GP_OK);
  506 }
  507 
  508 static int
  509 get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
  510            CameraFileType type, CameraFile *file, void *user_data,
  511            GPContext *context)
  512 {
  513         char path[1024];
  514     int result = GP_OK;
  515     struct stat stbuf;
  516     int fd, id;
  517     off_t curread, toread;
  518     unsigned char *buf;
  519 #ifdef HAVE_LIBEXIF
  520     ExifData *data;
  521     unsigned int buf_len;
  522 #endif /* HAVE_LIBEXIF */
  523     Camera *camera = (Camera*)user_data;
  524 
  525     result = _get_path (camera->port, folder, filename, path, sizeof(path));
  526     if (result < GP_OK)
  527         return result;
  528 
  529     if (-1 == lstat(path,&stbuf))
  530         return GP_ERROR_IO_READ;
  531 
  532     gp_file_set_mtime (file, stbuf.st_mtime);
  533 
  534     switch (type) {
  535     case GP_FILE_TYPE_NORMAL:
  536 #ifdef DEBUG
  537     case GP_FILE_TYPE_PREVIEW:
  538 #endif
  539         fd = open (path,O_RDONLY);
  540         if (fd == -1)
  541             return GP_ERROR_IO_READ;
  542         break;
  543 #ifdef HAVE_LIBEXIF
  544     case GP_FILE_TYPE_EXIF:
  545         data = exif_data_new_from_file (path);
  546         if (!data) {
  547             gp_context_error (context, _("Could not open '%s'."),
  548                       path);
  549             return (GP_ERROR);
  550         }
  551         exif_data_save_data (data, &buf, &buf_len);
  552         exif_data_unref (data);
  553         gp_file_set_data_and_size (file, (char *)buf, buf_len);
  554         return (GP_OK);
  555 #endif /* HAVE_LIBEXIF */
  556     default:
  557         return (GP_ERROR_NOT_SUPPORTED);
  558     }
  559 #define BLOCKSIZE 65536
  560     /* do it in 64kb blocks */
  561     buf = malloc(BLOCKSIZE);
  562     if (!buf) {
  563         close (fd);
  564         return GP_ERROR_NO_MEMORY;
  565     }
  566     if (-1 == fstat(fd,&stbuf)) {
  567         free (buf);
  568         close (fd);
  569         return GP_ERROR_IO_READ;
  570     }
  571 
  572     curread = 0;
  573     id = gp_context_progress_start (context, (1.0*stbuf.st_size/BLOCKSIZE), _("Getting file..."));
  574     GP_DEBUG ("Progress id: %i", id);
  575     result = GP_OK;
  576     while (curread < stbuf.st_size) {
  577         int ret;
  578 
  579         toread = stbuf.st_size-curread;
  580         if (toread>BLOCKSIZE) toread = BLOCKSIZE;
  581         ret = read(fd,buf,toread);
  582         if (ret == -1) {
  583             result = GP_ERROR_IO_READ;
  584             break;
  585         }
  586         curread += ret;
  587         gp_file_append (file, (char *)buf, ret);
  588         gp_context_progress_update (context, id, (1.0*curread/BLOCKSIZE));
  589         gp_context_idle (context);
  590         if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
  591             result = GP_ERROR_CANCEL;
  592             break;
  593         }
  594 #if 0
  595         /* We could take 2 seconds to download this image. everytime. */
  596         /* But actually this driver is used in production by some frontends,
  597          * so do not delay at all
  598          */
  599         usleep(2000000/(stbuf.st_size/BLOCKSIZE));
  600 #endif
  601     }
  602     gp_context_progress_stop (context, id);
  603     free (buf);
  604     close (fd);
  605     return (GP_OK);
  606 }
  607 
  608 static int
  609 camera_manual (Camera *camera, CameraText *manual, GPContext *context)
  610 {
  611         strcpy (manual->text, _("The Directory Browse \"camera\" lets "
  612         "you index photos on your hard drive."));
  613 
  614         return (GP_OK);
  615 }
  616 
  617 static int
  618 camera_about (Camera *camera, CameraText *about, GPContext *context)
  619 {
  620         strcpy (about->text, _("Directory Browse Mode - written "
  621         "by Scott Fritzinger <scottf@unr.edu>."));
  622 
  623         return (GP_OK);
  624 }
  625 
  626 static int
  627 make_dir_func (CameraFilesystem *fs, const char *folder, const char *name,
  628            void *data, GPContext *context)
  629 {
  630     char path[2048];
  631     Camera *camera = (Camera*)data;
  632     int result;
  633 
  634     result = _get_path (camera->port, folder, name, path, sizeof(path));
  635     if (result < GP_OK)
  636         return result;
  637     return gp_system_mkdir (path);
  638 }
  639 
  640 static int
  641 remove_dir_func (CameraFilesystem *fs, const char *folder, const char *name,
  642          void *data, GPContext *context)
  643 {
  644     char path[2048];
  645     Camera *camera = (Camera*)data;
  646     int result;
  647 
  648     result = _get_path (camera->port, folder, name, path, sizeof(path));
  649     if (result < GP_OK)
  650         return result;
  651     return gp_system_rmdir (path);
  652 }
  653 
  654 static int
  655 delete_file_func (CameraFilesystem *fs, const char *folder,
  656           const char *file, void *data, GPContext *context)
  657 {
  658     char path[2048];
  659     int result;
  660     Camera *camera = (Camera*)data;
  661 
  662     result = _get_path (camera->port, folder, file, path, sizeof(path));
  663     if (result < GP_OK)
  664         return result;
  665     result = unlink (path);
  666     if (result) {
  667         int saved_errno = errno;
  668         gp_context_error (context, _("Could not delete file '%s' "
  669                          "in folder '%s' (error code %i: %s)."),
  670                   file, folder, result, strerror(saved_errno));
  671         return (GP_ERROR);
  672     }
  673 
  674     return (GP_OK);
  675 }
  676 
  677 static int
  678 put_file_func (CameraFilesystem *fs, const char *folder, const char *name,
  679            CameraFileType type, CameraFile *file, void *data, GPContext *context)
  680 {
  681     char path[2048];
  682     int result;
  683 #ifdef DEBUG
  684     unsigned int i, id;
  685 #endif
  686     Camera *camera = (Camera*)data;
  687 
  688     result = _get_path (camera->port, folder, name, path, sizeof(path));
  689     if (result < GP_OK)
  690         return result;
  691 
  692     result = gp_file_save (file, path);
  693     if (result < 0)
  694         return (result);
  695 
  696 #ifdef DEBUG
  697     id = gp_context_progress_start (context, 500., "Uploading file...");
  698     for (i = 0; i < 500; i++) {
  699         gp_context_progress_update (context, id, i + 1);
  700         gp_context_idle (context);
  701         if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL)
  702             return (result);
  703         usleep (10);
  704     }
  705     gp_context_progress_stop (context, id);
  706 #endif
  707 
  708     return (GP_OK);
  709 }
  710 
  711 #ifdef DEBUG
  712 static int
  713 camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context)
  714 {
  715     int r;
  716 
  717     r = gp_file_open (file, "/usr/share/pixmaps/gnome-logo-large.png");
  718     if (r < 0)
  719         return (r);
  720 
  721     return (GP_OK);
  722 }
  723 
  724 static int
  725 camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path,
  726         GPContext *context)
  727 {
  728     if (path) {
  729         strcpy (path->folder, "/usr/share/pixmaps");
  730         strcpy (path->name, "gnome-logo-large.png");
  731     }
  732 
  733     return (GP_OK);
  734 }
  735 #endif
  736 
  737 static int
  738 storage_info_func (CameraFilesystem *fs,
  739                 CameraStorageInformation **sinfos,
  740                 int *nrofsinfos,
  741                 void *data, GPContext *context
  742 ) {
  743     Camera              *camera = data;
  744     CameraStorageInformation    *sfs;
  745 
  746 #if defined(HAVE_STATVFS)
  747     struct  statvfs     stfs;
  748     char *xpath;
  749     int ret;
  750 
  751     ret = _get_mountpoint (camera->port, &xpath);
  752     if (ret < GP_OK)
  753         return ret;
  754     if (-1 == statvfs (xpath, &stfs))
  755         return GP_ERROR_NOT_SUPPORTED;
  756 
  757     sfs = malloc (sizeof (CameraStorageInformation));
  758     if (!sfs)
  759         return GP_ERROR_NO_MEMORY;
  760     *sinfos = sfs;
  761     *nrofsinfos = 1;
  762 
  763     sfs->fields =   GP_STORAGEINFO_BASE     |
  764             GP_STORAGEINFO_DESCRIPTION  |
  765             GP_STORAGEINFO_STORAGETYPE  |
  766             GP_STORAGEINFO_FILESYSTEMTYPE   |
  767             GP_STORAGEINFO_ACCESS       |
  768             GP_STORAGEINFO_MAXCAPACITY  |
  769             GP_STORAGEINFO_FREESPACEKBYTES;
  770     ;
  771     strcpy (sfs->basedir, "/");
  772     strcpy (sfs->description, "Directory Driver");
  773     sfs->type       = GP_STORAGEINFO_ST_REMOVABLE_RAM;
  774     sfs->fstype     = GP_STORAGEINFO_FST_GENERICHIERARCHICAL;
  775     sfs->access     = GP_STORAGEINFO_AC_READWRITE;
  776     if (stfs.f_bsize >= 1024) {
  777         sfs->capacitykbytes = stfs.f_blocks*(stfs.f_bsize/1024);
  778         sfs->freekbytes     = stfs.f_bavail*(stfs.f_bsize/1024);
  779     } else {
  780         sfs->capacitykbytes = stfs.f_blocks/(1024/stfs.f_bsize);
  781         sfs->freekbytes     = stfs.f_bavail/(1024/stfs.f_bsize);
  782     }
  783     return GP_OK;
  784 #endif
  785 
  786     return GP_ERROR_NOT_SUPPORTED;
  787 }
  788 
  789 static CameraFilesystemFuncs fsfuncs = {
  790     .file_list_func = file_list_func,
  791     .folder_list_func = folder_list_func,
  792     .set_info_func = set_info_func,
  793     .get_info_func = get_info_func,
  794     .get_file_func = get_file_func,
  795     .put_file_func = put_file_func,
  796     .del_file_func = delete_file_func,
  797     .make_dir_func = make_dir_func,
  798     .remove_dir_func = remove_dir_func,
  799     .storage_info_func = storage_info_func,
  800 };
  801 
  802 int
  803 camera_init (Camera *camera, GPContext *context)
  804 {
  805         /* First, set up all the function pointers */
  806         camera->functions->manual               = camera_manual;
  807         camera->functions->about                = camera_about;
  808         return gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);
  809 }