/*FUNCTION*/ int hook_truncate(pExecuteObject pEo, FILE *fp, long lNewFileSize ){ /*noverbatim CUT*/ return file_truncate(fp,lNewFileSize); }
/* convert file using UNIX98 iconv functions returns 0 on success, nonzero error code otherwise when iconv implementation is not transitive (ICONV_TRANSITIVE is not defined), it may help to perform conversion via Unicode, so we try it too (probably UCS-2/ISO-10646, but maybe UTF-8---whatever has been detected at configure time) */ int convert_iconv(File *file, EncaEncoding from_enc) { static int ascii = ENCA_CS_UNKNOWN; File *tempfile = NULL; int err; iconv_t icd; if (!enca_charset_is_known(ascii)) { ascii = enca_name_to_charset("ascii"); assert(enca_charset_is_known(ascii)); } /* When iconv doesn't know the encodings, it can't convert between them. * We also don't try conversion to ASCII, it can only damage the files and * upset users, nothing else. * And fail early on really silly surfaces. */ if (!enca_charset_name(from_enc.charset, ENCA_NAME_STYLE_ICONV) || (enca_charset_is_known(options.target_enc.charset) && !enca_charset_name(options.target_enc.charset, ENCA_NAME_STYLE_ICONV)) || options.target_enc.charset == ascii || !acceptable_surface(from_enc) || !acceptable_surface(options.target_enc)) return ERR_CANNOT; /* Is the conversion possible? */ if (do_iconv_open(from_enc, options.target_enc, &icd) != 0) return ERR_CANNOT; /* Since iconv doesn't recode files in place, we make a temporary file and copy contents of file fname to it. save the current content first, then copy the rest. When the file is stdin, fake-reopen it to stdout. */ err = ERR_IOFAIL; if ((tempfile = file_temporary(file->buffer, 1)) && file_write(tempfile) != -1 && copy_and_convert(file, tempfile, NULL) == 0 && (!file->name || file_seek(file, 0, SEEK_SET) == 0) && file_seek(tempfile, 0, SEEK_SET) == 0 && (!file->name || file_truncate(file, 0) == 0) && (file->name || (file_close(file) == 0 && file_open(file, "wb") == 0))) { /* Create the second buffer when we don't have any yet but don't make it unnecessarily large, system default suffices */ if (!buffer_iconv) buffer_iconv = buffer_new(0); tempfile->buffer = buffer_iconv; err = iconv_one_step(tempfile, file, icd); } file_free(tempfile); do_iconv_close(icd); return err; }
int sys_truncate(int fd) { struct file *file = fd_get_file(fd); int r = -1; if (!file) return -1; r = file_truncate(file); put_file(file); return r; }
int dir_truncateat(struct dir *dir, const char *filename, uint64_t size) { struct file *file = file_open_rw(dir, filename); if (file == NULL) { return -1; } int r = file_truncate(file, size); file_close(file); return r; }
static void file_truncate_file(struct file_info *file) { int fd; char *path; path = dir_path(file->links->parent, file->links->name); fd = open(path, O_WRONLY); CHECK(fd != -1); file_truncate(file, fd); CHECK(close(fd) != -1); free(path); }
int sys_ftruncate(int fd, off_t len) { int r = -EBADF; file_t* f = file_get(fd); if (f) { r = file_truncate(f, len); file_decref(f); } return r; }
/* Randomly select something to do with an open file */ static void operate_on_open_file(struct fd_info *fdi) { size_t r; r = tests_random_no(1000); if (shrink && r == 0) file_truncate(fdi->file, fdi->fd); else if (r < 21) file_close(fdi); else if (shrink && r < 121 && !fdi->file->deleted) file_delete(fdi->file); else file_write(fdi->file, fdi->fd); }
int file_appendv(struct file *file, const struct iovec *iov, int iovcnt, uint64_t file_size) { int i; uint64_t len = 0; for (i=0; i < iovcnt; i++) { len += iov[i].iov_len; } int r = writev(file->fd, iov, iovcnt); FILETRACE(file, r, "writev(\"%s\", %llu)", file->pathname, (unsigned long long)len); /* TODO: are we really sure writev won't write in chunks? */ if (r < 0 || (unsigned)r != len) { file_truncate(file, file_size); return -1; } return len; }
/* Randomly select something to do with an open file */ static void operate_on_open_file(struct fd_info *fdi) { size_t r; r = tests_random_no(1000); if (shrink && r < 5) file_truncate(fdi->file, fdi->fd); else if (r < 21) file_close(fdi); else if (shrink && r < 121 && !fdi->file->deleted) file_delete(fdi->file); else { file_write(fdi->file, fdi->fd); if (r >= 999) { if (tests_random_no(100) >= 50) CHECK(fsync(fdi->fd) != -1); else CHECK(fdatasync(fdi->fd) != -1); } } }
/* * -EINVAL, -EEXIST, -ENOENT, -ENOTDIR, -ENAMETOOLONG, -EISDIR */ int sys_open(const char *path, int flags, __unused mode_t mode) { int64_t parent_inum, inum, fd; struct file *file; const char *child; if ((flags & O_ACCMODE) == 0) return -EINVAL; if ((flags & O_TRUNC) && (flags & O_APPEND || (flags & O_WRONLY) == 0)) return -EINVAL; inum = name_i(path); if (flags & O_CREAT) { if (inum > 0 && (flags & O_EXCL)) return -EEXIST; if (inum == -ENOENT) { parent_inum = path_parent_child(path, &child, NO_DIR); inum = (parent_inum < 0) ? parent_inum : file_new(parent_inum, child, EXT2_FT_REG_FILE); } } if (inum < 0) return inum; if (is_dir(inum)) return -EISDIR; file = kmalloc(sizeof(*file)); file_init(file, inum, flags); fd = unrolled_insert(¤t->fdtable, file); if (flags & O_TRUNC) file_truncate(inum); if (flags & O_APPEND) assert(sys_lseek(fd, 0, SEEK_END) > 0); return fd; }
int net_delroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask) { struct route_match_ipv6_s match; struct net_route_ipv6_s route; struct file fshandle; off_t filesize; ssize_t nwritten; ssize_t nread; off_t pos; int nentries; int index; int ret; /* We must lock out other accesses to the routing table while we remove * entry */ ret = net_lockroute_ipv6(); if (ret < 0) { nerr("ERROR: net_lockroute_ipv6 failed: %d\n", ret); return ret; } /* Get the size of the routing table (in entries) */ nentries = net_routesize_ipv6(); if (nentries < 0) { ret = nentries; goto errout_with_lock; } else if (nentries == 0) { ret = -ENOENT; goto errout_with_lock; } /* Set up the comparison structure */ net_ipv6addr_copy(match.target, target); net_ipv6addr_copy(match.netmask, netmask); match.index = 0; /* Then find the index into the routing table where the match can be found */ ret = net_foreachroute_ipv6(net_match_ipv6, &match); if (ret < 0) { /* And error occurred */ ret = ret; goto errout_with_lock; } else if (ret == 0) { /* No match found */ ret = -ENOENT; goto errout_with_lock; } /* Open the routing table for read/write access */ ret = net_openroute_ipv6(O_RDWR, &fshandle); if (ret < 0) { nerr("ERROR: Could not open IPv6 routing table: %d\n", ret); goto errout_with_lock; } #ifdef CONFIG_ROUTE_IPv6_CACHEROUTE /* We are committed to modifying the routing table. Flush the in-memory * routing table cache. */ net_flushcache_ipv6(); #endif /* Loop, copying each entry, to the previous entry thus removing the entry * to be deleted. */ for (index = match.index + 1; index < nentries; index++) { /* Seek to the current entry to be moved */ pos = net_seekroute_ipv6(&fshandle, index); if (pos < 0) { nerr("ERROR: net_readroute_ipv6 failed: %ld\n", (long)pos); ret =(int)pos; goto errout_with_fshandle; } /* Read the routing table entry at this position */ nread = net_readroute_ipv6(&fshandle, &route); if (nread < 0) { nerr("ERROR: net_readroute_ipv6 failed: %ld\n", (long)nread); ret = (int)nread; goto errout_with_fshandle; } else if (nread == 0) { nerr("ERROR: Unexpected end of file\n"); ret = -EINVAL; goto errout_with_fshandle; } /* Seek to the previous entry to be replaced */ pos = net_seekroute_ipv6(&fshandle, index - 1); if (pos < 0) { nerr("ERROR: net_readroute_ipv6 failed: %ld\n", (long)pos); ret =(int)pos; goto errout_with_fshandle; } /* Now write the record to its new location */ nwritten = net_writeroute_ipv6(&fshandle, &route); if (nwritten < 0) { nerr("ERROR: net_readroute_ipv6 failed: %ld\n", (long)nwritten); ret = (int)nwritten; goto errout_with_fshandle; } } /* Now truncate the one duplicate entry at the end of the file. This may * result in a zero length file. */ filesize = (nentries - 1) * sizeof(struct net_route_ipv6_s); ret = file_truncate(&fshandle, filesize); errout_with_fshandle: (void)net_closeroute_ipv6(&fshandle); errout_with_lock: (void)net_unlockroute_ipv6(); return ret; }
/* convert file using GNU recode library returns 0 on success, nonzero error code otherwise */ int convert_recode(File *file, EncaEncoding from_enc) { RECODE_REQUEST request; RECODE_TASK task; File *tempfile = NULL; bool success; const char *encreq; /* Allocate librecode outer if we are called first time. */ if (outer == NULL) { if ((outer = recode_new_outer(false)) == NULL) { fprintf(stderr, "%s: recode library doesn't like us\n", program_name); return ERR_LIBCOM; } } /* Construct recode request string, try to mimic surfaceless converter now. */ { EncaEncoding enc; enc.charset = from_enc.charset; enc.surface = from_enc.surface | ENCA_SURFACE_REMOVE; encreq = format_request_string(enc, options.target_enc, ENCA_SURFACE_EOL_LF); } /* Create a recode request from it. */ request = get_recode_request(encreq); if (request == NULL) return ERR_CANNOT; /* Now we have to distinguish between file and stdin, namely because * in case of stdin, it's first part is already loaded in the buffer. */ if (file->name != NULL) { /* File is a regular file. Since recode doesn't recode files in place, we make a temporary file and copy contents of file fname to it. */ if (file_seek(file, 0, SEEK_SET) != 0) return ERR_IOFAIL; file->buffer->pos = 0; if ((tempfile = file_temporary(file->buffer, 1)) == NULL || copy_and_convert(file, tempfile, NULL) != 0 || file_seek(file, 0, SEEK_SET) != 0 || file_seek(tempfile, 0, SEEK_SET) != 0 || file_truncate(file, 0) != 0) { file_free(tempfile); return ERR_IOFAIL; } /* Create a task from the request. */ task = recode_new_task(request); task->fail_level = enca_recode_fail_level; task->abort_level = RECODE_SYSTEM_ERROR; task->input.name = NULL; task->input.file = tempfile->stream; task->output.name = NULL; task->output.file = file->stream; /* Now run conversion temporary file -> original. */ success = recode_perform_task(task); /* If conversion wasn't successfull, original file is probably damaged (damned librecode!) try to restore it from the temporary copy. */ if (!success) { if (task->error_so_far >= RECODE_SYSTEM_ERROR) { fprintf(stderr, "%s: librecode probably damaged file `%s'. " "Trying to recover... ", program_name, file->name); tempfile->buffer->pos = 0; if (file_seek(tempfile, 0, SEEK_SET) != -1 && file_seek(file, 0, SEEK_SET) != -1 && file_truncate(file, file->size) == 0 && copy_and_convert(tempfile, file, NULL) == 0) fprintf(stderr, "succeeded.\n"); else fprintf(stderr, "failed\n"); } else print_recode_warning(task->error_so_far, file->name); } recode_delete_task(task); file_free(tempfile); } else { /* File is stdin. First recode begining saved in io_buffer, then append rest of stdin. */ enum recode_error errmax = RECODE_NO_ERROR; /* Create a task from the request. * Set it up for buffer -> stdout conversion */ task = recode_new_task(request); task->fail_level = enca_recode_fail_level; task->abort_level = RECODE_SYSTEM_ERROR; task->input.name = NULL; task->input.file = NULL; task->input.buffer = (char*)file->buffer->data; task->input.cursor = (char*)file->buffer->data; task->input.limit = (char*)file->buffer->data + file->buffer->pos; task->output.name = NULL; task->output.file = stdout; success = recode_perform_task(task); if (!success) { if (task->error_so_far >= RECODE_SYSTEM_ERROR) { fprintf(stderr, "%s: librecode probably damaged `%s'. " "No way to recover in a pipe.\n", program_name, ffname_r(NULL)); recode_delete_task(task); return ERR_IOFAIL; } else errmax = task->error_so_far; } recode_delete_task(task); /* Create a task from the request. * Set it up for stdin -> stdout conversion */ task = recode_new_task(request); task->fail_level = enca_recode_fail_level; task->abort_level = RECODE_SYSTEM_ERROR; task->input.name = NULL; task->input.file = stdin; task->output.name = NULL; task->output.file = stdout; success = recode_perform_task(task); if (!success) { if (task->error_so_far >= RECODE_SYSTEM_ERROR) { fprintf(stderr, "%s: librecode probably damaged `%s'. " "No way to recover in a pipe.\n", program_name, ffname_r(NULL)); recode_delete_task(task); return ERR_IOFAIL; } else { if (errmax < task->error_so_far) errmax = task->error_so_far; } } if (errmax >= enca_recode_fail_level) print_recode_warning(errmax, ffname_r(NULL)); recode_delete_task(task); } /* return ERR_IOFAIL on failure since it means file-related problems */ return success ? ERR_OK : ERR_IOFAIL; }
/* perform one conversion step using conversion descriptor icd reading for file_from and putting result to file_to */ static int iconv_one_step(File *file_from, File *file_to, iconv_t icd) { size_t size_from, size_to, n; char *p_from, *p_to; int hit_eof; /* convert */ do { /* read to io_buffer */ if (file_read(file_from) == -1) return ERR_IOFAIL; p_from = (char*)file_from->buffer->data; size_from = file_from->buffer->pos; hit_eof = (ssize_t)file_from->buffer->size > file_from->buffer->pos; /* convert without reading more data until io_buffer is exhausted or some error occurs */ do { p_to = (char*)file_to->buffer->data; size_to = file_to->buffer->size; n = iconv(icd, (ICONV_CONST char**)&p_from, &size_from, &p_to, &size_to); file_to->buffer->pos = file_to->buffer->size - size_to; if (n != (size_t)-1 || errno != E2BIG) break; if (file_write(file_to) == -1) return ERR_IOFAIL; } while (1); if (n == (size_t)-1) { /* EINVAL means some multibyte sequence has been splitted---that's ok, move it to the begining and go on */ if (errno == EINVAL && !hit_eof) { memmove(file_from->buffer->data, p_from, size_from); file_from->buffer->pos = size_from; } else { /* but other errors are critical, conversion and try to recover */ fprintf(stderr, "%s: Iconv conversion error on `%s': %s\n", program_name, ffname_r(file_from->name), strerror(errno)); if (file_from->name && file_to->name) { Buffer *buf; int err; /* regular file */ fprintf(stderr, "Trying to recover... "); if (file_seek(file_from, 0, SEEK_SET) != 0 || file_seek(file_to, 0, SEEK_SET) != 0 || file_truncate(file_to, file_to->size) != 0) { fprintf(stderr, "failed\n"); return ERR_IOFAIL; } file_from->buffer->pos = 0; buf = file_to->buffer; file_to->buffer = file_from->buffer; err = copy_and_convert(file_from, file_to, NULL); file_to->buffer = buf; if (err != 0) { fprintf(stderr, "failed\n"); return ERR_IOFAIL; } fprintf(stderr, "succeeded.\n"); } else { fprintf(stderr, "No way to recover in a pipe.\n"); return ERR_IOFAIL; } return ERR_MALFORM; } } else file_from->buffer->pos = 0; /* write the remainder */ if (file_write(file_to) == -1) return ERR_IOFAIL; } while (!hit_eof); /* file might end with an unfinished multibyte sequence */ if (size_from > 0) { fprintf(stderr, "%s: File `%s' seems to be truncated, " "the trailing incomplete multibyte sequence " "has been lost\n", program_name, ffname_r(file_from->name)); return ERR_MALFORM; } return ERR_OK; }
bool filesys_remove (const char *path){ struct block *d = NULL; struct ext2_meta_data *meta = NULL; char *parent = NULL, *name = NULL; struct directory *parent_dir = NULL; struct file *parent_file = NULL, *file = NULL; struct directory *directory_data = NULL; struct directory *file_entry = NULL, *last_entry = NULL; uint32_t file_size = 0, bytes_read = 0; bool success = false; ASSERT(path != NULL && strlen(path) > 0); // Get device d = block_get_role (BLOCK_FILESYS); ASSERT(d != NULL); meta = ext2_get_meta(d); ASSERT(meta != NULL && meta->sb != NULL); // open file file = filesys_open(path); if(file == NULL){ // file does not exists printf("filesys_remove: %s does not exist!.\n",path); goto cleanup; } //Check file type if(file->dir->file_type != EXT2_FT_REG_FILE){ printf("filesys_remove %s is not a regular file.\n",path); goto cleanup; } // Split path filesys_split_path(path, &parent, &name); ASSERT(parent != NULL && name != NULL); // Get parent directory parent_dir = dir_lookup(d,parent); if(parent_dir == NULL){ printf("Directory %s does not exist.\n",parent); goto cleanup; } // Check parent type if(parent_dir -> file_type != EXT2_FT_DIR){ printf("Path %s is not a directory.\n",parent); goto cleanup; } // Get directory file parent_file = filesys_open(parent); if(parent_file == NULL) goto cleanup; // Get parent directory data file_size = parent_file->inode->i_size; directory_data = kmalloc(file_size); bytes_read = file_read(parent_file,directory_data,file_size); if(bytes_read != file_size) goto cleanup; // Get file directory entry file_entry = directory_data; while (file_entry != NULL && memcmp(file_entry->name,name,file_entry->name_len) != 0 && (uint8_t*)file_entry+file_entry->rec_len < (uint8_t*)directory_data+file_size){ last_entry = file_entry; file_entry = dir_get_next(file_entry); } // check if file entry if found. if( (uint8_t*)file_entry >= (uint8_t*)directory_data+file_size || memcmp(file_entry->name,name,file_entry->name_len) != 0 ) goto cleanup; // Truncate file to zero length // Aka. Free blocks file_truncate(file,0); // Zero inode memset(file->inode,0,sizeof(struct inode)); ext2_write_inode(d,file->dir->inode,file->inode); // Free inode freemap_free_inode(file_entry->inode); // Delete directory record // Use last entry record length to skip file entry if(last_entry->inode != 0) last_entry->rec_len += file_entry->rec_len; // Write directory file file_write_at(parent_file,directory_data,file_size,0); // file deleted successfully. success = true; cleanup: // close file if(file != NULL) file_close(file); if(parent_file != NULL) file_close(parent_file); // release memory if(parent != NULL) kfree(parent); if(name != NULL) kfree(name); if(parent_dir != NULL) kfree(parent_dir); if(directory_data != NULL) kfree(directory_data); return success; }
int config_write(struct config *conf, const char *filename) { struct file_descriptor *fd; struct KeyValuePair *e; uint64 offset; int res; res = 0; fd = NULL; ASSERT(conf); if (filename == NULL) { ASSERT(conf->fileName); } else { free(conf->fileName); conf->fileName = safe_strdup(filename); } res = file_open(conf->fileName, FALSE, FALSE, &fd); if (res != 0) { Log(LGPFX" Failed to open config '%s': %s (%d)\n", filename, strerror(res), res); return res; } res = file_truncate(fd, 0); if (res != 0) { Log(LGPFX" Failed to truncate '%s': %s (%d)\n", filename, strerror(res), res); goto exit; } e = conf->list; offset = 0; while (e) { size_t numBytes; char *s = NULL; if (e->save == 0) { Log(LGPFX" not writing key '%s'\n", e->key); e = e->next; continue; } switch (e->type) { case CONFIG_KV_INT64: s = safe_asprintf("%s = \"%lld\"\n", e->key, e->u.val); break; case CONFIG_KV_BOOL: s = safe_asprintf("%s = \"%s\"\n", e->key, e->u.trueOrFalse ? "TRUE" : "FALSE"); break; default: ASSERT(e->type == CONFIG_KV_UNKNOWN || e->type == CONFIG_KV_STRING); if (e->u.str) { s = safe_asprintf("%s = \"%s\"\n", e->key, e->u.str); } } if (s) { numBytes = 0; res = file_pwrite(fd, offset, s, strlen(s), &numBytes); if (res != 0 || numBytes != strlen(s)) { Log(LGPFX" Failed to pwrite %zd bytes: %s (%d)\n", strlen(s), strerror(res), res); free(s); goto exit; } offset += numBytes; free(s); } e = e->next; } exit: if (res != 0) { // XXX: consider cleaning-up. } if (fd) { file_close(fd); } return res; }
int gsiftp_truncate(int handle, LONGLONG filesize) { return file_truncate(handle, filesize); }