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