/api/program/on-usb
GETDetects whether the CloudCoin Console program is running from a USB drive or removable storage device.
Description
The `/api/program/on-usb` endpoint determines if the CloudCoin Console server is running from a USB drive or other removable storage device. This is particularly useful for portable wallet deployments where users carry their CloudCoin wallets on USB flash drives, external hard drives, or SD cards.
This endpoint is useful for:
- Portable Wallet Detection - Identify when users are running CloudCoin from a USB drive
- Security Recommendations - Warn users about USB drive security risks (physical theft, loss)
- Backup Reminders - Prompt USB users to maintain cloud or desktop backups
- Performance Adjustments - Optimize I/O operations for slower USB 2.0 drives
- Auto-eject Warnings - Prevent users from removing USB drives during critical operations
- Licensing/DRM - Implement portable licensing tied to USB storage
USB drive detection varies by operating system:
- Windows: Full support using
GetDriveTypeA()Win32 API. DetectsDRIVE_REMOVABLEtype drives including USB flash drives, external hard drives, and SD card readers. - Linux/macOS: Currently returns
false(placeholder implementation). Full support requires parsing/proc/mountsor equivalent system information.
Note: On Windows, the detection checks the drive letter (e.g., E:\, F:\) from the program's root path. Network drives and virtual drives are not classified as removable.
Parameters
This endpoint does not require any parameters.
Response
Returns a JSON object indicating whether the program is running from a USB or removable drive.
Response Properties
true if running from a removable drive (USB flash drive, external HDD, SD card),
false if running from internal storage (HDD, SSD, or non-removable drive).
E:\CloudCoin\Pro on Windows or /media/usb/CloudCoin/Pro on Linux).Example Response (USB Drive - Windows)
{
"status": "success",
"operation": "program_on_usb",
"on_usb": true,
"root_path": "E:\\CloudCoin\\Pro"
}
Example Response (Internal Drive - Windows)
{
"status": "success",
"operation": "program_on_usb",
"on_usb": false,
"root_path": "C:\\Program Files\\CloudCoin\\Pro"
}
Example Response (Linux - Not Implemented)
{
"status": "success",
"operation": "program_on_usb",
"on_usb": false,
"root_path": "/home/user/CloudCoin/Pro"
}
Examples
JavaScript (fetch)
const API_HOST = 'http://localhost:8080';
async function checkUSBStorage() {
try {
const response = await fetch(`${API_HOST}/api/program/on-usb`);
const result = await response.json();
console.log(`Running from USB: ${result.on_usb}`);
console.log(`Root path: ${result.root_path}`);
if (result.on_usb) {
// Show portable mode features
displayPortableWalletUI();
// Warn about USB-specific risks
showSecurityWarning(
'USB Drive Detected',
'Your wallet is on removable storage. Keep your USB drive secure and maintain backups.'
);
// Enable auto-save before eject
enableAutoSaveOnEject();
} else {
// Standard desktop installation
displayStandardUI();
}
} catch (error) {
console.error('Error checking USB status:', error);
}
}
function displayPortableWalletUI() {
// Add "Safely Eject" button
const ejectBtn = document.createElement('button');
ejectBtn.textContent = 'Safely Eject USB Drive';
ejectBtn.onclick = safelyEjectUSB;
document.body.appendChild(ejectBtn);
}
function showSecurityWarning(title, message) {
// Display warning banner
const banner = document.createElement('div');
banner.className = 'warning-banner';
banner.innerHTML = `${title}: ${message}`;
document.body.prepend(banner);
}
function enableAutoSaveOnEject() {
// Monitor for USB removal events
window.addEventListener('beforeunload', (e) => {
// Save wallet state before USB is ejected
saveWalletState();
});
}
checkUSBStorage();
cURL
# Check if running from USB drive
curl -X GET "http://localhost:8080/api/program/on-usb"
# With formatted output using jq
curl -X GET "http://localhost:8080/api/program/on-usb" | jq '.'
# Check USB status and extract boolean value
curl -s "http://localhost:8080/api/program/on-usb" | jq -r '.on_usb'
Go
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
const ApiHost = "http://localhost:8080"
type USBResponse struct {
Status string `json:"status"`
Operation string `json:"operation"`
OnUSB bool `json:"on_usb"`
RootPath string `json:"root_path"`
}
func main() {
resp, err := http.Get(fmt.Sprintf("%s/api/program/on-usb", ApiHost))
if err != nil {
log.Fatalf("Failed to check USB status: %v", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalf("Failed to read response: %v", err)
}
var result USBResponse
if err := json.Unmarshal(body, &result); err != nil {
log.Fatalf("Failed to parse JSON: %v", err)
}
fmt.Printf("CloudCoin Console Location: %s\n", result.RootPath)
if result.OnUSB {
fmt.Println("⚠️ Running from USB drive (removable storage)")
fmt.Println("Security Recommendations:")
fmt.Println(" - Keep your USB drive physically secure")
fmt.Println(" - Maintain encrypted backups on separate storage")
fmt.Println(" - Use 'Safely Eject' before removing USB")
fmt.Println(" - Consider using AES-256 encryption for wallet files")
// Adjust settings for portable mode
enablePortableMode()
} else {
fmt.Println("✓ Running from internal/fixed storage")
// Use standard configuration
enableStandardMode()
}
}
func enablePortableMode() {
// Reduce caching to minimize data loss on sudden USB removal
fmt.Println("\nEnabling portable mode:")
fmt.Println(" - Aggressive auto-save: Every 30 seconds")
fmt.Println(" - Reduced cache size: 10 MB")
fmt.Println(" - Safe-eject monitoring: Enabled")
}
func enableStandardMode() {
fmt.Println("\nUsing standard mode:")
fmt.Println(" - Auto-save: Every 5 minutes")
fmt.Println(" - Cache size: 100 MB")
}
Python
import requests
import json
from datetime import datetime
API_HOST = 'http://localhost:8080'
def check_usb_storage():
"""Check if CloudCoin Console is running from USB drive"""
try:
response = requests.get(f'{API_HOST}/api/program/on-usb')
result = response.json()
on_usb = result.get('on_usb', False)
root_path = result.get('root_path', 'Unknown')
print(f'CloudCoin Location: {root_path}')
print(f'USB Drive: {"Yes" if on_usb else "No"}')
print()
if on_usb:
print('⚠️ PORTABLE WALLET DETECTED')
print('=' * 50)
print('Security Recommendations:')
print(' 1. Enable wallet encryption (AES-256)')
print(' 2. Maintain cloud/desktop backups')
print(' 3. Use "Safely Eject" before removing USB')
print(' 4. Keep USB drive in secure location')
print(' 5. Consider using a hardware wallet lock')
print()
# Configure for USB mode
config = get_usb_configuration()
apply_configuration(config)
else:
print('✓ Standard Installation')
print('Using default desktop configuration')
print()
config = get_standard_configuration()
apply_configuration(config)
return result
except requests.exceptions.RequestException as e:
print(f'Error checking USB status: {e}')
return None
def get_usb_configuration():
"""Get optimized configuration for USB drives"""
return {
'auto_save_interval': 30, # seconds
'cache_size_mb': 10,
'enable_safe_eject_monitor': True,
'io_buffer_size': 4096, # Smaller buffer for USB 2.0
'encryption_recommended': True,
'backup_reminder_frequency': 'daily'
}
def get_standard_configuration():
"""Get standard configuration for internal drives"""
return {
'auto_save_interval': 300, # 5 minutes
'cache_size_mb': 100,
'enable_safe_eject_monitor': False,
'io_buffer_size': 65536, # Larger buffer for SSDs
'encryption_recommended': False,
'backup_reminder_frequency': 'weekly'
}
def apply_configuration(config):
"""Apply configuration settings"""
print('Configuration Applied:')
for key, value in config.items():
print(f' {key}: {value}')
def monitor_usb_ejection():
"""Monitor for USB drive removal (Windows only)"""
import time
print('\nMonitoring USB drive (Press Ctrl+C to stop)...')
try:
while True:
response = requests.get(f'{API_HOST}/api/program/on-usb')
result = response.json()
if not result.get('on_usb', True):
print(f'\n[{datetime.now()}] WARNING: USB drive removed!')
print('Wallet may no longer be accessible.')
break
time.sleep(5) # Check every 5 seconds
except KeyboardInterrupt:
print('\nMonitoring stopped.')
if __name__ == '__main__':
result = check_usb_storage()
if result and result.get('on_usb'):
# Optionally start USB ejection monitoring
monitor = input('\nStart USB ejection monitoring? (y/n): ')
if monitor.lower() == 'y':
monitor_usb_ejection()
Implementation Details
The USB drive detection uses platform-specific system calls to identify removable storage:
// Windows implementation (filesystem.c)
bool is_usb_drive(const char* path) {
#ifdef _WIN32
if (strlen(path) < 3) return false;
// Extract drive letter (e.g., "E:\")
char drive[4] = {path[0], ':', '\\', '\0'};
// Query Windows for drive type
UINT drive_type = GetDriveTypeA(drive);
// DRIVE_REMOVABLE = 2 (USB flash, SD cards, external drives)
// DRIVE_FIXED = 3 (internal HDD/SSD)
// DRIVE_REMOTE = 4 (network drives)
// DRIVE_CDROM = 5 (CD/DVD drives)
return (drive_type == DRIVE_REMOVABLE);
#else
// Linux/macOS: Requires parsing /proc/mounts
// Currently not implemented (returns false)
return false;
#endif
}
| Platform | Detection Method | Detects | Status |
|---|---|---|---|
| Windows | GetDriveTypeA() Win32 API |
USB flash drives, external HDDs, SD cards | ✓ Fully Supported |
| Linux | Requires /proc/mounts parsing |
USB mounts (e.g., /media/usb) |
⚠️ Not Implemented |
| macOS | Requires /Volumes analysis |
External drives mounted in /Volumes |
⚠️ Not Implemented |
Practical Applications
1. Security Warnings for Portable Wallets
Automatically display security recommendations when USB storage is detected:
async function initializeWallet() {
const response = await fetch('/api/program/on-usb');
const result = await response.json();
if (result.on_usb) {
// Show prominent security banner
showSecurityBanner({
title: 'Portable Wallet Detected',
message: 'Your wallet is on removable storage.',
recommendations: [
'Enable AES-256 encryption for all coin files',
'Create encrypted backups on cloud storage',
'Use "Safely Eject" before removing USB',
'Store USB drive in a secure, fireproof location'
],
icon: '⚠️',
dismissible: false
});
// Offer to enable encryption
if (!walletIsEncrypted()) {
offerEncryptionWizard();
}
}
}
2. Performance Optimization for USB 2.0
Adjust I/O buffer sizes and batch operations for slower USB drives:
async function getOptimalIOSettings() {
const response = await fetch('/api/program/on-usb');
const result = await response.json();
const settings = {
// USB 2.0: ~35 MB/s, USB 3.0: ~400 MB/s, SSD: ~500 MB/s
bufferSize: result.on_usb ? 4096 : 65536,
batchSize: result.on_usb ? 25 : 100,
simultaneousOps: result.on_usb ? 1 : 4,
cacheEnabled: !result.on_usb, // Disable cache on USB
autoSaveInterval: result.on_usb ? 30000 : 300000 // 30s vs 5min
};
console.log('I/O Settings:', settings);
return settings;
}
async function importCoins(files) {
const settings = await getOptimalIOSettings();
// Process in smaller batches on USB to prevent timeouts
for (let i = 0; i < files.length; i += settings.batchSize) {
const batch = files.slice(i, i + settings.batchSize);
await processBatchWithSettings(batch, settings);
}
}
3. Safe Eject Monitoring
Prevent data loss by blocking USB removal during critical operations:
let criticalOperationInProgress = false;
async function detectCoins(coinFiles) {
const response = await fetch('/api/program/on-usb');
const result = await response.json();
if (result.on_usb) {
// Enable USB removal monitoring
startUSBMonitoring();
criticalOperationInProgress = true;
}
try {
await performDetection(coinFiles);
} finally {
criticalOperationInProgress = false;
if (result.on_usb) {
stopUSBMonitoring();
}
}
}
function startUSBMonitoring() {
// Poll USB status every 2 seconds
window.usbMonitor = setInterval(async () => {
const response = await fetch('/api/program/on-usb');
const result = await response.json();
if (!result.on_usb && criticalOperationInProgress) {
// USB was removed during operation!
showCriticalError(
'USB Drive Removed',
'Your wallet USB drive was removed during a critical operation. ' +
'Data may be corrupted. Please reinsert the drive immediately.'
);
clearInterval(window.usbMonitor);
}
}, 2000);
}
function stopUSBMonitoring() {
if (window.usbMonitor) {
clearInterval(window.usbMonitor);
}
}
4. Portable Licensing
Tie software licenses to USB drives for portable installations:
async function validatePortableLicense() {
const response = await fetch('/api/program/on-usb');
const result = await response.json();
if (result.on_usb) {
console.log('Portable wallet detected - no cloud sync required');
// Check for license file on USB
const licenseValid = await checkLocalLicense(result.root_path);
if (licenseValid) {
console.log('✓ Portable license validated');
return true;
} else {
console.error('⚠️ No valid license found on USB drive');
showLicensePrompt();
return false;
}
} else {
// Desktop installation - check online license
return await validateOnlineLicense();
}
}
async function checkLocalLicense(rootPath) {
// Look for license.key file on USB
const licenseResponse = await fetch(`/api/license/check?path=${rootPath}`);
return licenseResponse.json();
}
Related Endpoints
/api/program/on-mobile
Check if the program is running on a mobile device (Android, iOS, ARM platforms).
/api/program/status
Get comprehensive program status including version, active wallet, and server time.
/api/wallet/list
List all configured wallets - useful for managing multiple USB wallets.