static void poll_poll (EV_P_ ev_tstamp timeout) { struct pollfd *p; int res = poll (polls, pollcnt, (int)ceil (timeout * 1000.)); if (expect_false (res < 0)) { if (errno == EBADF) fd_ebadf (EV_A); else if (errno == ENOMEM && !syserr_cb) fd_enomem (EV_A); else if (errno != EINTR) syserr ("(libev) poll"); } else for (p = polls; res; ++p) if (expect_false (p->revents)) /* this expect is debatable */ { --res; if (expect_false (p->revents & POLLNVAL)) fd_kill (EV_A_ p->fd); else fd_event ( EV_A_ p->fd, (p->revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0) | (p->revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0) ); } }
/*! * @brief 参照ポインタ先の保存フロアを抹消する / kill a saved floor and get an empty space * @param sf_ptr 保存フロアの参照ポインタ * @return なし */ static void kill_saved_floor(saved_floor_type *sf_ptr) { char floor_savefile[1024]; /* Paranoia */ if (!sf_ptr) return; /* Already empty */ if (!sf_ptr->floor_id) return; if (sf_ptr->floor_id == p_ptr->floor_id) { /* Kill current floor */ p_ptr->floor_id = 0; /* Current floor doesn't have temporal file */ } else { /* File name */ sprintf(floor_savefile, "%s.F%02d", savefile, (int)sf_ptr->savefile_id); /* Grab permissions */ safe_setuid_grab(); /* Simply kill the temporal file */ (void)fd_kill(floor_savefile); /* Drop permissions */ safe_setuid_drop(); } /* No longer exists */ sf_ptr->floor_id = 0; }
void inline_speed port_associate_and_check (EV_P_ int fd, int ev) { if (0 > port_associate ( backend_fd, PORT_SOURCE_FD, fd, (ev & EV_READ ? POLLIN : 0) | (ev & EV_WRITE ? POLLOUT : 0), 0 ) ) { if (errno == EBADFD) fd_kill (EV_A_ fd); else ev_syserr ("(libev) port_associate"); } }
/*! * @brief キャラクタダンプを作って BUFに保存 * @param dumpbuf 伝送内容バッファ * @return エラーコード */ static errr make_dump(BUF* dumpbuf) { char buf[1024]; FILE *fff; char file_name[1024]; /* Open a new file */ fff = my_fopen_temp(file_name, 1024); if (!fff) { #ifdef JP msg_format("一時ファイル %s を作成できませんでした。", file_name); #else msg_format("Failed to create temporary file %s.", file_name); #endif msg_print(NULL); return 1; } /* 一旦一時ファイルを作る。通常のダンプ出力と共通化するため。 */ (void)make_character_dump(fff); /* Close the file */ my_fclose(fff); /* Open for read */ fff = my_fopen(file_name, "r"); while (fgets(buf, 1024, fff)) { (void)buf_sprintf(dumpbuf, "%s", buf); } /* Close the file */ my_fclose(fff); /* Remove the file */ fd_kill(file_name); /* Success */ return (0); }
void mut_do_cmd_knowledge(void) { FILE *fff; char file_name[1024]; /* Open a new file */ fff = my_fopen_temp(file_name, 1024); /* Dump the mutations to file */ if (fff) mut_dump_file(fff); /* Close the file */ my_fclose(fff); /* Display the file contents */ show_file(TRUE, file_name, T("Mutations", "突然変異"), 0, 0); /* Remove the file */ fd_kill(file_name); }
static void poll_poll (EV_P_ ev_tstamp timeout) { struct pollfd *p; int res; EV_RELEASE_CB; res = poll (polls, pollcnt, timeout * 1e3); EV_ACQUIRE_CB; if (expect_false (res < 0)) { if (errno == EBADF) fd_ebadf (EV_A); else if (errno == ENOMEM && !syserr_cb) fd_enomem (EV_A); else if (errno != EINTR) ev_syserr ("(libev) poll"); } else for (p = polls; res; ++p) { assert (("libev: poll() returned illegal result, broken BSD kernel?", p < polls + pollcnt)); if (expect_false (p->revents)) /* this expect is debatable */ { --res; if (expect_false (p->revents & POLLNVAL)) fd_kill (EV_A_ p->fd); else fd_event ( EV_A_ p->fd, (p->revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0) | (p->revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0) ); } } }
/*! * @brief 保存フロア用テンポラリファイルを削除する / Kill temporal files * @details Should be called just before the game quit. * @return なし */ void clear_saved_floor_files(void) { char floor_savefile[1024]; int i; #ifdef SET_UID # ifdef SECURE /* Get "games" permissions */ beGames(); # endif #endif for (i = 0; i < MAX_SAVED_FLOORS; i++) { saved_floor_type *sf_ptr = &saved_floors[i]; /* No temporal file */ if (!sf_ptr->floor_id) continue; if (sf_ptr->floor_id == p_ptr->floor_id) continue; /* File name */ sprintf(floor_savefile, "%s.F%02d", savefile, i); /* Grab permissions */ safe_setuid_grab(); /* Simply kill the temporal file */ (void)fd_kill(floor_savefile); /* Drop permissions */ safe_setuid_drop(); } #ifdef SET_UID # ifdef SECURE /* Drop "games" permissions */ bePlayer(); # endif #endif }
/*! * @brief ファイルロック処理 * @return なし */ void remove_loc(void) { #ifdef VERIFY_SAVEFILE char temp[1024]; #endif /* VERIFY_SAVEFILE */ #ifdef SET_UID # ifdef SECURE /* Get "games" permissions */ beGames(); # endif /* SECURE */ #endif /* SET_UID */ #ifdef VERIFY_SAVEFILE /* Lock on savefile */ strcpy(temp, savefile); strcat(temp, ".lok"); /* Remove lock file */ fd_kill(temp); #endif /* VERIFY_SAVEFILE */ #ifdef SET_UID # ifdef SECURE /* Drop "games" permissions */ bePlayer(); # endif /* SECURE */ #endif /* SET_UID */ }
/*! * @brief ゲームプレイ中のフロア一時保存出力処理メインルーチン / Attempt to save the temporally saved-floor data * @param sf_ptr 保存フロア参照ポインタ * @param mode 保存オプション * @return なし */ bool save_floor(saved_floor_type *sf_ptr, u32b mode) { FILE *old_fff = NULL; byte old_xor_byte = 0; u32b old_v_stamp = 0; u32b old_x_stamp = 0; char floor_savefile[1024]; int fd = -1; bool ok = FALSE; if (!(mode & SLF_SECOND)) { #ifdef SET_UID # ifdef SECURE /* Get "games" permissions */ beGames(); # endif #endif } /* We have one file already opened */ else { /* Backup original values */ old_fff = fff; old_xor_byte = xor_byte; old_v_stamp = v_stamp; old_x_stamp = x_stamp; } /* New savefile */ sprintf(floor_savefile, "%s.F%02d", savefile, (int)sf_ptr->savefile_id); /* Grab permissions */ safe_setuid_grab(); /* Remove it */ fd_kill(floor_savefile); /* Drop permissions */ safe_setuid_drop(); /* Attempt to save the player */ /* No file yet */ fff = NULL; /* File type is "SAVE" */ FILE_TYPE(FILE_TYPE_SAVE); /* Grab permissions */ safe_setuid_grab(); /* Create the savefile */ fd = fd_make(floor_savefile, 0644); /* Drop permissions */ safe_setuid_drop(); /* File is okay */ if (fd >= 0) { /* Close the "fd" */ (void)fd_close(fd); /* Grab permissions */ safe_setuid_grab(); /* Open the savefile */ fff = my_fopen(floor_savefile, "wb"); /* Drop permissions */ safe_setuid_drop(); /* Successful open */ if (fff) { /* Write the savefile */ if (save_floor_aux(sf_ptr)) ok = TRUE; /* Attempt to close it */ if (my_fclose(fff)) ok = FALSE; } /* Remove "broken" files */ if (!ok) { /* Grab permissions */ safe_setuid_grab(); (void)fd_kill(floor_savefile); /* Drop permissions */ safe_setuid_drop(); } } if (!(mode & SLF_SECOND)) { #ifdef SET_UID # ifdef SECURE /* Drop "games" permissions */ bePlayer(); # endif #endif } /* We have one file already opened */ else { /* Restore original values */ fff = old_fff; xor_byte = old_xor_byte; v_stamp = old_v_stamp; x_stamp = old_x_stamp; } /* Return the result */ return ok; }
/*! * @brief セーブデータ読み込みのメインルーチン / * Attempt to Load a "savefile" * @return 成功すればtrue * @details * <pre> * Version 2.7.0 introduced a slightly different "savefile" format from * older versions, requiring a completely different parsing method. * * Note that savefiles from 2.7.0 - 2.7.2 are completely obsolete. * * Pre-2.8.0 savefiles lose some data, see "load2.c" for info. * * Pre-2.7.0 savefiles lose a lot of things, see "load1.c" for info. * * On multi-user systems, you may only "read" a savefile if you will be * allowed to "write" it later, this prevents painful situations in which * the player loads a savefile belonging to someone else, and then is not * allowed to save his game when he quits. * * We return "TRUE" if the savefile was usable, and we set the global * flag "character_loaded" if a real, living, character was loaded. * * Note that we always try to load the "current" savefile, even if * there is no such file, so we must check for "empty" savefile names. * </pre> */ bool load_player(void) { int fd = -1; errr err = 0; byte vvv[4]; #ifdef VERIFY_TIMESTAMP struct stat statbuf; #endif cptr what = "generic"; /* Paranoia */ turn = 0; /* Paranoia */ p_ptr->is_dead = FALSE; /* Allow empty savefile name */ if (!savefile[0]) return (TRUE); #if !defined(MACINTOSH) && !defined(WINDOWS) && !defined(VM) /* XXX XXX XXX Fix this */ /* Verify the existance of the savefile */ if (access(savefile, 0) < 0) { /* Give a message */ msg_print(_("セーブファイルがありません。", "Savefile does not exist.")); msg_print(NULL); /* Allow this */ return (TRUE); } #endif #ifdef VERIFY_SAVEFILE /* Verify savefile usage */ if (!err) { FILE *fkk; char temp[1024]; /* Extract name of lock file */ strcpy(temp, savefile); strcat(temp, ".lok"); /* Check for lock */ fkk = my_fopen(temp, "r"); /* Oops, lock exists */ if (fkk) { /* Close the file */ my_fclose(fkk); /* Message */ msg_print(_("セーブファイルは現在使用中です。", "Savefile is currently in use.")); msg_print(NULL); /* Oops */ return (FALSE); } /* Create a lock file */ fkk = my_fopen(temp, "w"); /* Dump a line of info */ fprintf(fkk, "Lock file for savefile '%s'\n", savefile); /* Close the lock file */ my_fclose(fkk); } #endif /* Okay */ if (!err) { /* Open the savefile */ fd = fd_open(savefile, O_RDONLY); /* No file */ if (fd < 0) err = -1; /* Message (below) */ if (err) what = _("セーブファイルを開けません。", "Cannot open savefile"); } /* Process file */ if (!err) { #ifdef VERIFY_TIMESTAMP /* Get the timestamp */ (void)fstat(fd, &statbuf); #endif /* Read the first four bytes */ if (fd_read(fd, (char*)(vvv), 4)) err = -1; /* What */ if (err) what = _("セーブファイルを読めません。", "Cannot read savefile"); /* Close the file */ (void)fd_close(fd); } /* Process file */ if (!err) { /* Extract version */ z_major = vvv[0]; z_minor = vvv[1]; z_patch = vvv[2]; sf_extra = vvv[3]; /* Clear screen */ Term_clear(); /* Attempt to load */ err = rd_savefile_new(); /* Message (below) */ if (err) what = _("セーブファイルを解析出来ません。", "Cannot parse savefile"); } /* Paranoia */ if (!err) { /* Invalid turn */ if (!turn) err = -1; /* Message (below) */ if (err) what = _("セーブファイルが壊れています", "Broken savefile"); } #ifdef VERIFY_TIMESTAMP /* Verify timestamp */ if (!err && !arg_wizard) { /* Hack -- Verify the timestamp */ if (sf_when > (statbuf.st_ctime + 100) || sf_when < (statbuf.st_ctime - 100)) { /* Message */ what = _("無効なタイム・スタンプです", "Invalid timestamp"); /* Oops */ err = -1; } } #endif /* Okay */ if (!err) { /* Give a conversion warning */ if ((FAKE_VER_MAJOR != z_major) || (FAKE_VER_MINOR != z_minor) || (FAKE_VER_PATCH != z_patch)) { if (z_major == 2 && z_minor == 0 && z_patch == 6) { msg_print(_("バージョン 2.0.* 用のセーブファイルを変換しました。", "Converted a 2.0.* savefile.")); } else { /* Message */ #ifdef JP msg_format("バージョン %d.%d.%d 用のセーブ・ファイルを変換しました。", (z_major > 9) ? z_major-10 : z_major , z_minor, z_patch); #else msg_format("Converted a %d.%d.%d savefile.", (z_major > 9) ? z_major-10 : z_major , z_minor, z_patch); #endif } msg_print(NULL); } /* Player is dead */ if (p_ptr->is_dead) { /* Cheat death */ if (arg_wizard) { /* A character was loaded */ character_loaded = TRUE; /* Done */ return (TRUE); } /* Player is no longer "dead" */ p_ptr->is_dead = FALSE; /* Count lives */ sf_lives++; /* Done */ return (TRUE); } /* A character was loaded */ character_loaded = TRUE; { u32b tmp = counts_read(2); if (tmp > p_ptr->count) p_ptr->count = tmp; if (counts_read(0) > playtime || counts_read(1) == playtime) counts_write(2, ++p_ptr->count); counts_write(1, playtime); } /* Success */ return (TRUE); } #ifdef VERIFY_SAVEFILE /* Verify savefile usage */ if (TRUE) { char temp[1024]; /* Extract name of lock file */ strcpy(temp, savefile); strcat(temp, ".lok"); /* Remove lock */ fd_kill(temp); } #endif /* Message */ #ifdef JP msg_format("エラー(%s)がバージョン%d.%d.%d 用セーブファイル読み込中に発生。", what, (z_major>9) ? z_major - 10 : z_major, z_minor, z_patch); #else msg_format("Error (%s) reading %d.%d.%d savefile.", what, (z_major>9) ? z_major - 10 : z_major, z_minor, z_patch); #endif msg_print(NULL); /* Oops */ return (FALSE); }
/*! * @brief セーブデータ書き込みのメインルーチン / * Attempt to save the player in a savefile * @return 成功すればtrue */ bool save_player(void) { int result = FALSE; char safe[1024]; #ifdef SET_UID # ifdef SECURE /* Get "games" permissions */ beGames(); # endif #endif /* New savefile */ strcpy(safe, savefile); strcat(safe, ".new"); #ifdef VM /* Hack -- support "flat directory" usage on VM/ESA */ strcpy(safe, savefile); strcat(safe, "n"); #endif /* VM */ /* Grab permissions */ safe_setuid_grab(); /* Remove it */ fd_kill(safe); /* Drop permissions */ safe_setuid_drop(); update_playtime(); /* Attempt to save the player */ if (save_player_aux(safe)) { char temp[1024]; /* Old savefile */ strcpy(temp, savefile); strcat(temp, ".old"); #ifdef VM /* Hack -- support "flat directory" usage on VM/ESA */ strcpy(temp, savefile); strcat(temp, "o"); #endif /* VM */ /* Grab permissions */ safe_setuid_grab(); /* Remove it */ fd_kill(temp); /* Preserve old savefile */ fd_move(savefile, temp); /* Activate new savefile */ fd_move(safe, savefile); /* Remove preserved savefile */ fd_kill(temp); /* Drop permissions */ safe_setuid_drop(); /* Hack -- Pretend the character was loaded */ character_loaded = TRUE; #ifdef VERIFY_SAVEFILE /* Lock on savefile */ strcpy(temp, savefile); strcat(temp, ".lok"); /* Grab permissions */ safe_setuid_grab(); /* Remove lock file */ fd_kill(temp); /* Drop permissions */ safe_setuid_drop(); #endif /* Success */ result = TRUE; } #ifdef SET_UID # ifdef SECURE /* Drop "games" permissions */ bePlayer(); # endif #endif /* Return the result */ return (result); }
/*! * @brief セーブデータ書き込みのサブルーチン / * Medium level player saver * @return 成功すればtrue * @details * XXX XXX XXX Angband 2.8.0 will use "fd" instead of "fff" if possible */ static bool save_player_aux(char *name) { bool ok = FALSE; int fd = -1; int mode = 0644; /* No file yet */ fff = NULL; /* File type is "SAVE" */ FILE_TYPE(FILE_TYPE_SAVE); /* Grab permissions */ safe_setuid_grab(); /* Create the savefile */ fd = fd_make(name, mode); /* Drop permissions */ safe_setuid_drop(); /* File is okay */ if (fd >= 0) { /* Close the "fd" */ (void)fd_close(fd); /* Grab permissions */ safe_setuid_grab(); /* Open the savefile */ fff = my_fopen(name, "wb"); /* Drop permissions */ safe_setuid_drop(); /* Successful open */ if (fff) { /* Write the savefile */ if (wr_savefile_new()) ok = TRUE; /* Attempt to close it */ if (my_fclose(fff)) ok = FALSE; } /* Grab permissions */ safe_setuid_grab(); /* Remove "broken" files */ if (!ok) (void)fd_kill(name); /* Drop permissions */ safe_setuid_drop(); } /* Failure */ if (!ok) return (FALSE); counts_write(0, playtime); /* Successful save */ character_saved = TRUE; /* Success */ return (TRUE); }
/* * Attempt to save the player in a savefile */ bool save_player(void) { int result = FALSE; char safe[1024]; // in final deployment versions, you cannot save in the tutorial if (DEPLOYMENT && p_ptr->game_type != 0) { return (FALSE); } /* New savefile */ my_strcpy(safe, savefile, sizeof(safe)); my_strcat(safe, ".new", sizeof(safe)); #ifdef VM /* Hack -- support "flat directory" usage on VM/ESA */ my_strcpy(safe, savefile, sizeof(safe)); my_strcat(safe, "n", sizeof(safe)); #endif /* VM */ /* Grab permissions */ safe_setuid_grab(); /* Remove it */ fd_kill(safe); /* Drop permissions */ safe_setuid_drop(); /* Attempt to save the player */ if (save_player_aux(safe)) { char temp[1024]; /* Old savefile */ my_strcpy(temp, savefile, sizeof(temp)); my_strcat(temp, ".old", sizeof(temp)); #ifdef VM /* Hack -- support "flat directory" usage on VM/ESA */ my_strcpy(temp, savefile, sizeof(temp)); my_strcat(temp, "o", sizeof(temp)); #endif /* VM */ /* Grab permissions */ safe_setuid_grab(); /* Remove it */ fd_kill(temp); /* Preserve old savefile */ fd_move(savefile, temp); /* Activate new savefile */ fd_move(safe, savefile); /* Remove preserved savefile */ fd_kill(temp); /* Drop permissions */ safe_setuid_drop(); /* Hack -- Pretend the character was loaded */ character_loaded = TRUE; #ifdef VERIFY_SAVEFILE /* Lock on savefile */ my_strcpy(temp, savefile, sizeof(temp)); my_strcat(temp, ".lok", sizeof(temp)); /* Grab permissions */ safe_setuid_grab(); /* Remove lock file */ fd_kill(temp); /* Drop permissions */ safe_setuid_drop(); #endif /* VERIFY_SAVEFILE */ /* Success */ result = TRUE; } /* Return the result */ return (result); }
/*! * @brief 保存フロア配列を初期化する / Initialize saved_floors array. * @param force テンポラリファイルが残っていた場合も警告なしで強制的に削除する。 * @details Make sure that old temporal files are not remaining as gurbages. * @return なし */ void init_saved_floors(bool force) { char floor_savefile[1024]; int i; int fd = -1; BIT_FLAGS mode = 0644; #ifdef SET_UID # ifdef SECURE /* Get "games" permissions */ beGames(); # endif #endif for (i = 0; i < MAX_SAVED_FLOORS; i++) { saved_floor_type *sf_ptr = &saved_floors[i]; /* File name */ sprintf(floor_savefile, "%s.F%02d", savefile, i); /* Grab permissions */ safe_setuid_grab(); /* Try to create the file */ fd = fd_make(floor_savefile, mode); /* Drop permissions */ safe_setuid_drop(); /* Failed! */ if (fd < 0) { if (!force) { #ifdef JP msg_print("エラー:古いテンポラリ・ファイルが残っています。"); msg_print("短愚蛮怒を二重に起動していないか確認してください。"); msg_print("過去に短愚蛮怒がクラッシュした場合は一時ファイルを"); msg_print("強制的に削除して実行を続けられます。"); if (!get_check("強制的に削除してもよろしいですか?")) quit("実行中止"); #else msg_print("Error: There are old temporal files."); msg_print("Make sure you are not running two game processes simultaneously."); msg_print("If the temporal files are garbages of old crashed process, "); msg_print("you can delete it safely."); if (!get_check("Do you delete old temporal files? ")) quit("Aborted."); #endif force = TRUE; } } else { /* Close the "fd" */ (void)fd_close(fd); } /* Grab permissions */ safe_setuid_grab(); /* Simply kill the temporal file */ (void)fd_kill(floor_savefile); /* Drop permissions */ safe_setuid_drop(); sf_ptr->floor_id = 0; } /* No floor_id used yet (No.0 is reserved to indicate non existance) */ max_floor_id = 1; /* vist_mark is from 1 */ latest_visit_mark = 1; /* A sign to mark temporal files */ saved_floor_file_sign = (u32b)time(NULL); /* No next floor yet */ new_floor_id = 0; /* No change floor mode yet */ change_floor_mode = 0; #ifdef SET_UID # ifdef SECURE /* Drop "games" permissions */ bePlayer(); # endif #endif }
/* * Attempt to Load a "savefile" * * On multi-user systems, you may only "read" a savefile if you will be * allowed to "write" it later, this prevents painful situations in which * the player loads a savefile belonging to someone else, and then is not * allowed to save his game when he quits. * * We return "TRUE" if the savefile was usable, and we set the global * flag "character_loaded" if a real, living, character was loaded. * * Note that we always try to load the "current" savefile, even if * there is no such file, so we must check for "empty" savefile names. */ bool load_player(void) { int fd = -1; errr err = 0; byte vvv[4]; #ifdef VERIFY_TIMESTAMP struct stat statbuf; #endif /* VERIFY_TIMESTAMP */ cptr what = "generic"; /* Paranoia */ turn = 0; /* Paranoia */ p_ptr->is_dead = FALSE; // Set a flag to show that we are restoring a game p_ptr->restoring = TRUE; /* Allow empty savefile name */ if (!savefile[0]) return (TRUE); /* Grab permissions */ safe_setuid_grab(); /* Open the savefile */ fd = fd_open(savefile, O_RDONLY); /* Drop permissions */ safe_setuid_drop(); /* No file */ if (fd < 0) { /* Give a message */ msg_format("Savefile \"%s\" does not exist.", savefile); message_flush(); /* Allow this */ p_ptr->restoring = FALSE; return (FALSE);//// } /* Close the file */ fd_close(fd); #ifdef VERIFY_SAVEFILE /* Verify savefile usage */ if (!err) { FILE *fkk; char temp[1024]; /* Extract name of lock file */ my_strcpy(temp, savefile, sizeof(temp)); my_strcat(temp, ".lok", sizeof(temp)); /* Grab permissions */ safe_setuid_grab(); /* Check for lock */ fkk = my_fopen(temp, "r"); /* Drop permissions */ safe_setuid_drop(); /* Oops, lock exists */ if (fkk) { /* Close the file */ my_fclose(fkk); /* Message */ msg_print("Savefile is currently in use."); message_flush(); /* Oops */ return (FALSE); } /* Grab permissions */ safe_setuid_grab(); /* Create a lock file */ fkk = my_fopen(temp, "w"); /* Drop permissions */ safe_setuid_drop(); /* Dump a line of info */ fprintf(fkk, "Lock file for savefile '%s'\n", savefile); /* Close the lock file */ my_fclose(fkk); } #endif /* VERIFY_SAVEFILE */ /* Okay */ if (!err) { /* Grab permissions */ safe_setuid_grab(); /* Open the savefile */ fd = fd_open(savefile, O_RDONLY); /* Drop permissions */ safe_setuid_drop(); /* No file */ if (fd < 0) err = -1; /* Message (below) */ if (err) what = "Cannot open savefile"; } /* Process file */ if (!err) { #ifdef VERIFY_TIMESTAMP /* Grab permissions */ safe_setuid_grab(); /* Get the timestamp */ (void)fstat(fd, &statbuf); /* Drop permissions */ safe_setuid_drop(); #endif /* VERIFY_TIMESTAMP */ /* Read the first four bytes */ if (fd_read(fd, (char*)(vvv), sizeof(vvv))) err = -1; /* What */ if (err) what = "Cannot read savefile"; /* Close the file */ fd_close(fd); } /* Process file */ if (!err) { /* Extract version */ sf_major = vvv[0]; sf_minor = vvv[1]; sf_patch = vvv[2]; sf_extra = vvv[3]; /* Clear screen */ Term_clear(); if (older_than(OLD_VERSION_MAJOR, OLD_VERSION_MINOR, OLD_VERSION_PATCH)) { err = -1; what = "Savefile is too old"; } else if (!older_than(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH + 1)) { err = -1; what = "Savefile is from the future"; } else { /* Attempt to load */ err = rd_savefile(); /* Message (below) */ if (err) what = "Cannot parse savefile"; } } /* Paranoia */ if (!err) { /* Invalid turn */ if (!turn) err = -1; /* Message (below) */ if (err) what = "Broken savefile"; } #ifdef VERIFY_TIMESTAMP /* Verify timestamp */ if (!err && !arg_wizard) { /* Hack -- Verify the timestamp */ if (sf_when > (statbuf.st_ctime + 100) || sf_when < (statbuf.st_ctime - 100)) { /* Message */ what = "Invalid timestamp"; /* Oops */ err = -1; } } #endif /* VERIFY_TIMESTAMP */ /* Okay */ if (!err) { /* Give a conversion warning */ if ((version_major != sf_major) || (version_minor != sf_minor) || (version_patch != sf_patch)) { /* Message */ msg_format("Converted a %d.%d.%d savefile.", sf_major, sf_minor, sf_patch); message_flush(); } // if Morgoth has lost his crown... if ((&a_info[ART_MORGOTH_3])->cur_num == 1) { // lower Morgoth's protection, remove his light source, increase his will and perception (&r_info[R_IDX_MORGOTH])->pd -= 1; (&r_info[R_IDX_MORGOTH])->light = 0; (&r_info[R_IDX_MORGOTH])->wil += 5; (&r_info[R_IDX_MORGOTH])->per += 5; } /* Player is dead */ if (p_ptr->is_dead) { /* Cheat death (unless the character retired) */ if (arg_wizard) { /*heal the player*/ hp_player(100, TRUE, TRUE); /* Forget death */ p_ptr->is_dead = FALSE; /* A character was loaded */ character_loaded = TRUE; // put the character somewhere sensible p_ptr->depth = min_depth(); // Mark savefile p_ptr->noscore |= 0x0001; /* Done */ return (TRUE); } /* Forget death */ p_ptr->is_dead = FALSE; /* Count lives */ sf_lives++; /* Forget turns */ turn = 0; playerturn = 0; /* A dead character was loaded */ character_loaded_dead = TRUE;//// /* Done */ return (TRUE); } /* A character was loaded */ character_loaded = TRUE; /* Still alive */ if (p_ptr->chp >= 0) { /* Reset cause of death */ my_strcpy(p_ptr->died_from, "(alive and well)", sizeof (p_ptr->died_from)); } // count the artefacts seen for the player p_ptr->artefacts = artefact_count(); /* Success */ return (TRUE); } #ifdef VERIFY_SAVEFILE /* Verify savefile usage */ if (TRUE) { char temp[1024]; /* Extract name of lock file */ my_strcpy(temp, savefile, sizeof(temp)); my_strcat(temp, ".lok", sizeof(temp)); /* Grab permissions */ safe_setuid_grab(); /* Remove lock */ fd_kill(temp); /* Drop permissions */ safe_setuid_drop(); } #endif /* VERIFY_SAVEFILE */ /* Message */ msg_format("Error (%s) reading %d.%d.%d savefile.", what, sf_major, sf_minor, sf_patch); message_flush(); /* Oops */ return (FALSE); }
static void kqueue_poll (EV_P_ ev_tstamp timeout) { int res, i; struct timespec ts; /* need to resize so there is enough space for errors */ if (kqueue_changecnt > kqueue_eventmax) { ev_free (kqueue_events); kqueue_eventmax = array_nextsize (sizeof (struct kevent), kqueue_eventmax, kqueue_changecnt); kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax); } EV_RELEASE_CB; EV_TS_SET (ts, timeout); res = kevent (backend_fd, kqueue_changes, kqueue_changecnt, kqueue_events, kqueue_eventmax, &ts); EV_ACQUIRE_CB; kqueue_changecnt = 0; if (expect_false (res < 0)) { if (errno != EINTR) ev_syserr ("(libev) kevent"); return; } for (i = 0; i < res; ++i) { int fd = kqueue_events [i].ident; if (expect_false (kqueue_events [i].flags & EV_ERROR)) { int err = kqueue_events [i].data; /* we are only interested in errors for fds that we are interested in :) */ if (anfds [fd].events) { if (err == ENOENT) /* resubmit changes on ENOENT */ kqueue_modify (EV_A_ fd, 0, anfds [fd].events); else if (err == EBADF) /* on EBADF, we re-check the fd */ { if (fd_valid (fd)) kqueue_modify (EV_A_ fd, 0, anfds [fd].events); else fd_kill (EV_A_ fd); } else /* on all other errors, we error out on the fd */ fd_kill (EV_A_ fd); } } else fd_event ( EV_A_ fd, kqueue_events [i].filter == EVFILT_READ ? EV_READ : kqueue_events [i].filter == EVFILT_WRITE ? EV_WRITE : 0 ); } if (expect_false (res == kqueue_eventmax)) { ev_free (kqueue_events); kqueue_eventmax = array_nextsize (sizeof (struct kevent), kqueue_eventmax, kqueue_eventmax + 1); kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax); } }
/* * Attempt to Load a "savefile" * * On multi-user systems, you may only "read" a savefile if you will be * allowed to "write" it later, this prevents painful situations in which * the player loads a savefile belonging to someone else, and then is not * allowed to save his game when he quits. * * We return "TRUE" if the savefile was usable, and we set the global * flag "character_loaded" if a real, living, character was loaded. * * Note that we always try to load the "current" savefile, even if * there is no such file, so we must check for "empty" savefile names. */ bool load_player(void) { int fd = -1; errr err = 0; byte vvv[4]; #ifdef VERIFY_TIMESTAMP struct stat statbuf; #endif /* VERIFY_TIMESTAMP */ cptr what = "generic"; /* Paranoia */ turn = 0; /* Paranoia */ p_ptr->is_dead = FALSE; /* Allow empty savefile name */ if (!savefile[0]) return (TRUE); /* Grab permissions */ safe_setuid_grab(); /* Open the savefile */ fd = fd_open(savefile, O_RDONLY); /* Drop permissions */ safe_setuid_drop(); /* No file */ if (fd < 0) { /* Give a message */ msg_print("Savefile does not exist."); message_flush(); /* Allow this */ return (TRUE); } /* Close the file */ fd_close(fd); #ifdef VERIFY_SAVEFILE /* Verify savefile usage */ if (!err) { FILE *fkk; char temp[1024]; /* Extract name of lock file */ strcpy(temp, savefile); strcat(temp, ".lok"); /* Grab permissions */ safe_setuid_grab(); /* Check for lock */ fkk = my_fopen(temp, "r"); /* Drop permissions */ safe_setuid_drop(); /* Oops, lock exists */ if (fkk) { /* Close the file */ my_fclose(fkk); /* Message */ msg_print("Savefile is currently in use."); message_flush(); /* Oops */ return (FALSE); } /* Grab permissions */ safe_setuid_grab(); /* Create a lock file */ fkk = my_fopen(temp, "w"); /* Drop permissions */ safe_setuid_drop(); /* Dump a line of info */ fprintf(fkk, "Lock file for savefile '%s'\n", savefile); /* Close the lock file */ my_fclose(fkk); } #endif /* VERIFY_SAVEFILE */ /* Okay */ if (!err) { /* Grab permissions */ safe_setuid_grab(); /* Open the savefile */ fd = fd_open(savefile, O_RDONLY); /* Drop permissions */ safe_setuid_drop(); /* No file */ if (fd < 0) err = -1; /* Message (below) */ if (err) what = "Cannot open savefile"; } /* Process file */ if (!err) { #ifdef VERIFY_TIMESTAMP /* Grab permissions */ safe_setuid_grab(); /* Get the timestamp */ (void)fstat(fd, &statbuf); /* Drop permissions */ safe_setuid_drop(); #endif /* VERIFY_TIMESTAMP */ /* Read the first four bytes */ if (fd_read(fd, (char*)(vvv), sizeof(vvv))) err = -1; /* What */ if (err) what = "Cannot read savefile"; /* Close the file */ fd_close(fd); } /* Process file */ if (!err) { /* Extract version */ sf_major = vvv[0]; sf_minor = vvv[1]; sf_patch = vvv[2]; sf_extra = vvv[3]; /* Clear screen */ Term_clear(); if (older_than(OLD_VERSION_MAJOR, OLD_VERSION_MINOR, OLD_VERSION_PATCH)) { err = -1; what = "Savefile is too old"; } else if (!older_than(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH + 1)) { err = -1; what = "Savefile is from the future"; } else { /* Attempt to load */ err = rd_savefile(); /* Message (below) */ if (err) what = "Cannot parse savefile"; } } /* Paranoia */ if (!err) { /* Invalid turn */ if (!turn) err = -1; /* Message (below) */ if (err) what = "Broken savefile"; } #ifdef VERIFY_TIMESTAMP /* Verify timestamp */ if (!err && !arg_wizard) { /* Hack -- Verify the timestamp */ if (sf_when > (statbuf.st_ctime + 100) || sf_when < (statbuf.st_ctime - 100)) { /* Message */ what = "Invalid timestamp"; /* Oops */ err = -1; } } #endif /* VERIFY_TIMESTAMP */ /* Okay */ if (!err) { /* Give a conversion warning */ if ((version_major != sf_major) || (version_minor != sf_minor) || (version_patch != sf_patch)) { /* Message */ msg_format("Converted a %d.%d.%d savefile.", sf_major, sf_minor, sf_patch); message_flush(); } /* Player is dead */ if (p_ptr->is_dead) { /* Forget death */ p_ptr->is_dead = FALSE; /* Cheat death */ if (arg_wizard) { /* A character was loaded */ character_loaded = TRUE; /* Done */ return (TRUE); } /* Count lives */ sf_lives++; /* Forget turns */ turn = old_turn = 0; /* Done */ return (TRUE); } /* A character was loaded */ character_loaded = TRUE; /* Still alive */ if (p_ptr->chp >= 0) { /* Reset cause of death */ strcpy(p_ptr->died_from, "(alive and well)"); } /* Success */ return (TRUE); } #ifdef VERIFY_SAVEFILE /* Verify savefile usage */ if (TRUE) { char temp[1024]; /* Extract name of lock file */ strcpy(temp, savefile); strcat(temp, ".lok"); /* Grab permissions */ safe_setuid_grab(); /* Remove lock */ fd_kill(temp); /* Drop permissions */ safe_setuid_drop(); } #endif /* VERIFY_SAVEFILE */ /* Message */ msg_format("Error (%s) reading %d.%d.%d savefile.", what, sf_major, sf_minor, sf_patch); message_flush(); /* Oops */ return (FALSE); }
/* * Display current pets */ static void do_cmd_knowledge_pets(void) { s32b i; PHYSFS_file *fff; monster_type *m_ptr; monster_race *r_ptr; s32b t_friends = 0; s32b t_levels = 0; s32b show_upkeep = 0; s32b upkeep_divider = 20; char file_name[1024]; /* Temporary file */ if (path_temp(file_name, 1024)) return; /* Open a new file */ fff = my_fopen(file_name, "w"); if (has_ability(AB_PERFECT_CASTING)) upkeep_divider = 15; /* Process the monsters (backwards) */ for_flags(&monst_list); { i = __key; /* Access the monster */ m_ptr = get_monster(i); r_ptr = &r_info[m_ptr->r_idx]; /* Ignore "dead" monsters */ if (!m_ptr->r_idx) continue; /* Calculate "upkeep" for friendly monsters */ if (is_friend(m_ptr) == 1) { char pet_name[80]; t_friends++; t_levels += m_ptr->level; monster_desc(pet_name, m_ptr, 0x88); fprintf(fff, "%s%s (%s)\n", ((has_flag(m_ptr, FLAG_UNIQUE))) ? "#####G" : "", pet_name, (has_flag(m_ptr, FLAG_PERMANENT)) ? "friend" : "companion"); } } end_for_flags(); if (t_friends > 1 + (p_ptr->lev / (upkeep_divider))) { show_upkeep = (t_levels); if (show_upkeep > 100) show_upkeep = 100; else if (show_upkeep < 10) show_upkeep = 10; } fprintf(fff, "----------------------------------------------\n"); fprintf(fff, " Total: %d pet%s.\n", t_friends, (t_friends == 1 ? "" : "s")); fprintf(fff, " Upkeep: %d%% mana.\n", show_upkeep); /* Close the file */ my_fclose(fff); /* Display the file contents */ show_file(file_name, "Current Pets", 0, 0); /* Remove the file */ fd_kill(file_name); }