This is basically a continuation of the work from #1002 but her for the camlibs directory. The purpose was to replace spaces as a means for indentation with tab characters. Note: there are some files which are still offending the general rule but are (mostly) consistent within themselves. I let them be for the moment. Fixing them would basically replace the whole file. Also: there are still a ton of whitespace related inconsistencies like "x=10" vs "x = 10" or "func(10)" vs "func (10)". This is a whitespace only change (if you include newlines as whitespace).
791 lines
19 KiB
C
791 lines
19 KiB
C
/* directory.c
|
|
*
|
|
* Copyright (c) 2001 Lutz Mueller <lutz@users.sf.net>
|
|
* Copyright (c) 2005 Marcus Meissner <marcus@jet.franken.de>
|
|
* Copyright (c) 2007 Hubert Figuiere <hub@figuiere.net>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#define _DEFAULT_SOURCE
|
|
|
|
#include "config.h"
|
|
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <utime.h>
|
|
#ifdef HAVE_SYS_STATVFS_H
|
|
# include <sys/statvfs.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_PARAM_H
|
|
# include <sys/param.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_VFS_H
|
|
# include <sys/vfs.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_MOUNT_H
|
|
# include <sys/mount.h>
|
|
#endif
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
/* will happen only on Win32 */
|
|
#ifndef HAVE_LSTAT
|
|
#define lstat stat
|
|
#endif
|
|
|
|
#ifdef HAVE_LIBEXIF
|
|
#include <libexif/exif-data.h>
|
|
#endif
|
|
|
|
#include <gphoto2/gphoto2-setting.h>
|
|
#include <gphoto2/gphoto2-library.h>
|
|
#include <gphoto2/gphoto2-port.h>
|
|
#include <gphoto2/gphoto2-port-log.h>
|
|
#include <gphoto2/gphoto2-port-portability.h>
|
|
|
|
#include "libgphoto2/i18n.h"
|
|
|
|
|
|
static const struct {
|
|
const char *extension;
|
|
const char *mime_type;
|
|
} mime_table[] = {
|
|
{"jpeg", GP_MIME_JPEG},
|
|
{"jpg", GP_MIME_JPEG},
|
|
{"thm", GP_MIME_JPEG},
|
|
{"tif", GP_MIME_TIFF},
|
|
{"ppm", GP_MIME_PPM},
|
|
{"pgm", GP_MIME_PGM},
|
|
{"avi", GP_MIME_AVI},
|
|
{"mov", GP_MIME_QUICKTIME},
|
|
{"moov", GP_MIME_QUICKTIME},
|
|
{"qt", GP_MIME_QUICKTIME},
|
|
{"qtvr", GP_MIME_QUICKTIME},
|
|
{"mp2", GP_MIME_MPEG},
|
|
{"mp3", GP_MIME_MPEG},
|
|
{"mp4", GP_MIME_MPEG},
|
|
{"mpg", GP_MIME_MPEG},
|
|
{"mpeg", GP_MIME_MPEG},
|
|
{"mpe", GP_MIME_MPEG},
|
|
{"ogg", GP_MIME_OGG},
|
|
{"mts", GP_MIME_AVCHD},
|
|
{"m2ts", GP_MIME_AVCHD},
|
|
{"pbm", "image/x-portable-bitmap"},
|
|
{"crw", GP_MIME_CRW},
|
|
{"rw2", GP_MIME_RW2},
|
|
{"cr2", GP_MIME_RAW},
|
|
{"cr3", GP_MIME_RAW},
|
|
{"nef", GP_MIME_RAW},
|
|
{"mrw", GP_MIME_RAW},
|
|
{"dng", GP_MIME_RAW},
|
|
{"sr2", GP_MIME_RAW},
|
|
{"raf", GP_MIME_RAW},
|
|
{"erf", GP_MIME_RAW},
|
|
{"orf", GP_MIME_RAW},
|
|
{"arw", GP_MIME_RAW},
|
|
{"pef", GP_MIME_RAW},
|
|
{"raw", GP_MIME_RAW},
|
|
{"dcr", GP_MIME_RAW},
|
|
{"x3f", GP_MIME_RAW},
|
|
{"srw", GP_MIME_RAW},
|
|
{"gf1", GP_MIME_RAW},
|
|
{"srw", GP_MIME_RAW},
|
|
{"nrw", GP_MIME_RAW},
|
|
{"png", GP_MIME_PNG},
|
|
{"wav", GP_MIME_WAV},
|
|
{"3gp", "video/3gpp"},
|
|
{"3g2", "video/x-3gpp2"},
|
|
{"dif", "video/dv"},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
/* #define DEBUG */
|
|
/* #define FOLLOW_LINKS */
|
|
|
|
#define GP_MODULE "directory"
|
|
|
|
static const char *
|
|
get_mime_type (const char *filename)
|
|
{
|
|
|
|
char *dot;
|
|
int x=0;
|
|
|
|
dot = strrchr(filename, '.');
|
|
if (dot) {
|
|
for (x = 0; mime_table[x].extension; x++) {
|
|
if (!strcasecmp (mime_table[x].extension, dot+1))
|
|
return (mime_table[x].mime_type);
|
|
}
|
|
}
|
|
|
|
return (NULL);
|
|
}
|
|
|
|
int camera_id (CameraText *id)
|
|
{
|
|
strcpy(id->text, "directory");
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
|
|
int camera_abilities (CameraAbilitiesList *list)
|
|
{
|
|
CameraAbilities a;
|
|
|
|
memset(&a, 0, sizeof(a));
|
|
strcpy(a.model, "Directory Browse");
|
|
a.status = GP_DRIVER_STATUS_PRODUCTION;
|
|
a.port = GP_PORT_DISK;
|
|
a.speed[0] = 0;
|
|
|
|
a.operations = GP_OPERATION_NONE;
|
|
|
|
#ifdef DEBUG
|
|
a.file_operations = GP_FILE_OPERATION_PREVIEW |
|
|
GP_FILE_OPERATION_DELETE |
|
|
GP_FILE_OPERATION_EXIF;
|
|
#else
|
|
a.file_operations = GP_FILE_OPERATION_DELETE |
|
|
GP_FILE_OPERATION_EXIF;
|
|
#endif
|
|
a.folder_operations = GP_FOLDER_OPERATION_MAKE_DIR |
|
|
GP_FOLDER_OPERATION_REMOVE_DIR |
|
|
GP_FOLDER_OPERATION_PUT_FILE;
|
|
|
|
gp_abilities_list_append(list, a);
|
|
|
|
/* Since "Directory Browse" is hardcoded in clients,
|
|
* better also add a new name here.
|
|
*/
|
|
strcpy(a.model, "Mass Storage Camera");
|
|
gp_abilities_list_append(list, a);
|
|
return (GP_OK);
|
|
}
|
|
|
|
static int
|
|
_get_mountpoint(GPPort *port, char **path) {
|
|
GPPortInfo info;
|
|
int ret;
|
|
char *p;
|
|
|
|
ret = gp_port_get_info (port, &info);
|
|
if (ret < GP_OK)
|
|
return ret;
|
|
ret = gp_port_info_get_path (info, path);
|
|
if (ret < GP_OK)
|
|
return ret;
|
|
p = strchr (*path, ':');
|
|
if (p) *path = p+1;
|
|
return GP_OK;
|
|
}
|
|
|
|
static int
|
|
_get_path (GPPort *port, const char *folder, const char *file, char *path, unsigned int size) {
|
|
if (port->type == GP_PORT_DISK) {
|
|
int ret;
|
|
char *xpath;
|
|
|
|
ret = _get_mountpoint (port, &xpath);
|
|
if (ret < GP_OK)
|
|
return ret;
|
|
snprintf (path, size, "%s/%s/%s", xpath, folder, file);
|
|
} else {
|
|
/* old style access */
|
|
snprintf (path, size, "%s/%s", folder, file);
|
|
}
|
|
return GP_OK;
|
|
}
|
|
|
|
|
|
static int
|
|
file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
|
|
void *data, GPContext *context)
|
|
{
|
|
gp_system_dir dir;
|
|
gp_system_dirent de;
|
|
char buf[1024], f[1024];
|
|
unsigned int id, n;
|
|
int ret;
|
|
Camera *camera = (Camera*)data;
|
|
|
|
if (camera->port->type == GP_PORT_DISK) {
|
|
char *path;
|
|
|
|
ret = _get_mountpoint (camera->port, &path);
|
|
if (ret < GP_OK)
|
|
return ret;
|
|
snprintf (f, sizeof(f), "%s/%s/", path, folder);
|
|
/* UNIX / is empty, or we recurse through the whole fs */
|
|
if ( (!strcmp(path, "") || !strcmp(path, "/")) &&
|
|
!strcmp(folder,"/")
|
|
)
|
|
return GP_OK;
|
|
} else {
|
|
/* old style access */
|
|
if (folder[strlen(folder)-1] != '/') {
|
|
snprintf (f, sizeof(f), "%s%c", folder, '/');
|
|
} else {
|
|
strncpy (f, folder, sizeof(f));
|
|
}
|
|
}
|
|
dir = gp_system_opendir ((char*) f);
|
|
if (!dir)
|
|
return (GP_ERROR);
|
|
|
|
/* Make sure we have 1 delimiter */
|
|
|
|
/* Count the files */
|
|
n = 0;
|
|
while (gp_system_readdir (dir))
|
|
n++;
|
|
|
|
gp_system_closedir (dir);
|
|
dir = gp_system_opendir (f);
|
|
if (!dir)
|
|
return (GP_ERROR);
|
|
id = gp_context_progress_start (context, n, _("Listing files in "
|
|
"'%s'..."), f);
|
|
n = 0;
|
|
while ((de = gp_system_readdir(dir))) {
|
|
const char * filename = NULL;
|
|
/* Give some feedback */
|
|
gp_context_progress_update (context, id, n + 1);
|
|
gp_context_idle (context);
|
|
if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
|
|
gp_system_closedir (dir);
|
|
return (GP_ERROR_CANCEL);
|
|
}
|
|
|
|
filename = gp_system_filename(de);
|
|
if (*filename != '.') {
|
|
snprintf (buf, sizeof(buf), "%s%s", f, filename);
|
|
if (gp_system_is_file (buf) && (get_mime_type (buf))) {
|
|
gp_list_append (list, filename, NULL);
|
|
}
|
|
}
|
|
n++;
|
|
}
|
|
gp_system_closedir (dir);
|
|
gp_context_progress_stop (context, id);
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
static int
|
|
folder_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
|
|
void *data, GPContext *context)
|
|
{
|
|
gp_system_dir dir;
|
|
gp_system_dirent de;
|
|
char buf[1024], f[1024];
|
|
unsigned int id, n;
|
|
struct stat st;
|
|
Camera *camera = (Camera*)data;
|
|
|
|
if (camera->port->type == GP_PORT_DISK) {
|
|
char *path;
|
|
int ret;
|
|
|
|
ret = _get_mountpoint (camera->port, &path);
|
|
if (ret < GP_OK)
|
|
return ret;
|
|
|
|
snprintf (f, sizeof(f), "%s/%s/", path, folder);
|
|
/* UNIX / is empty, or we recurse through the whole fs */
|
|
if ( (!strcmp(path, "") || !strcmp(path, "/")) &&
|
|
!strcmp(folder,"/")
|
|
)
|
|
return GP_OK;
|
|
} else {
|
|
/* old style access */
|
|
/* Make sure we have 1 delimiter */
|
|
if (folder[strlen(folder)-1] != '/') {
|
|
snprintf (f, sizeof(f), "%s%c", folder, '/');
|
|
} else {
|
|
strncpy (f, folder, sizeof(f));
|
|
}
|
|
}
|
|
dir = gp_system_opendir ((char*) f);
|
|
if (!dir)
|
|
return GP_ERROR;
|
|
/* Count the files */
|
|
n = 0;
|
|
while (gp_system_readdir (dir))
|
|
n++;
|
|
gp_system_closedir (dir);
|
|
|
|
dir = gp_system_opendir (f);
|
|
if (!dir)
|
|
return GP_ERROR;
|
|
id = gp_context_progress_start (context, n, _("Listing folders in "
|
|
"'%s'..."), folder);
|
|
n = 0;
|
|
while ((de = gp_system_readdir (dir))) {
|
|
const char * filename = NULL;
|
|
|
|
/* Give some feedback */
|
|
gp_context_progress_update (context, id, n + 1);
|
|
gp_context_idle (context);
|
|
if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
|
|
gp_system_closedir (dir);
|
|
return GP_ERROR_CANCEL;
|
|
}
|
|
filename = gp_system_filename (de);
|
|
if (*filename != '.') {
|
|
snprintf (buf, sizeof(buf), "%s%s", f, filename);
|
|
|
|
/* lstat ... do not follow symlinks */
|
|
if (lstat (buf, &st) != 0) {
|
|
int saved_errno = errno;
|
|
gp_context_error (context, _("Could not get information "
|
|
"about '%s' (%s)."),
|
|
buf, strerror(saved_errno));
|
|
gp_system_closedir (dir);
|
|
return GP_ERROR;
|
|
}
|
|
if (S_ISDIR (st.st_mode)) {
|
|
gp_list_append(list, filename, NULL);
|
|
}
|
|
}
|
|
n++;
|
|
}
|
|
gp_system_closedir (dir);
|
|
gp_context_progress_stop (context, id);
|
|
return (GP_OK);
|
|
}
|
|
|
|
static int
|
|
get_info_func (CameraFilesystem *fs, const char *folder, const char *file,
|
|
CameraFileInfo *info, void *data, GPContext *context)
|
|
{
|
|
char path[1024];
|
|
const char *mime_type;
|
|
struct stat st;
|
|
Camera *camera = (Camera*)data;
|
|
int result;
|
|
|
|
result = _get_path (camera->port, folder, file, path, sizeof(path));
|
|
if (result < GP_OK)
|
|
return result;
|
|
|
|
if (lstat (path, &st) != 0) {
|
|
int saved_errno = errno;
|
|
gp_context_error (context, _("Could not get information "
|
|
"about '%s' in '%s' (%s)."),
|
|
file, folder, strerror(saved_errno));
|
|
return (GP_ERROR);
|
|
}
|
|
|
|
info->preview.fields = GP_FILE_INFO_NONE;
|
|
info->file.fields = GP_FILE_INFO_SIZE |
|
|
GP_FILE_INFO_TYPE | GP_FILE_INFO_PERMISSIONS |
|
|
GP_FILE_INFO_MTIME;
|
|
|
|
info->file.mtime = st.st_mtime;
|
|
info->file.permissions = GP_FILE_PERM_NONE;
|
|
if (st.st_mode & S_IRUSR)
|
|
info->file.permissions |= GP_FILE_PERM_READ;
|
|
if (st.st_mode & S_IWUSR)
|
|
info->file.permissions |= GP_FILE_PERM_DELETE;
|
|
info->file.size = st.st_size;
|
|
mime_type = get_mime_type (file);
|
|
if (!mime_type)
|
|
mime_type = GP_MIME_UNKNOWN;
|
|
strcpy (info->file.type, mime_type);
|
|
return (GP_OK);
|
|
}
|
|
|
|
static int
|
|
set_info_func (CameraFilesystem *fs, const char *folder, const char *file,
|
|
CameraFileInfo info, void *data, GPContext *context)
|
|
{
|
|
int retval;
|
|
char path[1024];
|
|
Camera *camera = (Camera*)data;
|
|
|
|
retval = _get_path (camera->port, folder, file, path, sizeof(path));
|
|
if (retval < GP_OK)
|
|
return retval;
|
|
|
|
/* We don't support updating permissions (yet) */
|
|
if (info.file.fields & GP_FILE_INFO_PERMISSIONS)
|
|
return (GP_ERROR_NOT_SUPPORTED);
|
|
|
|
if (info.file.fields & GP_FILE_INFO_MTIME) {
|
|
struct utimbuf utimbuf;
|
|
|
|
utimbuf.actime = info.file.mtime;
|
|
utimbuf.modtime = info.file.mtime;
|
|
if (utime (path, &utimbuf) != 0) {
|
|
int saved_errno = errno;
|
|
gp_context_error (context, _("Could not change "
|
|
"time of file '%s' in '%s' (%s)."),
|
|
file, folder, strerror(saved_errno));
|
|
return (GP_ERROR);
|
|
}
|
|
}
|
|
|
|
#if 0 /* implement this using new api -Marcus */
|
|
if (info.file.fields & GP_FILE_INFO_NAME) {
|
|
if (!strcasecmp (info.file.name, file))
|
|
return (GP_OK);
|
|
|
|
/* We really have to rename the poor file... */
|
|
if (strlen (folder) == 1) {
|
|
snprintf (path_old, sizeof (path_old), "/%s",
|
|
file);
|
|
snprintf (path_new, sizeof (path_new), "/%s",
|
|
info.file.name);
|
|
} else {
|
|
snprintf (path_old, sizeof (path_old), "%s/%s",
|
|
folder, file);
|
|
snprintf (path_new, sizeof (path_new), "%s/%s",
|
|
folder, info.file.name);
|
|
}
|
|
retval = rename (path_old, path_new);
|
|
if (retval != 0) {
|
|
switch (errno) {
|
|
case EISDIR:
|
|
return (GP_ERROR_DIRECTORY_EXISTS);
|
|
case EEXIST:
|
|
return (GP_ERROR_FILE_EXISTS);
|
|
case EINVAL:
|
|
return (GP_ERROR_BAD_PARAMETERS);
|
|
case EIO:
|
|
return (GP_ERROR_IO);
|
|
case ENOMEM:
|
|
return (GP_ERROR_NO_MEMORY);
|
|
case ENOENT:
|
|
return (GP_ERROR_FILE_NOT_FOUND);
|
|
default:
|
|
return (GP_ERROR);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
static int
|
|
get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
|
|
CameraFileType type, CameraFile *file, void *user_data,
|
|
GPContext *context)
|
|
{
|
|
char path[1024];
|
|
int result = GP_OK;
|
|
struct stat stbuf;
|
|
int fd, id;
|
|
off_t curread, toread;
|
|
unsigned char *buf;
|
|
#ifdef HAVE_LIBEXIF
|
|
ExifData *data;
|
|
unsigned int buf_len;
|
|
#endif /* HAVE_LIBEXIF */
|
|
Camera *camera = (Camera*)user_data;
|
|
|
|
result = _get_path (camera->port, folder, filename, path, sizeof(path));
|
|
if (result < GP_OK)
|
|
return result;
|
|
|
|
if (-1 == lstat(path,&stbuf))
|
|
return GP_ERROR_IO_READ;
|
|
|
|
gp_file_set_mtime (file, stbuf.st_mtime);
|
|
|
|
switch (type) {
|
|
case GP_FILE_TYPE_NORMAL:
|
|
#ifdef DEBUG
|
|
case GP_FILE_TYPE_PREVIEW:
|
|
#endif
|
|
fd = open (path,O_RDONLY);
|
|
if (fd == -1)
|
|
return GP_ERROR_IO_READ;
|
|
break;
|
|
#ifdef HAVE_LIBEXIF
|
|
case GP_FILE_TYPE_EXIF:
|
|
data = exif_data_new_from_file (path);
|
|
if (!data) {
|
|
gp_context_error (context, _("Could not open '%s'."),
|
|
path);
|
|
return (GP_ERROR);
|
|
}
|
|
exif_data_save_data (data, &buf, &buf_len);
|
|
exif_data_unref (data);
|
|
gp_file_set_data_and_size (file, (char *)buf, buf_len);
|
|
return (GP_OK);
|
|
#endif /* HAVE_LIBEXIF */
|
|
default:
|
|
return (GP_ERROR_NOT_SUPPORTED);
|
|
}
|
|
#define BLOCKSIZE 65536
|
|
/* do it in 64kb blocks */
|
|
buf = malloc(BLOCKSIZE);
|
|
if (!buf) {
|
|
close (fd);
|
|
return GP_ERROR_NO_MEMORY;
|
|
}
|
|
if (-1 == fstat(fd,&stbuf)) {
|
|
free (buf);
|
|
close (fd);
|
|
return GP_ERROR_IO_READ;
|
|
}
|
|
|
|
curread = 0;
|
|
id = gp_context_progress_start (context, (1.0*stbuf.st_size/BLOCKSIZE), _("Getting file..."));
|
|
GP_DEBUG ("Progress id: %i", id);
|
|
result = GP_OK;
|
|
while (curread < stbuf.st_size) {
|
|
int ret;
|
|
|
|
toread = stbuf.st_size-curread;
|
|
if (toread>BLOCKSIZE) toread = BLOCKSIZE;
|
|
ret = read(fd,buf,toread);
|
|
if (ret == -1) {
|
|
result = GP_ERROR_IO_READ;
|
|
break;
|
|
}
|
|
curread += ret;
|
|
gp_file_append (file, (char *)buf, ret);
|
|
gp_context_progress_update (context, id, (1.0*curread/BLOCKSIZE));
|
|
gp_context_idle (context);
|
|
if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
|
|
result = GP_ERROR_CANCEL;
|
|
break;
|
|
}
|
|
#if 0
|
|
/* We could take 2 seconds to download this image. everytime. */
|
|
/* But actually this driver is used in production by some frontends,
|
|
* so do not delay at all
|
|
*/
|
|
usleep(2000000/(stbuf.st_size/BLOCKSIZE));
|
|
#endif
|
|
}
|
|
gp_context_progress_stop (context, id);
|
|
free (buf);
|
|
close (fd);
|
|
return (GP_OK);
|
|
}
|
|
|
|
static int
|
|
camera_manual (Camera *camera, CameraText *manual, GPContext *context)
|
|
{
|
|
strcpy (manual->text, _("The Directory Browse \"camera\" lets "
|
|
"you index photos on your hard drive."));
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
static int
|
|
camera_about (Camera *camera, CameraText *about, GPContext *context)
|
|
{
|
|
strcpy (about->text, _("Directory Browse Mode - written "
|
|
"by Scott Fritzinger <scottf@unr.edu>."));
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
static int
|
|
make_dir_func (CameraFilesystem *fs, const char *folder, const char *name,
|
|
void *data, GPContext *context)
|
|
{
|
|
char path[2048];
|
|
Camera *camera = (Camera*)data;
|
|
int result;
|
|
|
|
result = _get_path (camera->port, folder, name, path, sizeof(path));
|
|
if (result < GP_OK)
|
|
return result;
|
|
return gp_system_mkdir (path);
|
|
}
|
|
|
|
static int
|
|
remove_dir_func (CameraFilesystem *fs, const char *folder, const char *name,
|
|
void *data, GPContext *context)
|
|
{
|
|
char path[2048];
|
|
Camera *camera = (Camera*)data;
|
|
int result;
|
|
|
|
result = _get_path (camera->port, folder, name, path, sizeof(path));
|
|
if (result < GP_OK)
|
|
return result;
|
|
return gp_system_rmdir (path);
|
|
}
|
|
|
|
static int
|
|
delete_file_func (CameraFilesystem *fs, const char *folder,
|
|
const char *file, void *data, GPContext *context)
|
|
{
|
|
char path[2048];
|
|
int result;
|
|
Camera *camera = (Camera*)data;
|
|
|
|
result = _get_path (camera->port, folder, file, path, sizeof(path));
|
|
if (result < GP_OK)
|
|
return result;
|
|
result = unlink (path);
|
|
if (result) {
|
|
int saved_errno = errno;
|
|
gp_context_error (context, _("Could not delete file '%s' "
|
|
"in folder '%s' (error code %i: %s)."),
|
|
file, folder, result, strerror(saved_errno));
|
|
return (GP_ERROR);
|
|
}
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
static int
|
|
put_file_func (CameraFilesystem *fs, const char *folder, const char *name,
|
|
CameraFileType type, CameraFile *file, void *data, GPContext *context)
|
|
{
|
|
char path[2048];
|
|
int result;
|
|
#ifdef DEBUG
|
|
unsigned int i, id;
|
|
#endif
|
|
Camera *camera = (Camera*)data;
|
|
|
|
result = _get_path (camera->port, folder, name, path, sizeof(path));
|
|
if (result < GP_OK)
|
|
return result;
|
|
|
|
result = gp_file_save (file, path);
|
|
if (result < 0)
|
|
return (result);
|
|
|
|
#ifdef DEBUG
|
|
id = gp_context_progress_start (context, 500., "Uploading file...");
|
|
for (i = 0; i < 500; i++) {
|
|
gp_context_progress_update (context, id, i + 1);
|
|
gp_context_idle (context);
|
|
if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL)
|
|
return (result);
|
|
usleep (10);
|
|
}
|
|
gp_context_progress_stop (context, id);
|
|
#endif
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
static int
|
|
camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context)
|
|
{
|
|
int r;
|
|
|
|
r = gp_file_open (file, "/usr/share/pixmaps/gnome-logo-large.png");
|
|
if (r < 0)
|
|
return (r);
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
static int
|
|
camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path,
|
|
GPContext *context)
|
|
{
|
|
if (path) {
|
|
strcpy (path->folder, "/usr/share/pixmaps");
|
|
strcpy (path->name, "gnome-logo-large.png");
|
|
}
|
|
|
|
return (GP_OK);
|
|
}
|
|
#endif
|
|
|
|
static int
|
|
storage_info_func (CameraFilesystem *fs,
|
|
CameraStorageInformation **sinfos,
|
|
int *nrofsinfos,
|
|
void *data, GPContext *context
|
|
) {
|
|
Camera *camera = data;
|
|
CameraStorageInformation *sfs;
|
|
|
|
#if defined(HAVE_STATVFS)
|
|
struct statvfs stfs;
|
|
char *xpath;
|
|
int ret;
|
|
|
|
ret = _get_mountpoint (camera->port, &xpath);
|
|
if (ret < GP_OK)
|
|
return ret;
|
|
if (-1 == statvfs (xpath, &stfs))
|
|
return GP_ERROR_NOT_SUPPORTED;
|
|
|
|
sfs = malloc (sizeof (CameraStorageInformation));
|
|
if (!sfs)
|
|
return GP_ERROR_NO_MEMORY;
|
|
*sinfos = sfs;
|
|
*nrofsinfos = 1;
|
|
|
|
sfs->fields = GP_STORAGEINFO_BASE |
|
|
GP_STORAGEINFO_DESCRIPTION |
|
|
GP_STORAGEINFO_STORAGETYPE |
|
|
GP_STORAGEINFO_FILESYSTEMTYPE |
|
|
GP_STORAGEINFO_ACCESS |
|
|
GP_STORAGEINFO_MAXCAPACITY |
|
|
GP_STORAGEINFO_FREESPACEKBYTES;
|
|
;
|
|
strcpy (sfs->basedir, "/");
|
|
strcpy (sfs->description, "Directory Driver");
|
|
sfs->type = GP_STORAGEINFO_ST_REMOVABLE_RAM;
|
|
sfs->fstype = GP_STORAGEINFO_FST_GENERICHIERARCHICAL;
|
|
sfs->access = GP_STORAGEINFO_AC_READWRITE;
|
|
if (stfs.f_bsize >= 1024) {
|
|
sfs->capacitykbytes = stfs.f_blocks*(stfs.f_bsize/1024);
|
|
sfs->freekbytes = stfs.f_bavail*(stfs.f_bsize/1024);
|
|
} else {
|
|
sfs->capacitykbytes = stfs.f_blocks/(1024/stfs.f_bsize);
|
|
sfs->freekbytes = stfs.f_bavail/(1024/stfs.f_bsize);
|
|
}
|
|
return GP_OK;
|
|
#endif
|
|
|
|
return GP_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
static CameraFilesystemFuncs fsfuncs = {
|
|
.file_list_func = file_list_func,
|
|
.folder_list_func = folder_list_func,
|
|
.set_info_func = set_info_func,
|
|
.get_info_func = get_info_func,
|
|
.get_file_func = get_file_func,
|
|
.put_file_func = put_file_func,
|
|
.del_file_func = delete_file_func,
|
|
.make_dir_func = make_dir_func,
|
|
.remove_dir_func = remove_dir_func,
|
|
.storage_info_func = storage_info_func,
|
|
};
|
|
|
|
int
|
|
camera_init (Camera *camera, GPContext *context)
|
|
{
|
|
/* First, set up all the function pointers */
|
|
camera->functions->manual = camera_manual;
|
|
camera->functions->about = camera_about;
|
|
return gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);
|
|
}
|