int _rfs_link(struct rfs_instance *instance, const char *path, const char *target) { if (instance->sendrecv.socket == -1) { return -ECONNABORTED; } uint32_t path_len = strlen(path) + 1; unsigned target_len = strlen(target) + 1; unsigned overall_size = sizeof(path_len) + path_len + target_len; struct rfs_command cmd = { cmd_link, overall_size }; char *buffer = malloc(cmd.data_len); pack(target, target_len, pack(path, path_len, pack_32(&path_len, buffer ))); send_token_t token = { 0 }; if (do_send(&instance->sendrecv, queue_data(buffer, overall_size, queue_cmd(&cmd, &token))) < 0) { free(buffer); return -ECONNABORTED; } free(buffer); struct rfs_answer ans = { 0 }; if (rfs_receive_answer(&instance->sendrecv, &ans) == -1) { return -ECONNABORTED; } if (ans.command != cmd_link || ans.data_len != 0) { return cleanup_badmsg(instance, &ans); } if (ans.ret == 0) { delete_from_cache(&instance->attr_cache, path); } return ans.ret == -1 ? -ans.ret_errno : ans.ret; }
int _rfs_open(struct rfs_instance *instance, const char *path, int flags, uint64_t *desc) { if (instance->sendrecv.socket == -1) { return -ECONNABORTED; } unsigned path_len = strlen(path) + 1; uint16_t fi_flags = rfs_file_flags(flags); unsigned overall_size = sizeof(fi_flags) + path_len; struct rfs_command cmd = { cmd_open, overall_size }; char *buffer = malloc(cmd.data_len); pack(path, path_len, pack_16(&fi_flags, buffer )); send_token_t token = { 0 }; if (do_send(&instance->sendrecv, queue_data(buffer, overall_size, queue_cmd(&cmd, &token))) < 0) { free(buffer); return -ECONNABORTED; } free(buffer); struct rfs_answer ans = { 0 }; if (rfs_receive_answer(&instance->sendrecv, &ans) == -1) { return -ECONNABORTED; } if (ans.command != cmd_open) { return cleanup_badmsg(instance, &ans); } if (ans.ret == -1) { if (ans.ret_errno == -ENOENT) { delete_from_cache(&instance->attr_cache, path); } return -ans.ret_errno; } uint32_t stat_failed = 0; uint32_t user_len = 0; uint32_t group_len = 0; #define ans_buffer_size sizeof(*desc) \ + sizeof(stat_failed) + STAT_BLOCK_SIZE + sizeof(user_len) + sizeof(group_len) \ + (MAX_SUPPORTED_NAME_LEN + 1) + (MAX_SUPPORTED_NAME_LEN + 1) char ans_buffer[ans_buffer_size] = { 0 }; if (ans.data_len > sizeof(ans_buffer)) { return cleanup_badmsg(instance, &ans); } #undef ans_buffer_size if (rfs_receive_data(&instance->sendrecv, ans_buffer, ans.data_len) == -1) { return -ECONNABORTED; } struct stat stbuf = { 0 }; const char *user = unpack_32(&group_len, unpack_32(&user_len, unpack_stat(&stbuf, unpack_32(&stat_failed, unpack_64(desc, ans_buffer ))))); const char *group = user + user_len; DEBUG("handle: %llu\n", (long long unsigned)(*desc)); stbuf.st_uid = resolve_username(instance, user); stbuf.st_gid = resolve_groupname(instance, group, user); if (ans.ret_errno == 0) { if (stat_failed == 0) { cache_file(&instance->attr_cache, path, &stbuf); } resume_add_file_to_open_list(&instance->resume.open_files, path, flags, *desc); } else { delete_from_cache(&instance->attr_cache, path); } return ans.ret == -1 ? -ans.ret_errno : ans.ret; }
int _rfs_lock(struct rfs_instance *instance, const char *path, uint64_t desc, int lock_cmd, struct flock *fl) { if (instance->sendrecv.socket == -1) { return -ECONNABORTED; } if (fl->l_type == F_UNLCK && resume_is_file_in_locked_list(instance->resume.locked_files, path) == 0) { return 0; } uint16_t flags = 0; switch (lock_cmd) { case F_GETLK: flags = RFS_GETLK; break; case F_SETLK: flags = RFS_SETLK; break; case F_SETLKW: flags = RFS_SETLKW; break; default: return -EINVAL; } uint16_t type = 0; switch (fl->l_type) { case F_UNLCK: type = RFS_UNLCK; break; case F_RDLCK: type = RFS_RDLCK; break; case F_WRLCK: type = RFS_WRLCK; break; default: return -EINVAL; } uint16_t whence = fl->l_whence; uint64_t start = fl->l_start; uint64_t len = fl->l_len; uint64_t fd = desc; #define overall_size sizeof(fd) + sizeof(flags) + sizeof(type) + sizeof(whence) + sizeof(start) + sizeof(len) char buffer[overall_size] = { 0 }; pack_64(&len, pack_64(&start, pack_16(&whence, pack_16(&type, pack_16(&flags, pack_64(&fd, buffer )))))); struct rfs_command cmd = { cmd_lock, overall_size }; send_token_t token = { 0 }; if (do_send(&instance->sendrecv, queue_data(buffer, overall_size, queue_cmd(&cmd, &token))) < 0) { return -ECONNABORTED; } #undef overall_size struct rfs_answer ans = { 0 }; if (rfs_receive_answer(&instance->sendrecv, &ans) == -1) { return -ECONNABORTED; } if (ans.command != cmd_lock || ans.data_len != 0) { return cleanup_badmsg(instance, &ans); } if (ans.ret == 0 && (lock_cmd == F_SETLK || lock_cmd == F_SETLKW)) { if (fl->l_type == F_UNLCK) { resume_remove_file_from_locked_list(&instance->resume.locked_files, path); } else { resume_add_file_to_locked_list(&instance->resume.locked_files, path, fl->l_type, is_file_fully_locked(fl)); } } return ans.ret != 0 ? -ans.ret_errno : 0; }
int _rfs_create(struct rfs_instance *instance, const char *path, mode_t mode, int flags, uint64_t *desc) { if (instance->sendrecv.socket == -1) { return -ECONNABORTED; } unsigned path_len = strlen(path) + 1; uint32_t fmode = mode; uint16_t fi_flags = rfs_file_flags(flags); if ((fmode & 0777) == 0) { fmode |= 0600; } unsigned overall_size = sizeof(fmode) + sizeof(fi_flags) + path_len; struct rfs_command cmd = { cmd_create, overall_size }; char *buffer = malloc(cmd.data_len); pack(path, path_len, pack_16(&fi_flags, pack_32(&fmode, buffer ))); send_token_t token = { 0 }; if (do_send(&instance->sendrecv, queue_data(buffer, overall_size, queue_cmd(&cmd, &token))) < 0) { free(buffer); return -ECONNABORTED; } free(buffer); struct rfs_answer ans = { 0 }; if (rfs_receive_answer(&instance->sendrecv, &ans) == -1) { return -ECONNABORTED; } if (ans.command != cmd_create) { return cleanup_badmsg(instance, &ans); } if (ans.ret == 0) { uint64_t handle = (uint64_t)(-1); if (ans.data_len != sizeof(handle)) { return cleanup_badmsg(instance, &ans); } if (rfs_receive_data(&instance->sendrecv, &handle, ans.data_len) == -1) { return -ECONNABORTED; } *desc = ntohll(handle); /* add file to open list, but without O_CREAT flag to just reopen file * on connection resume */ resume_add_file_to_open_list(&instance->resume.open_files, path, (flags & ~O_CREAT), *desc); } return (ans.ret == 0 ? 0 : -ans.ret_errno); }
/** * commandParser parse commands received by the twi interface and trigger the * associated functions */ void parse_cmd(uint8_t cmd[CMD_SIZE]) { uint8_t i; /* Check new conditions and update status from tuxaudio */ if (cmd[0] == SEND_AUDIOSENSORS_CMD) { if ((cmd[1] & STATUS_HEADBTN_MK) && !(gStatus.sw & GSTATUS_HEADBTN_MK)) cond_flags.head = 1; if ((cmd[1] & STATUS_LEFTWINGBTN_MK) && !(gStatus.sw & GSTATUS_LEFTWINGBTN_MK)) cond_flags.left_flip = 1; if ((cmd[1] & STATUS_RIGHTWINGBTN_MK) && !(gStatus.sw & GSTATUS_RIGHTWINGBTN_MK)) cond_flags.right_flip = 1; if ((cmd[1] & STATUS_CHARGER_MK) && !(gStatus.sw & GSTATUS_CHARGER_MK)) cond_flags.charger_start = 1; if (!(cmd[1] & STATUS_POWERPLUGSW_MK) && (gStatus.sw & GSTATUS_POWERPLUGSW_MK)) cond_flags.unplug = 1; if ((cmd[1] & STATUS_RF_MK) && !(gStatus.sw & GSTATUS_RF_MK)) { cond_flags.rf_conn = 1; cond_flags.rf_disconn = 0; } if (!(cmd[1] & STATUS_RF_MK) && (gStatus.sw & GSTATUS_RF_MK)) { cond_flags.rf_conn = 0; cond_flags.rf_disconn = 1; } gStatus.sw = cmd[1]; gStatus.audio_play = cmd[2]; gStatus.audio_status = cmd[3]; return; } /* Ping */ else if (cmd[0] == PING_CMD) { pingCnt = cmd[1]; return; } /* Sound */ else if (cmd[0] == PLAY_SOUND_CMD) { /* Forward the cmd to the audio CPU. */ queue_cmd(cmd); return; } else if (cmd[0] == MUTE_CMD) { /* Forward the cmd to the audio CPU. */ queue_cmd(cmd); return; } /* Sleep mode */ else if (cmd[0] == SLEEP_CMD) { cond_flags.sleep = true; return; } /* Version */ else if (cmd[0] == INFO_TUXCORE_CMD) { uint8_t *p = (uint8_t *) &tag_version; uint8_t info[12]; for (i = 0; i < 12; i++) info[i] = pgm_read_byte(p++); queue_cmd(&info[0]); queue_cmd(&info[4]); queue_cmd(&info[8]); return; } /* Reset condition flags */ else if (cmd[0] == COND_RESET_CMD) { uint8_t *addr = (uint8_t *) & cond_flags; for (i = 0; i < COND_RESET_NBR; i++) *addr++ = 0; return; } else if (cmd[0] == LED_FADE_SPEED_CMD) { led_set_fade_speed(cmd[1], cmd[2], cmd[3]); } else if (cmd[0] == LED_SET_CMD) { led_set_intensity(cmd[1], cmd[2]); } else if (cmd[0] == IR_SEND_RC5_CMD) { irSendRC5(cmd[1], cmd[2]); } else if (cmd[0] == MOTORS_CONFIG_CMD) { motors_config(cmd[1], cmd[2]); } /* Leds */ else if (cmd[0] == LED_PULSE_RANGE_CMD) { led_pulse_range(cmd[1], cmd[2], cmd[3]); } /* Move */ else { if (cmd[0] == MOTORS_SET_CMD) { motors_run(cmd[1], cmd[2], cmd[3]); } else if (cmd[0] == LED_PULSE_CMD) { led_pulse(cmd[1], cmd[2], cmd[3]); } /* Deprecated functions, though they can be kept for the standalone as * they're simpler than the other LED functions. */ else if (cmd[0] == LED_ON_CMD) { led_set_intensity(LED_BOTH, 0xFF); } else if (cmd[0] == LED_OFF_CMD) { led_set_intensity(LED_BOTH, 0x0); } else if (cmd[0] == LED_TOGGLE_CMD) { leds_toggle(cmd[1], cmd[2]); } /* Moves */ else if (cmd[0] == BLINK_EYES_CMD) { blink_eyes(cmd[1]); } else if (cmd[0] == STOP_EYES_CMD) { stop_eyes(); } else if (cmd[0] == OPEN_EYES_CMD) { open_eyes(); } else if (cmd[0] == CLOSE_EYES_CMD) { close_eyes(); } else if (cmd[0] == MOVE_MOUTH_CMD) { move_mouth(cmd[1]); } else if (cmd[0] == OPEN_MOUTH_CMD) { open_mouth(); } else if (cmd[0] == CLOSE_MOUTH_CMD) { close_mouth(); } else if (cmd[0] == STOP_MOUTH_CMD) { stop_mouth(); } else if (cmd[0] == WAVE_WINGS_CMD) { wave_flippers(cmd[1], cmd[2]); } else if (cmd[0] == RAISE_WINGS_CMD) { raise_flippers(); } else if (cmd[0] == LOWER_WINGS_CMD) { lower_flippers(); } else if (cmd[0] == RESET_WINGS_CMD) { reset_flippers(); } else if (cmd[0] == STOP_WINGS_CMD) { stop_flippers(); } else if (cmd[0] == SPIN_LEFT_CMD) { spin_left(cmd[1], cmd[2]); } else if (cmd[0] == SPIN_RIGHT_CMD) { spin_right(cmd[1], cmd[2]); } else if (cmd[0] == STOP_SPIN_CMD) { stop_spinning(); } /* Undefined commands */ else return; /* simply drop it */ /* Send an updated status here for functions that need it */ updateStatusFlag = 1; } }