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 21 using std::nothrow; 22 23 24 status_t 25 CopyFileData(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 80 status_t 81 CopyAttributes(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 130 status_t 131 CopyFile(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