bool CUDevProvider::PumpDriveChangeEvents(IStorageEventsCallback *callback) { bool changed = false; fd_set readfds; FD_ZERO(&readfds); FD_SET(udev_monitor_get_fd(m_udevMon), &readfds); // non-blocking, check the file descriptor for received data struct timeval tv = {0}; int count = select(udev_monitor_get_fd(m_udevMon) + 1, &readfds, NULL, NULL, &tv); if (count < 0) return false; if (FD_ISSET(udev_monitor_get_fd(m_udevMon), &readfds)) { struct udev_device *dev = udev_monitor_receive_device(m_udevMon); if (!dev) return false; const char *action = udev_device_get_action(dev); const char *devtype = udev_device_get_devtype(dev); if (action) { const char *label = udev_device_get_property_value(dev, "ID_FS_LABEL"); const char *mountpoint = get_mountpoint(udev_device_get_devnode(dev)); if (!label) label = URIUtils::GetFileName(mountpoint); if (!strcmp(action, "add") && !strcmp(devtype, "partition")) { CLog::Log(LOGNOTICE, "UDev: Added %s", mountpoint); if (callback) callback->OnStorageAdded(label, mountpoint); changed = true; } if (!strcmp(action, "remove") && !strcmp(devtype, "partition")) { CLog::Log(LOGNOTICE, "UDev: Removed %s", mountpoint); if (callback) callback->OnStorageSafelyRemoved(label); changed = true; } } udev_device_unref(dev); } return changed; }
int oem_wipe_partition(int argc, char **argv) { int retval = -1; char mnt_point[MOUNT_POINT_SIZE] = ""; if (argc != 2) { error("oem erase called with wrong parameter!"); goto end; } if (get_mountpoint(argv[1], mnt_point)) goto end; print("CMD '%s %s'...\n", argv[0], mnt_point); retval = nuke_volume(mnt_point, BUFFER_SIZE); if (retval != 0) error("wipe partition failed: %s\n", mnt_point); end: return retval; }
int oem_erase_partition(int argc, char **argv) { int retval = -1; char mnt_point[MOUNT_POINT_SIZE] = ""; if (argc != 2) { /* Should not pass here ! */ error("oem erase called with wrong parameter!"); goto end; } if (get_mountpoint(argv[1], mnt_point)) goto end; print("CMD '%s %s'...\n", argv[0], mnt_point); print("ERASE step 1/2...\n"); retval = nuke_volume(mnt_point, BUFFER_SIZE); if (retval != 0) { error("format_volume failed: %s\n", mnt_point); goto end; } else { print("format_volume succeeds: %s\n", mnt_point); } print("ERASE step 2/2...\n"); retval = format_volume(mnt_point); if (retval != 0) { error("format_volume failed: %s\n", mnt_point); } else { print("format_volume succeeds: %s\n", mnt_point); } end: return retval; }
void CUDevProvider::GetDisks(VECSOURCES& disks, bool removable) { // enumerate existing block devices struct udev_enumerate *u_enum = udev_enumerate_new(m_udev); if (u_enum == NULL) { fprintf(stderr, "Error: udev_enumerate_new(udev)\n"); return; } udev_enumerate_add_match_subsystem(u_enum, "block"); udev_enumerate_add_match_property(u_enum, "DEVTYPE", "disk"); udev_enumerate_add_match_property(u_enum, "DEVTYPE", "partition"); udev_enumerate_scan_devices(u_enum); struct udev_list_entry *u_list_ent; struct udev_list_entry *u_first_list_ent; u_first_list_ent = udev_enumerate_get_list_entry(u_enum); udev_list_entry_foreach(u_list_ent, u_first_list_ent) { const char *name = udev_list_entry_get_name(u_list_ent); struct udev *context = udev_enumerate_get_udev(u_enum); struct udev_device *device = udev_device_new_from_syspath(context, name); if (device == NULL) continue; // filter out devices that are not mounted const char *mountpoint = get_mountpoint(udev_device_get_devnode(device)); if (!mountpoint) { udev_device_unref(device); continue; } // filter out things mounted on /tmp if (strstr(mountpoint, "/tmp")) { udev_device_unref(device); continue; } // look for usb devices on the usb bus, or mounted on /media/usbX (sdcards) or cdroms const char *bus = udev_device_get_property_value(device, "ID_BUS"); const char *cdrom = udev_device_get_property_value(device, "ID_CDROM"); if (removable && ((bus && strstr(bus, "usb")) || (cdrom && strstr(cdrom,"1")) || (mountpoint && strstr(mountpoint, "/media/")))) { const char *label = udev_device_get_property_value(device, "ID_FS_LABEL"); if (!label) label = URIUtils::GetFileName(mountpoint); CMediaSource share; share.strName = label; share.strPath = mountpoint; share.m_ignore = true; share.m_iDriveType = CMediaSource::SOURCE_TYPE_REMOVABLE; AddOrReplace(disks, share); } udev_device_unref(device); } udev_enumerate_unref(u_enum); }
int main(int argc, char *argv[]) { //todo: add param for specific array char mdstat[] = "mdstat"; char mtab[] = "mounts"; char fstab[] = "fstab"; int foobar; char line[80]; char *ptr = NULL; char *tmp = NULL; char delim[2] = ":"; const char devname[22]; const char *uuid = NULL; FILE *fd; fd = fopen(mdstat, "r"); if (fd == NULL) { printf("Error: Could not open file %s", mdstat); return 1; } else { /*******************************************/ /* Getting number of arrays */ /*******************************************/ int arr_count = 0; int i = 0; while(fgets(line,80,fd) != NULL) { //todo: status, metadaten, member ptr = strtok(line, delim); if(ptr != NULL) { tmp = truncate_whitespace(ptr, strlen(ptr)); } if (strcmp(tmp, "Personalities") == 0) continue; if (strcmp(tmp, "read_ahead") == 0) continue; if (strcmp(tmp, "unused") == 0) continue; if (tmp[0] == '\n') continue; if (strlen(tmp) < 1) continue; if((strlen(tmp) > 0) && tmp[0] != '\n') { arr_count++; } } md_array cur_array[arr_count]; /*******************************************/ /* Getting the array name and skipping the */ /* "Personalities" */ /* "read_ahead" */ /* "unused" lines */ /*******************************************/ rewind(fd); char *p = NULL; while(fgets(line,80,fd) != NULL) { if(strstr(line, "raid") != NULL) { //Found a valid array line p=strstr(line, "raid0"); if(p != NULL) { cur_array[i].personality = 0; } p=strstr(line, "raid1"); if(p != NULL) { cur_array[i].personality = 1; } p=strstr(line, "raid5"); if(p != NULL) { cur_array[i].personality = 5; } p=strstr(line, "raid6"); if(p != NULL) { cur_array[i].personality = 6; } p=strstr(line, "raid10"); if(p != NULL) { cur_array[i].personality = 10; } } ptr = strtok(line, delim); if(ptr != NULL) { tmp = truncate_whitespace(ptr, strlen(ptr)); } if (strcmp(tmp, "Personalities") == 0) continue; if (strcmp(tmp, "read_ahead") == 0) continue; if (strcmp(tmp, "unused") == 0) continue; if (tmp[0] == '\n') continue; if (strlen(tmp) < 1) continue; snprintf(cur_array[i].name, sizeof cur_array[i].name, tmp); snprintf(cur_array[i].devpath, sizeof cur_array[i].devpath, "%s%s", "/dev/", cur_array[i].name); uuid = map_uuid(cur_array[i].devpath); if((strlen(uuid) != 36)) { uuid = "N/A"; snprintf(cur_array[i].uuid, sizeof cur_array[i].uuid, uuid); } else { snprintf(cur_array[i].uuid, sizeof cur_array[i].uuid, uuid); } snprintf(cur_array[i].mnt, sizeof cur_array[i].mnt, get_mountpoint(cur_array[i].devpath, mtab)); snprintf(cur_array[i].fstab, sizeof cur_array[i].fstab, get_mountpoint(cur_array[i].devpath, fstab)); cur_array[i].degraded = 0; cur_array[i].member_count = 0; cur_array[i].members = ""; i++; } fclose(fd); for (i = 0; i < arr_count; i++) { print_array_information(cur_array, i); printf("----------------------------------------------------------\n"); } } return 0; }
bool CUDevProvider::PumpDriveChangeEvents(IStorageEventsCallback *callback) { bool changed = false; fd_set readfds; FD_ZERO(&readfds); FD_SET(udev_monitor_get_fd(m_udevMon), &readfds); // non-blocking, check the file descriptor for received data struct timeval tv = {0}; int count = select(udev_monitor_get_fd(m_udevMon) + 1, &readfds, NULL, NULL, &tv); if (count < 0) return false; if (FD_ISSET(udev_monitor_get_fd(m_udevMon), &readfds)) { struct udev_device *dev = udev_monitor_receive_device(m_udevMon); if (!dev) return false; const char *action = udev_device_get_action(dev); if (action) { std::string label; const char *udev_label = udev_device_get_property_value(dev, "ID_FS_LABEL"); const char *mountpoint = get_mountpoint(udev_device_get_devnode(dev)); if (udev_label) label = udev_label; else if (mountpoint) label = URIUtils::GetFileName(mountpoint); const char *fs_usage = udev_device_get_property_value(dev, "ID_FS_USAGE"); if (mountpoint && strcmp(action, "add") == 0 && (fs_usage && strcmp(fs_usage, "filesystem") == 0)) { CLog::Log(LOGNOTICE, "UDev: Added %s", mountpoint); if (callback) callback->OnStorageAdded(label, mountpoint); changed = true; } if (strcmp(action, "remove") == 0 && (fs_usage && strcmp(fs_usage, "filesystem") == 0)) { if (callback) callback->OnStorageSafelyRemoved(label); changed = true; } if (strcmp(action, "change") == 0) { if (mountpoint) { CLog::Log(LOGNOTICE, "UDev: Changed / Added %s", mountpoint); if (callback) callback->OnStorageAdded(label, mountpoint); changed = true; } const char *eject_request = udev_device_get_property_value(dev, "DISK_EJECT_REQUEST"); if (eject_request && strcmp(eject_request, "1") == 0) { if (callback) callback->OnStorageSafelyRemoved(label); changed = true; } } } udev_device_unref(dev); } return changed; }
void CUDevProvider::GetDisks(VECSOURCES& disks, bool removable) { // enumerate existing block devices struct udev_enumerate *u_enum = udev_enumerate_new(m_udev); if (u_enum == NULL) { fprintf(stderr, "Error: udev_enumerate_new(udev)\n"); return; } udev_enumerate_add_match_subsystem(u_enum, "block"); udev_enumerate_add_match_property(u_enum, "DEVTYPE", "disk"); udev_enumerate_add_match_property(u_enum, "DEVTYPE", "partition"); udev_enumerate_scan_devices(u_enum); struct udev_list_entry *u_list_ent; struct udev_list_entry *u_first_list_ent; u_first_list_ent = udev_enumerate_get_list_entry(u_enum); udev_list_entry_foreach(u_list_ent, u_first_list_ent) { const char *name = udev_list_entry_get_name(u_list_ent); struct udev *context = udev_enumerate_get_udev(u_enum); struct udev_device *device = udev_device_new_from_syspath(context, name); if (device == NULL) continue; // filter out devices that are not mounted const char *mountpoint = get_mountpoint(udev_device_get_devnode(device)); if (!mountpoint) { udev_device_unref(device); continue; } // filter out root partition if (strcmp(mountpoint, "/") == 0) { udev_device_unref(device); continue; } // filter out things mounted on /tmp if (strstr(mountpoint, "/tmp")) { udev_device_unref(device); continue; } // look for devices on the usb bus, or mounted on */media/ (sdcards), or optical devices const char *bus = udev_device_get_property_value(device, "ID_BUS"); const char *optical = udev_device_get_property_value(device, "ID_CDROM"); // matches also DVD, Blu-ray bool isRemovable = ((bus && strstr(bus, "usb")) || (optical && strstr(optical,"1")) || (mountpoint && strstr(mountpoint, "/media/"))); // filter according to requested device type if (removable != isRemovable) { udev_device_unref(device); continue; } const char *udev_label = udev_device_get_property_value(device, "ID_FS_LABEL"); std::string label; if (udev_label) label = udev_label; else label = URIUtils::GetFileName(mountpoint); CMediaSource share; share.strName = label; share.strPath = mountpoint; share.m_ignore = true; if (isRemovable) { if (optical) share.m_iDriveType = CMediaSource::SOURCE_TYPE_DVD; else share.m_iDriveType = CMediaSource::SOURCE_TYPE_REMOVABLE; } else share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL; disks.push_back(share); udev_device_unref(device); } udev_enumerate_unref(u_enum); }
int main(int argc, char *argv[]) { if(argc<2) { std::cout << "Not enough parameters" << std::endl; return 1; } std::string cmd; int mode = 0; if((std::string)argv[1]!="test") { if(argc<3) { std::cout << "Not enough parameters" << std::endl; return 1; } cmd=argv[2]; mode=atoi(argv[1]); } else { cmd=argv[1]; } std::string backupfolder=getBackupfolderPath(mode); if(backupfolder.empty()) { if(mode==mode_btrfs) { std::cout << "Backupfolder not set" << std::endl; } else if(mode==mode_zfs) { std::cout << "ZFS image dataset not set" << std::endl; } else if(mode==mode_zfs_file) { std::cout << "ZFS file dataset not set" << std::endl; } else { std::cout << "Unknown mode: " << mode << std::endl; } return 1; } if(cmd!="test" && mode==mode_zfs_file) { mode=mode_zfs; } #ifndef _WIN32 if(seteuid(0)!=0) { std::cout << "Cannot become root user" << std::endl; return 1; } #endif if(cmd=="create") { if(argc<5) { std::cout << "Not enough parameters for create" << std::endl; return 1; } std::string clientname=handleFilename(argv[3]); std::string name=handleFilename(argv[4]); std::string subvolume_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+name; return create_subvolume(mode, subvolume_folder)?0:1; } else if(cmd=="mountpoint") { if(argc<5) { std::cout << "Not enough parameters for mountpoint" << std::endl; return 1; } std::string clientname=handleFilename(argv[3]); std::string name=handleFilename(argv[4]); std::string subvolume_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+name; return get_mountpoint(mode, subvolume_folder)?0:1; } else if(cmd=="snapshot") { if(argc<6) { std::cout << "Not enough parameters for snapshot" << std::endl; return 1; } std::string clientname=handleFilename(argv[3]); std::string src_name=handleFilename(argv[4]); std::string dst_name=handleFilename(argv[5]); std::string subvolume_src_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+src_name; std::string subvolume_dst_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+dst_name; return create_snapshot(mode, subvolume_src_folder, subvolume_dst_folder)?0:1; } else if(cmd=="remove") { if(argc<5) { std::cout << "Not enough parameters for remove" << std::endl; return 1; } std::string clientname=handleFilename(argv[3]); std::string name=handleFilename(argv[4]); std::string subvolume_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+name; return remove_subvolume(mode, subvolume_folder)?0:1; } else if(cmd=="test") { std::cout << "Testing for btrfs..." << std::endl; std::string clientdir=backupfolder+os_file_sep()+"testA54hj5luZtlorr494"; bool create_dir_rc=os_create_dir(clientdir); if(!create_dir_rc) { remove_subvolume(mode_zfs, clientdir, true); remove_subvolume(mode_btrfs, clientdir+os_file_sep()+"A", true); remove_subvolume(mode_btrfs, clientdir+os_file_sep()+"B", true); os_remove_dir(clientdir); } create_dir_rc = create_dir_rc || os_create_dir(clientdir); if(create_dir_rc) { if(!create_subvolume(mode_btrfs, clientdir+os_file_sep()+"A") ) { std::cout << "TEST FAILED: Creating test btrfs subvolume failed" << std::endl; os_remove_dir(clientdir); return zfs_test(); } bool suc=true; if(!create_snapshot(mode_btrfs, clientdir+os_file_sep()+"A", clientdir+os_file_sep()+"B") ) { std::cout << "TEST FAILED: Creating test snapshot failed" << std::endl; suc=false; } if(suc) { writestring("test", clientdir+os_file_sep()+"A"+os_file_sep()+"test"); if(!os_create_hardlink(clientdir+os_file_sep()+"B"+os_file_sep()+"test", clientdir+os_file_sep()+"A"+os_file_sep()+"test", true, NULL)) { std::cout << "TEST FAILED: Creating cross sub-volume reflink failed. Need Linux kernel >= 3.6." << std::endl; suc=false; } else { if(getFile(clientdir+os_file_sep()+"B"+os_file_sep()+"test")!="test") { std::cout << "TEST FAILED: Cannot read reflinked file" << std::endl; suc=false; } } } if(!remove_subvolume(mode_btrfs, clientdir+os_file_sep()+"A") ) { std::cout << "TEST FAILED: Removing subvolume A failed" << std::endl; suc=false; } if(!remove_subvolume(mode_btrfs, clientdir+os_file_sep()+"B") ) { std::cout << "TEST FAILED: Removing subvolume B failed" << std::endl; suc=false; } if(!os_remove_dir(clientdir)) { std::cout << "TEST FAILED: Removing test clientdir failed" << std::endl; return 1; } if(!suc) { return 1; } } else { std::cout << "TEST FAILED: Creating test clientdir \"" << clientdir << "\" failed" << std::endl; return zfs_test(); } std::cout << "BTRFS TEST OK" << std::endl; return 10 + mode_btrfs; } else if(cmd=="issubvolume") { if(argc<5) { std::cout << "Not enough parameters for issubvolume" << std::endl; return 1; } std::string clientname=handleFilename(argv[3]); std::string name=handleFilename(argv[4]); std::string subvolume_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+name; return is_subvolume(mode, subvolume_folder)?0:1; } else if(cmd=="makereadonly") { if(argc<5) { std::cout << "Not enough parameters for makereadonly" << std::endl; return 1; } std::string clientname=handleFilename(argv[3]); std::string name=handleFilename(argv[4]); std::string subvolume_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+name; return make_readonly(mode, subvolume_folder)?0:1; } else { std::cout << "Command not found" << std::endl; return 1; } }