vfs: check userland buffers before reading them.
[haiku.git] / src / apps / soundrecorder / FileUtils.cpp
blob70e90082a44731ed2a0eab96e6c1095e045a1b3f
1 /******************************************************************************
3 / File: FileUtils.cpp
5 / Description: Utility functions for copying file data and attributes.
7 / Copyright 1998-1999, Be Incorporated, All Rights Reserved
9 ******************************************************************************/
10 #include "FileUtils.h"
12 #include <algorithm>
13 #include <new>
14 #include <stdio.h>
15 #include <string.h>
17 #include <fs_attr.h>
19 #include "AutoDeleter.h"
22 using std::nothrow;
25 status_t
26 CopyFileData(BFile& dst, BFile& src)
28 struct stat src_stat;
29 status_t err = src.GetStat(&src_stat);
30 if (err != B_OK) {
31 printf("couldn't get stat: %#010" B_PRIx32 "\n", err);
32 return err;
35 size_t bufSize = src_stat.st_blksize;
36 if (bufSize == 0)
37 bufSize = 32768;
39 char* buf = new (nothrow) char[bufSize];
40 if (buf == NULL)
41 return B_NO_MEMORY;
42 ArrayDeleter<char> _(buf);
44 printf("copy data, bufSize = %ld\n", bufSize);
45 // copy data
46 while (true) {
47 ssize_t bytes = src.Read(buf, bufSize);
48 if (bytes > 0) {
49 ssize_t result = dst.Write(buf, bytes);
50 if (result != bytes) {
51 fprintf(stderr, "Failed to write %ld bytes: %s\n", bytes,
52 strerror((status_t)result));
53 if (result < 0)
54 return (status_t)result;
55 else
56 return B_IO_ERROR;
58 } else {
59 if (bytes < 0) {
60 fprintf(stderr, "Failed to read file: %s\n", strerror(
61 (status_t)bytes));
62 return (status_t)bytes;
63 } else {
64 // EOF
65 break;
70 // finish up miscellaneous stat stuff
71 dst.SetPermissions(src_stat.st_mode);
72 dst.SetOwner(src_stat.st_uid);
73 dst.SetGroup(src_stat.st_gid);
74 dst.SetModificationTime(src_stat.st_mtime);
75 dst.SetCreationTime(src_stat.st_crtime);
77 return B_OK;
81 status_t
82 CopyAttributes(BNode& dst, BNode& src)
84 // copy attributes
85 src.RewindAttrs();
86 char attrName[B_ATTR_NAME_LENGTH];
87 while (src.GetNextAttrName(attrName) == B_OK) {
88 attr_info info;
89 if (src.GetAttrInfo(attrName, &info) != B_OK) {
90 fprintf(stderr, "Failed to read info for attribute '%s'\n",
91 attrName);
92 continue;
94 // copy one attribute in chunks of 4096 bytes
95 size_t size = 4096;
96 uint8 buffer[size];
97 off_t offset = 0;
98 ssize_t read = src.ReadAttr(attrName, info.type, offset, buffer,
99 std::min((off_t)size, info.size));
100 if (read < 0) {
101 fprintf(stderr, "Error reading attribute '%s'\n", attrName);
102 return (status_t)read;
104 // NOTE: Attributes of size 0 are perfectly valid!
105 while (read >= 0) {
106 ssize_t written = dst.WriteAttr(attrName, info.type, offset,
107 buffer, read);
108 if (written != read) {
109 fprintf(stderr, "Error writing attribute '%s'\n", attrName);
110 if (written < 0)
111 return (status_t)written;
112 else
113 return B_IO_ERROR;
115 offset += read;
116 read = src.ReadAttr(attrName, info.type, offset, buffer,
117 std::min((off_t)size, info.size - offset));
118 if (read < 0) {
119 fprintf(stderr, "Error reading attribute '%s'\n", attrName);
120 return (status_t)read;
122 if (read == 0)
123 break;
127 return B_OK;
131 status_t
132 CopyFile(BFile& dst, BFile& src)
134 status_t err = CopyFileData(dst, src);
135 if (err != B_OK)
136 return err;
138 return CopyAttributes(dst, src);