blob: 79a4624bbe57bb7746b02bb9e3623647720fbc79 [file] [log] [blame]
Alistair Delvabeaee832021-02-24 11:27:23 -08001/* 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{
Yi Kong39bbd962022-01-09 19:41:38 +080033 ssize_t n;
Alistair Delvabeaee832021-02-24 11:27:23 -080034 *error = 0;
Yi Kong39bbd962022-01-09 19:41:38 +080035 if((n=force_pread(entry->Dir, (char *) (&entry->dir),
36 (mt_off_t) entry->entry * MDIR_SIZE,
37 MDIR_SIZE)) != MDIR_SIZE) {
Alistair Delvabeaee832021-02-24 11:27:23 -080038 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);
Yi Kong39bbd962022-01-09 19:41:38 +080055 DeclareThis(Fs_t);
56 ssize_t ret;
Alistair Delvabeaee832021-02-24 11:27:23 -080057 unsigned int buflen;
58 char *buffer;
Yi Kong39bbd962022-01-09 19:41:38 +080059
Alistair Delvabeaee832021-02-24 11:27:23 -080060 if (!getfreeMinClusters(Dir, 1))
61 return -1;
62
Yi Kong39bbd962022-01-09 19:41:38 +080063 buflen = getClusterBytes(This);
Alistair Delvabeaee832021-02-24 11:27:23 -080064
65 if(! (buffer=malloc(buflen)) ){
66 perror("dir_grow: malloc");
67 return -1;
68 }
Yi Kong39bbd962022-01-09 19:41:38 +080069
Alistair Delvabeaee832021-02-24 11:27:23 -080070 memset((char *) buffer, '\0', buflen);
Yi Kong39bbd962022-01-09 19:41:38 +080071 ret = force_pwrite(Dir, buffer, (mt_off_t) size * MDIR_SIZE, buflen);
Alistair Delvabeaee832021-02-24 11:27:23 -080072 free(buffer);
73 if(ret < (int) buflen)
74 return -1;
75 return 0;
76}
77
78
79void low_level_dir_write(direntry_t *entry)
80{
Yi Kong39bbd962022-01-09 19:41:38 +080081 force_pwrite(entry->Dir,
82 (char *) (&entry->dir),
83 (mt_off_t) entry->entry * MDIR_SIZE, MDIR_SIZE);
Alistair Delvabeaee832021-02-24 11:27:23 -080084}
85
86void low_level_dir_write_end(Stream_t *Dir, int entry)
87{
88 char zero = ENDMARK;
Yi Kong39bbd962022-01-09 19:41:38 +080089 force_pwrite(Dir, &zero, (mt_off_t) entry * MDIR_SIZE, 1);
Alistair Delvabeaee832021-02-24 11:27:23 -080090}
91
92/*
93 * Make a directory entry. Builds a directory entry based on the
94 * name, attribute, starting cluster number, and size. Returns a pointer
95 * to a static directory structure.
96 */
97
98struct directory *mk_entry(const dos_name_t *dn, unsigned char attr,
Yi Kong39bbd962022-01-09 19:41:38 +080099 unsigned int fat, uint32_t size, time_t date,
Alistair Delvabeaee832021-02-24 11:27:23 -0800100 struct directory *ndir)
101{
102 struct tm *now;
103 time_t date2 = date;
Yi Kong39bbd962022-01-09 19:41:38 +0800104 uint8_t hour, min_hi, min_low, sec;
105 uint8_t year, month_hi, month_low, day;
Alistair Delvabeaee832021-02-24 11:27:23 -0800106
107 now = localtime(&date2);
108 dosnameToDirentry(dn, ndir);
109 ndir->attr = attr;
110 ndir->ctime_ms = 0;
Yi Kong39bbd962022-01-09 19:41:38 +0800111 hour = (uint8_t) (now->tm_hour << 3);
112 min_hi = (uint8_t) (now->tm_min >> 3);
113 min_low = (uint8_t) (now->tm_min << 5);
114 sec = (uint8_t) (now->tm_sec / 2);
Alistair Delvabeaee832021-02-24 11:27:23 -0800115 ndir->ctime[1] = ndir->time[1] = hour + min_hi;
116 ndir->ctime[0] = ndir->time[0] = min_low + sec;
Yi Kong39bbd962022-01-09 19:41:38 +0800117 year = (uint8_t) ((now->tm_year - 80) << 1);
118 month_hi = (uint8_t) ((now->tm_mon + 1) >> 3);
119 month_low = (uint8_t) ((now->tm_mon + 1) << 5);
120 day = (uint8_t) (now->tm_mday);
Alistair Delvabeaee832021-02-24 11:27:23 -0800121 ndir -> adate[1] = ndir->cdate[1] = ndir->date[1] = year + month_hi;
122 ndir -> adate[0] = ndir->cdate[0] = ndir->date[0] = month_low + day;
123
124 set_word(ndir->start, fat & 0xffff);
125 set_word(ndir->startHi, fat >> 16);
126 set_dword(ndir->size, size);
127 return ndir;
128}
129
130/*
131 * Make a directory entry from base name. This is supposed to be used
132 * from places such as mmd for making special entries (".", "..", "/", ...)
133 * Thus it doesn't bother with character set conversions
134 */
135struct directory *mk_entry_from_base(const char *base, unsigned char attr,
Yi Kong39bbd962022-01-09 19:41:38 +0800136 unsigned int fat, uint32_t size, time_t date,
Alistair Delvabeaee832021-02-24 11:27:23 -0800137 struct directory *ndir)
138{
139 struct dos_name_t dn;
140 strncpy(dn.base, base, 8);
141 strncpy(dn.ext, " ", 3);
142 return mk_entry(&dn, attr, fat, size, date, ndir);
143}