13ee96407SJérôme Duval /******************************************************************************
257e2f323SJérôme Duval /
357e2f323SJérôme Duval / File: FileUtils.cpp
457e2f323SJérôme Duval /
557e2f323SJérôme Duval / Description: Utility functions for copying file data and attributes.
657e2f323SJérôme Duval /
757e2f323SJérôme Duval / Copyright 1998-1999, Be Incorporated, All Rights Reserved
857e2f323SJérôme Duval /
93ee96407SJérôme Duval ******************************************************************************/
1057e2f323SJérôme Duval #include "FileUtils.h"
1157e2f323SJérôme Duval
12*e367c056SJérôme Duval #include <algorithm>
13c1c81d42SStephan Aßmus #include <new>
14c1c81d42SStephan Aßmus #include <stdio.h>
15c1c81d42SStephan Aßmus #include <string.h>
16c1c81d42SStephan Aßmus
17c1c81d42SStephan Aßmus #include <fs_attr.h>
18c1c81d42SStephan Aßmus
19c1c81d42SStephan Aßmus #include "AutoDeleter.h"
20c1c81d42SStephan Aßmus
21c1c81d42SStephan Aßmus
22c1c81d42SStephan Aßmus using std::nothrow;
23c1c81d42SStephan Aßmus
24c1c81d42SStephan Aßmus
25c1c81d42SStephan Aßmus status_t
CopyFileData(BFile & dst,BFile & src)26c1c81d42SStephan Aßmus CopyFileData(BFile& dst, BFile& src)
2757e2f323SJérôme Duval {
2857e2f323SJérôme Duval struct stat src_stat;
2957e2f323SJérôme Duval status_t err = src.GetStat(&src_stat);
3057e2f323SJérôme Duval if (err != B_OK) {
317f4d1af4SSergei Reznikov printf("couldn't get stat: %#010" B_PRIx32 "\n", err);
3257e2f323SJérôme Duval return err;
3357e2f323SJérôme Duval }
3457e2f323SJérôme Duval
3557e2f323SJérôme Duval size_t bufSize = src_stat.st_blksize;
36c1c81d42SStephan Aßmus if (bufSize == 0)
3757e2f323SJérôme Duval bufSize = 32768;
3857e2f323SJérôme Duval
39c1c81d42SStephan Aßmus char* buf = new (nothrow) char[bufSize];
40c1c81d42SStephan Aßmus if (buf == NULL)
41c1c81d42SStephan Aßmus return B_NO_MEMORY;
42c1c81d42SStephan Aßmus ArrayDeleter<char> _(buf);
4357e2f323SJérôme Duval
4457e2f323SJérôme Duval printf("copy data, bufSize = %ld\n", bufSize);
4557e2f323SJérôme Duval // copy data
4657e2f323SJérôme Duval while (true) {
4757e2f323SJérôme Duval ssize_t bytes = src.Read(buf, bufSize);
4857e2f323SJérôme Duval if (bytes > 0) {
4957e2f323SJérôme Duval ssize_t result = dst.Write(buf, bytes);
5057e2f323SJérôme Duval if (result != bytes) {
51c1c81d42SStephan Aßmus fprintf(stderr, "Failed to write %ld bytes: %s\n", bytes,
52c1c81d42SStephan Aßmus strerror((status_t)result));
53c1c81d42SStephan Aßmus if (result < 0)
54c1c81d42SStephan Aßmus return (status_t)result;
55c1c81d42SStephan Aßmus else
56c1c81d42SStephan Aßmus return B_IO_ERROR;
5757e2f323SJérôme Duval }
5857e2f323SJérôme Duval } else {
5957e2f323SJérôme Duval if (bytes < 0) {
60c1c81d42SStephan Aßmus fprintf(stderr, "Failed to read file: %s\n", strerror(
61c1c81d42SStephan Aßmus (status_t)bytes));
62c1c81d42SStephan Aßmus return (status_t)bytes;
6357e2f323SJérôme Duval } else {
6457e2f323SJérôme Duval // EOF
6557e2f323SJérôme Duval break;
6657e2f323SJérôme Duval }
6757e2f323SJérôme Duval }
6857e2f323SJérôme Duval }
6957e2f323SJérôme Duval
7057e2f323SJérôme Duval // finish up miscellaneous stat stuff
7157e2f323SJérôme Duval dst.SetPermissions(src_stat.st_mode);
7257e2f323SJérôme Duval dst.SetOwner(src_stat.st_uid);
7357e2f323SJérôme Duval dst.SetGroup(src_stat.st_gid);
7457e2f323SJérôme Duval dst.SetModificationTime(src_stat.st_mtime);
7557e2f323SJérôme Duval dst.SetCreationTime(src_stat.st_crtime);
7657e2f323SJérôme Duval
7757e2f323SJérôme Duval return B_OK;
7857e2f323SJérôme Duval }
7957e2f323SJérôme Duval
8057e2f323SJérôme Duval
81c1c81d42SStephan Aßmus status_t
CopyAttributes(BNode & dst,BNode & src)82c1c81d42SStephan Aßmus CopyAttributes(BNode& dst, BNode& src)
8357e2f323SJérôme Duval {
8457e2f323SJérôme Duval // copy attributes
8557e2f323SJérôme Duval src.RewindAttrs();
86c1c81d42SStephan Aßmus char attrName[B_ATTR_NAME_LENGTH];
87c1c81d42SStephan Aßmus while (src.GetNextAttrName(attrName) == B_OK) {
8857e2f323SJérôme Duval attr_info info;
89c1c81d42SStephan Aßmus if (src.GetAttrInfo(attrName, &info) != B_OK) {
90c1c81d42SStephan Aßmus fprintf(stderr, "Failed to read info for attribute '%s'\n",
91c1c81d42SStephan Aßmus attrName);
92c1c81d42SStephan Aßmus continue;
9357e2f323SJérôme Duval }
94c1c81d42SStephan Aßmus // copy one attribute in chunks of 4096 bytes
95c1c81d42SStephan Aßmus size_t size = 4096;
96c1c81d42SStephan Aßmus uint8 buffer[size];
97c1c81d42SStephan Aßmus off_t offset = 0;
98c1c81d42SStephan Aßmus ssize_t read = src.ReadAttr(attrName, info.type, offset, buffer,
99*e367c056SJérôme Duval std::min((off_t)size, info.size));
100c1c81d42SStephan Aßmus if (read < 0) {
101c1c81d42SStephan Aßmus fprintf(stderr, "Error reading attribute '%s'\n", attrName);
102c1c81d42SStephan Aßmus return (status_t)read;
103c1c81d42SStephan Aßmus }
104c1c81d42SStephan Aßmus // NOTE: Attributes of size 0 are perfectly valid!
105c1c81d42SStephan Aßmus while (read >= 0) {
1063ee96407SJérôme Duval ssize_t written = dst.WriteAttr(attrName, info.type, offset,
1073ee96407SJérôme Duval buffer, read);
108c1c81d42SStephan Aßmus if (written != read) {
109c1c81d42SStephan Aßmus fprintf(stderr, "Error writing attribute '%s'\n", attrName);
110c1c81d42SStephan Aßmus if (written < 0)
111c1c81d42SStephan Aßmus return (status_t)written;
112c1c81d42SStephan Aßmus else
113c1c81d42SStephan Aßmus return B_IO_ERROR;
114c1c81d42SStephan Aßmus }
115c1c81d42SStephan Aßmus offset += read;
116c1c81d42SStephan Aßmus read = src.ReadAttr(attrName, info.type, offset, buffer,
117*e367c056SJérôme Duval std::min((off_t)size, info.size - offset));
118c1c81d42SStephan Aßmus if (read < 0) {
119c1c81d42SStephan Aßmus fprintf(stderr, "Error reading attribute '%s'\n", attrName);
120c1c81d42SStephan Aßmus return (status_t)read;
121c1c81d42SStephan Aßmus }
122c1c81d42SStephan Aßmus if (read == 0)
123c1c81d42SStephan Aßmus break;
12457e2f323SJérôme Duval }
12557e2f323SJérôme Duval }
12657e2f323SJérôme Duval
12757e2f323SJérôme Duval return B_OK;
12857e2f323SJérôme Duval }
12957e2f323SJérôme Duval
13057e2f323SJérôme Duval
131c1c81d42SStephan Aßmus status_t
CopyFile(BFile & dst,BFile & src)132c1c81d42SStephan Aßmus CopyFile(BFile& dst, BFile& src)
13357e2f323SJérôme Duval {
13457e2f323SJérôme Duval status_t err = CopyFileData(dst, src);
13557e2f323SJérôme Duval if (err != B_OK)
13657e2f323SJérôme Duval return err;
13757e2f323SJérôme Duval
13857e2f323SJérôme Duval return CopyAttributes(dst, src);
13957e2f323SJérôme Duval }
140