vfs: check userland buffers before reading them.
[haiku.git] / src / apps / debugger / user_interface / report / ReportUserInterface.cpp
blobfb5f1f3286e776034f3dc80312b6231ada47b5bf
1 /*
2 * Copyright 2015-2016, Rene Gollent, rene@gollent.com.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "ReportUserInterface.h"
9 #include <stdio.h>
11 #include <Entry.h>
12 #include <FindDirectory.h>
13 #include <Path.h>
15 #include <AutoLocker.h>
17 #include "MessageCodes.h"
18 #include "UiUtils.h"
21 ReportUserInterface::ReportUserInterface(thread_id targetThread,
22 const char* reportPath)
24 fTeam(NULL),
25 fListener(NULL),
26 fTargetThread(targetThread),
27 fReportPath(reportPath),
28 fShowSemaphore(-1),
29 fReportSemaphore(-1),
30 fShown(false),
31 fTerminating(false)
36 ReportUserInterface::~ReportUserInterface()
38 if (fShowSemaphore >= 0)
39 delete_sem(fShowSemaphore);
41 fTeam->RemoveListener(this);
45 const char*
46 ReportUserInterface::ID() const
48 return "ReportUserInterface";
52 status_t
53 ReportUserInterface::Init(Team* team, UserInterfaceListener* listener)
55 fShowSemaphore = create_sem(0, "show report");
56 if (fShowSemaphore < 0)
57 return fShowSemaphore;
59 fReportSemaphore = create_sem(0, "report generator wait");
60 if (fReportSemaphore < 0)
61 return fReportSemaphore;
63 fTeam = team;
64 fListener = listener;
66 fTeam->AddListener(this);
68 return B_OK;
72 void
73 ReportUserInterface::Show()
75 fShown = true;
76 release_sem(fShowSemaphore);
80 void
81 ReportUserInterface::Terminate()
83 fTerminating = true;
87 UserInterface*
88 ReportUserInterface::Clone() const
90 // the report interface does not support cloning, since
91 // it won't ever be asked to interactively restart.
92 return NULL;
96 bool
97 ReportUserInterface::IsInteractive() const
99 return false;
103 status_t
104 ReportUserInterface::LoadSettings(const TeamUiSettings* settings)
106 return B_OK;
110 status_t
111 ReportUserInterface::SaveSettings(TeamUiSettings*& settings) const
113 return B_OK;
117 void
118 ReportUserInterface::NotifyUser(const char* title, const char* message,
119 user_notification_type type)
124 void
125 ReportUserInterface::NotifyBackgroundWorkStatus(const char* message)
130 int32
131 ReportUserInterface::SynchronouslyAskUser(const char* title,
132 const char* message, const char* choice1, const char* choice2,
133 const char* choice3)
135 return -1;
139 status_t
140 ReportUserInterface::SynchronouslyAskUserForFile(entry_ref* _ref)
142 return B_UNSUPPORTED;
146 void
147 ReportUserInterface::Run()
149 // Wait for the Show() semaphore to be released.
150 status_t error;
151 do {
152 error = acquire_sem(fShowSemaphore);
153 } while (error == B_INTERRUPTED);
155 if (error != B_OK)
156 return;
158 bool waitNeeded = false;
159 if (fTargetThread > 0) {
160 AutoLocker< ::Team> teamLocker(fTeam);
161 ::Thread* thread = fTeam->ThreadByID(fTargetThread);
162 if (thread == NULL)
163 waitNeeded = true;
164 else if (thread->State() != THREAD_STATE_STOPPED) {
165 waitNeeded = true;
166 fListener->ThreadActionRequested(fTargetThread, MSG_THREAD_STOP);
170 if (waitNeeded) {
171 do {
172 error = acquire_sem(fShowSemaphore);
173 } while (error == B_INTERRUPTED);
175 if (error != B_OK)
176 return;
179 entry_ref ref;
180 if (fReportPath != NULL && fReportPath[0] == '/') {
181 error = get_ref_for_path(fReportPath, &ref);
182 } else {
183 char filename[B_FILE_NAME_LENGTH];
184 if (fReportPath != NULL)
185 strlcpy(filename, fReportPath, sizeof(filename));
186 else
187 UiUtils::ReportNameForTeam(fTeam, filename, sizeof(filename));
189 BPath path;
190 error = find_directory(B_DESKTOP_DIRECTORY, &path);
191 if (error == B_OK)
192 error = path.Append(filename);
193 if (error == B_OK)
194 error = get_ref_for_path(path.Path(), &ref);
197 if (error != B_OK)
198 printf("Unable to get ref for report path %s\n", strerror(error));
199 else {
200 fListener->DebugReportRequested(&ref);
202 do {
203 error = acquire_sem(fReportSemaphore);
204 } while (error == B_INTERRUPTED);
207 fListener->UserInterfaceQuitRequested(
208 UserInterfaceListener::QUIT_OPTION_ASK_KILL_TEAM);
212 void
213 ReportUserInterface::ThreadAdded(const Team::ThreadEvent& event)
215 ::Thread* thread = event.GetThread();
216 if (thread->ID() != fTargetThread)
217 return;
219 if (thread->State() != THREAD_STATE_STOPPED)
220 fListener->ThreadActionRequested(thread->ID(), MSG_THREAD_STOP);
221 else
222 release_sem(fShowSemaphore);
226 void
227 ReportUserInterface::ThreadStateChanged(const Team::ThreadEvent& event)
229 ::Thread* thread = event.GetThread();
230 if (thread->ID() != fTargetThread)
231 return;
232 else if (thread->State() == THREAD_STATE_STOPPED)
233 release_sem(fShowSemaphore);
237 void
238 ReportUserInterface::DebugReportChanged(const Team::DebugReportEvent& event)
240 if (event.GetFinalStatus() == B_OK)
241 printf("Debug report saved to %s\n", event.GetReportPath());
242 else {
243 fprintf(stderr, "Failed to write debug report: %s\n", strerror(
244 event.GetFinalStatus()));
246 release_sem(fReportSemaphore);