1/* Copyright 1995 David C. Niemi 2 * Copyright 1996-2002,2008,2009 Alain Knaff. 3 * This file is part of mtools. 4 * 5 * Mtools is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * Mtools is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with Mtools. If not, see <http://www.gnu.org/licenses/>. 17 */ 18#include "sysincludes.h" 19#include "msdos.h" 20#include "stream.h" 21#include "mtools.h" 22#include "file.h" 23#include "fs.h" 24#include "file_name.h" 25 26/* #define DEBUG */ 27 28/* 29 * Read a directory entry into caller supplied buffer 30 */ 31struct directory *dir_read(direntry_t *entry, int *error) 32{ 33 int n; 34 *error = 0; 35 if((n=force_read(entry->Dir, (char *) (&entry->dir), 36 (mt_off_t) entry->entry * MDIR_SIZE, 37 MDIR_SIZE)) != MDIR_SIZE) { 38 if (n < 0) { 39 *error = -1; 40 } 41 return NULL; 42 } 43 return &entry->dir; 44} 45 46/* 47 * Make a subdirectory grow in length. Only subdirectories (not root) 48 * may grow. Returns a 0 on success, 1 on failure (disk full), or -1 49 * on error. 50 */ 51 52int dir_grow(Stream_t *Dir, int size) 53{ 54 Stream_t *Stream = GetFs(Dir); 55 DeclareThis(FsPublic_t); 56 int ret; 57 int buflen; 58 char *buffer; 59 60 if (!getfreeMinClusters(Dir, 1)) 61 return -1; 62 63 buflen = This->cluster_size * This->sector_size; 64 65 if(! (buffer=malloc(buflen)) ){ 66 perror("dir_grow: malloc"); 67 return -1; 68 } 69 70 memset((char *) buffer, '\0', buflen); 71 ret = force_write(Dir, buffer, (mt_off_t) size * MDIR_SIZE, buflen); 72 free(buffer); 73 if(ret < buflen) 74 return -1; 75 return 0; 76} 77 78 79void low_level_dir_write(direntry_t *entry) 80{ 81 force_write(entry->Dir, 82 (char *) (&entry->dir), 83 (mt_off_t) entry->entry * MDIR_SIZE, MDIR_SIZE); 84} 85 86 87/* 88 * Make a directory entry. Builds a directory entry based on the 89 * name, attribute, starting cluster number, and size. Returns a pointer 90 * to a static directory structure. 91 */ 92 93struct directory *mk_entry(const dos_name_t *dn, char attr, 94 unsigned int fat, size_t size, time_t date, 95 struct directory *ndir) 96{ 97 struct tm *now; 98 time_t date2 = date; 99 unsigned char hour, min_hi, min_low, sec; 100 unsigned char year, month_hi, month_low, day; 101 102 now = localtime(&date2); 103 dosnameToDirentry(dn, ndir); 104 ndir->attr = attr; 105 ndir->ctime_ms = 0; 106 hour = now->tm_hour << 3; 107 min_hi = now->tm_min >> 3; 108 min_low = now->tm_min << 5; 109 sec = now->tm_sec / 2; 110 ndir->ctime[1] = ndir->time[1] = hour + min_hi; 111 ndir->ctime[0] = ndir->time[0] = min_low + sec; 112 year = (now->tm_year - 80) << 1; 113 month_hi = (now->tm_mon + 1) >> 3; 114 month_low = (now->tm_mon + 1) << 5; 115 day = now->tm_mday; 116 ndir -> adate[1] = ndir->cdate[1] = ndir->date[1] = year + month_hi; 117 ndir -> adate[0] = ndir->cdate[0] = ndir->date[0] = month_low + day; 118 119 set_word(ndir->start, fat & 0xffff); 120 set_word(ndir->startHi, fat >> 16); 121 set_dword(ndir->size, size); 122 return ndir; 123} 124 125/* 126 * Make a directory entry from base name. This is supposed to be used 127 * from places such as mmd for making special entries (".", "..", "/", ...) 128 * Thus it doesn't bother with character set conversions 129 */ 130struct directory *mk_entry_from_base(const char *base, char attr, 131 unsigned int fat, size_t size, time_t date, 132 struct directory *ndir) 133{ 134 struct dos_name_t dn; 135 strncpy(dn.base, base, 8); 136 strncpy(dn.ext, " ", 3); 137 return mk_entry(&dn, attr, fat, size, date, ndir); 138} 139