fxsdk/fxlink/modes/udisks2.c

133 lines
3.3 KiB
C

//---------------------------------------------------------------------------//
// ==>/[_]\ fxlink: A community communication tool for CASIO calculators. //
// |:::| Made by Lephe' as part of the fxSDK. //
// \___/ License: MIT <https://opensource.org/licenses/MIT> //
//---------------------------------------------------------------------------//
#include <fxlink/config.h>
#ifndef FXLINK_DISABLE_UDISKS2
#include "../fxlink.h"
#include <fxlink/tooling/udisks2.h>
#include <fxlink/filter.h>
#include <fxlink/logging.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main_send(struct fxlink_filter *filter, delay_t *delay, char **files,
char *outfolder)
{
fxlink_filter_clean_udisks2(filter);
GError *error = NULL;
char **argv = NULL;
int rc = 0;
UDisksClient *udc = NULL;
UDisksManager *udm = NULL;
if(ud2_start(&udc, &udm)) return 1;
UDisksBlock *block = NULL;
UDisksDrive *drive = NULL;
UDisksFilesystem *fs = NULL;
rc = ud2_unique_wait(filter, delay, udc, udm, &block, &drive, &fs);
if(rc != FXLINK_FILTER_UNIQUE) {
rc = 1;
goto end;
}
/* Determine a mount folder, mounting the volume if needed */
gchar *folder = NULL;
gchar const *dev = udisks_block_get_device(block);
gchar const * const * mount_points =
udisks_filesystem_get_mount_points(fs);
if(!mount_points || !mount_points[0]) {
GVariant *args = g_variant_new("a{sv}", NULL);
udisks_filesystem_call_mount_sync(fs, args, &folder, NULL, &error);
if(error) {
rc = elog("cannot mount %s: %s\n", dev, error->message);
goto end;
}
printf("Mounted %s to %s.\n", dev, folder);
}
else {
folder = mount_points[0];
printf("Already mounted at %s.\n", folder);
}
gchar *outpath = folder;
if(outfolder)
asprintf(&outpath, "%s/%s/", folder, outfolder);
/* Copy files with external cp(1) */
int file_count = 0;
while(files[file_count]) file_count++;
argv = malloc((file_count + 3) * sizeof *argv);
if(!argv) {
rc = elog("cannot allocate argv array for cp(1)\n");
goto end;
}
argv[0] = "cp";
for(int i = 0; files[i]; i++)
argv[i+1] = files[i];
argv[file_count+1] = outpath;
argv[file_count+2] = NULL;
/* Print command */
printf("Running cp");
for(int i = 1; argv[i]; i++) printf(" '%s'", argv[i]);
printf("\n");
pid_t pid = fork();
if(pid == 0) {
execvp("cp", argv);
}
else if(pid == -1) {
rc = elog("failed to fork to invoke cp\n");
goto end;
}
else {
int wstatus;
waitpid(pid, &wstatus, 0);
if(!WIFEXITED(wstatus))
elog("process did not terminate normally\n");
else if(WEXITSTATUS(wstatus) != 0) {
elog("process terminated with error %d\n", WEXITSTATUS(wstatus));
}
}
if(outfolder)
free(outpath);
/* Unmount the filesystem and eject the device */
GVariant *args = g_variant_new("a{sv}", NULL);
udisks_filesystem_call_unmount_sync(fs, args, NULL, &error);
if(error)
elog("while unmounting %s: %s\n", dev, error->message);
else
printf("Unmounted %s.\n", dev);
args = g_variant_new("a{sv}", NULL);
udisks_drive_call_power_off_sync(drive, args, NULL, &error);
if(error)
elog("while ejecting %s: %s\n", dev, error->message);
else
printf("Ejected %s.\n", dev);
end:
if(argv) free(argv);
if(fs) g_object_unref(fs);
if(drive) g_object_unref(drive);
if(block) g_object_unref(block);
if(udc && udm) ud2_end(udc, udm);
return rc;
}
#endif /* FXLINK_DISABLE_UDISKS2 */